2011-09-07 57 views
9

让我们假设我想要一个为记录描述行为的类,其中每个记录都有一组属性。如何存储Java类型,只允许某些特定的类型?

每个属性都有一个唯一的名称,应该有对应于一定的Java类型,如整数,字符串短,双,特定类型的...

可能的类型列表应如限制例如,我只支持Integer和String。

private HashMap<String, Class> attributeList = new HashMap<String, Class>(); 

在上面的例子中的HashMap是属性的列表,其中作为密钥是属性名字和值应为属性(整型或字符串)的类型。

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

回答

10

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

对于这一点,我真的不使用Integer.class和String.class,但是一个枚举:

enum Types { String, Integer }; 

private Map<String, Types> attributeList = new HashMap<String, Types>(); 

UPDATE:

试想想起来了,还有另外一个(但更复杂)的解决方案,如果你坚持Class对象:您可以使用假枚举模式,即使用一组常量(通常使用整数2 ^我)像一个枚举。所以你可以定义你的Class对象作为常量。这当然不能保证没有其他类对象被放入地图中。这就是为什么Joshua Bloch第30项说“使用枚举而不是int常量”。然后你可以使用Checker Framework在使用假枚举检查您的常量拉一个额外的类型系统:

private HashMap<String, @Fenum("Types") Class> attributeList 
    = new HashMap<String, @Fenum("Types") Class>(); 

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

然后你就可以与该类型类别的管制定义地图

当然,您需要将Fenum Checker包含到您的编译器中。

+0

我刚刚发布几乎相同的答案。该方法足够清晰和灵活。但是你打算如何处理空值? –

+0

null值呢? – DaveFar

+0

我其实正在寻找那样的东西! Thx - 会考虑到这一点! –

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

在我看来,你有三种选择:

  1. 使用定义你拥有了它,当你拉值检查它是正确的类型之一。
  2. 子类化HashMap并在添加元素时在所述子类中强制实现类型限制。
  3. 有多个地图,每种类型您想要允许,适当地键入。

每个选项都有优点和缺点,您应该使用哪一个选项应该如何使用它。

0

方法过载怎么样?

import java.time.LocalDate; 
import java.time.LocalDateTime; 
import java.time.OffsetDateTime; 

public class CarrierDate<T> { 

    private T localDate; 

    private CarrierDate(T localDate) { 
     this.localDate = localDate; 
    } 

    public T getLocalDate() { 
     return localDate; 
    } 

    public static CarrierDate<LocalDate> instance(LocalDate date) { 
     return new CarrierDate<>(date); 
    } 

    public static CarrierDate<LocalDateTime> instance(LocalDateTime date) { 
     return new CarrierDate<>(date); 
    } 

    public static CarrierDate<OffsetDateTime> instance(OffsetDateTime date) { 
     return new CarrierDate<>(date); 
    } 
} 
相关问题