java access通过反射访问整数构造函数

时间:2015-01-07 13:41:20

标签: java

我有这个代码。为什么它不起作用?(工作意味着它显示3)我该如何解决?

public class Main {
    public static<V> V copy(V var){
        try{ 
            return (V) var.getClass().getConstructor(var.getClass()).newInstance(var);
        }
        catch(Exception e){
            System.out.println("Copy faield " + e.getMessage() + " ");
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        Integer a = new Integer(3);
        Integer b = copy(a);

        System.out.println(a);
        System.out.println(b);


    }
}

这是输出:

 Copy faield java.lang.Integer.<init>(java.lang.Integer) 
    java.lang.NoSuchMethodException: java.lang.Integer.<init>(java.lang.Integer)
        at java.lang.Class.getConstructor0(Class.java:2818)
        at java.lang.Class.getConstructor(Class.java:1723)
        at Main.copy(Main.java:7)
        at Main.main(Main.java:19)
    3
    null

谢谢!

4 个答案:

答案 0 :(得分:5)

这里的问题是:

之间的区别
Integer.class
int.class

Integer的构造函数采用int参数, Integer

要使你的魔法方法起作用,你需要对类型进行特殊检查,如果它是一个包装类,实际上要查找一个构造函数,其参数是相应的主要类型。

AFAIK没有内置的方法从包装类中获取primatove类 - 您可以使用地图并使用映射填充它:

private static final Map<Class<?>, Class<?>> MAP = new HashMap<>() {{
    put(Integer.class, int.class);
    put(Long.class, long.class);
    // etc
}};

然后在你的方法中:

Class<?> type = MAP.containsKey(var.getClass()) ? MAP.get(var.getClass()) : var.getClass();
return (V) var.getClass().getConstructor(type).newInstance(var);

可以将int作为Integer传递给参数值 - 至少会自动取消装箱。

答案 1 :(得分:2)

将任何对象复制到另一个对象的一般方法。这个util类可以在包中找到 - org.apache.commons.lang3。

 Integer c = (Integer) SerializationUtils.clone(a);

答案 2 :(得分:1)

要真正理解为什么“new Integer(new Integer(5))”在反射不起作用的同时查看第一种情况下生成的字节代码是有用的:

ICONST_5
INVOKESPECIAL java/lang/Integer.<init> (I)V
INVOKEVIRTUAL java/lang/Integer.intValue ()I
INVOKESPECIAL java/lang/Integer.<init> (I)V

...正如你所看到的,正在调用Integer的intValue()方法“引擎盖下”。因此,java编译器实际上是将“new Integer(new Integer(5))”转换为“new Integer(new Integer(5).intValue())”。这意味着它可以使用带有int的构造函数。

因为java编译器无法知道反射调用的变量的实际运行时类型,所以它不能做类似的操作,只能查找具有实际运行时类型参数的构造函数。

答案 3 :(得分:-1)

int是一个类型,但Integer是一个包装器(类),它使用int作为具有许多功能的对象