Java使用泛型类对象调用超类构造函数

时间:2014-08-29 00:54:06

标签: java

我是这样的一个班级:

public class GenericClass<T> {
    public void wrap(T item) {...}
}

public abstract class AbstractClass<T, G extends GenericClass<T>> {
    protected G wrapper;

    public AbstractClass(Class<G> generic, T something) {
        wrapper = generic.newInstance();
        wrapper.wrap(something);
    }

    public G wrapAndGet(T item) throws Exception {
        wrapper.wrap(item);
        return wrapper;
    }
}

// 90% of the time people only need this:
public class GeneralClass<T> extends AbstractClass<T, GenericClass<T>> {
    public GeneralClass(T something) {
        super(GenericClass.class, something);    // !error, asking for Class<GenericClass<T>>
    }
}

// and use it like this:
new GeneralClass<String>("foo").wrapAndGet("bar");

// but sometimes you might need:
public class AdvancedWrapper<T> extends GenericClass<T> {
    public T advancedMethod();
}

public class ClassUseAdvancedWrapper<T> extends AbstractClass<T, AdvancedWrapper<T>> {
    public ClassUseAdvancedWrapper(T something) {
        super(AdvancedWrapper.class, something);    // error, but let's say it compiles
    }
}

// then you can use:
new ClassUseAdvancedWrapper<String>("foo").wrapAndGet("bar").advancedMethod();

这对我来说没有意义:aren&#39; t GenericClass<T>和GenericClass在运行时具有相同的类?我怎样才能获得GenericClass<T>的类对象呢?

编辑:添加用例

2 个答案:

答案 0 :(得分:5)

班级文字,例如Foo.class,不包含泛型类型信息。 The JLS states

  

C.class的类型,C是类,接口或数组类型(第4.3节)的名称,是Class<C>

这也意味着表达式的类型包含原始类型,即。在Class<GenericClass>中,GenericClass未参数化,因此是原始的。

所以,这里的问题是你的抽象类'构造函数期望

Class<G> generic

其中G

G extends GenericClass<T>>

所以(接近)

Class<G extends GenericClass<T>>

但是你提供

Class<GenericClass>

那些不可转让。

你问

  

如何获取GenericClass的类对象呢?

你做不到。它不存在。在运行时,Class没有GenericClass<T>个对象,Class只有GenericClass个对象。

你必须更详细地解释你想要做的事情,但你可以用

编译你的代码
abstract class AbstractClass<T, G extends GenericClass<T>> {
    public AbstractClass(Class<? super G> generic, T something) {
    }
}

现在,您的构造函数需要Class<? super G extends GenericClass<T>>,并且您提供Class<GenericClass>。在您的super构造函数调用中,GenericClass<T>绑定到G,而GenericClassGenericClass<anything>的超类型,因此Class<GenericClass>可分配给Class<? super GenericClass<T>> 1}}。您会发现此解决方案还有许多其他限制。这一切都取决于你的目标。

答案 1 :(得分:2)

这是我需要做的一些代码来编译。我不知道你要做什么,但至少这给了一个蓝图。我看到的主要问题是AbstractClass需要两个参数用于其CTOR,并且你不能通过只将一个参数传递给GeneralClass的CTOR来做到这一点,所以我不得不添加第二个参数。

public class GenericTest {
   public static void main(String[] args) {
      GenericClass<Integer> generic = null;
      AbstractClass<Integer, GenericClass<Integer>> abstr = new AbstractClass( generic.getClass(), 1 );
      GeneralClass<Integer, GenericClass<Integer>> general = new GeneralClass( generic.getClass(), 1 );
   }
}

class GenericClass<T> {
}

class AbstractClass<T, G extends GenericClass<T>> {
   public AbstractClass(Class<G> generic, T something) {
   }
}

class GeneralClass<T,G extends GenericClass<T>> 
extends AbstractClass<T, G> {
   public GeneralClass( Class<G> generic, T something) {
      super( generic, something);
   }
}

编辑:所以为了回应评论中的讨论,我使AbstractClass具体化,以便我可以展示其构造函数所采用的参数。 (另外,我必须在我自己的代码中做到这一点,以弄清楚到底发生了什么,所以我正在展示我的工作。)

我希望上面主要方法中的示例/测试用例清楚地说明发生了什么。重申Sotirios Delimanolis所说的话:

How can I get the class object of GenericClass then?
     

你做不到。它不存在。在运行时,没有Class对象   GenericClass,GenericClass只有一个Class对象。

在这种情况下,

GenericClass设置T = Integer。系统类Integer与您刚刚声明的类之间显然没有任何关系。没有get()你可以调用一个整数来获得你的班级GenericClass。我认为我的例子就是这一天。

我可以假设制作一些扫描.java文件或.class文件的处理工具,并构建一个GenericClass(及其子类?)使用的类型参数数据库,但是这种方法在疯狂上是不可行的。如果你有资源,那么它可以完成,但除了最大的项目之外没有任何意义,可能只有一个公共框架。