Остановка повторения в перечислениях Java
У меня есть следующее enum
в классе Java:
public enum Resolution {
RES_32 (32),
RES_64 (64);
private final int asInt;
private Resolution(int asInt) {
this.asInt = asInt;
}
};
У меня есть больше классов, которые нуждаются в подобном виде enum
с тем же asInt
Свойство и тот же конструктор, но с разными константами. Итак, в другом классе мне нужно следующее enum
:
public enum Resolution {
RES_32 (32),
RES_64 (64),
RES_128 (128);
private final int asInt;
private Resolution(int asInt) {
this.asInt = asInt;
}
};
Если бы это был класс, я мог бы использовать наследование, чтобы не повторять код в конструкторе (и, вероятно, сделал бы для этого геттер asInt
имущество). Что я могу сделать, чтобы перестать повторяться каждый раз, когда мне нужно такое Resolution
enum
? В идеале я хотел бы просто указать константы для каждого Resolution
и сохранить конструктор и свойство.
4 ответа
EnumSet
может быть полезным в этом контексте. Учитывая следующее,
public enum Resolution {
RES_32(32),
RES_64(64),
RES_128(128),
RES_256(256);
public static Set<Resolution> deluxe = EnumSet.allOf(Resolution.class);
public static Set<Resolution> typical = EnumSet.range(RES_64, RES_128);
public static Set<Resolution> ecomomy = EnumSet.of(RES_32);
private final int asInt;
private Resolution(int asInt) {
this.asInt = asInt;
}
};
Подходящие именованные наборы могут использоваться, как показано ниже.
for (Resolution r : Resolution.deluxe) {
System.out.println(r.asInt);
}
Почему бы не извлечь перечисления из класса и создать автономный файл перечисления, в котором для всей обработки используется только второй (файл с RES_128)?
Редактировать 1
Ваш комментарий:
Потому что не все классы должны иметь одинаковые константы. Некоторые должны иметь только 32 и 64, в то время как другие должны иметь 32, 64 и 128
В действительности существует только один тип разрешения, и это предполагает, что должно быть только одно перечисление разрешения, но проблема заключается в том, что не все классы принимают все разрешения. Одним из возможных решений является использование одного перечисления для представления всех разрешений, но с EnumMap для разных классов, причем некоторые классы помечают разрешение как ложное или означают недопустимое для этого класса.
Редактировать 2
Или даже просто иметь HashSet принятых перечислений.
Редактировать 3
например, используя HashSet
class Foo002 {
public static Set<Resolution> allowedResolution = new HashSet<Resolution>();
static {
allowedResolution.add(Resolution.RES_32);
allowedResolution.add(Resolution.RES_64);
}
private Resolution resolution;
public void setResolution(Resolution resolution) {
if (!(allowedResolution.contains(resolution))) {
throw new IllegalArgumentException("Disallowed Resolution: " + resolution);
}
this.resolution = resolution;
}
}
enum Resolution {
RES_32 (32),
RES_64 (64),
RES_128 (128);
private final int asInt;
private Resolution(int asInt) {
this.asInt = asInt;
}
public int getIntValue() {
return asInt;
}
};
Я бы добавил новое значение к исходному перечислению, а новые классы просто использовали его повторно. Почему они не могут позвонить первому, кого вы опубликовали? У вас есть большие проблемы, чем просто повторение конструктора, если вы копируете и расширяете первый.
Следующее позволяет вам работать с перечислениями во время выполнения, это ссылка http://www.theserverside.com/news/thread.tss?thread_id=50190:
Constructor con = Day.class.getDeclaredConstructors()[0];
Method[] methods = con.getClass().getDeclaredMethods();
for (Method m : methods)
{
if (m.getName().equals("acquireConstructorAccessor"))
{
m.setAccessible(true);
m.invoke(con, new Object[0]);
}
}
Field[] fields = con.getClass().getDeclaredFields();
Object ca = null;
for (Field f : fields)
{
if (f.getName().equals("constructorAccessor"))
{
f.setAccessible(true);
ca = f.get(con);
}
}
Method m = ca.getClass().getMethod( "newInstance", new Class[] { Object[].class });
m.setAccessible(true);
Day v = (Day) m.invoke(ca, new Object[] { new Object[] { "VACATION", Integer.MAX_VALUE } });
System.out.println(v.getClass() + ":" + v.name() + ":" + v.ordinal());