我在java工作,想要使用输出参数之类的东西。这是一个例子:
ClassA objA = null;
if(myMethod(objA))
{
// position (1)
//use objA somehow
}
======================
public bool myMethod(ClassA obj)
{
obj = .....
}
我正在使用Eclipse,我遇到的问题是日食显示警告:
Null pointer access. The variable objA can only be null at this location
当我到达职位(1)时
由于java中没有out
参数的概念,我有点难过
=============================================== ===================
编辑:我已经有几个人提到改变方法返回我的对象而不是布尔。但是,如果我需要一种方法来改变几个对象呢?
例如:
ClassA objA = null;
ClassB objB = null;
if(myMethod(objA, objB))
{
// position (1)
//use objA and objB somehow
}
======================
public bool myMethod(ClassA obj, ClassB obj2)
{
//do stuff
}
我该怎么做?我不想为每种返回对象的风格制作一个自定义类吗?
感谢,
斯蒂芬妮
答案 0 :(得分:5)
因为没有out的概念 java中的参数......
引用obj
是引用objA
的副本,因此将新对象分配给obj
不会更改objA
。这意味着java不支持使用obj
作为out参数。
因此,java方法只能返回一个值。以下是可能的解决方案/解决方法。
解决方案1:异常而不是布尔值(仅当布尔表示错误时)
ClassA objA = null;
try{
objA = myMethod();
//DO something with objA
}catch(MyException ex){
}
解决方案2:出现错误时返回null。
ClassA objA = null;
objA = myMethod();
if(objA != null)
{ //DO something with objA
}
解决方案3:使用Pair返回多个值
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;
}
Soultion 4:使用单个元素数组 - 丑陋仅在极端情况下使用
ClassA[] objA = new ClassA[1];
if(myMethod(objA))
{
}
boolean myMethod(ClassA[] obj){
obj[0] = new ClassA();
}
答案 1 :(得分:3)
Java是按值传递的。在myMethod中为obj
指定值时,可以为调用代码的指针的副本分配新值。调用代码的指针继续指向其初始对象,该对象为null。这就是Eclipse警告你的原因:你试图使用objA,无论你在myMethod中做什么都是null。
答案 2 :(得分:3)
你不能真正做你在java中尝试做的事情,因为正如你所说,java不支持输出参数。
方法参数是局部变量,因此对它们进行赋值不会超出方法范围。换句话说,这个:
public void foo(Object obj) {
obj = new Object();
}
实际上是等效的(从调用foo(Object)的代码的角度来看)如下:
public void foo() {
Object obj = new Object();
}
毫无意义,因为一旦foo()
返回,创建的对象将被抛出。
您可能想要做的是更改方法以返回方法创建的对象:
public ClassA myMethod() {
ClassA obj = ....
...
return obj;
}
然后在你的主叫代码中:
ClassA objA = myMethod();
if (objA != null) {
...
}
或者,您可以在方法之外实例化ClassA的实例并传递该值,并让方法以某种方式修改它:
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 ++引用。
为了使其更具体,请考虑以下类:
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
}
}
}
答案 3 :(得分:1)
在obj
内为myMethod
分配值不会更改objA
的值。在Java中,引用按值传递。如果您希望myMethod
初始化ClassA
的实例,则应将该逻辑移动到ClassA
的构造函数或工厂方法中。
要发出错误信号,您将抛出异常而不是返回布尔值。
答案 4 :(得分:1)
我很确定Java不支持这种行为;即你不能这样做。返回你的对象或null而不是bool。
答案 5 :(得分:1)
基本上,你不能用Java做到这一点。当您调用方法时,您正在传递对该对象的引用,您没有传递方法可以写入的内存位置。你可以做的是传入一个对象并允许该函数操纵该对象。然后当函数返回时,您可以访问被操作的字段但函数。
ClassA objA = new ClassA();
if(myMethod(objA))
{
objA.getValue();
}
public boolean myMethod(ClassA obj)
{
obj.assignValue(1);
return true;
}
答案 6 :(得分:1)
实际上,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 Language Specification的这一部分中阅读这个领域中Java的语义,但是从代码片段中可能已经很明显地发生了什么。