2011-02-23 49 views
0

我在java中工作,想要使用類似輸出參數的東西。這裏有一個例子:當使用java輸出參數時'空指針訪問'

ClassA objA = null; 
if(myMethod(objA)) 
{ 
    // position (1) 
    //use objA somehow 
} 

======================

public bool myMethod(ClassA obj) 
{ 
    obj = ..... 
} 

我使用Eclipse和我的問題具有m個是蝕顯示警告:
Null pointer access. The variable objA can only be null at this location當我到達位置(1)

由於沒有在java的out參數概念我有點stumpped

================================================= =================
編輯:我得到了幾個人提到改變方法返回我的對象​​,而不是布爾。但是,如果我需要一種方法來改變幾個對象? 例如:

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 
} 

我怎樣才能做到這一點?我不想爲返回對象的每種風味製作一個自定義類?

感謝,
斯蒂芬妮

回答

3

你不能真正做你想在java中做什麼,因爲如你所說,java不支持輸出參數。

方法參數是局部變量,因此賦值給它們在方法範圍之外沒有任何作用。換句話說,這樣的:

public void foo(Object obj) { 
    obj = new Object(); 
} 

實際上等效(從視圖的代碼調用foo的(對象)的點),因爲這:

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

不知道更多關於您的具體問題,很難說哪種設計更好。

UPDATE:

所添加的多參數的例子是平展不可能在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()方法對valNullval0涉及的內容沒有影響。

如果你真的需要多個「輸出」參數的單一方法,你將不得不把它們包裝在其他對象,或重新考慮你的設計。也許你可以使引用的成員變量,而不是本地人,有你的方法直接對其進行修改:

public class MyClass { 
    private ClassA objA; 
    private ClassB objB; 

    ... 

    private boolean initObjects() { 
     objA = ...; 
     objB = ...; 
     return true; 
    } 

    public void otherMethod() { 
     ... 
     if(initObjects() { 
      // Use objA, objB 
     } 
    } 
} 
+0

進出口你最後一個例子混淆使用。它是否顯示如果我爲對象的實例分配內存,那麼當我將它來回傳遞時,它實際上是在同一實例上運行?所以我唯一的問題是,在將它傳遞給myMethod之前,我實例化爲null? – 2011-02-23 19:19:51

+0

有一種使用Ref參數的方法,使用'java.util.concurrent.atomic'工具集來包裝對象。畢竟,完全有可能接收現有的對象,並且只是改變它的內部屬性**。一個函數可以_edit_一個對象,但是如果你嘗試_replacing_,那麼你只能通過引用一個新對象來替換你的局部變量。它不以任何方式影響原始對象;你在這個時候就停止使用它。 – Nyerguds 2011-06-29 06:32:56

1

myMethod值分配給obj不會改變的objA值。在Java中,引用是按值傳遞的。如果你想讓myMethod初始化一個ClassA的實例,你應該將該邏輯移動到構造函數ClassA或工廠方法中。

要發出錯誤信號,您將拋出異常而不是返回布爾值。

1

我很確定這種行爲在Java中不受支持;即你不能那樣做。返回你的對象或null而不是布爾。

3

Java是通過價值。當您在myMethod中爲obj賦值時,您將爲調用代碼的指針的副本分配一個新值。調用代碼的指針繼續指向它的初始對象,該對象爲null。這就是爲什麼Eclipse會警告你:你試圖使用objA,它是null,無論你在myMethod中做什麼。

1

基本上,你不能用Java來做到這一點。當你調用一個方法時,你傳遞一個對象的引用,你沒有傳遞一個方法可以寫入的內存位置。你可以做的是傳入一個對象並允許該函數操作該對象。然後,當函數返回時,您可以訪問被操縱的字段,但該函數。

ClassA objA = new ClassA(); 
if(myMethod(objA)) 
{ 
    objA.getValue(); 
} 

public boolean myMethod(ClassA obj) 
{ 
    obj.assignValue(1); 
    return true; 
} 
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的語義在Java Language Specification本節,但是從代碼片段中可以明顯看出實際發生的情況。

5

由於沒有在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:使用一對返回幾個值

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(); 
} 
相關問題