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();
    }   
}

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

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

即使不可能,我为什么要认为那是不合理的?如果编译器是智能的并且比典型的 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();
    }   
}

想象一下,笼子里只能有脊椎动物(昆虫/蛛形纲动物不至于大猩猩/章鱼需要水生介质)

另一个类 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)

我想知道的是:有什么方法(只使用类型/泛型而不使用 supressingWarnings 或铸件)来避免整个 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>();
}

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

于 2012-04-24T00:49:35.603 回答
1

Java 不支持类型推断。

如果你对此感兴趣,你应该看看 Scala。

在 Java 7 中,您可以省略右侧 < > 之间的类型。在 Java 6 中,您可以使用带有 Guava 的静态方法来做到这一点。Java 8 可能/将有文字(或至少上次检查),因此这也可能有所帮助。

我不同意这些都是真正的类型推断 (见下面的评论)

于 2012-04-24T00:50:34.313 回答