繁体   English   中英

对泛型类型使用 Class 参数(例如 ArrayList)

[英]Use Class parameter for generic type (e.g ArrayList)

我正在尝试创建一个通用方法来处理 Java 中不同类型的 ArrayList。 这些类型完全不同,但都包含一个相同的参数,我想在此方法中对其进行评估。

但是我无法使用给定的类信息创建正确的ArrayList<type>

我究竟做错了什么?

private String test(ArrayList<?> list, Class<?> type) {
    for(type i : list){  // for (type i : (ArrayList<type>) list){
     // do something
    }
    return "xxx"
}

private void init() {
    ArrayList<Type_1> a1 = new ArrayList<>();
    ArrayList<Type_2> a2 = new ArrayList<>();

    String s1 = test(a1, Type_1.class);
    String s2 = test(a2, Type_2.class);
}

更新找到解决方案

private String test(ArrayList<?> list) {
    for (Object i : list){
        try {
            Method m = i.getClass().getMethod("getName", null);
            System.out.println(m.invoke(i));
        } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
            //Handle Exception
        }
    }
 }

您需要声明一个显式类型参数:

  private <T> String test(ArrayList<T> list, Class<T> type) {
      for (T i : list) {
         // do something with 'i'
      }
      return "xxx"
  }

如果您不需要Class<T>参数,则可以将其省略; 例如

  private <T> String test(ArrayList<T> list) {
      for (T i : list) {
         // do something
      }
      return "xxx"
  }

如果您打算创建该类的实例...或该类的数组,您通常只需要传递一个Class<T> type的对象。


注释掉的代码版本不会编译,因为它混合了编译时和运行时类型。

for (type i : (ArrayList<type>) list) {

编译器需要在编译时知道类型代表什么type 但它是一个运行时变量。 但这甚至在此之前也是无效的,因为 Java 语法在那时需要类型的标识符......而不是变量的标识符。

我创建了一个与这两种解决方案相关的混合答案:

实现接口

第一个是通过一个简单的接口MyType完成的,该接口定义了Type_1Type_2类的契约方法 这是干净且正确的 Java 方式。 这样编译器就会告诉你是否可以执行某些操作。 这也表明初学者在实施想法的概念上存在问题。

缺点是所有类都必须实现该接口(可以在其继承层次结构的任何地方定义)。

但是 Java 完全是关于类型安全和编译器警告的优势。 所以这显然是首选方式。

使用反射

可以使用反射来完成这项任务,是的。 但不一定是个好主意。 使用反射,存在多个问题:

  • 您将收到运行时错误或必须处理这些异常
  • 项目将开始,但如果你的设计、你的概念有缺陷,这将很难确定
  • 许多库不能很好地处理反射(面向方面​​的编程、应用程序容器、GraalVM NativeImage 等特殊编译器等)
  • 使用反射会更慢并消耗更多内存

因此,如果远离反射是可能且容易的,您应该避开。 特别是如果这有一个如此简单的适当解决方案。

(我还用反射清理了你的代码,那里有一些小的不一致,不会让它编译)

代码:

package stackoverflow;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

public class SimpleInterfacing {
    interface MyType {
        String getName();
    }
    static class Type_1 implements MyType {
        @Override public String getName() {
            return "This is type 1";
        }
    }
    static class Type_2 implements MyType {
        @Override public String getName() {
            return "This is type 2";
        }
    }

    private String test(final ArrayList<? extends MyType> list) {
        String returnValue = null;
        for (final MyType t : list) {
            // do something
            System.out.println("Got name: " + t.getName());
            returnValue = t.getName();
        }
        return returnValue; // returns last value, null is lists are empty
    }

    private void init() {
        final ArrayList<Type_1> a1 = new ArrayList<>();
        a1.add(new Type_1());

        final ArrayList<Type_2> a2 = new ArrayList<>();
        a2.add(new Type_2());

        {
            final String s1 = test(a1);
            System.out.println("s1 is " + s1);
        }
        {
            final String s2 = test(a2);
            System.out.println("s2 is " + s2);
        }
        {
            test_reflection(a1);
            test_reflection(a2);
        }
    }

    public static void main(final String[] args) {
        new SimpleInterfacing().init();
    }

    private String test_reflection(final ArrayList<?> list) {
        for (final Object i : list) {
            try {
                final Method m = i.getClass().getMethod("getName");
                System.out.println("Invoked: " + m.invoke(i));
            } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
                //Handle Exception
                ex.printStackTrace();
            }
        }
        return null;
    }



}

暂无
暂无

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

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