Home > front end >  How to get default value of java datatype using generic method?
How to get default value of java datatype using generic method?

Time:07-13

I'm writing a program and need to get the default value of datatype (for example null for List, 0 for int, false for boolean, etc...). I have this method

private static <T> T getDefaultValue(Class<T> type) {
    if (!type.isPrimitive()) return null;
    // something should go there
}

and I don't know how to recognize the type and return the value without errors. I tried if (type.equals(Integer.class)) return new Integer(0); but I get an error for the return statement Required type: T, Provided: Integer.

How can I do that and is there any other method than mine? (I don't want the method to return Object ofc)

Thanks!

CodePudding user response:

You can just check each primitive type manually (there are not so many primitives in Java):

    @SuppressWarnings("unchecked")
    public static <T> T defaultValue(Class<T> clazz) {
        if (!clazz.isPrimitive()) {
            return null;
        }
        if (clazz == int.class) {
            return (T) Integer.valueOf(0);
        } else if (clazz == long.class) {
            return (T) Long.valueOf(0);
        } else if (clazz == float.class) {
            return (T) Float.valueOf(0);
        } else if (clazz == double.class) {
            return (T) Double.valueOf(0);
        } else if (clazz == char.class) {
            return (T) Character.valueOf('\0');
        } else if (clazz == byte.class) {
            return (T) Byte.valueOf((byte) 0);
        } else if (clazz == short.class) {
            return (T) Short.valueOf((short) 0);
        } else if (clazz == boolean.class) {
            return (T) Boolean.valueOf(false);
        } else {
            throw new IllegalArgumentException("Unsupported primitive type: "   clazz);
        }
    }

To test you can use:

    public static void main(String[] args) {
        List.of(String.class, int.class, long.class, double.class, float.class, boolean.class, byte.class, char.class).forEach(
                cls -> System.out.printf("%s - %s\n", cls.getName(), defaultValue(cls))
        );
    }

CodePudding user response:

In addition to Kirill's solution, I'd like to add some background reasoning.

Your approach is correct, you only need an additional (T) cast:

private static <T> T getDefaultValue(Class<T> type) {
    if (!type.isPrimitive()) return null;
    if (type.equals(Integer.class)) return (T) (new Integer(0));
    // and so on for the other primitive types
}

This (T) cast will earn you a warning, as the compiler can't infer that it's in fact safe.

By writing the (T) cast, you as the developer guarantee that in this case (being called with Integer.class) the new Integer(0) instance is of the requested type T, and that's correct, as with the argument being Integer.class, T can only be Integer.

You need not even consider superclass/subclass situations, as you specified an exact type <T>, not <? super T> or <? extends T>, so you can be sure that the class object received as argument exactly matches the generic type T (unless you ignore errors/warnings elsewhere).

  • Related