简体   繁体   English

为什么 Java 在通过反射调用不装箱的方法时不支持访问原始返回值?

[英]Why does Java not support accessing primitive return values when invoking methods without boxing via reflection?

I noticed that Java Reflection supports access on fields of primitive types such as boolean or int without boxing:我注意到 Java 反射支持访问原始类型的字段,例如 boolean 或没有装箱的 int:

public final class Field extends AccessibleObject implements Member {
    //...
    public boolean getBoolean(Object obj) throws IllegalArgumentException, IllegalAccessException { ... }
    public char getChar(Object obj) throws IllegalArgumentException, IllegalAccessException { ... }
    public byte getByte(Object obj) throws IllegalArgumentException, IllegalAccessException { ... }
    public short getShort(Object obj) throws IllegalArgumentException, IllegalAccessException { ... }
    public int getInt(Object obj) throws IllegalArgumentException, IllegalAccessException { ... }
    public long getLong(Object obj) throws IllegalArgumentException, IllegalAccessException { ... }
    public float getFloat(Object obj) throws IllegalArgumentException, IllegalAccessException { ... }
    public double getDouble(Object obj) throws IllegalArgumentException, IllegalAccessException { ... }
    //...
}

However, there is only invoke(...) for methods which always returns Object. This forces boxing when it is used with methods with primitive return values.但是,对于始终返回 Object 的方法只有 invoke(...)。当它与具有原始返回值的方法一起使用时,这会强制装箱。 I wonder why there is no support for that yet.我想知道为什么还没有对此的支持。 Has it not been asked for or are there serious issues which prevent it?是否没有被要求或是否存在阻止它的严重问题?

are there serious issues which prevent it?有严重的问题阻止它吗?

Yes, the return value is not the only part of invoke() that boxes primitives, the method arguments are boxed too.是的,返回值不是invoke()的唯一部分将基元装箱,方法 arguments 也被装箱。

Eg if you have method boolean foo(String a, int b, double c) , then you invoke it like this:例如,如果您有方法boolean foo(String a, int b, double c) ,那么您可以这样调用它:

String a = ...;
int b = ...;
double c = ...;

boolean result = method.invoke(obj, a, b, c);

Before auto-boxing and varargs, it would have been like this, which is what the compiler actually generates:在自动装箱和可变参数之前,它会是这样的,这是编译器实际生成的:

boolean result = method.invoke(obj,
                               new Object[] { a,
                                              Integer.valueOf(b)/*auto-boxing*/,
                                              Double.valueOf(c)/*auto-boxing*/ })
                       .booleanValue()/*auto-unboxing*/;

To eliminate the need for boxing of primitives, the API would need to provide an overloaded invoke() method that exactly matches the signature of the method, not just one that matches the return type.为了消除对原语装箱的需要,API 需要提供一个重载的invoke()方法,它与方法的签名完全匹配,而不仅仅是与返回类型匹配的方法。

There would have to be a gazillion overloads, and that would be a serious issue.必须有大量的超载,这将是一个严重的问题。

Making overloads for the various return types without also making overloads for the arguments wouldn't make sense, because what are you trying to fix with that?对各种返回类型进行重载而不对 arguments 进行重载是没有意义的,因为你想用它来解决什么问题? Nothing.没有什么。

The overhead of making a reflexive method call is high enough that the boxing of the return value is a non-issue.进行自反方法调用的开销足够高,以至于对返回值进行装箱不是问题。

There is a way, but you need the "newer" reflection.有一种方法,但是您需要“更新”的反射。 For example:例如:

static class Test {

    public long go(int x, int y) {
        return x + y;
    }

}


static void methodHandles() throws Throwable {
    MethodType mt = MethodType.methodType(long.class, int.class, int.class);
    MethodHandles.Lookup lookup = MethodHandles.lookup();
    MethodHandle goMethod = lookup.findVirtual(Test.class, "go", mt);

    long result = (long)goMethod.invokeExact(new Test(), 40, 2);
    System.out.println(result);
}

This will compile to:这将编译为:

Method java/lang/invoke/MethodHandle.invokeExact:(LDeleteMe$Test;II)J

Notice the signature: ...II)L , not java/lang/Integer nor java/lang/Long .请注意签名: ...II)L而不是java/lang/Integerjava/lang/Long These are also called compiler overloads.这些也称为编译器重载。

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

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