问题
这是我最近在一次采访中提出的一个问题,即候选人希望看到添加到Java语言中的问题。它通常被认为是Java没有的痛苦reified generics但是,当被推动时,候选人实际上无法告诉我他在那里可能取得的那些事情。
显然因为Java中允许使用原始类型(以及不安全的检查),所以可以颠覆泛型并最终得到(例如)实际包含537777662的aList。如果确定了类型信息,这显然是不可能的;但必须有更多!
人们可以发布他们真正想要做的事情的例子,他们真正想要做的事情是**,是否可以使用具体的仿制品?我的意思是,显然你可以获得aListat运行时的类型 - 但是你会用它做什么?
public void foo(List l) {
if (l.getGenericType() == Integer.class) {
//yeah baby! err, what now?
编辑:对此的快速更新,因为答案似乎主要是关注需要传递aClass作为参数(例如EnumSet.noneOf(TimeUnit.class))。我正在寻找更多的东西,这是不可能的。例如:
List> l1 = api.gimmeAList();
List> l2 = api.gimmeAnotherList();
if (l1.getGenericType().isAssignableFrom(l2.getGenericType())) {
l1.addAll(l2); //why on earth would I be doing this anyway?
#1 热门回答(97 赞)
最常引诱我的是无法利用多个泛型类型的多个调度。以下是不可能的,并且在许多情况下它将是最佳解决方案:
public void my_method(List input) { ... }
public void my_method(List input) { ... }
#2 热门回答(80 赞)
从我遇到这个"需要"的几次,它最终归结为这个结构:
public class Foo {
private T t;
public Foo() {
this.t = new T(); // Help?
}
}
这在C#中有效,假设T具有adefaultconstructor。你甚至可以通过typeof(T)获取运行时类型,并通过Type.GetConstructor()获取构造函数。
常见的Java解决方案是传递Classas参数。
public class Foo {
private T t;
public Foo(Class cls) throws Exception {
this.t = cls.newInstance();
}
}
(它不一定需要作为构造函数参数传递,因为方法参数也很好,上面只是一个例子,为简洁起见省略了try-catch)
对于所有其他泛型类型构造,可以通过一些反射帮助轻松解析实际类型。以下问答说明了用例和可能性:
获取java.util.List的泛型类型
如何在运行时获取泛型类型?
在抽象超类上获取实际类型的泛型类型参数
#3 热门回答(33 赞)
类型安全记住了。如果没有具体的泛型,向下转换为参数化类型将始终是不安全的:
List myFriends = new ArrayList();
myFriends.add("Alice");
getSession().put("friends", myFriends);
// later, elsewhere
List myFriends = (List) getSession().get("friends");
myFriends.add(new Friend("Bob")); // works like a charm!
// and so...
List myFriends = (List) getSession().get("friends");
for (String friend : myFriends) print(friend); // ClassCastException, wtf!?
此外,抽象将泄漏更少-至少可能对其类型参数的运行时信息感兴趣的那些。今天,如果你需要有关其中一个通用参数类型的任何类型的运行时信息,你也必须通过其Class。这样,你的外部接口取决于你的实现(无论你是否使用RTTI关于你的参数)。