2015-09-05 73 views
0

出于性能方面的原因我需要使用数组来存储数据。我在一个通用的方式是这样实现了这个(见this answer):复杂类型的通用数组

import java.lang.reflect.Array; 

public class SimpleArray<T> { 

    private T[] data; 

    @SuppressWarnings("unchecked") 
    public SimpleArray(Class<T> cls, int size) { 
     this.data = (T[]) Array.newInstance(cls, size); 

    } 

    public T get(int i) { 
     return data[i]; 
    } 
} 

的问题是,我需要参与Class<?> ES。不过,我可能有更复杂的类层次结构包含泛型:

public class Outer<T> { 

    public class Inner { 

    } 

} 

我想数组初始化,因为我会用普通类:

SimpleArray<Integer> intArray = new SimpleArray<>(Integer.class, 10); 
intArray.get(0); 

SimpleArray<Outer<Integer>> outerArray; 
// how to initialize this? 

SimpleArray<Outer<String>.Inner> innerArray; 
// how to initialize this? 

我读了关于如何在后(不是)得到通用的Classhere),但底线似乎是一切都是类型安全相关的语法糖。

我的问题如下:如何创建SimpleArray类的实例,同时避免尽可能多的丑陋?

+6

对我来说,它看起来像你想实现你自己的数组列表类。这是你为什么这样做的原因吗?或者为什么这个班如何实施并不适合你? – user902383

+1

只需使用Object []'作为基础数据结构。或者首先使用'ArrayList'并放弃你自己的实现。 –

+0

为什么需要'Array.newInstance',如果你只需传递一个准备使用的数组?你也可以使用'new SimpleArray <>(Outer.class,10)'(不管类是否为内部类),然后将结果转换为参数化类型,比如'@SuppressWarnings({“rawtypes”,“unchecked “} SimpleArray > supplierSimpleArray =(SimpleArray)new SimpleArray <>(Outer.class,10)'(你不能参数化类文字,你必须”盲“编译器去除参数化,使演员表合法化,而你可以禁止让编译器知道这个转换是安全的警告)。 –

回答

1

这里有两个问题。

  1. 您真的需要通过Class吗?在这种情况下,不。你的类实际上并不需要知道运行时的元素类型来完成它的工作。例如,你可以做:

    public class SimpleArray<T> { 
    
        private Object[] data; 
    
        public SimpleArray(int size) { 
         this.data = new Object[size]; 
    
        } 
    
        @SuppressWarnings("unchecked") 
        public T get(int i) { 
         return (T)data[i]; 
        } 
    } 
    
  2. 如果你真的需要一个Class<T>,你会怎么获得?那么,首先你需要问自己,你打算怎么用这个?对于不可确定的类型T,永远不会有“真实的”Class<T>,因为使用Class<T>可以执行诸如.isInstance()之类的操作,以检查在运行时是否有某个实例是T;但在运行时当然不可能使用不可修饰的类型来检查实例。

    在这种情况下,你只打算将它传递给Array.newInstance(),并Array.newInstance()使用原始类型反正(它不关心Class参数的编译时类型 - 参数类型是Class<?> - 它仅使用Class对象的运行值),它是足够简单地裹胁Class对象代表原始类型到合适的参数化Class类型:

    (Class<Outer<Integer>>)(Class<?>)Outer.class 
    
1

您似乎试图制作一个包装数组并提供方法到get元素的类。 Arrays.ArrayList这个类已经完成了,所以没有必要重新发明轮子。其工作原理如下:

List<String> list = Arrays.asList(new String[30]); 
list.set(3, "foo"); 
System.out.println(list.get(3)); 

不能使用Arrays.asList产生List<T>如果类型T是不抑制警告,因为它是不可能创建一个通用的阵列一般。尽管如此,你可以编写一个辅助方法来为你做这件事。

@SuppressWarnings("unchecked") 
public static <T> List<T> newArray(int size) { 
    return (List<T>) Arrays.asList(new Object[size]); 
} 

您可以使用返回List获取和设置元素而无需进行转换,即使型T是通用的。例如:

List<List<String>> list = newArray(30); 
list.set(4, Arrays.asList("A", "B", "C")); 
System.out.println(list.get(4));