';空指针访问';使用java输出参数时
我在java中工作,希望使用输出参数之类的东西。以下是一个例子:';空指针访问';使用java输出参数时,java,eclipse,parameters,Java,Eclipse,Parameters,我在java中工作,希望使用输出参数之类的东西。以下是一个例子: ClassA objA = null; if(myMethod(objA)) { // position (1) //use objA somehow } ====================== public bool myMethod(ClassA obj) { obj = ..... } public bool myMethod(ClassA obj, C
ClassA objA = null;
if(myMethod(objA))
{
// position (1)
//use objA somehow
}
======================
public bool myMethod(ClassA obj)
{
obj = .....
}
public bool myMethod(ClassA obj, ClassB obj2)
{
//do stuff
}
我正在使用Eclipse,问题是Eclipse显示了警告:Null指针访问。当我到达位置(1)时,变量objA只能在此位置为空
由于java中没有out
参数的概念,我有点不知所措
==================================================================================
编辑:我已经有几个人提到要更改返回我的对象而不是bool的方法。但是如果我需要一个方法来改变几个对象呢?
例:
======================
public bool myMethod(ClassA obj)
{
obj = .....
}
public bool myMethod(ClassA obj, ClassB obj2)
{
//do stuff
}
我该怎么做?我不想为每种风格的返回对象都创建一个自定义类
谢谢,
Stephanie在myMethod
中为obj
赋值不会改变objA
的值。在Java中,引用是按值传递的。如果希望myMethod
初始化ClassA
的实例,则应将该逻辑移到ClassA
的构造函数或工厂方法中
要发出错误条件的信号,您将抛出一个异常,而不是返回一个布尔值。我很确定Java不支持这种行为;i、 你不能那样做。返回对象或null而不是布尔值。Java是按值传递的。当您在myMethod中将一个值分配给obj
时,您将一个新值分配给调用代码指针的副本。调用代码的指针继续指向其初始对象,该对象为null。这就是为什么Eclipse警告您:无论您在myMethod中做什么,您都在尝试使用objA,它是空的。基本上,您不能用Java来做这件事。调用方法时,传递的是对对象的引用,而不是方法可以写入的内存位置。您可以做的是传入一个对象并允许函数操作该对象。然后,当函数返回时,您可以访问除函数外已处理的字段
ClassA objA = new ClassA();
if(myMethod(objA))
{
objA.getValue();
}
public boolean myMethod(ClassA obj)
{
obj.assignValue(1);
return true;
}
实际上,Eclipse在这种情况下是正确的。考虑下面的代码:
public class NullThing {
private static class ClassA {
public int x;
}
public static boolean myMethod(ClassA obj) {
obj = new ClassA();
obj.x = 5;
return obj.x == 5;
}
public static void main(String[] args) {
ClassA objA = null;
if (myMethod(objA)) {
System.out.println(objA.x);
}
}
}
如果您使用javac
编译此文件以避免Eclipse的警告,您将得到:
adrian:~/ $ javac NullThing.java [14:05:47]
adrian:~/ $ java NullThing [14:06:43]
Exception in thread "main" java.lang.NullPointerException
at NullThing.main(NullThing.java:15)
在本节中,您可以了解Java在这方面的语义,但从代码片段中可以很明显地看出实际发生了什么。您不能真正用Java做您想做的事情,因为正如您所说,Java不支持输出参数
方法参数是局部变量,因此在方法范围之外为其赋值不会产生任何影响。换言之,这:
public void foo(Object obj) {
obj = new Object();
}
实际上相当于(从调用foo(Object)的代码的角度来看),如下所示:
毫无意义,因为一旦foo()
返回,创建的对象将被抛出
可能,您要做的是更改方法以返回方法创建的对象:
public ClassA myMethod() {
ClassA obj = ....
...
return obj;
}
然后在您的呼叫代码中:
ClassA objA = myMethod();
if (objA != null) {
...
}
或者,您可以在方法外部实例化ClassA实例,并传递该值is,然后让方法以某种方式对其进行修改:
public boolean myMethod(ClassA obj) {
obj.setValue(...);
return true;
}
...
ClassA objA = new ClassA();
if (myMethod(objA) {
Object val = objA.getValue();
...
}
如果不了解您的具体问题,很难说哪种设计更好
更新:
不幸的是,您添加的多参数示例在java中完全不可能实现。每个人都说java是通过引用传递的,但实际上它更像是通过引用传递的值。方法可以修改传递给它的对象,但不能修改调用范围中的变量引用的对象。如果你来自C++背景,java中的对象引用更像指针(没有指针运算),而不是C++引用。
<> P>为了使这更具体,考虑下面的类:
public class ParameterPassing {
public static void setParams(Integer value1, Integer value2) {
System.out.println("value1 before: " + value1);
System.out.println("value2 before: " + value2);
value1 = new Integer(1);
value2 = new Integer(2);
System.out.println("value1 after: " + value1);
System.out.println("value2 after: " + value2);
}
public static void main(String[] args) {
Integer valNull = null;
Integer val0 = new Integer(0);
System.out.println("valNull before: " + valNull);
System.out.println("val0 before: " + val0);
setParams(valNull, val0);
System.out.println("valNull after: " + valNull);
System.out.println("val0 after: " + val0);
}
}
运行此操作时,您将获得以下输出:
valNull before: null
val0 before: 0
value1 before: null
value2 before: 0
value1 after: 1
value2 after: 2
valNull after: null
val0 after: 0
如您所见,setParams()
方法中的赋值对valNull
和val0
引用的内容没有影响
如果一个方法确实需要多个“输出”参数,则必须将它们包装到其他对象中,或者重新考虑您的设计。也许您可以使引用成为成员变量而不是局部变量,并让您的方法直接修改它们:
public class MyClass {
private ClassA objA;
private ClassB objB;
...
private boolean initObjects() {
objA = ...;
objB = ...;
return true;
}
public void otherMethod() {
...
if(initObjects() {
// Use objA, objB
}
}
}
因为没有“走出去”的概念
java中的参数
参考obj
是参考objA
的副本,因此将新对象分配给obj
不会改变objA
。这意味着java不支持使用obj
作为out参数
因此,java方法只能返回一个值。以下是可能的解决方案/解决办法
解决方案1:异常而不是布尔值(仅当布尔值指示错误时)
解决方案2:出现错误时返回null
ClassA objA = null;
objA = myMethod();
if(objA != null)
{ //DO something with objA
}
解决方案3:使用一对返回多个值
MyPair mp = myMethod();
if(mp.first){
}
MyPair myMethod(){
MyPair ret = new MyPair();
mp.first = ...;//boolean
mp.second = new ClassA();
return ret;
}
class MyPair {
boolean first;
ClassA second;
}
解决方案4:使用单元素数组-仅在极端情况下使用
ClassA[] objA = new ClassA[1];
if(myMethod(objA))
{
}
boolean myMethod(ClassA[] obj){
obj[0] = new ClassA();
}
我被你最后的例子弄糊涂了。它是否表明,如果我为对象的实例分配内存,那么当我来回传递它时,它实际上在同一个实例上运行?所以我唯一的问题是,我在将其传递给myMethod之前实例化为null?有一种方法可以使用Ref参数,使用java.util.concurrent.atomic
工具集包装对象。毕竟,完全有可能接收现有对象并更改其内部属性。一个函数可以编辑一个对象,但如果你试图替换它,你只是用一个新对象的引用替换你的局部变量。它不会以任何方式影响原始对象;你就在那一点上停止使用它。
ClassA[] objA = new ClassA[1];
if(myMethod(objA))
{
}
boolean myMethod(ClassA[] obj){
obj[0] = new ClassA();
}