Java泛型类型

Java泛型类型,java,generics,enums,Java,Generics,Enums,考虑下面的代码 public class Test { public interface I {} public enum E1 implements I {M, N} public enum E2 implements I {O, P} public static class A<T extends Enum<T> & I> { void test() { // how to print

考虑下面的代码

public class Test {

    public interface I {}
    public enum E1 implements I {M, N}
    public enum E2 implements I {O, P}
    public static class A<T extends Enum<T> & I> {
        void test() {
            // how to print the enum constants here ?
            System.out.println("... ");
        }
    }

    public static class B extends A<E2> {}

    public static void main(final String[] args) {
        A<E1> a = new A<E1>();
        B b = new B();

        a.test();
        b.test();
    }
}
公共类测试{
公共接口I{}
公共枚举E1实现I{M,N}
公共枚举E2实现I{O,P}
公共静态A类{
无效测试(){
//如何在此处打印枚举常量?
System.out.println(“…”);
}
}
公共静态类B扩展了{}
公共静态void main(最终字符串[]args){
A=新的A();
B=新的B();
a、 test();
b、 test();
}
}

如何访问
test
中的
T
类?e、 g.如何打印枚举常量?

不幸的是,案例A的通用信息在运行时不可用。你必须使用模式。在案例B中,您可以使用“hack”获取常量:

    void test() {
        Type superclass = this.getClass().getGenericSuperclass();
        if (ParameterizedType.class.isAssignableFrom(superclass.getClass())) {
            ParameterizedType genericSuperclass = (ParameterizedType) superclass;
            Class enumClass = (Class) genericSuperclass.getActualTypeArguments()[0];
            for (Object o : enumClass.getEnumConstants()) {
                System.out.println(o);
            }
        }
    }

是否有理由创建类型参数化类型,然后不使用参数化类型?使用参数化类型并查看
java.lang.Class
的javadoc,实现起来很简单,下面是一种方法

public class Test {

    public interface I { }
    public enum E1 implements I {M, N}
    public enum E2 implements I {O, P}
    public static class A<T extends Enum<T> & I> {
        void test(Class<T> ct) {
            for(T t: ct.getEnumConstants()) {
                System.out.println("... " + t);
            }
        }
    }

    public static class B extends A<E2> {}

    public static void main(final String[] args) {
        A<E1> a = new A<E1>();
        B b = new B();

        System.out.println("Using E1");
        a.test(E1.class);
        System.out.println("Using E2");
        b.test(E2.class);
    }
}

考虑如何在没有泛型的情况下编写程序是很有启发性的。任何可以使用泛型编写的程序也可以通过简单地删除类型参数并在适当的位置插入类型转换而转换为没有泛型的等效程序。(忽略类元数据中的泛型之类的东西,这在这里并不相关。)这称为类型擦除


如果没有泛型就无法编写程序,那么也无法使用泛型编写程序。

这可能会有所帮助:无论如何,为什么您需要能够列出枚举的值?@AJMansfield LOL!:-)您可以添加到的构造函数中,并保留一个类对象,然后使用它来获取枚举常量。@thelost No,认真地说。如果您觉得需要这样做,您可能应该使用来处理这个问题。Getting java.lang.Class不能强制转换为java.lang.reflect.ParameterizedTypeI已添加类型检查(在案例中会引发类强制转换),谢谢!我怎样才能用另一个
C
扩展
B
?在这种情况下,您必须手动获取supeclass并对其泛型信息进行操作:this.getClass().getSuperclass().getGenericSuperclass()。如果类型参数可用,使用它可以为您提供一个简单得多的解决方案,而不必使用过度反射。那么我为什么要执行
new a()
然后
a.test(E1.class)?第一个是类型参数,第二个是方法参数。当您使用
E2
调用
A.test
时,您不能像这样调用
A.test(E2.class)
我建议您读一本关于泛型的好书,让您了解最新情况,
Java泛型和集合
是一个好的开始。如果你对我的答案投了反对票,你能解释一下原因吗?我想知道答案是否只是“我不明白您编写了什么代码”或其他可能对我有用的东西。问题是我不想再次指定类,而是从类型推断它
类型
类型参数
不同。您在问题中编写的代码没有使用
类型参数
,您可以将其完全删除,也不会产生任何影响,如果这是您想要的,反射解决方案就是一条出路,您将失去类型系统的好处。
Using E1
... M
... N
Using E2
... O
... P
public class Test {

    public interface I {}
    public enum E1 implements I {M, N}
    public enum E2 implements I {O, P}
    public static class A {
        void test() {
            // how to print the enum constants here ?
            System.out.println("... ");
        }
    }

    public static class B extends A {}

    public static void main(final String[] args) {
        A a = new A();
        B b = new B();

        a.test();
        b.test();
    }
}