简体   繁体   English

Java调用具有通用类对象的超类构造函数

[英]Java call super class constructor with generic class object

I've a class like this: 我上了这样的课:

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();

This doesn't make sense to me: aren't GenericClass<T> and GenericClass having the same class at runtime? 这对我来说没有意义: GenericClass<T>和GenericClass在运行时是否具有相同的类吗? How can I get the class object of GenericClass<T> then? 那我怎样才能得到GenericClass<T>的类对象呢?

EDIT: add use case 编辑:添加用例

Class literals, ex. 类文字,例如。 Foo.class , don't include generic type information. Foo.class ,不包括泛型类型信息。 The JLS states JLS州

The type of C.class , where C is the name of a class, interface, or array type (§4.3), is Class<C> . C.class类型为Class<C> ,其中C是类,接口或数组类型(第C.class )的名称。

This also means that the type of the expression contains a raw type, ie. 这也意味着表达式的类型包含原始类型,即。 in Class<GenericClass> , GenericClass is not parameterized and is therefore raw. Class<GenericClass>GenericClass没有参数化,因此是原始的。

So, the problem here is your abstract class' constructor expects 所以,这里的问题是您的抽象类的构造函数期望

Class<G> generic

where G is G在哪里

G extends GenericClass<T>>

so (close to) 如此靠近)

Class<G extends GenericClass<T>>

but you are providing 但是你提供

Class<GenericClass>

Those are not assignable. 这些是不可分配的。

You ask 你问

How can I get the class object of GenericClass then? 那我怎样才能得到GenericClass的类对象呢?

You can't. 你不能 It doesn't exist. 它不存在。 At runtime, there is no Class object for GenericClass<T> , there's only a Class object for GenericClass . 在运行时,不存在Class为对象GenericClass<T>这里只有一个Class为对象GenericClass

You'd have to explain what you are trying to do in more detail, but you could make your code compile with 您必须更详细地说明您要尝试执行的操作,但是可以使用以下命令编译代码

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

Now your constructor expects a Class<? super G extends GenericClass<T>> 现在,您的构造函数期望Class<? super G extends GenericClass<T>> Class<? super G extends GenericClass<T>> and you are providing a Class<GenericClass> . Class<? super G extends GenericClass<T>>并且您正在提供Class<GenericClass> In your super constructor invocation GenericClass<T> is bound to G and GenericClass is a supertype of GenericClass<anything> , so Class<GenericClass> is assignable to a Class<? super GenericClass<T>> 在您的super构造函数调用中, GenericClass<T>绑定到GGenericClassGenericClass<anything>的超类型,因此Class<GenericClass>可分配给Class<? super GenericClass<T>> Class<? super GenericClass<T>> . Class<? super GenericClass<T>> You'll find there are many other limitations with this solution. 您会发现此解决方案还有许多其他限制。 It all depends on your goal. 这完全取决于您的目标。

This is what I had to do to get some code to compile. 这是我需要做的一些编译代码。 I don't know what you are trying to do, but at least this gives a blueprint to follow. 我不知道您要做什么,但是至少这给出了一个可遵循的蓝图。 The main problem I saw was that AbstractClass needs two arguments for its CTOR, and you can't do that by passing only one argument to the CTOR of GeneralClass , so I had to add a second argument. 我看到的主要问题是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);
   }
}

EDIT: So to echo the discussion in the comments, I made AbstractClass concrete so I could show what arguments its constructor takes. 编辑:因此,为了回应评论中的讨论,我将AbstractClass具体化,以便可以显示其构造函数采用的参数。 (Also, I had to do that in my own code to figure out what the heck was going on, so I'm showing my work.) (此外,我必须在自己的代码中执行此操作以弄清楚到底发生了什么,因此,我正在展示自己的工作。)

I hope the examples/test cases in the main method above make it clear what's going on. 我希望上面主要方法中的示例/测试用例可以清楚说明正在发生的事情。 To reiterate what Sotirios Delimanolis said: 重申Sotirios Delimanolis的看法:

 How can I get the class object of GenericClass then? 

You can't. 你不能 It doesn't exist. 它不存在。 At runtime, there is no Class object for GenericClass, there's only a Class object for GenericClass. 在运行时,GenericClass没有Class对象,GenericClass只有Class对象。

GenericClass in this case sets T = Integer. 在这种情况下,GenericClass设置T =整数。 There's clearly no relationship between the system class Integer and the class you just declared. 系统类Integer与您刚刚声明的类之间显然没有任何关系。 There's no get() you can call on an integer to get your class GenericClass . 没有get()可以调用整数来获取类GenericClass I think my example makes this plain as day. 我认为我的榜样使这一天变得平淡无奇。

You could I suppose make some sort of processing tool that scans .java files or .class files, and builds a database of type parameters used by GenericClass (and its subclasses?), but that's boarding on crazy unfeasible. 您可以假设我可以制作一种处理工具,该工具可以扫描.java文件或.class文件,并建立GenericClass(及其子类?)使用的类型参数的数据库,但是这简直是行不通的。 If you have the resources, it could be done, but it won't make sense for any but the largest projects, and probably only a public framework at that. 如果您有足够的资源,则可以完成此工作,但是对于最大的项目,除了最大的项目之外,其他任何项目都没有意义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM