2017-02-14 44 views
0

想象我有两种方法:类型安全的代理创建

private <T> T testGenericsT(Class<T> clazz) { 
    Class[] classArray = {clazz}; 
    return (T) newProxyInstance(
     clazz.getClassLoader(), 
     classArray, 
     (proxy, method, args) -> null 
    ); 
    } 

和:

private AccessibleStreamable testGenerics(Class<AccessibleStreamable> clazz) { 
    Class[] classArray = { clazz }; 
    return (AccessibleStreamable) newProxyInstance(
     clazz.getClassLoader(), 
     classArray, 
     (proxy, method, args) -> null 
    ); 
    } 

上一个不是类型安全的,我得到警告

选中投的java .lang.Object to T

但是较低的一个被接受,从我的角度来看,我不确定这些不同在哪里。有没有一种方法可以让鞋帮变得更安全?

我在这里错过了什么,为什么将它投射到AccessibleStreamable而不是T是完全正确的?

我甚至可以改变我的代码,这样

private AccessibleStreamable testGenerics(Class<AccessibleStreamable> clazz) { 
    Class[] classArray = { List.class }; 
    return (AccessibleStreamable) newProxyInstance(
     Map.class.getClassLoader(), 
     classArray, 
     (proxy, method, args) -> null 
    ); 
    } 

它仍然不会说任何警告。当然,我不希望它给我一个警告,说我正在对T做一个不加限制的演员阵容。

但是我想我的主要问题是,有没有办法让上面一个安全? (我不通过抑制警告的意思)

+2

不,由于类型删除,没有办法。这就是警告所说的:如果对象不是T的一个实例,那么没有办法让T对象失败,因为T在运行时会被擦除。 –

回答

2

很简单:

从我的角度来看我不知道这些地方不同。

第一个例子使用一个通用类型参数T.这可以是任何

第二个示例使用一个显式类名称(AccessibleStreamable)。

当然:由于type erasure,该类型T ...在运行时不存在。而第二种方法有一个固定的类型,这是没有问题的投。

2

(T)的演员阵容并不一定是不安全的(尽管如此,它仍然是一个阵容)。该警告仅意味着在该点没有实际的投影,因为没有内置的对实际类T的引用。

我看到你也通过了Class<T>的方法。您可以使用它在当时手动执行选中的演员阵容,与您的第二个片段类似:

private <T> T testGenericsT(Class<T> clazz) { 
    Class<?>[] classArray = {clazz}; 
    return clazz.cast(newProxyInstance(
     clazz.getClassLoader(), 
     classArray, 
     (proxy, method, args) -> null 
    )); 
} 
+0

该类是我从Spring获得的东西,因此它超出了我的控制范围,但是感谢您的答复。我以前使用过像ParameterizedType这样的东西来查找可选和类似事物中的值,并且正在考虑是否有类似的东西可以在这里做。 – nesohc

+0

@nesohc但是一个ParameterizedType为实际参数返回一个'Type []'。'Class'也是'Type',所以你已经在那里了。我真的不明白你的意思吗? –

+0

这是一个糟糕的例子,我的意思是如果我能以某种方式访问​​它。我的意思是将它作为我对ParameterizedType所做的一个例子,通过转换它,我可以访问其他方法来获取它。 – nesohc