简体   繁体   English

如何在java中创建一个类型安全的通用数组?

[英]How to create a type safe generic array in java?

I want to create a generic array in java maintaining the type safety usually offered by Java. 我想在java中创建一个通用数组,保持Java通常提供的类型安全性。

I am using this code : 我正在使用此代码:

class Stack<T> { 

private T[] array = null;
public Stack(Class<T> tClass, int size) {
   maximumSize = size;
   // type unsafe
   //array = (T[])new Object[maximumSize];

   this.array = (T[])java.lang.reflect.Array.newInstance(tClass,maximumSize);
}

is this code type safe? 这个代码类型安全吗? ans if so, why? 如果是这样,为什么? why if it is type safe I need a cast? 为什么如果它是类型安全我需要演员?

The Array.newInstance(..) method has a return type of Object . Array.newInstance(..)方法的返回类型为Object As such, you cannot directly assign it to anything other than Object . 因此,您无法直接将其分配给除Object之外的任何内容。 You therefore need a cast. 因此你需要一个演员。

The method delegates to a native method which 该方法委托给一个native方法

Creates a new array with the specified component type and length 创建具有指定组件类型和长度的新数组

Therefore it is creating an array of type T . 因此它创建了一个T类型的数组。

The type safety, assuming array is declared as 类型安全,假设array声明为

T[] array;

, is guaranteed by the Class<T> parameter and the cast using the same type variable. ,由Class<T>参数和使用相同类型变量的强制转换保证。

You should add the 你应该添加

@SuppressWarnings("unchecked")

with a comment explaining the above reason in your source code. 在您的源代码中解释上述原因的评论。 Always comment why a cast whose warning you are suppressing is safe. 总是评论为什么一个警告你压制的演员是安全的。

It's not type safe because of the primitive Class objects. 由于原始的Class对象,它不是类型安全的。 For example I can create a new Stack in the following manner: 例如,我可以通过以下方式创建一个新的Stack:

new Stack<Boolean>(boolean.class, 10);

Which is OK with the compiler but throws an exception because boolean.class is a Class<Boolean> and boolean[] cannot be cast to Boolean[] . 编译器可以,但抛出异常,因为boolean.class是一个Class<Boolean>boolean[]不能转换为Boolean[]

The alternative you show commented out: 您展示的替代方案已注释掉:

array = (T[])new Object[size];

Is actually somewhat type safe but for a different reason: it is due to erasure. 实际上有些类型安全的,但出于不同的原因:是由于擦除。 You cannot, for example, cast a new Object[size] to a Number[] , but the cast never happens on the array. 例如,您不能将new Object[size]转换为Number[] ,但是数组中的转换不会发生。 It happens some time later, like when you return an element of the array from a method (in which case the element is casted). 它会在一段时间后发生,就像从方法中返回数组元素一样(在这种情况下元素被转换)。 If you tried to do something like return the array to outside the object it will throw an exception. 如果您尝试执行某些操作(例如将数组返回到对象外部),则会引发异常。

Usually the solution is not to generically type the array. 通常,解决方案不是一般地键入数组。 Instead, do something like this: 相反,做这样的事情:

class Stack<E> {
    Object[] array = new Object[10];
    int top;

    void push(E elem) {
        if(top == array.length)
            array = Arrays.copyOf(array, array.length * 2);

        array[top++] = elem;
    }

    E pop() {
        @SuppressWarnings("unchecked")
        E elem = (E)array[--top]; // type safe cast

        array[top] = null;

        return elem;
    }
}

The above cast is type safe because you can only push an E in to the array. 上面的强制类型是类型安全的,因为你只能将E推入数组。 Both the JDK Stack (which extends Vector) and ArrayList work this way. JDK Stack(扩展Vector)和ArrayList都以这种方式工作。

If you want to use newInstance , you would have to reject primitives as there is no way to represent them generically: 如果要使用newInstance ,则必须拒绝原语,因为无法一般地表示它们:

Stack(Class<T> tClass, int size) {
    if(tClass.isPrimitive())
        throw new IllegalArgumentException();

    // ...
}

Since Array.newInstance returns an Object it needs a cast. 由于Array.newInstance返回一个Object它需要一个Array.newInstance The compiler will always give warning in such cases. 在这种情况下,编译器将始终发出警告。 This is the limitation of generics. 这是泛型的限制。

As we know that generics are checked at the compile time so, my friend java.lang.reflect.Array.newInstance(tClass,size); 我们知道在编译时检查泛型所以,我的朋友java.lang.reflect.Array.newInstance(tClass,size); returns you the object and you are type casting it, and if array is not of type T[] then there can be compile time error 返回对象并输入类型,如果数组不是T []类型,则可能存在编译时错误

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM