10

在这段代码中,为什么不能将 type 声明为Class<? extends B>

public class Foo<B> {
    public void doSomething(B argument) {
        Class<? extends Object> type = argument.getClass();
    }
}
4

4 回答 4

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());
于 2012-12-06T09:02:55.293 回答
0

这就是全部generic type erasure。从这里

如果类型参数是无界的,则将泛型类型中的所有类型参数替换为其边界或 Object。因此,生成的字节码只包含普通的类、接口和方法。[在编译时]

所以你不能得到Class实际类型,B但只有?or ? extends Object

如果您的界限将变成<B extends SomeClass>而不是<B>仅,那么您可以获取Class类型的对象<? extends SomeClass>

于 2012-12-06T08:57:16.867 回答
0

Object.getClass()被定义为返回一个类,其中 T 是接收者的静态已知类型(对象 getClass() 被调用)。请特别注意竖线,即擦除运算符。类型变量的擦除是其最左边界的擦除。在您的情况下,这是隐式绑定对象。所以你得到一个 Class,而不是一个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));
}

// ...

}

于 2012-12-06T09:03:12.070 回答
0

因为不能保证给定对象的类与存储它的类型相同。

例如。

Object o = "some string";

Class<Object> clazz = o.getClass(); // actually Class<String>

通过查看类型,您应该期望 Class for Object,但实际上您会得到类 for String。您可能会问这是什么问题 -Object是 的超类String,因此String实现了 . 实现的所有方法Object

问题

问题是,当获取一个Field类时,将返回实际类的字段而不是泛型类型。此外,Method如果给定对象中存在覆盖方法,则虽然能够调用正确的方法,但它无法执行相反的操作并找到适用于给定对象的方法的实现。

例如, Object 声明hashCode,因此所有对象都有一个哈希码方法。但是,以下将产生运行时异常:

Object.class.getMethod("hashCode").invoke("some string"); // works
String.class.getMethod("hashCode").invoke(new Object()); // fails

这是因为Method对象 forhashCode期待一个String. 它期望从字符序列生成哈希码,但提供的对象没有用于该方法工作的 char 数组,因此它失败了。

这意味着以下看起来应该可以工作,但不会因为返回的实际方法getMethodString.

Object obj = "string";
Class<Object> clazz = obj.getClass();
clazz.getMethod("hashCode").invoke("another string");
于 2012-12-06T10:25:22.333 回答