Получение значения по умолчанию для примитивных типов - PullRequest
49 голосов
/ 23 мая 2010

У меня есть примитивный тип Java:

Class<?> c = int.class; // or long.class, or boolean.class

Я бы хотел получить значение по умолчанию для этого класса - в частности, значение присваивается полям этого типа, если они не инициализированы. Например, 0 для числа, false для логического значения.

Есть ли общий способ сделать это? Я попробовал это:

c.newInstance()

Но я получаю InstantiationException, а не экземпляр по умолчанию.

Ответы [ 8 ]

51 голосов
/ 23 мая 2010

Библиотеки Гуавы уже содержат:
http://guava -libraries.googlecode.com / SVN / багажник / Javadoc / COM / Google / общие / база / Defaults.html

Вызов defaultValue вернет значение по умолчанию для любого примитивного типа (как указано в JLS) и ноль для любого другого типа.

Используйте это так:

import com.google.common.base.Defaults;
Defaults.defaultValue(Integer.TYPE); //will return 0
16 голосов
/ 07 июля 2016

Можно получить значение по умолчанию любого типа, создав массив из одного элемента и получив его первое значение.

private static <T> T getDefaultValue(Class<T> clazz) {
    return (T) Array.get(Array.newInstance(clazz, 1), 0);
}

Таким образом, нет необходимости учитывать все возможные типы примитивов при обычно незначительной стоимости создания массива из одного элемента.

11 голосов
/ 23 мая 2010

Вот о чём я думаю (хотя и не проходит тест на элегантность):

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");
        }
    }
}
7 голосов
/ 07 марта 2014

Альтернатива Defaults.java в Guava, которая позволяет реализации выяснить значения по умолчанию (улучшено с помощью ответа Antag99 ):

import static java.util.stream.Collectors.toMap;

import java.lang.reflect.Array;
import java.util.Map;
import java.util.stream.Stream;

public class DefaultValue {
    /**
     * @param clazz
     *            the class for which a default value is needed
     * @return A reasonable default value for the given class (the boxed default
     *         value for primitives, <code>null</code> otherwise).
     */
    @SuppressWarnings("unchecked")
    public static <T> T forClass(Class<T> clazz) {
        return (T) DEFAULT_VALUES.get(clazz);
    }

    private static final Map<Class<?>, Object> DEFAULT_VALUES = Stream
            .of(boolean.class, byte.class, char.class, double.class, float.class, int.class, long.class, short.class)
            .collect(toMap(clazz -> (Class<?>) clazz, clazz -> Array.get(Array.newInstance(clazz, 1), 0)));

    public static void main(String... args) {
        System.out.println(DefaultValue.forClass(int.class)); // 0
        System.out.println(DefaultValue.forClass(Integer.class)); // null
    }
}
2 голосов
/ 23 мая 2010

Вы можете сделать это с помощью рефлексии, но записать это проще и понятнее, например,

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

Конечно, вы, возможно, захотите переместить инициализацию карты в конструктор или аналогичный для однократной инициализации.

Разумно кратко - это элегантно?

1 голос
/ 23 мая 2010

Нет элегантного способа сделать это. На самом деле, даже невозможно объявить сигнатуру метода, который будет возвращать примитивные значения как таковые.

Самое близкое, что вы можете прийти - что-то вроде этого:

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;
    }
}
0 голосов
/ 21 января 2014

На основании ответа Джека Лиу , я создал этот класс:

/**
   {@code java InitializedObjectUtil}
 **/
