我对仿制药感到困惑.您可以声明一个字段,如:
Class<Collection<String>> clazz = ...
Run Code Online (Sandbox Code Playgroud)
您可以使用以下命令分配此字段似乎合乎逻辑:
Class<Collection<String>> clazz = Collection<String>.class;
Run Code Online (Sandbox Code Playgroud)
但是,这会产生错误:
令牌">"上的语法错误,此令牌后预期为void
所以看起来.class运算符不适用于泛型.所以我尝试过:
class A<S> { }
class B extends A<String> { }
Class<A<String>> c = B.class;
Run Code Online (Sandbox Code Playgroud)
也不起作用,生成:
类型不匹配:无法转换
Class<Test.StringCollection> to Class<Collection<String>>
现在,我真的不明白为什么这不起作用.我知道泛型类型没有具体化,但在这两种情况下,它似乎完全是类型安全的,无需访问运行时泛型类型.有人有想法吗?
我使用.class-operator向泛型类提供有关包含类型的信息.对于非通用包含类型,例如Integer.class,这没有任何问题.但是包含的类型是通用的,例如List<Integer>.class,List.class它会导致关于类转换的编译时错误.
有办法规避错误,但我很好奇这里发生了什么.有人可以解释发生了什么吗?为什么事情就像它们一样?以及解决问题的最佳方法是什么?
以下行演示了此问题:请注意外部泛型类型需要Class<T>作为参数,因此在这种情况下Class<List<Integer>>.
Class<Integer> tInt = Integer.class; // Works as expected.
Class<List> tList = List.class; // Works with warning, but is not
// what i'm looking for.
Class<List<Integer>> tListInt1 = List.class; // Error
Class<List<Integer>> tListInt2 = (Class<List<Integer>>) List.class; // Error
Class<List<?>> tListGeneric = (Class<List<Integer>>) List.class; // Error
Run Code Online (Sandbox Code Playgroud)
下一行有效:
Class<List<Integer>> tListInt3 =
(Class<List<Integer>>) ((Class<Integer>)List.class);
Run Code Online (Sandbox Code Playgroud)
为什么声明tListInt2和tListGeneric给出和错误?为什么upcast然后downcast而tListInt3不会产生错误?有更好的方式申报tListInt3吗?
亲切的问候,
Kasper van den Berg
PS.如果您希望将代码视为需要此类型信息的外部通用容器,请告诉我们.如果需要,我会发布它.
如何public <T> T doit(Class<T> clazz);使用MyClass<String>.classclazz作为clazz,我无法实例化或扩展MyClass.
编辑:'大卫温斯洛'和'bmargulies'的回答是(MyClass<String>) doit(MyClass.class);原始问题的正确作品,但令人惊讶的是,当方法返回说MyClass<T>而不是T铸造将不再编译.
编辑:我已用MyClass替换了List并将条件添加到我原来的问题中.
我有一个类,它接受一个类型标记,然后生成一个由该类型参数化的类型的对象(好吧,它比这更复杂,但这是一个简洁的例子):
public class Test {
public static void main(String[] args) throws Exception {
Holder<HashSet<Integer>> i = newObjectHolder(HashSet.class); // this fails
}
static class Holder<T> {
public Holder(T newInstance) {}
}
public static <T> Holder<T> newObjectHolder(Class<T> typeToken) throws Exception {
Constructor<T> ctor = typeToken.getConstructor();
return new Holder<T>(ctor.newInstance());
}
}
Run Code Online (Sandbox Code Playgroud)
如果传递非泛型类型,这可以正常工作,如:
Holder<Integer> i = Test.newObjectHolder(Integer.class);
Run Code Online (Sandbox Code Playgroud)
但是,如果传递的类型标记是通用的,则它不起作用,如上面指示的行:
Holder<HashSet<Integer>> i = Test.newObjectHolder(HashSet.class); // this fails
Run Code Online (Sandbox Code Playgroud)
我遇到了问题,但有解决方案吗?我可以在代码中添加@SuppressWarnings("unused")newObject,如果它不降低安全性的话.直观地说,似乎newObject应该能够使一个有效的转换,我们知道擦除泛型类型的一个"新"对象与任何其他对象相同,我们还没有T在该方法中使用.
我正在使用Spring的转换服务,并在其中注册了我自己的转换器:
public class MyTypeConverter implements Converter<String, MyType> {
@Override
public Currency convert(String text) {
MyType object = new MyType();
// do some more work here...
return object;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,在我的应用程序中,我可以进行转换String,MyType并且运行良好:
@Autowired
private ConversionService cs;
public void doIt() {
MyType object = cs.convert("Value1", MyType.class);
}
Run Code Online (Sandbox Code Playgroud)
但是我也注意到,例如,我可以在我的MVC控制器中使用相同的转换器,它也以某种方式处理列表:
@RequestMapping(method = RequestMethod.GET, value = "...")
@ResponseBody
public final String doIt(@RequestParam("param1") List<MyType> objects) throws Exception {
// ....
}
Run Code Online (Sandbox Code Playgroud)
因此,如果我param1=value1,value2在控制器中提交,我会收到一个List<MyType>包含两个元素的内容.所以spring会用逗号分割String,然后将每个元素分别转换为MyType.是否有可能以编程方式执行此操作?
我需要类似这样的东西:
List<MyType> objects = cs.convert("Value1,Value2", …Run Code Online (Sandbox Code Playgroud) 我需要将泛型类传递给类的构造函数.类是SpiceRequest从RoboSpice的Android库来构造参考.
奇怪的是,类需要将泛型类传递给contstructor,当它可以从泛型类型本身访问时,在这种情况下RESULT.class,但是我可能错了.无论如何,我不是要更改库的代码,而是需要使用泛型类型SpiceRequest,Map<String, ? extends Object>.这是我的代码:
SpiceRequest<Map<String, ? extends Object>> request =
new SpiceRequest<Map<String, ? extends Object>>(???) {
...
};
Run Code Online (Sandbox Code Playgroud)
和SpiceRequest构造函数的签名:
public SpiceRequest(final Class<RESULT> clazz) {
...
}
Run Code Online (Sandbox Code Playgroud)
对于??? 我试过Map.class编译错误:The constructor SpiceRequest<Map<String,? extends Object>>(Class<Map>) is undefined.
Map<String, ? extends Object>.class给出错误:Syntax error on tokens, PrimitiveType expected instead特别强调? extends Object.它也给出了相同的错误Map.class.
并且也Map.<String, ? extends Object>class给出了相同的编译器错误.
获取泛型类的正确方法是什么Class<Map<String, ? extends Object>> …
class.forName可以采用泛型参数吗?鉴于java确实键入了擦除,因此看起来不太可能,因此没有泛型类型信息.在运行时可用.
如果是这样,如果我传递泛型参数会有什么行为?它扔了吗?
我想采用自定义比较器类的类型
Comparator<String[]>
Run Code Online (Sandbox Code Playgroud)
并实例化它.什么是最安全的重写方式?我可以避免吗?
Comparator<String[]>
Run Code Online (Sandbox Code Playgroud)
总是投了?
this.keyComparer =
(Comparator<String[]>) Class.forName(comparatorClass).asSubclass(
Class.forName("Comparator<String[]>")
).newInstance();
Run Code Online (Sandbox Code Playgroud) 我需要像Class>那样实例化泛型变量.例如,
Class<? extends List<String>> = ...
Run Code Online (Sandbox Code Playgroud)
变式1:
Class<? extends List<String>> clazz = LinkedList.class;
Run Code Online (Sandbox Code Playgroud)
不工作 - "不兼容的类型".
变式2:
Class<? extends List> clazz = LinkedList.class;
Run Code Online (Sandbox Code Playgroud)
工作,但在这种情况下,List是原始类型 - 不好.
如何实例化这样的变量?
在寻找我最近遇到的有趣情况的答案时,我遇到了以下问题:类型安全,Java泛型和查询
我写了下面的课(清理了一下)
public abstract class BaseDaoImpl<T extends Serializable> extends HibernateDaoSupport implements BaseDao<T> {
/**
* Finds and Returns a list of persistent objects by a collection of criterions
* @param criterions
* @return list of persistent objects
* @throws DBException
*/
@SuppressWarnings("unchecked")
protected List<T> findByCriteria(Collection<Criterion> criterions) throws DBException {
try {
DetachedCriteria criteria = DetachedCriteria.forClass(T.class); // BAD!!!
for (Criterion criterion : criterions) {
criteria.add(criterion);
}
List<T> result = getHibernateTemplate().findByCriteria(criteria);
return result;
}
catch (Exception e) {
throw new DBException(T.class …Run Code Online (Sandbox Code Playgroud)