正确施放泛型

时间:2014-10-17 02:17:41

标签: java generics

如何将Class<? extends Enum<?>>投射到Class<T><T extends Enum<T>>?具体来说,我需要将Class<? extends Enum<?>>的实例传递给Enum.valueOf()方法。 http://docs.oracle.com/javase/7/docs/api/java/lang/Enum.html#valueOf(java.lang.Class,%20java.lang.String)

以下是我的课程:

enum Foo1 implements Bar {
  VALUE1("A"), VALUE2("B");

  String me;

  Foo1(String me) { 
    this.me = me;
  }

  String getMe() {return me;}
}

enum Foo2 implements Bar {
  V1("A"), V2("B");

  String me;

  Foo2(String me) { 
    this.me = me;
  }

  String getMe() {return me;}
}

interface Bar {
  String getMe();
}

enum Z { 
  Z1(Foo1.class), Z2(Foo2.class);
  private final Class<? extends Enum<? extends Bar>> myEnum;
  Z(Class<? extends Enum<? extends Bar>> myEnum) {
     this.myEnum = myEnum;
  }

  Class<? extends Enum<? extends Bar>> getMyEnum() {
     return myEnum;
  }
}

class X {
   public getMe(Z z, String fooValue) {
       Class<? extends Enum<? extends Bar>> fooEnum = z.getMyEnum();
       // does not compile
       return ((Bar)Enum.valueOf(fooEnum, fooValue)).getMe();
   }
}

3 个答案:

答案 0 :(得分:0)

这是一种方法

class X {
    @SuppressWarnings("unchecked")
    public <T extends Enum<T> & Bar> String getMe(Z z, String fooValue) {
        Class<T> fooEnum = (Class<T>) z.getMyEnum();
        return Enum.valueOf(fooEnum, fooValue).getMe();
    }
}

在外部,type参数无用。在内部,它允许我们声明一个既是Enum又是Bar的子类型的类型。也不再需要施放到Bar

答案 1 :(得分:0)

基于Java目前的通用语法结构,基本上不可能表达您需要的类型关系。所以你可以做一些未经检查的事情,或者,如果您需要的是做

之类的事情
String str = someX.getMe(Z1, "VALUE1");

然后你可以抛弃枚举并将Z声明为带参数的常规类。这样就可以保留一个完整的类型参数,以后可以使用它。

public final class Z<E extends Enum<E> & Bar> {
    public static final Z<Foo1> Z1 = new Z<>(Foo1.class);
    public static final Z<Foo2> Z2 = new Z<>(Foo2.class);

    private final Class<E> myEnumClass;

    private Z(Class<E> myEnumClass) {
        this.myEnumClass = myEnumClass;
    }

    public Class<E> getMyEnumClass() {
        return myEnumClass;
    }

    /*
     * recreate enum functionality if needed
     */
}

public <E extends Enum<E> & Bar> String getMe(Z<E> z, String fooValue) {
    Class<E> fooEnumClass = z.getMyEnumClass();
    return Enum.valueOf(fooEnumClass, fooValue).getMe();
}

Enum不是很灵活。有些东西是不能做的,可能不合适。

答案 2 :(得分:0)

执行此操作的简单方法是转换为原始类型Class

return ((Bar)Enum.valueOf((Class)fooEnum, fooValue)).getMe();

如果你不喜欢演员表,你可以将你的枚举类包装在另一个类中,当你把它们放在Z中以保留更多的类型关系。

enum Z {
    Z1(new Holder<>(Foo1.class)), Z2(new Holder<>(Foo2.class));
    private final Holder<?> myEnum;

    Z(Holder<?> myEnum) {
        this.myEnum = myEnum;
    }
    Holder<?> getMyEnumHolder() {
        return myEnum;
    }

    static class Holder<T extends Enum<T> & Bar> {
        private final Class<T> myEnum;

        private Holder(Class<T> myEnum) {
            this.myEnum = myEnum;
        }

        Class<T> getMyEnum() {
            return myEnum;
        }
    }
}

class X {
    public static String getMe(Z z, String fooValue) {
        return Enum.valueOf(z.getMyEnumHolder().getMyEnum(), fooValue).getMe();
    }
}