简体   繁体   中英

Java generics type

Consider the code below...

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

How to access the T class in test ? eg how to print the enum constants ?

Unfortunately those generic informations for case A are not available in runtime. You have to use type token pattern. In case B you can use "hack" to get constants:

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

It is instructive to consider how to write your program without generics. Any program that can be written with generics can also be turned into an equivalent program without generics by simply removing the type parameters and inserting casts in the appropriate places. (Ignoring a few things like generics in the metadata of classes, which is not relevant here.) This is called type erasure .

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

If your program cannot be written without generics, it cannot be written with generics either.

Is there a reason to create a type parameterized type and then not use the parameterized type? Use the parameterized type and take a look at the javadoc for java.lang.Class and it is straightforward to implement, here is one way to do it.

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

Output

Using E1
... M
... N
Using E2
... O
... P

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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