public class InitializedObjectUtil  {
      public static final void main(String[] igno_red)  {
         printDefault("boolean");
         printDefault("char");
         printDefault("byte");
         printDefault("short");
         printDefault("int");
         printDefault("long");
         printDefault("float");
         printDefault("double");
         printDefault("java.lang.AnythingAndEverythingElse");
      }
         private static final void printDefault(String s_type)  {
            Object oDflt = InitializedObjectUtil.getForClassName(s_type);
            System.out.println(s_type + " default is \"" + oDflt + "\"");
         }
      /**
         The default value for a boolean is {@code false}.

         Viewed 1/21/2014
         
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html: Default Values: It's not always necessary to assign a value when a field is declared. Fields that are declared but not initialized will be set to a reasonable default by the compiler. Generally speaking, this default will be zero or null, depending on the data type. Relying on such default values, however, is generally considered bad programming style. The following chart summarizes the default values for the above data types. {@literal Data Type Default Value (for fields) -------------------------------------- byte 0 short 0 int 0 long 0L float 0.0f double 0.0d char '\u0000' String (or any object) null boolean false}
@see #getForClass (String) getForClass (s) @see #getForClassName (String) getForClassName (s) @see #DEFAULT_CHAR @see #DEFAULT_BYTE @see #DEFAULT_SHORT @see #DEFAULT_INT @see #DEFAULT_LONG @see #DEFAULT_FLOAT @see #DEFAULT_DOUBLE ** / public static final Boolean DEFAULT_BOOLEAN = false; / **

Значение по умолчанию для символа {@code '\ u0000'}.

@see #DEFAULT_BOOLEAN ** / public static final Character DEFAULT_CHAR = '\ u0000'; / **

Значением по умолчанию для байта является {@code 0}.

@see #DEFAULT_BOOLEAN ** / открытый статический финальный байт DEFAULT_BYTE = 0; / **

Значением по умолчанию для короткого замыкания является {@code 0}.

@see #DEFAULT_BOOLEAN ** / public static final Short DEFAULT_SHORT = 0; / **

Значением по умолчанию для int является {@code 0}.

@see #DEFAULT_BOOLEAN ** / public static final Integer DEFAULT_INT = 0; / **

Значением по умолчанию для long является {@code 0L}.

@see #DEFAULT_BOOLEAN ** / общедоступная статическая финальная Long DEFAULT_LONG = 0L; / **

Значение по умолчанию для числа с плавающей запятой {@code 0.0f}.

@see #DEFAULT_BOOLEAN ** / public static final Float DEFAULT_FLOAT = 0.0f; / **

Значение по умолчанию для двойного {@code 0.0d}.

@see #DEFAULT_BOOLEAN ** / public static final Double DEFAULT_DOUBLE = 0.0d; / **

Получить объект, содержащий инициализированное значение для статического типа класса.

@param cls_static Не может быть {@code null}. @return {@link getForClassName(String) getForClassName}(cls_static.getName()) ** / public static final Object getForClass (Class cls_static) { пытаться { return getForClassName (cls_static.getName ()); } catch (RuntimeException rtx) { бросить новое исключение NullPointerException ("getForClass: cls_static"); } } / **

Получить объект, содержащий инициализированное значение для типа, имя которого находится в строке.

Идея от (просмотрено 1/2/2014)
& nbsp; & NBSP; {@code /2236073/poluchenie-znacheniya-po-umolchaniy-dlya-primitivnyh-tipov#2236079}

@param s_type Не может быть {@code null}. @return, если {@code s_type} равен
  • {@ code "boolean"}: {@link #DEFAULT_BOOLEAN}
  • {@ code "char"}: {@link #DEFAULT_CHAR}
  • {@ code "byte"}: {@link #DEFAULT_BYTE}
  • {@ code "short"}: {@link #DEFAULT_SHORT}
  • {@ code "int"}: {@link #DEFAULT_INT}
  • {@ code "long"}: {@link #DEFAULT_LONG}
  • {@ code "float"}: {@link #DEFAULT_FLOAT}
  • {@ code "double"}: {@link #DEFAULT_DOUBLE}
  • что-нибудь еще : {@code null}
@see #getForClass (Class) getForClass (cls) ** / public static final Object getForClassName (String s_type) { пытаться { if (s_type.equals ("boolean")) { вернуть DEFAULT_BOOLEAN; } } catch (NullPointerException npx) { бросить новое исключение NullPointerException ("getForClassName: s_type"); } if (s_type.equals ("char")) { вернуть DEFAULT_CHAR; } if (s_type.equals ("byte")) { вернуть DEFAULT_BYTE; } if (s_type.equals ("short")) { вернуть DEFAULT_SHORT; } if (s_type.equals ("int")) { return DEFAULT_INT; } if (s_type.equals ("long")) { return DEFAULT_LONG; } if (s_type.equals ("float")) { return DEFAULT_FLOAT; } if (s_type.equals ("double")) { return DEFAULT_DOUBLE; } // Непримитивный тип вернуть ноль; } }
0 голосов
/ 23 мая 2010

Переменные класса примитивов не нужно инициализировать или устанавливать со значением по умолчанию. Однако переменные, объявленные в другой области видимости, должны быть инициализированы, иначе вы получите ошибки компиляции.

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

}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...