2012-04-24 113 views
3

我會盡量縮短這個問題的答案。對於長時間的解釋,請遵循這個簡報。Java泛型愚蠢的事情(爲什麼不能推斷這種類型?)

我會顯示我在做什麼。事情是這樣的(爲了在另一種方法getLeaderHerd作爲返回類型使用它從構造infering輸入型)...:

public class ZooCage{ 

    private CageFamily<T> inhabitants; 

    public <T>ZooCage(CageFamily<T> herd) { 
     this.inhabitants=herd;  
    } 

    public T getHerdLeader() { 
     return inhabitants.getLeader(); 
    } 
} 

或本

public class ZooCage{ 

    private (Type) T; 

    public ZooCage(CageFamily<T> herd) { 
     this.T=T;  
    } 

    public T getHerdLeader() { 
     return inhabitants.getLeader(); 
    } 
} 

,所以我可以從打電話主要是這樣的:

ZooCage cage = new ZooCage(new CageFamily<Lion>()); //Imagine new CageFamily its not empty 
Lion leader = cage.getHerdLeader(); 

即使它不可能,爲什麼我認爲這是不合理的功能?它的類型安全,如果編譯器是智能的並且沒有冗餘的類型ZooCage不是必需的類型

我,m評估使用泛型爲特定行爲。我設法得到它的工作,但我不明白爲什麼不能從arg中推斷出這種類型。所以我創建了這個示例,它可以在沒有警告的情況下正常運行,以簡化實際的體系結構。

(直接看最後2行片斷的快速簡報)

想我得到了這兩個類。目標之一:

package Zoo; 
import Zoo.Main.CageFamily; 
import Zoo.Main.Vertebrate; 

public class ZooCage<T extends Vertebrate>{ 

    private CageFamily<T> inhabitants; 

    public ZooCage(CageFamily<T> herd) { 
     this.inhabitants=herd;  
    } 

    public T getHerdLeader() { 
     return inhabitants.getLeader(); 
    } 
} 

試想一下,在籠子裏只能有脊椎動物(昆蟲/ aracnids並不大昂巨頭quids /章魚需要水介質)

另外一類,Main.java

package Zoo; 
import java.util.ArrayList; 

public class Main { 

    public static void main(String[] args){ 
     new Main().test(); 
    } 

    public void test(){ 
     CageFamily<Lion> lionsHerd = new CageFamily<Lion>(); 
     lionsHerd.add(new Lion("Simba")); 
     lionsHerd.add(new Lion("Nala")); 

     CageFamily<Bear> bearsHerd = new CageFamily<Bear>(); 
     bearsHerd.add(new Bear("Yogi")); 
     bearsHerd.add(new Bear("Boo-boo")); 

     ZooCage<Lion> cageLions = new ZooCage<Lion>(lionsHerd);  
     ZooCage<Bear> cageBears = new ZooCage<Bear>(bearsHerd); 

     for (ZooCage<?> cage : new ZooCage[]{cageLions,cageBears}) 
      System.out.println("The leader is "+ cage.getHerdLeader()); 

    } 

    public interface Vertebrate{ 
     public String toString(); 
     public int numBones(); 
    } 
    public class Lion implements Vertebrate{ 
     private String name; 
     public Lion (String name){this.name=name;} 
     public String toString(){return name + " (who has "+numBones()+" bones)";} 
     public int numBones(){return 345;} 
    } 
    public class Bear implements Vertebrate{ 
     private String name; 
     public Bear (String name){this.name=name;}  
     public String toString(){return name + " (who has "+numBones()+" bones)";} 
     public int numBones(){return 658;} 
    } 
    public class CageFamily<E extends Vertebrate> extends ArrayList<E>{ 
     final static long serialVersionUID = 1L; 
     public E getLeader(){ 
      return get(0); //Let,s assume the first added is the leader 
     } 
    } 
} 

這編譯OK並打印

