在此代码中,为什么不能将类型声明为Class<? extends B>
?
public class Foo<B> {
public void doSomething(B argument) {
Class<? extends Object> type = argument.getClass();
}
}
答案 0 :(得分:4)
这个问题是Java的语法不允许getClass()说它返回的类型与它定义的类相匹配,就编译器而言,这不是一个特例。所以你被迫投射结果。
在许多情况下,您希望能够指定this
类型,例如对于链接,所以我希望有一天能包括这个功能。
你可以写
Class<? extends this> getClass();
或
public this clone(); // must return a type of this class.
或
class ByteBuffer {
this order(ByteOrder order);
}
class MappedByteBuffer extends ByteBuffer {
}
// currently this won't work as ByteBuffer defines order()
MappedByteBuffer mbb = fc.map(MapMode.READ_WRITE, 0, fc.size())
.order(ByteOrder.nativeOrder());
答案 1 :(得分:0)
这完全是generic type erasure
。来自here:
如果类型参数是无界的,则将泛型类型中的所有类型参数替换为其边界或对象。因此,生成的字节码仅包含普通的类,接口和方法。 [编译时]
因此,您无法获得Class
的{{1}}实际类型,只能获得B
或?
。
如果您的界限只会变为? extends Object
而不是<B extends SomeClass>
,那么您可以抓取<B>
Class
类型的对象。
答案 2 :(得分:0)
Object.getClass()
被定义为返回一个Class,其中T是静态已知类型的接收者(调用对象getClass())。特别注意垂直条,擦除操作符。类型变量的擦除是其最左边界的擦除。在你的情况下,这是隐式绑定对象。所以你得到一个班级,而不是Class<? extends T>
。
正确的方法是,
abstract class AbstractExecutor<E> {
public void execute() throws Exception {
List<E> list = new ArrayList<E>();
Class<E> cls = (Class<E>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
E e = cls.getConstructor(String.class).newInstance("Gate");
list.add(e);
System.out.println(format(list));
}
// ...
}
答案 3 :(得分:0)
因为不能保证给定对象的类与它所存储的类型相同。
例如
Object o = "some string";
Class<Object> clazz = o.getClass(); // actually Class<String>
通过查看类型Object
,您应该期望String
的类,但实际上您获得了Object
的类。您可能会问的问题是什么?String
是String
的超类,因此Object
实现了Field
实现的所有方法。
问题在于,当获得Method
类时,将返回实际类的字段而不是泛型类型。此外,如果在给定对象中存在重写方法,hashCode
能够调用正确的方法,则它无法执行相反的操作并找到将对给定对象起作用的方法的实现。
例如,Object声明Object.class.getMethod("hashCode").invoke("some string"); // works
String.class.getMethod("hashCode").invoke(new Object()); // fails
,因此所有对象都有一个哈希码方法。但是,以下内容将产生运行时异常:
Method
这是因为hashCode
的{{1}}对象期待String
。它期望从字符序列生成哈希代码,但是提供的对象没有用于处理该方法的char数组,因此它失败。
意味着以下内容看起来应该有效,但不会因为getMethod
返回的实际方法是String
的哈希码方法。
Object obj = "string";
Class<Object> clazz = obj.getClass();
clazz.getMethod("hashCode").invoke("another string");