如何存储Java类型,只允许某些特定类型?

Jac*_*son 9 java generics

让我们假设我想要一个用于记录描述符的类,其中每个记录都有一组属性.

每个属性都有一个唯一的名称,并且应该具有与某种Java类型相对应的特定类型,例如Integer,String,Short,Double,...

应该限制​​可能类型的列表,例如我仅支持Integer和String.

private HashMap<String, Class> attributeList = new HashMap<String, Class>();
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,HashMap是一个属性列表,其中键是属性名称,值应该是属性的类型(Integer或String).

限制Hashmap值定义的最佳方法是什么?

Dav*_*Far 11

您当然可以使用包装器方法向地图添加元素,并检查Integer和Sring.但是你只会遇到运行时错误.我同意你的观点,限制类型以获得静态错误要好得多.

为此,我实际上不会使用Integer.class和String.class,而是使用枚举:

enum Types { String, Integer };

private Map<String, Types> attributeList = new HashMap<String, Types>();
Run Code Online (Sandbox Code Playgroud)

更新:

想想看,有另一种(但更复杂的)解决方案,如果你必须坚持使用Class对象:你可以使用伪枚举模式,即使用一组常量(通常使用整数2 ^ i)像一个枚举.因此,您可以将Class对象定义为常量.当然,这并不能保证没有其他类对象被放入地图中.这就是为什么Joshua Bloch第30项说"使用枚举而不是int常量".但是,您可以使用Checker Framework使用Fake Enum检查器在常量上引入其他类型系统:

@SuppressWarnings("fenum:assignment.type.incompatible")
public class TypeEnum {
  public static final @Fenum("Types") Class INT_CONST = Integer.class;
  public static final @Fenum("Types") Class STR_CONST = String.class;
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用类型Class的限制来定义您的地图:

private HashMap<String, @Fenum("Types") Class> attributeList
   = new HashMap<String, @Fenum("Types") Class>();
Run Code Online (Sandbox Code Playgroud)

当然,您需要将Fenum Checker包含在编译器中.

  • 为什么不在这里做那个:`public enum SupportedAttributeTypes {String(String.class),Integer(Integer.class); 私人班级; SupportedAttributeTypes(Class cl){this.cl = cl; public class getAttributeType(){return cl; 然后以这种方式使用HashMap:`private HashMap <String,SupportedAttributeTypes> attributeList = new HashMap <String,SupportedAttributeTypes>();`有什么问题吗? (2认同)

Sto*_*ney 6

子类HashMap怎么样并覆盖put方法,在使用不支持的类型时抛出异常?(未经测试......就在我的头顶.)

class MyAttributes extends HashMap<String, Class> {
    private Set<Class> allowedTypes;

    public MyAttributes() {
        allowedTypes = new HashSet<Class>();
        allowedTypes.add(Integer.class);
    }
    public Class put(String key, Class value) {
        if(!allowedTypes.contains(value)) {
            throw new UnsupportedTypeException(); // <-- Your new exception type.
        }
        return super.put(key, value);
    }
}
Run Code Online (Sandbox Code Playgroud)