У меня есть тип примитива Java под рукой:
Class<?> c = int.class; // or long.class, or boolean.class
Я хотел бы получить значение по умолчанию для этого класса - а именно, значение присвоено полям этого типа, если они не инициализируются. Например, 0
для числа, false
для булевской переменной.
Существует ли универсальный способ сделать это? Я попробовал это:
c.newInstance()
Но я добираюсь InstantiationException
, и не экземпляр по умолчанию.
В библиотеках Guava это уже есть:
http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/base/Defaults.html
Вызов defaultValue
вернет значение по умолчанию для любого примитивного типа (как указано в JLS), и null для любого другого типа.
Используйте его так:
import com.google.common.base.Defaults;
Defaults.defaultValue(Integer.TYPE); //will return 0
Нет элегантного способа сделать это. Фактически, невозможно даже объявить сигнатуру метода, который будет возвращать примитивные значения как таковые.
Ближайшее, что вы можете подойти, выглядит примерно так:
public Object defaultValue(Class cls) {
if (class == Boolean.TYPE) {
return Boolean.FALSE;
} else if (class == Byte.TYPE) {
return Byte.valueOf(0);
} else if (class == Short.TYPE) {
...
} else {
return null;
}
}
Переменные класса примитивов не нужно инициализировать или устанавливать со значением по умолчанию. Однако переменные, объявленные в другой области, должны быть инициализированы, иначе вы получите ошибки компиляции.
public class PrimitiveStuff {
private int aInt;
private long aLong;
private boolean aBoolean;
public PrimitiveStuff() {
System.out.println("aInt : " + aInt); //prints 0
System.out.println("aLong: "+ aLong);//prints 0
System.out.println("aBoolean: " + aBoolean);//prints false
}
public void doStuff(){
int outherInt;
System.out.println(outherInt); //will not compile
}
public static void main(String[] args) {
new PrimitiveStuff();
}
}
Вот о чем я думаю (хотя и не прошел тест на элегантность):
public class PrimitiveDefaults {
// These gets initialized to their default values
private static boolean DEFAULT_BOOLEAN;
private static byte DEFAULT_BYTE;
private static short DEFAULT_SHORT;
private static int DEFAULT_INT;
private static long DEFAULT_LONG;
private static float DEFAULT_FLOAT;
private static double DEFAULT_DOUBLE;
public static Object getDefaultValue(Class clazz) {
if (clazz.equals(boolean.class)) {
return DEFAULT_BOOLEAN;
} else if (clazz.equals(byte.class)) {
return DEFAULT_BYTE;
} else if (clazz.equals(short.class)) {
return DEFAULT_SHORT;
} else if (clazz.equals(int.class)) {
return DEFAULT_INT;
} else if (clazz.equals(long.class)) {
return DEFAULT_LONG;
} else if (clazz.equals(float.class)) {
return DEFAULT_FLOAT;
} else if (clazz.equals(double.class)) {
return DEFAULT_DOUBLE;
} else {
throw new IllegalArgumentException(
"Class type " + clazz + " not supported");
}
}
}
Вы можете сделать это с помощью отражения, но проще и яснее всего это записать, например
Object defaultValue(Class cls)
{
Map defaults = new HashMap();
defaults.put(Integer.TYPE, Integer.valueOf(0));
defaults.put(Double.TYPE, Double.valueOf(0));
defaults.put(Boolean.TYPE, Boolean.FALSE);
//... etc
return defaults.get(cls);
}
Конечно, вы, вероятно, захотите перенести инициализацию карты в конструктор или аналогичный для однократной инициализации.
Достаточно лаконично - это элегантно?