使用Reflection的任何构造函数实例化任何类的Java通用方法

vik*_*.rk 1 java oop generics reflection

我们知道Java使用擦除,因此任何Generic类都无法做到

T t = new T();
Run Code Online (Sandbox Code Playgroud)

所以我试图用Java反射来创建一个带有静态方法的类,用任何构造函数实例化任何类.这是代码.

import java.lang.reflect.*;

public class GenericNewInstance {
    public static <T> T createInstance(Class<T> cObj) {
        try {
            return cObj.newInstance();
        } catch (InstantiationException e) {
            System.out.println("Instantiation Exception");
            return null;
        } catch (IllegalAccessException e) {
            System.out.println("Illegal Access Exception");
            return null;
        }
    }

    public static <T> T createInstanceUsingRelection(Class<T> c, Object... initArgs) {
        Constructor<T> cTor = null;
        Class<?>[] cObjs = new Class<?>[initArgs.length];
        int i = 0;

        for(Object o : initArgs) {
            cObjs[i++] = o.getClass();
        }

        try {
            cTor = c.getConstructor(cObjs);
        } catch (SecurityException e) {
            System.out.println("security exception. Cannot get Constructor");
            return null;
        } catch (NoSuchMethodException e) {
            System.out.println("NoSuchMethodException Cannot get constructor");
            return null;
        }

        try {
            return cTor.newInstance(initArgs);
        } catch (IllegalArgumentException e) {
            System.out.println("Illegal Argument Exception");
            return null;
        } catch (InstantiationException e) {
            System.out.println("Instantiation Exception");
            return null;
        } catch (IllegalAccessException e) {
            System.out.println("Illegal Access Exception");
            return null;
        } catch (InvocationTargetException e) {
            System.out.println("Invocation Target Exception");
            return null;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

使用它的示例.

Integer i = GenericNewInstance.createInstanceUsingRelection(Integer.class, "0");
Run Code Online (Sandbox Code Playgroud)

所以我的问题:

  1. 这是实施它的正确方法吗?(或者它是冗长的吗?)
  2. 这样做的典型用例是什么?
  3. 可以/应该在使用泛型时避免使用反射吗?

Mar*_*nik 6

您的代码将失败,c.getConstructor(cObjs)因为这不会考虑类型层次结构.如果任何参数是构造函数声明的param类型的子类型,则此调用不会返回它.你需要更多的类型杂耍来让它工作.我建议你看看已经解决了这个问题代码.也许您甚至可以按原样使用该库,这是您的选择.它是Clojure的实现代码,Clojure是一种基于JVM的动态语言,完全需要这些东西.图书馆可从Maven中央仓库购买.

BTW您的异常处理是多余的.要么只是声明throws Exception或捕获任何Exception并将其包装在一个RuntimeException.当某些内容失败时,原始异常是最佳诊断.