Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic primitive type with casting

I've got a problem with my Java code. I want to make my method universal with using of generics types. It's easier to explain it with code:

public interface Destroyable {

    void destroy();

    default void destroyArray(byte[] array) {
        Arrays.fill(array, (byte)0);
    }

    default void destroyArray(char[] array) {
        Arrays.fill(array, (char)0);
    }

}

The point is, that I want my default method destroyArray to work with any type, like this:

public interface Destroyable {

    void destroy();

    default <E> void destroyArray(Class<E>[] array) {
        Arrays.fill(array, (E)0);
    }

}

It gives me error:

Inconvertible types; cannot cast 'int' to 'E'

Is there any simple solution to achieve this?

like image 715
PatrykMilewski Avatar asked Dec 03 '22 19:12

PatrykMilewski


1 Answers

Default value of objects

The problem with your code:

default <E> void destroyArray(E[] array) {
    Arrays.fill(array, (E) 0);
}

is that a general E type is of course not necessarily an int (or something that can be autoboxed like Integer). But you want to actually write some default value. Therefore you would need to create valid instances of E. Which, in general, is hard because you don't know anything about the type, including its constructors.

However, there is one valid value for all Objects, namely null. It indicates that there simply is no instance at the moment.

So the following would work for arbitrary types E:

default <E> void destroyArray(E[] array) {
    Arrays.fill(array, null);
}

Primitives

However, with that you are still not able to fill primitive-type arrays like int[] since E can only be used for Objects, not primitives. You would need to hard-code additional methods for each primitive:

default void destroyArray(int[] array) {
    Arrays.fill(array, 0);
}

default void destroyArray(double[] array) {
    Arrays.fill(array, 0.0);
}

// ...

Note on Class<E>

Your original code had Class<E>[] instead of E[]. Note that Class<E> means something completely different than E[].

Class<E> is a Class object, a wrapper that provides Reflection-API access to analyze contents of the class. Like getting names of methods and stuff like that. Whereas E is the class itself.

So Person would be a Person class and Class<Person> is like a class which knows stuff about the Person class, like its method names.

See the documentation of Class for more details.

like image 154
Zabuzard Avatar answered Dec 23 '22 05:12

Zabuzard