2012-04-24 13 views
3

質問にはあまり答えられていないので、私は短くしようとします。長い説明のために、このブリーフィングを行ってください。Java Generics Silly Thing(なぜ私は型を推測できないのですか?)

私は何をしようとしているかを示します。 (戻り値の型など、別の方法を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を必要としないクラスを表す冗長性が低い場合は型の安全です。

私は特定の動作についてジェネリックスを使用して評価しています。私はそれを働かせることができたが、なぜ私はargからタイプを推測することができないのか理解していない。そこで、実際のアーキテクチャを単純化する目的で警告なしでokを実行するこのサンプルを作成しました。

(最後の2行は、高速ブリーフィングのためのスニペットを直接見て)

は、私はこの2つのクラスを得たとします。ターゲット1:

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は大きなANGの巨人にはないタコは水生メディアを必要とする/ 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のタイプを避けるために、何らかの方法(タイプ/ジェネリックとsupressingWarningsもキャスティングも使用しないでください)がありますか?私は、getHerdLeaderの戻り値にZooCageのコンストラクタargから型の推論を得るために何千もの方法を試しました。コンストラクタに期待される型がある場合、ZooCageを型定義する必要はありません。重複しているようで、あなたはあらかじめそのタイプを知っている必要があります!

大変ありがとうございました!

+1

どの部分、まさにあなたは避けようとしていますか?あなたは「タイプ化を避ける」ことは何を意味しますか? –

+0

をクラスのZooCage定義に指定しないでください。そのため、私はZooCageとして使用する必要があります =新しいZooCage 。 Idは、getHerdLeaderの戻り値の型をコンストラクタの入力型から推測するのが好きです。私はCageFamilyの引数でTの着信を返し、ジェネリックのクラス定義を忘れることを意味します。 – Whimusical

答えて

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を連れて来なければならないと確信しています。{ this.inhabitants = herd; } public T getHerdLeader(){ return inhabitants.getLeader(); } – Whimusical

+0

FYI Java 5で静的なファクトリメソッドを実行するとバグが(現在は修正されています)あります。つまり、 "ZooCage b = ZooCage.newZooCage();" ...あなたはZooCageをしなければならない b = ZooCage .newZooCage();しかし、前者はEclipse JDTで動作します。 –

+0

ありがとう、私は状況を公開していない良いと思います。ジェネリック医薬品なしでZooCageを綴りたい私は例をコンパイルするためにそれを行う必要がありましたが、私はZooCageを作成するためのソリューションを探していました。新しいZooCage(およびgetHerdLeaderの戻り型をコンストラクタの引数として渡されたCageFamily の型から排他的に取得しています。すでに動作しているので、<>でパラメータ化するZooCageが必要な解決策は私には無効です – Whimusical

1

Javaは型推論をサポートしていません。

あなたが興味を持ったら、Scalaをご覧ください。

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まで、コンストラクタはサポートされていませんでした。 –

+1

@PaulBellora彼ら(オラクル)は、型推論をすることに何らかの深刻な自由を取っています。真の型推論では、メソッド引数と左辺宣言の両方で型を宣言することができません。 IMHO Java(7)は、C#、Scala、F#、OcamlまたはHaskellの型推論に近いものさえありません。 –

+0

はい私はJava 6で実際に入力される型を推論することができます。問題は、コンストラクタの範囲外にそれを伝播できないということです。クラスTのプライベートvar Tに割り当てようとすると、クラス全体のスコープにTが定義されていないので、明らかに文句を言う() – Whimusical

関連する問題