我刚刚了解了这个fine looking syntax
Collections.<String>emptyList()
获取一个空的List
,其元素应该是String
类型的元素。 Java的源代码如下:
public static final List EMPTY_LIST = new EmptyList<Object>();
:
public static final <T> List<T> emptyList() {
return (List<T>) EMPTY_LIST;
}
现在,如果我以通用类型未出现在参数列表中的方式编写方法,那么我是否可以访问变为T
的实际类?
我说,到目前为止我的代码处理方法一直是
private <T> T get(String key, Class<T> clazz) {
// here I can do whatever I want with clazz, e.g.:
return clazz.cast(value);
}
如果我删除clazz
- 参数,我将无法执行cast()
。显然我可以做到
return (T) value;
但这给了我通常的警告Type safety: Unchecked cast from Object to T
。好的,@SuppressWarnings("unchecked")
在这里有帮助,但实际上我想用方法的预期返回类型做一些事情。如果我添加一个局部变量
T retValue;
我必须用一些东西初始化它,null
没有帮助。在我分配之后
@SuppressWarnings("unchecked")
T retValue = (T) value;
我能做到,例如
retValue.getClass().getName()
但如果演员表失败,我最终没有再次提供有关T
的信息。
由于Java(或至少我的Java 6)在运行时不再具有通用信息,因此我目前无法想到这样做的方法。有办法吗?或者我必须坚持我的“旧”方法吗?
请注意,我列出的示例非常简单,没有多大意义。我想在这里做更复杂的事情,但这超出了范围。
答案 0 :(得分:5)
如果您希望在运行时使用泛型类型,则需要将其作为字段或为特定类型组合创建类型的子类。
e.g。
List<String> list = new ArrayList<String>() {}; // creates a generic sub-type
final Class type = (Class) ((ParameterizedType) list.getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
System.out.println(type);
打印
class java.lang.String
答案 1 :(得分:4)
不幸的是,你不能。所有泛型和类型参数都在运行时擦除。因此,在运行时,T
的类型只是Object
答案 2 :(得分:2)
retValue.getClass().getName()
将始终返回对象的运行时类型,而不是参数类型的类名。
如果你想获取参数类,除了使用你的第一个解决方案之外别无他法。 (也就是说,明确传递类对象。)
答案 3 :(得分:1)
正如您所提到的,Java泛型只是构建时间。它们不会在运行时使用。
因此,您使用的旧方法将是您实现此目标的唯一方法。
答案 4 :(得分:-2)
我发现从T获得Class<?>
有一个解决方案:
public class Action<T>{
}
public Class<?> getGenericType(Object action) throws ClassNotFoundException{
Type type =
((ParameterizedType)action.getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
String sType[] = type.toString().split(" ");
if(sType.length != 2)
throw new ClassNotFoundException();
return Class.forName(sType[1]);
}
以上代码的使用:
Action<String> myAction = new Action<String>();
getGenericType(myAction);
我没有用原始类型(int,byte,boolean)测试它。
我认为它不是很快,但您不必将Class<?>
传递给构造函数。
修改强>
上述用法不正确,因为Action<String>
无法使用通用超类。通用超类仅适用于class ActionWithParam extends Action<String>{}
等继承类。这就是我改变主意的原因,现在我建议将类参数传递给构造函数。感谢newacct进行更正。