在这种情况下,为什么Class没有一个很好的泛型?

时间:2012-12-06 08:41:29

标签: java

在此代码中,为什么不能将类型声明为Class<? extends B>

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

4 个答案:

答案 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的类。您可能会问的问题是什么?StringString的超类,因此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");