具有强制转换的通用基元类型

时间:2018-06-11 11:06:03

标签: java generics casting

我的Java代码存在问题。我想通过使用泛型类型来使我的方法具有通用性。用代码解释它更容易:

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

}

关键是,我希望我的默认方法destroyArray可以使用任何类型,如下所示:

public interface Destroyable {

    void destroy();

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

}

它给了我错误:

  

不可转换的类型;无法投射&#39; int&#39;到&#39; E&#39;

有没有简单的解决方案来实现这个目标?

3 个答案:

答案 0 :(得分:9)

对象的默认值

您的代码存在问题:

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

一般E类型当然不一定是int(或者像Integer那样可以自动装箱的东西)。但是你想要实际写一些默认值。因此,您需要创建E的有效实例。总的来说,这很难,因为你对类型一无所知,包括它的构造函数。

但是,所有Object都有一个有效值,即null。它表明目前根本就没有实例。

因此以下内容适用于任意类型E

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

基元

但是,由于int[] E只能用于Object,而不是基元,因此您仍然无法填充default void destroyArray(int[] array) { Arrays.fill(array, 0); } default void destroyArray(double[] array) { Arrays.fill(array, 0.0); } // ... 等基本类型数组。您需要为每个原语硬编码其他方法:

Class<E>

关于Class<E>[]

的说明

您的原始代码有E[]而不是Class<E>。请注意,E[]表示与Class<E>完全不同的内容。

Class是一个E对象,它是一个包装器,提供对分析类的内容的Reflection-API访问权限。就像获取方法的名称和类似的东西。而Person是类本身。

所以Person将是Class<Person>类,而Person就像一个类,它知道Class类的内容,就像它的方法名一样。

有关详细信息,请参阅~/.bundle/config的{​​{3}}。

答案 1 :(得分:4)

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

以上可能就是您的意图。 然而,这不适用于原始类型。由于原始类型不允许作为泛型类型参数传递,因此您仍需要destroyByteArraydestroyIntArray等。

此外,destroyArray似乎不属于Destroyable。难道它只是在一个充满静态方法的辅助类中吗?如果我是你,我会把它移到那里。它甚至没有调用destroy方法,因此没有理由进入Destroyable

答案 2 :(得分:3)

使用许多重载方法的原始方法很好。

对于基本类型,泛型适用于数组

default <A> void destroyArray(A array) {
    Class<?> arrayType = array.getClass();
    if (!arrayType.isArray()) {
        return;
    }
    Class<?> type = arrayType.getComponentType();
    if (type == int.class) {
        Arrays.fill((int[])array, 0);
    } else if (type == char.class) {
        Arrays.fill((char[])array, '\0');
    }
    //...
}

正如您所看到的:这几乎不是更紧凑,更慢,更少类型安全,并且安全被遗忘的原始类型。