Java Generics Silly Thing(为什么我不能推断出这种类型?)

Whi*_*cal 3 java generics types inference

我会尽量做空,因为这个问题还没有得到很好的回答.经过长时间的解释,请参阅此简报.

我将展示我想做的事情.像这样的东西(从构造函数中推断传入的类型,以便在另一个方法getLeaderHerd中使用它作为返回类型)...:

public class ZooCage{

    private CageFamily<T> inhabitants;  

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

    public T getHerdLeader() {
        return inhabitants.getLeader();
    }   
}
Run Code Online (Sandbox Code Playgroud)

或这个

public class ZooCage{

    private (Type) T;   

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

    public T getHerdLeader() {
        return inhabitants.getLeader();
    }   
}
Run Code Online (Sandbox Code Playgroud)

所以我可以从Main调用类似的东西:

ZooCage cage = new ZooCage(new CageFamily<Lion>()); //Imagine new CageFamily its not empty
Lion leader = cage.getHerdLeader();
Run Code Online (Sandbox Code Playgroud)

即使它不可能,为什么我认为这是不合理的功能?它的类型是安全的,如果编译器是智能的并且不那么冗余,那就是没有必要的类ZooCage

我,正在评估使用泛型的特定行为.我设法让它工作,但我不明白为什么我不能从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();
    }   
}
Run Code Online (Sandbox Code Playgroud)

想象一下,在网箱中只能有脊椎动物(昆虫/ 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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这编译好并打印

The leader is Simba (who has bones)
The leader is Yogi (who has bones)
Run Code Online (Sandbox Code Playgroud)

我想知道的是:有没有办法(只使用类型/泛型,没有压制警告或铸件)来避免整个类ZooCage的典型化?我尝试了几千种方法来从ZooCage,s构造函数arg获取类型推断到getHerdLeader的返回值.当他的构造函数带有期望的类型时,应该没有必要代表ZooCage.似乎多余,让你必须事先知道类型!

非常感谢所有能提供帮助的人!

Lou*_*man 10

Java 7允许您这样做ZooCage<Type> = new ZooCage<>(argument).但是,该功能在Java 7中是新功能,并且在早期版本的Java中不可用.

或者,绕过Java 6缺乏类型推断的传统方法是编写工厂方法

public static <T> ZooCage<T> newZooCage() {
  return new ZooCage<T>();
}
Run Code Online (Sandbox Code Playgroud)

然后newZooCage()自动推断它的类型,因为即使Java 5也有方法的类型推断- 只是没有构造函数.