簡體   English   中英

獲取原始類型的默認值

[英]Getting default value for primitive types

我手頭有一個 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

通過創建一個包含一個元素的數組並檢索其第一個值,可以獲得任何類型的默認值。

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

這樣就不需要考慮每一種可能的原始類型,而創建單元素數組的成本通常可以忽略不計。

這就是我的想法(雖然沒有通過優雅測試):

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

Guava 的Defaults.java的替代方案,它讓實現找出默認值(通過使用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
    }
}

你可以用反射來做到這一點,但寫出來是最簡單和最清晰的,例如

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

當然,您可能希望將地圖初始化移到構造函數或類似的構造函數中,以進行一次性初始化。

相當簡潔——它優雅嗎?

沒有一種優雅的方法可以做到這一點。 事實上,甚至不可能聲明將返回原始值本身的方法的簽名。

最接近你的地方是這樣的:

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

}

如果您想要包含字符串數據類型的默認值,請嘗試此操作:

private static Object getDefaultValue(Field field) {
        if (Number.class.isAssignableFrom(field.getType())) {
            if (Double.class.isAssignableFrom(field.getType())
                || Float.class.isAssignableFrom(field.getType())) {
                return 0.0;
            } else {
                return 0;
            }
        } else if (Boolean.class.isAssignableFrom(field.getType())) {
            return false;
        } else if (Timestamp.class.isAssignableFrom(field.getType())) {
            return new Timestamp(Instant.now().toEpochMilli());
        } else {
            return "NULL";
        }
    }

根據Jack Leow 的回答,我創建了這個類:

/**
   <P>{@code java InitializedObjectUtil}</P>
 **/
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 + "\"");
         }
      /**
         <P>The default value for a boolean is {@code false}.</P>

         <P>Viewed 1/21/2014
         <BR><CODE><A HREF="http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html">http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html</A></CODE>:</P>

         <P><B>Default Values:</B> </P>

         <P>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.</P>

   <PRE>{@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}</PRE>

      @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;
   /**
      <P>The default value for a char {@code '\u0000'}.</P>

         @see  #DEFAULT_BOOLEAN
    **/
   public static final Character DEFAULT_CHAR = '\u0000';
   /**
      <P>The default value for a byte is {@code 0}.</P>

         @see  #DEFAULT_BOOLEAN
    **/
   public static final Byte DEFAULT_BYTE = 0;
   /**
      <P>The default value for a short is {@code 0}.</P>

         @see  #DEFAULT_BOOLEAN
    **/
   public static final Short DEFAULT_SHORT = 0;
   /**
      <P>The default value for a int is {@code 0}.</P>

         @see  #DEFAULT_BOOLEAN
    **/
   public static final Integer DEFAULT_INT = 0;
   /**
      <P>The default value for a long is {@code 0L}.</P>

         @see  #DEFAULT_BOOLEAN
    **/
   public static final Long DEFAULT_LONG = 0L;
   /**
      <P>The default value for a float {@code 0.0f}.</P>

         @see  #DEFAULT_BOOLEAN
    **/
   public static final Float DEFAULT_FLOAT = 0.0f;
   /**
      <P>The default value for a double {@code 0.0d}.</P>

         @see  #DEFAULT_BOOLEAN
    **/
   public static final Double DEFAULT_DOUBLE = 0.0d;
    /**
        <P>Get an object containing an initialized value for the static class-type.</P>

        @param  cls_static  May not be {@code null}.
        @return  <CODE>{@link getForClassName(String) getForClassName}(cls_static.getName())</CODE>
     **/
    public static final Object getForClass(Class cls_static)  {
       try  {
          return  getForClassName(cls_static.getName());
       }  catch(RuntimeException rtx)  {
          throw  new NullPointerException("getForClass: cls_static");
       }
    }
   /**
      <P>Get an object containing an initialized value for the type whose name is in a string.</P>

         <P>Idea from (viewed 1/2/2014)
      <BR> &nbsp; &nbsp; {@code <A HREF="https://stackoverflow.com/questions/2891970/getting-default-value-for-java-primitive-types/2892067#2892067">https://stackoverflow.com/questions/2891970/getting-default-value-for-java-primitive-types/2892067#2892067</A>}</P>

      @param  s_type  May not be {@code null}.
      @return  If {@code s_type} is equal to<UL>
         <LI>{@code "boolean"}: {@link #DEFAULT_BOOLEAN}</LI>
         <LI>{@code "char"}: {@link #DEFAULT_CHAR}</LI>
         <LI>{@code "byte"}: {@link #DEFAULT_BYTE}</LI>
         <LI>{@code "short"}: {@link #DEFAULT_SHORT}</LI>
         <LI>{@code "int"}: {@link #DEFAULT_INT}</LI>
         <LI>{@code "long"}: {@link #DEFAULT_LONG}</LI>
         <LI>{@code "float"}: {@link #DEFAULT_FLOAT}</LI>
         <LI>{@code "double"}: {@link #DEFAULT_DOUBLE}</LI>
         <LI><I>anything else</I>: {@code null}</LI>
      </UL>
      @see  #getForClass(Class) getForClass(cls)
    **/
   public static final Object getForClassName(String s_type)  {
      try  {
         if(s_type.equals("boolean"))  {
            return  DEFAULT_BOOLEAN;
         }
      }  catch(NullPointerException npx)  {
         throw  new NullPointerException("getForClassName: s_type");
      }
      if(s_type.equals("char"))  {
         return  DEFAULT_CHAR;
      }
      if(s_type.equals("byte"))  {
         return  DEFAULT_BYTE;
      }
      if(s_type.equals("short"))  {
         return  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;
      }

      //Non-primitive type
      return  null;
   }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM