获取原始类型的默认值

发布于 2024-09-02 19:09:04 字数 358 浏览 6 评论 0原文

我手头有一个 Java 原始类型:

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

我想获得该类的默认值——具体来说,如果该类型的字段未初始化,则将该值分配给该类型的字段。例如,0 表示数字,false 表示布尔值。

有没有通用的方法来做到这一点?我尝试了这个:

c.newInstance()

但是我收到了 InstantiationException,而不是默认实例。

I have a Java primitive type at hand:

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

I'd like to get a default value for this class -- specifically, the value is assigned to fields of this type if they are not initialized. E.g., 0 for a number, false for a boolean.

Is there a generic way to do this? I tried this:

c.newInstance()

But I'm getting an InstantiationException, and not a default instance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

蛮可爱 2024-09-09 19:09:04

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

The Guava Libraries already contains that:
http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/base/Defaults.html

Calling defaultValue will return the default value for any primitive type (as specified by the JLS), and null for any other type.

Use it like so:

import com.google.common.base.Defaults;
Defaults.defaultValue(Integer.TYPE); //will return 0
沉鱼一梦 2024-09-09 19:09:04

通过创建一个元素的数组并检索其第一个值,可以获取任何类型的默认值。

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

这样,就不需要考虑每一种可能的基本类型,而创建单元素数组的成本通常可以忽略不计。

It's possible to get the default value of any type by creating an array of one element and retrieving its first value.

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

This way there is not need to take account for every possible primitive type, at the usually negligible cost of creating a one-element array.

以可爱出名 2024-09-09 19:09:04

这就是我的想法(尽管没有通过优雅测试):

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

This is what I'm thinking (fails the elegance test though):

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");
        }
    }
}
浅忆流年 2024-09-09 19:09:04

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

An alternative to Guava's Defaults.java, which lets the implementation figure out the default values (improved by using Antag99’s answer):

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
    }
}
も让我眼熟你 2024-09-09 19:09:04

您可以通过反射来完成此操作,但最简单、最清晰的方法是将其写出来,例如,

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

当然,您可能希望将映射初始化移至构造函数或类似的构造函数中以进行一次性初始化。

相当简洁——优雅?

You can do this with reflection, but it's easiest and clearest to write it out, e.g.

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

Of course, you will probably want to move the map initialization out to a constructor or similar for once-only initialization.

Reasonably concise - it is elegant?

久伴你 2024-09-09 19:09:04

没有一种优雅的方法可以做到这一点。事实上,甚至不可能声明返回原始值本身的方法的签名。

你能得到的最接近的是这样的:

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

There isn't an elegant way to do this. In fact, it is not even possible to declare the signature of a method that will return the primitive values per se.

The closest you can come is something like this:

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;
    }
}
乱世争霸 2024-09-09 19:09:04

基元的类变量不需要初始化或设置默认值。但是,在其他作用域中声明的变量必须进行初始化,否则您将收到编译错误。

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

}

Class variables of primitives do not need to be initialized or set with a default value. However variables declare in other scope must be initialized or you'll get compilation errors.

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

}

北渚 2024-09-09 19:09:04

如果您想要包含字符串数据类型的默认值,请尝试此操作:

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

Try this if you want default value including String data type:

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";
        }
    }
反差帅 2024-09-09 19:09:04

基于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>     {@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;
   }
}

Based on Jack Leow's answer, I created this class:

/**
   <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>     {@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;
   }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文