2011-11-19 98 views
8

我在這裏看到過多次類似的問題,但有一個很大的區別。Java方法中的動態返回類型

在其他問題中,返回類型由參數決定。我想要/需要做的是通過解析的0​​的值來確定返回類型。從我收集的,下面可以工作:

public Comparable getParam(String param, byte[] data) { 
    if(param.equals("some boolean variable") 
     return data[0] != 0; 
    else(param.equals("some float variable") { 
     //create a new float, f, from some 4 bytes in data 
     return f; 
    } 
    return null; 
} 

我只是想肯定這之前,我擰任何行動工作的機會。提前致謝。

+1

您**不能**從帶有簽名的方法返回'float'或'boolean'',表示它返回'Comparable'(這真的應該是'Comparable 順便說一下)。你只能返回Float或Boolean等。 –

+0

對於我的情況來說,一個更好的問題可能是「是否有方法來轉換返回類型,以便可以調用該方法而不必將其轉換爲變量?」 – Jon

+0

不在純Java中。 (IIRC,它可以在Java字節碼中完成,但我可能會對MSIL感到困惑)。 –

回答

10

你不能這樣做。 Java返回類型必須是固定的基本類型 或對象類。我很確定你能做的最好的是返回一個包裝類型 ,它具有獲取各種可能類型的值的方法,以及內部枚舉 ,它說哪一個是有效的。

---編輯---在Danieth的改正之後!

public <Any> Any getParam(boolean b){ 
return((Any)((Boolean)(!b))); 
} 
public <Any> Any getParam(float a) { 
return((Any)((Float)(a+1))); 
} 
public <Any> Any getParam(Object b) { 
return((Any)b); 
} 
public void test(){ 
    boolean foo = getParam(true); 
    float bar = getParam(1.0f); 
    float mumble = getParam(this); // will get a class cast exception 
} 

你仍然招致了拳擊項目的部分處罰和類型檢查 返回值,當然,如果你的電話是不是 相符什麼getParam的實現實際上做,你會得到一個類 拋出異常。

+0

+1,這是正確的答案。你可以提供一個例子嗎? –

+0

?或者把我指向一個?我明白你要做什麼,但是看它的代碼要容易得多。 – Jon

+0

public class genericvalue {String returnStringvalue(){} int returnIntvalue(){}}等等,其中每個方法都會執行所需的任何操作來生成所需類型的值。 – ddyer

1

如果你真的只是返回booleanfloat,那麼你可以做的最好的是Object

如果您要返回變量對象,則必須選擇具有最小公共超類的返回類型。基元沒有超類,但是它們會被裝入對象表示(如BooleanFloat),它們具有共同的超類Object

+1

我幾乎是upvoted的,但你說'Object'是基元的普通超類。這在Java中並不是真的。基元沒有共同的超類,儘管它們可以被裝箱成引用類型的等價物。 –

+1

你是正確的,原語不是對象,但會被自動裝箱。我正在更新我的答案以反映這一點。 – Kane

11

我不知道這些人在說什麼。你失去類型安全,這是一個問題,但你可以很容易地使用泛型做到這一點......是這樣的:

public <T> T getSomething(...) { } 

interface Wrapper<T> { T getObject(); } 

public <T> Wrapper<T> getSomething(...) { } 

後者促進了strategy pattern的可能性。將字節傳遞給策略,讓它執行並檢索輸出。你將有一個字節戰略,布爾戰略等

abstract class Strategy<T> { 
    final byte[] bytes; 

    Strategy(byte[] bytes) { this.bytes = bytes; } 

    protected abstract T execute(); 
} 

然後

class BooleanStrategy extends Strategy<Boolean> { 
    public BooleanStrategy(byte[] bytes) { super(bytes); } 

    @Override 
    public Boolean execute() { 
     return bytes[0] != 0; 
    } 

} 

你的示例代碼是不好用的情況下,雖然我不會推薦它。你的方法沒有多大意義。

+0

我認爲你在這裏的正確軌道,但我不完全按照你的建議。在這個問題中,Jon有一個'byte []',並且想要傳入一個字符串並取回一個他可以分配給一個原語而不需要轉換的值。我不認爲這是可能的。你是對的,如果不是傳遞一個字符串,而是傳遞一些更復雜的對象,你可以利用泛型來獲得正確的價值。 –

+2

另一方面,如果沒有至少一個未經檢查的轉換,你就無法實現'getSomething()'方法,所以如果使用不正確的話,你可能會在運行時失敗(例如'Boolean foo = getSomething(「someFloatParam」); ')。那時,你可能最好使用一個明確的轉換,因爲很明顯你可以在那個時候得到一個'ClassCastException'。 –

18

This CAN be done。以下代碼將起作用:

public byte BOOLEAN = 1; 
public byte FLOAT = 2; 
public static <Any> Any getParam(byte[] data) { 
    if (data[0] == BOOLEAN) { 
     return (Any)((Boolean)(boolean)(data[1] != 0)); 
    } else if (data[0] == FLOAT) { 
     return (Any)((Float)(float)data[1]); 
    } else { 
     return null; 
    } 
} 

通過對返回類型使用泛型,任何Java方法都可以動態返回任何對象或原始類型。無論你想要什麼,你都可以命名爲generic,在這種情況下,我稱之爲「Any」。使用此代碼可避免在調用方法時投射返回類型。你會使用的方法,像這樣:

byte[] data = new byte[] { 1, 5 }; 
boolean b = getParam(data); 
data = new byte[] { 2, 5 }; 
float f = getParam(data); 

可以不用這一招做的最好的是手工鑄造的對象:

float f = (float)getParam(data); 

Java的動態的返回類型可以減少樣板代碼。這是我在Java 8中編寫的一個quick example