У меня есть следующий класс, который представляет собой набор свойств.Альтернатива использованию объекта и литья на карте
public class Properties
{
/** String type properties. */
private final List<String> m_stringProperties = Arrays.asList("str1", "str2", "str3");
/** Float type properties. */
private final List<String> m_floatProperties = Arrays.asList("float1", "float2", "float3");
/** Integer type properties. */
private final List<String> m_intProperties = Arrays.asList("int1", "int2");
public class PropertyType
{
private final String m_name;
private final Object m_value;
public PropertyType(String name, Object value)
{
m_name = name;
m_value = value;
}
public String getName()
{
return m_name;
}
public Object getValue()
{
return m_value;
}
}
/** The container for the properties. */
private final Map<String, PropertyType> m_properties = new HashMap<>();
public PropertyType getProperty(String name)
{
return m_properties.get(name);
}
public void setProperty(String name, Object value)
{
if ((m_stringProperties.contains(name) && value instanceof String)
|| (m_floatProperties.contains(name) && value instanceof Float)
|| (m_intProperties.contains(name) && value instanceof Integer))
{
m_properties.put(name, new PropertyType(name, value));
}
else
{
assert false : "Invalid property name";
}
}
}
Примечания
- Каждое свойство имеет имя и значение.
- Значения свойств могут иметь тип String, Float или Integer.
- Имена свойств ограничены значениями, определенными в списке в верхней части класса.
- Данное свойство может быть добавлено только на карту, если оно является правильным типом для этого имени свойства.
Класс может быть использован следующим образом:
Properties properties = new Properties();
// set properties
properties.setProperty("str1", "testId");
properties.setProperty("float1", 1.0f);
// get properties
Properties.PropertyType str1 = properties.getProperty("str1");
Properties.PropertyType float1 = properties.getProperty("float1");
Properties.PropertyType invalid = properties.getProperty("unknown"); // return null
System.out.println("str1: " + str1.getValue());
System.out.println("float1: " + float1.getValue());
float f1 = (float) properties.getProperty("float1").getValue();
Object o1 = properties.getProperty("float1").getValue();
System.out.println("f1: " + f1);
System.out.println("o1: " + o1);
properties.setProperty("str1", 1.0f); // assertion - str1 property should be String, not Float
Я хотел бы знать, если есть лучший способ осуществить это. В частности, я хотел бы избежать использования Object
и кастинга, который идет с ним. Я экспериментировал с параметризованными классами и родовыми типами и даже с разнородным гетерогенным контейнером, как описано в пункте 20 Эффективной Java.
Я хотел бы сделать это как можно более типичным - т. Е. Обеспечить контроль типа с помощью компилятора - так, чтобы, если getProperty
называется, возвращаемое значение будет автоматически правильным.
Я понимаю, что я мог бы перегрузить setProperty
для каждого типа и что getProperty
может просто вернуть Object
вместо вложенного типа PropertyType
но все равно оставит меня с контейнером <String, Object>
.
Я новичок Java из C++. В C++ значение карты будет boost::variant
.