12

I have a Class<?> reference for an arbitrary type. How to get that type's initialisation value? Is there some library method for this or do I have to roll my own, such as:

Class<?> klass = ...
Object init = 
    (klass == boolean.class)
  ? false
  : (klass == byte.class)
  ? (byte) 0
  ...
  : (Object) null;

The use case is I have an arbitrary java.lang.reflect.Method reference, which I want to call using arbitrary parameters (for some testing), which may not be null in case the parameter is a primitive type, so I need to specify some value of that type.

Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509

4 Answers4

20

To do it without 3rd party libraries, you may create an array of length one and read out its first element (both operations via java.lang.reflect.Array):

Object o = Array.get(Array.newInstance(klass, 1), 0);

Starting with Java 9, you could also use

Object o = MethodHandles.zero(klass).invoke();
Holger
  • 285,553
  • 42
  • 434
  • 765
  • Nice thinking with the array trick. That `MethodHandles.zero(Class)` method is very cool and will do for me. – Lukas Eder Oct 25 '18 at 12:32
  • 3
    @LukasEder when method handles are an option, you can bind the `zero` handle directly to the parameter, avoiding any conversion/boxing overhead, e.g. `MethodHandle handle = MethodHandles.lookup().unreflect(method); while(handle.type().parameterCount() != 0) handle = MethodHandles.collectArguments(handle, 0, MethodHandles.zero(handle.type().parameterType(0))); /* prepared ... */ handle.invoke(); // invokes the method with all-default values` – Holger Oct 25 '18 at 13:53
7

You can use Defaults class from guava library:

public static void main(String[] args) {
    System.out.println(Defaults.defaultValue(boolean.class));
    System.out.println(Defaults.defaultValue(int.class));
    System.out.println(Defaults.defaultValue(String.class));
}

Prints:

false
0
null
awesoon
  • 32,469
  • 11
  • 74
  • 99
2

For completeness' sake, this is something that I think belongs to a reflection API, so I have added it to jOOR through #68

Object init = Reflect.initValue(klass);

Notably, Guava has a similar tool and there are JDK utilities that can do this as well

Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
0

To check if a parameter of a Method is primitive, call isPrimitive(); ont the parameter type:

Method m = ...;
// to test the first parameter only:
m.getParameterTypes()[0].isPrimitive();
Selaron
  • 6,105
  • 4
  • 31
  • 39
  • I don't need to check if the type is primitive. I want the initialisation value regardless of the specific primitive type. – Lukas Eder Oct 25 '18 at 11:56