【问题标题】:java: getting the class of the components of an arrayjava:获取数组组件的类
【发布时间】:2011-06-11 21:02:38
【问题描述】:

如果我有

public <T> doSomething(T[] array)
{
}

如何从array 获得T.class

如果我使用array.getClass(),那我会得到T[].class

【问题讨论】:

  • (注意,[即使非null] 数组可以是String[]String.class,但T 可以是CharSequence。最好避免引用数组和反射.
  • “最好避免反射”:当然,但在我的情况下,T 是一个 Enum,我正在接受一个 T[],进行一些计算并返回一个需要类的 EnumMap 作为构造函数参数。

标签: java arrays generics


【解决方案1】:

如果您想对多维数组执行此操作,则以下递归代码将起作用

    Class<?> getArrayType(Object array) {
        Object element = Array.get(array, 0);
        if (element.getClass().isArray()) {
            return getArrayType(element);
        } else {
            return array.getClass().getComponentType();
        }
    }

【讨论】:

    【解决方案2】:

    组件类型

    使用这个:

    array.getClass().getComponentType()
    

    返回Class 代表 数组的组件类型。如果这 类不代表数组 类此方法返回null

    参考:


    安全/不安全的铸造

    有没有办法可以转换为 Class 从类返回 getComponentType() 没有得到 编译器警告?

    采取这种方法:

    public <T> void doSomething(final T[] array) throws Exception{
        final Class<? extends Object[]> arrayClass = array.getClass();
        final Class<?> componentType = arrayClass.getComponentType();
        final T newInstance = (T) componentType.newInstance();
    }
    

    这是生成的字节码:

    public void doSomething(java.lang.Object[] array) throws java.lang.Exception;
         0  aload_1 [array]
         1  invokevirtual java.lang.Object.getClass() : java.lang.Class [21]
         4  astore_2 [arrayClass]
         5  aload_2 [arrayClass]
         6  invokevirtual java.lang.Class.getComponentType() : java.lang.Class [25]
         9  astore_3 [componentType]
        10  aload_3 [componentType]
        11  invokevirtual java.lang.Class.newInstance() : java.lang.Object [30]
        14  astore 4 [newInstance]
        16  return
    

    如您所见,参数类型被擦除为Object[],因此编译器无法知道T是什么。是的,编译器可以使用array.getClass().getComponentType(),但这有时会失败,因为你可以这样做:

    Object[] arr = new String[] { "a", "b", "c" };
    Integer[] integerArray = (Integer[]) arr;
    doSomething(integerArray);
    

    (在这种情况下array.getClass().getComponentType() 返回String.class,但T 代表Integer。是的,这是合法的并且不会生成编译器警告。)

    【讨论】:

    • 酷,谢谢。有没有办法可以从 getComponentType() 返回的 Class> 转换为 Class 而不会收到编译器警告?
    • @Jason S:我认为没有办法做到这一点,因为编译器不知道要转换成什么。
    • 是的,但我猜Class&lt;T&gt; 只是类型擦除后的Class
    • 当然,我了解运行时问题,但泛型的全部意义在于编译器在编译时知道擦除步骤之前的类型。
    • ahhhhhh... 很酷,感谢您的详细讨论和反例。我忘记了数组是协变的(?我的词汇是否正确),所以 String[] 也是 Object[]。很多 +1....
    猜你喜欢
    • 1970-01-01
    • 2011-06-21
    • 1970-01-01
    • 2013-10-28
    • 2010-09-27
    • 2021-05-24
    • 1970-01-01
    • 2010-12-13
    相关资源
    最近更新 更多