3

質問にはあまり答えられていないので、短くしようと思います。長い説明については、このブリーフィングの後に行ってください。

イムがやろうとしていることをお見せします。このようなもの(別のメソッドgetLeaderHerdで戻り型として使用するためにコンストラクターからの着信型を侵害する)...:

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を代表する必要がない場合、そのタイプセーフです。

私は、特定の動作に対してジェネリックを使用して評価しています。私はそれをうまく動かすことができましたが、なぜ引数からタイプを推測できないのかわかりません。そこで、実際のアーキテクチャを単純化する目的で、警告なしで正常に実行されるこの例を作成しました。

(簡単な説明については、最後の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();
    }   
}

檻の中には脊椎動物しかいないと想像してみてください(昆虫/クモ類は巨大なクモ類ではなく、タコは水生培地を必要とします)

もう1つのクラス、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を入力する必要はありません。冗長なようで、タイプを事前に知っておく必要があります!

助けてくれるすべての人に感謝します!

4

2 に答える 2

10

Java 7 では、それが可能ですZooCage<Type> = new ZooCage<>(argument)。ただし、この機能は Java 7 の新機能であり、以前のバージョンの Java では使用できません。

あるいは、Java 6 の型推論の欠如を回避する従来の方法は、ファクトリ メソッドを記述することです。

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

Java 5 でさえメソッドnewZooCage()の型推論があったため、コンストラクターの型推論ではなく、その型が自動的に推論されます。

于 2012-04-24T00:49:35.603 に答える
1

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

それに興味があるなら、Scala を見てください。

Java 7 では、右側の < > の間の型を省略できます。Java 6 では、 Guava を使用して静的メソッドで実行できます。Java 8にはリテラル(または少なくとも最後にチェックされたもの)があるかもしれない/あるので、それも役立つかもしれません。

これらのいずれかが真の型推論であることに同意しません (以下のコメントを参照)

于 2012-04-24T00:50:34.313 に答える