[英]Java : Implicit cast of Object at compile-time doesn't work but work with reflection
给出以下代码:
import java.lang.reflect.Array;
import java.lang.reflect.Method;
public class Test {
public static void test_function(int[] values) {
System.out.println("Class of values : " + values.getClass());
System.out.println(values[0]);
}
public static void main(String[] args) {
Object a = Array.newInstance(int.class, 3);
Array.set(a, 0, 5);
Class a_class = a.getClass();
Class int_array_class = int[].class;
System.out.println("Class of int[] : " + int[].class);
System.out.println("Class of a : " + a.getClass());
System.out.println("int_array_class : " + int_array_class);
System.out.println("a_class : " + a_class);
// These instructions will provoke a compile-time error
// test_function(a);
// test_function(a_class.cast(a));
// test_function(int_array_class.cast(a));
// The following call won't cause any problem
test_function((int[]) a);
Method testf = null;
try {
testf = Test.class.getMethod("test_function", int[].class);
testf.invoke(null, a); // Does not provoke exception at run-time either
testf.invoke(null, a_class.cast(a));
testf.invoke(null, int_array_class.cast(a));
}
catch(Exception e) {
e.printStackTrace();
}
}
}
我注意到显式地将Object传递给方法不起作用。 如果取消注释,三条注释说明将引发以下错误:
Test.java:25: error: method test_function in class Test cannot be applied to given types;
test_function(a);
^
required: int[]
found: Object
reason: actual argument Object cannot be converted to int[] by method invocation conversion
Test.java:26: error: method test_function in class Test cannot be applied to given types;
test_function(a_class.cast(a));
^
required: int[]
found: Object
reason: actual argument Object cannot be converted to int[] by method invocation conversion
Test.java:27: error: method test_function in class Test cannot be applied to given types;
test_function(int_array_class.cast(a));
^
required: int[]
found: Object
reason: actual argument Object cannot be converted to int[] by method invocation conversion
3 errors
但是,通过反射传递对象可以正常工作并产生预期的结果。
Class of int[] : class [I
Class of a : class [I
int_array_class : class [I
a_class : class [I
Class of values : class [I
5
Class of values : class [I
5
Class of values : class [I
5
Class of values : class [I
5
所以问题是:为什么编译器拒绝编译在运行时工作正常的三个命令指令?
反射访问能够在运行时确定对象的实际类型。 另一方面,编译器只知道声明的类型。 它没有任何其他检查实际类型参数的可能性。
您的变量a
声明为Object
。 因此
test_function(a);
您尝试使用签名void test_function(Object)
调用一个根本不存在的方法。 一个简单的演员 - 就像你和程序员一样知道正确的类型 - 会在这里有所帮助:
test_function((int[]) a); // works fine (even at runtime)
另外两个方法调用是相同的,但有点不同。 您使用类型Class
声明了a_class
和int_array_class
。 这是一个原始类型,因此编译器不知道这些变量可以引用哪种类型。 编译器必须推断类型Object
。 这导致了与以前相同的问题(和解决方案)。
但是, Class
是泛型类型,可以参数化。 通过以下更改,最后一个方法调用无需显式转换:
Class<int[]> int_array_class = int[].class;
test_function(int_array_class.cast(a));
test_function需要一个int []作为参数,你传递一个对象引用(Object a)。 难怪它不编译。
你的三个注释掉的函数需要显式转换为int[]
来编译。 像这样,
test_function((int[]) a);
test_function((int[]) a_class.cast(a));
test_function((int[]) int_array_class.cast(a));
当我在Java 8上测试它们时,它们毫无例外地运行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.