Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/eclipse/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
';空指针访问';使用java输出参数时_Java_Eclipse_Parameters - Fatal编程技术网

';空指针访问';使用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

我在java中工作,希望使用输出参数之类的东西。以下是一个例子:

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();
}