我对此代码有疑问:
Object obj = null;
someMethod(obj);
System.out.println(obj.getId());
..
..
void someMethod(Object obj) {
obj = new Object();
obj.setId("Id1");
}
以上代码正在抛出NullPointerException
。任何人都可以告诉我为什么即使在方法中实例化之后对象仍然为null?
答案 0 :(得分:8)
调用someMethod(obj)
无法更改obj
变量的值(因为Java是按值语言传递),因此obj
仍为null
通话结束后,System.out.println(obj.getId());
抛出NullPointerException
。
可行的替代方案:
Object obj = someMethod();
System.out.println(obj.getId());
..
..
Object someMethod() {
obj = new Object();
obj.setId("Id1");
return obj;
}
答案 1 :(得分:2)
Java是按值传递的,您将引用传递给对象,而不是对象本身。我认为了解这一点非常重要,因为这可以让你了解Java如何更好地工作,所以让我们一步一步地看看你的代码,看看为什么它不能按你期望的方式工作。
Object obj = null;
someMethod(obj);
void someMethod(Object obj) {
此处,obj
引用被复制(不是对象实例,只是对它的引用),然后传递给someMethod
。
obj = new Object();
在此处,您将覆盖obj
值,但在方法范围内仅 。请注意,调用方(obj
之外)中的someMethod
引用未更改,因为它是副本。方法完成后,此范围中的obj
引用将被丢弃,因为我们超出了范围,您将返回到调用方范围。在此范围内,obj
仍为null
。因此
System.out.println(obj.getId());
明显抛出NullPointerException
。
如果要从方法中获取新引用,可以将其返回并在调用者范围内分配,例如:
Object someMethod() {
obj = new Object();
// Do stuff with obj
return obj;
}
Object obj = someMethod();
答案 2 :(得分:1)
在Java中,您在将参数传递给方法时复制参数。当我们谈论对象时,您传递参考副本。因此,在方法内部分配对象 - 您将它们应用于引用副本。
你需要包装obj引用并在其中传递包装器,而不是使用setter方法来设置obj引用。
第二个解决方案是从你的方法返回你的对象。
答案 3 :(得分:1)
void someMethod(Object obj1) { // incoming obj1 with reference to obj
obj1 = new Object(); // now when you do new Object() obj1 contains new reference
obj1.setId("Id1"); // the object referred by the obj1 reference is updated
}
基本上java使用pass by value。当您调用someMethod(obj)
时,您只是将对obj
的引用作为参数传递而不是对象本身。当在someMethod
内时,对象变量被初始化,现在{ obj1
内的{1}}现在包含对其他对象的引用(不是您从调用类发送的对象)。
因此,当您的程序返回到调用类时,somemethod
再次引用最初发送的原始引用,即obj
对象。因此你得到一个null
。请注意,当调用方法时,它会被分配自己的堆栈帧,因此当调用返回时,调用类'堆栈内的nullpointerexception
和obj1
内的somemethod()
是不同的。 / p>
答案 4 :(得分:1)
由于变量 obj 的值 未更改,因此您获得 NullPointerException 。 当您调用方法 someMethod 并将 obj 传递给它时,您按价值传递了obj ,而未传递 。
答案 5 :(得分:0)
Java通过值传递方法参数:它将您提供的对象的副本作为参数,而不是向方法提供对它的引用;对复制的对象(您可以返回并使用)进行任何更改,而不是对实际对象进行更改。
答案 6 :(得分:0)
Java通过值传递对象的引用。
此时
someMethod(obj);
没有创建任何对象,因此引用值为null。
如果更新方法somemethod()
中的引用变量并将其返回到obj
变量,您将看到两个引用都指向同一个对象。