简体   繁体   English

泛型Java类中的反思

[英]Reflection in generic java class

I have followings classes (it's just a simplified example): 我有以下类(这只是一个简化的示例):

public abstract class Material {
    public abstract String name();
    /* ... */
}

public class Wood extends Material {
    @Override
    public String name() {
        return "<WOOD>";
    }
    /* ... */
}

public class Metal extends Material {
    @Override
    public String name() {
        return "{Metal}";
    }
    /* ... */
}

public class Car<T extends Material> {
    public void printName() {
        System.out.println(T.name()); // Here is the problem!
    }
    /* ... */
}

public class Main {
    public static void main(String[] args) {
        Car<Wood> myCar1 = new Car<Wood>();
        Car<Metal> myCar2 = new Car<Metal>();
        myCar1.printName();
        myCar1.printName();
    }
}

The problem is indicated in the code. 该问题在代码中指出。

This is probably how I would have implemented it. 这可能就是我实施它的方式。 If it satisfactory or not for your situation, I can't tell. 如果对您的情况满意还是不满意,我不能告诉您。

enum Material {

    WOOD("<WOOD>"),
    METAL("{Metal}");

    String name;
    private Material(String name) {
        this.name = name;
    }
    public String toString() {
        return name;
    }
}

class Car {
    Material material;
    public Car(Material material) {
        this.material = material;
    }
    public void printName() {
        System.out.println(material);
    }
}

public class Main {
    public static void main(String[] args) {
        Car myCar1 = new Car(Material.WOOD);
        Car myCar2 = new Car(Material.METAL);
        myCar1.printName();
        myCar2.printName();
    }
}

Here is one problem: 这是一个问题:

name is instance method ( not static ), but you are trying to call it as static. name是实例方法(不是static),但是您试图将其称为static。

This should fix it 这应该解决它

public class Car<T extends Material> {
    public void printName( T material ) {
        System.out.println( material.name()); 
    }
    /* ... */
}

问题是您试图在没有实例对象实例的情况下调用实例方法。

There are a lot of misunderstanding in your question: 您的问题有很多误解:

  1. name() is not a static function, therfore you need an instance of a material object to call it. name()不是静态函数,因此需要材质对象的实例才能调用它。
  2. even if name() were static, you cannot call a static method from a generic name. 即使name()是静态的,也不能从通用名称调用静态方法。

A solution? 一个解法? Create a enumeration of material: 创建材料的枚举:

public enum Material {
    WOOD("wood"), 
    METAL("metal");

    private final String name;

    Material(String name) {
        this.name = name;
    }
}

And in the car class became: 在汽车课上变成了:

public class Car {
    private final Material m;

    public Car(Material m) {
        this.m = m
    }

    public void printName() {
        System.out.println(m.name);
    }
    /* ... */
}

T defines the type, and the name() should be static to be called in that context. T定义类型,并且name()应该是静态的,以便在该上下文中被调用。 Also, consider: 另外,请考虑:

public class Car<T extends Material> {
    protected T material;
    // initialize material in constructor or wherever you want.
    ....
    public void printName() {
        System.out.println(material.name()); // there is no problem
    }
    /* ... */
}

This will never work, since your 'T' is only a "compiler hint", and you can't access the class defined by T at runtime, unless you refer to it explicitly in your functions. 这永远不会起作用,因为您的“ T”只是一个“编译器提示”,并且除非在函数中明确引用它,否则在运行时无法访问T定义的类。

That's not how java generics work: when you compile your code, any reference to Wood and Metal is lost, and your 2 "Car" objects are identical. 这不是java泛型的工作方式:编译代码时,对Wood和Metal的任何引用都会丢失,并且您的2个“ Car”对象是相同的。

Try this: 尝试这个:

myCar1 = new Car<Wood>();
System.out.println(myCar1 instanceof Car<Metal>);

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

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