The leader is Simba (who has bones) 
The leader is Yogi (who has bones) 

什麼我想知道的是:是有沒有辦法(只使用類型/泛型,沒有抑制威望或鑄件)來避免類ZooCage作爲一個整體的類型化?我嘗試了幾千種方法來從ZooCage的構造函數arg中得到對getHerdLeader的返回值的推斷。當他的構造函數帶有預期類型時,應該沒有必要對ZooCage進行典型化。看起來多餘,讓你不得不事先知道類型!

非常感謝所有能夠幫助的人!

+1

你試圖避免什麼部分? 「避免典型化」是什麼意思? – 2012-04-24 00:46:01

+0

避免在類的ZooCage定義中指定,所以我必須使用它作爲ZooCage = new ZooCage 。編號喜歡從構造函數中的傳入類型推斷getHerdLeader的返回類型。我的意思是返回T,它是CageFamily arg傳入的T,並僞造泛型的類定義。 – Whimusical 2012-04-24 00:48:45

回答

10

Java 7可以讓你做ZooCage<Type> = new ZooCage<>(argument)。但是,該功能在Java 7中是新功能,並且在早期版本的Java中不可用。

或者,圍繞Java 6的缺乏類型推斷得到的一種傳統方式是寫一個工廠方法

public static <T> ZooCage<T> newZooCage() { 
    return new ZooCage<T>(); 
} 

然後newZooCage()得到它的類型自動推斷,因爲即使Java 5的有類型推斷方法 - 不適用於構造函數。

+0

但Id喜歡不指定在任何地方的ZooCage調用類型。我很肯定,必須有一些公共的ZooCage(CageFamily 牧羣)帶來的T thisoffice = herd; } to the public T getHerdLeader(){ return inhabitants.getLeader(); } – Whimusical 2012-04-24 00:58:09

+0

僅供參考使用Java 5中的靜態工廠方法存在某種錯誤(現在可能已修復)。即,這不起作用「ZooCage b = ZooCage.newZooCage();」 ...你必須做ZooCage b = ZooCage .newZooCage();但是前者將與Eclipse JDT一起工作。 – 2012-04-24 00:59:37

+0

謝謝,但我認爲我不好暴露的情況。我想在沒有泛型的情況下拼寫ZooCage。我不得不編寫這個例子來編譯這個例子,但是我正在尋找一個解決方案來編寫ZooCage a = new ZooCage(並且從構造函數中傳遞的CageFamily 的類型中獲取getHerdLeader的返回類型。已經工作了,所以任何需要使用<>來參數化ZooCage的解決方案對我來說無效對不起 – Whimusical 2012-04-24 01:06:41

1

Java不支持類型推斷。

如果你有興趣,你應該看看斯卡拉。

在Java 7中,您可以在右側的<>之間省略類型。 In Java 6 you can do it with static methods with Guava。 Java 8可能會/將有文字(或至少上次檢查),這樣也可能有幫助。

我不同意任何這些都是真正的類型推斷(見下面的評論)

+1

Java確實支持類型推斷:http://docs.oracle.com/javase/tutorial/java/generics/gentypeinference.html直到7時,它才被構造函數支持,就像你記下的那樣。 – 2012-04-24 03:28:00

+1

@PaulBellora他們(Oracle)對於類型推斷的內容有一些認真的自由。 True類型推斷允許您不在方法參數和左側聲明中聲明類型。恕我直言Java(7)甚至沒有接近C#的,斯卡拉,F#,Ocaml或Haskell的類型推理。 – 2012-04-24 14:31:12

+0

是的,我可以實際推斷Java 6中的傳入類型。問題是我無法將它傳播到構造函數的範圍之外。如果我嘗試將它分配給一個類的私有變量T,那麼顯然它會抱怨,因爲T沒有在整個類的範圍內定義(ZooCage ) – Whimusical 2012-04-24 16:44:01