我正在准备面试,当我经历空指针异常时,我突然意识到每个对象都能以某种方式抛出空指针异常,但我似乎无法想象像System,Out这样的某些对象投掷NullPointerException
。
谁能提到这样的场景?谢谢!
例如:System.out.println(s.get(name));
答案 0 :(得分:8)
首先,System
不是对象。它是一个方法是静态的类。其次,out
是该类的静态字段,它(最初)是对标准输出PrintStream
的引用。您可以使用PrintStream
将System.setOut(PrintStream)
更改为您自己的System.setOut(null);
System.out.println("42"); // because out is now a null reference
。
最后,如果你做了
NullPointerException
你会得到System
。
当然,您可以找到NullPointerException
的方法,也可以抛出NullPointerException
。
当您尝试取消引用null
对象引用时,JVM会抛出大多数{{1}}。
你不要取消引用一个类。
只有可执行代码才能抛出NPE,例如方法,构造函数, 或初始化程序。 - Marko
答案 1 :(得分:1)
并非每个对象都能抛出NullPointerException。通常最好尝试编写不能编写的类!
public class ClassThatCannotNPE {
public int getOne() {
return 1;
}
}
你可以用上面的类做的唯一两件事就是运行它的构造函数,然后调用getOne()。这些东西都不能NPE。
我们必须小心地通过说“某事”引发异常来定义我们的意思。此代码将在第2行抛出NPE:
Date d = null;
System.setProperty("now",d.toString());
但这不是System的例子,也不是System的代码,抛出异常。上面的代码相当于:
Date d = null;
String temp = d.toString();
System.setProperty(temp);
这也会在第2行抛出一个NPE - 在System.setProperty()有机会运行之前。执行顺序与前一个示例完全相同。
怎么样:
System.out.print(null);
这会引发NPE。但是再一次,它不是来自系统的代码抛出它。它相当于:
PrintStream temp = System.out;
temp.print(null);
NPE发生在第2行 - 它不是指系统,也不是指任何涉及系统的东西。
System
是一个类,而不是一个对象。它没有构造函数,因此无法实例化。
但是,它有很多静态方法。是否有可能使任何一个抛出NullPointerException?
实际上,通过查看Javadoc for System并搜索“NullPointerException”,我们可以很快找到答案。许多人的第一场比赛是System.arraycopy():
如果dest为null,则抛出NullPointerException。
所以你有它:
System.arrayCopy(null,0,null,0,0);
...会导致System类中的某些代码抛出NPE。
实际上我们可以查看actual source code for System并查看它抛出NullPointerExceptions的位置。
488 public static native void arraycopy(Object src, int srcPos,
489 Object dest, int destPos,
490 int length);
喔。 arraycopy是native - 意味着实际的实现是JRE中的一些C代码。但我们还能找到什么?
825 private static void checkKey(String key) {
826 if (key == null) {
827 throw new NullPointerException("key can't be null");
828 }
...
和
777 public static String setProperty(String key, String value) {
778 checkKey(key);
...
因此,从System抛出NPE代码的另一种方法是:
System.setProperty(null,"value");
答案 2 :(得分:0)
对null
对象的操作将抛出NullPointerException
。在示例s.get(name)
中,如果s
为null
,则会引发NullPointerException
。由于System
是class
,因此静态引用不会为空。查看源代码,您可以看到out
是静态的final
,最终使用以下命令进行初始化。
setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true));
通常,因为它是final
,这意味着它不会是null
,也不能成为null
。但是public static void setOut(PrintStream out)
调用本机函数private static native void setOut0(PrintStream out)
,实现VM可以在其中创建空引用。
它取决于方法的实现是否会抛出NullPointerException
。具体来说,println(String)
将在对传入的变量进行操作之前进行空检查。
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
因此,在这种情况下,只要NullPointerException
被正确初始化,方法本身就不应该抛出PrintStream
,而System
就是{。}}。
我希望这有助于回答你的问题。如果没有,请在评论中明确说明您的目标。
答案 3 :(得分:0)
Wrapper类能够抛出NPE。尽管java提供了自动装箱,但默认情况下它们不会像原始数据类型那样初始化。
Integer r;
if(r>1)