Java:T obj; obj.getClass()的类型是Class <?>而不是Class <?延伸T>.为什么?

Alb*_*ert 9 java arrays generics

在这样的功能:

<T> void foo(T obj)
Run Code Online (Sandbox Code Playgroud)

obj.getClass()Class<?>和否的类型Class<? extends T>.为什么?

以下代码工作正常:

String foo = "";
Class<? extends String> fooClass = foo.getClass();
Run Code Online (Sandbox Code Playgroud)

所以签名T#getClass()似乎回归了Class<? extends T>,对吗?

如果T真的是通用的,为什么签名会有所不同?

为了克服这个问题(并使我更清楚地了解我的内容),我实现了这个功能:

@SuppressWarnings("unchecked") static <T> Class<? extends T> classOf(T obj) {
    return (Class<? extends T>) obj.getClass();
}
Run Code Online (Sandbox Code Playgroud)

问题是:为什么需要演员而不是String案件?为什么 SuppressWarnings需要?是不是总是从代码中清楚地知道它总是能够安全地进行这种演员表?

有什么办法,我可以得到一个Class<? extends T>obj?如果有,怎么样?如果没有,为什么不呢?

一种方法是使用classOf.那会安全的,对吧?如果这总是安全的并且提供了一种真正获得Class<? extends T>(而不是a Class<?>)的安全方法,为什么Java中没有这样的功能?还是有吗?


那个案子怎么样:

<T> void bar(T[] array)
Run Code Online (Sandbox Code Playgroud)

array.getClass().getComponentType()再次返回a Class<?>而不是a Class<? extends T>.为什么?

我已经实现了这个功能:

@SuppressWarnings("unchecked") static <T> Class<? extends T> classOf(T[] array) {
    return (Class<? extends T>) array.getClass().getComponentType();
}
Run Code Online (Sandbox Code Playgroud)

这是否安全使用?


澄清我想知道的更多内容.考虑这个演示代码:

static interface I<T> {
    Class<? extends T> myClass();
}

static class A implements I<A> {
    public Class<? extends A> myClass() {
        return this.getClass();
    }
}

static <T> void foo(I<T> obj) {
    Class<? extends T> clazz = obj.myClass(); // this works
}
Run Code Online (Sandbox Code Playgroud)

这很好用.但同样不适用Object#getClass().

例如,为什么不可能有一个类似于ClassInstance<T>函数的通用接口,getClass()并且每个Java对象都自动实现这个?这正是我正在谈论的解决方案,以便从非泛型基类扩展Object.

或者Object作为通用类:

static abstract class Object<T> {
    abstract Class<? extends T> myClass();
}

static class B extends Object<B> {
    public Class<? extends B> myClass() {
        return this.getClass();
    }
}

static <T> void bar(Object<T> obj) {
    Class<? extends T> clazz = obj.myClass(); // this works
}
Run Code Online (Sandbox Code Playgroud)

现在想myClass()作为getClass()想想吧,编译器会自动添加到每个班级.它会解决很多这些铸造问题.

我所说的主要问题是:为什么不是这样做的?


或者用不同的词语再说一遍:在这里,我更详细地描述了classOf克服这个问题的这种功能的解决方案.为什么它不是这样的,即为什么原始功能不是这样的?

(我真的不想得到这样的答案:Java现在的工作方式,即从Object定义此函数的非泛型扩展,使得这不可能.我在问为什么它不能以某种方式解决,所以这本来是可能的.)

Pet*_*rey 6

基本问题是getClass()不返回类,因为它在Object级别定义.即它被明确定义为扩展对象的类.他们可以定义getClass()之类的.

Class<this> getClass() { /**/ }
Run Code Online (Sandbox Code Playgroud)

而是它的

Class<?> getClass()
Run Code Online (Sandbox Code Playgroud)

这意味着泛型不了解getClass返回的内容.


mik*_*era 0

由于类型擦除,运行时不会保留泛型数组的类型信息。实际上,JVM 在内部将所有通用数组视为 Object[]。

如果您想获取运行时类型,最好的选择可能就是对数组中的第一项调用 getClass() 。显然,您需要找到一种方法来处理空情况以及所包含对象具有多种类型的情况等。