Java: implicit object listing at compile time does not work, but does work with reflection

Given the following code:

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();
    }

  }

}

      

I noticed that passing explicitly an object to a method doesn't work. Three commented instructions will provoke the following error if they were not taken into account:

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

      

However, passing objects through reflection works fine and gives the expected results.

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

      

So the question is, why does the compiler refuse to compile three comment commands that work fine at runtime?

+3


source to share


3 answers


Reflective access is able to determine the actual type of objects at runtime. On the other hand, the compiler only knows about the declared types. It has no other way to check the actual type of the arguments.

Your variable is a

declared as Object

. Therefore at

test_function(a);

      

you are trying to call a method with a signature void test_function(Object)

that simply does not exist. A simple selection - how you as a programmer know the correct type will help here:



test_function((int[]) a); // works fine (even at runtime)

      

The other two method calls are the same, but still slightly different. You have declared a_class

and int_array_class

with a type Class

. This is a raw type, so the compiler doesn't know what class type this variable might be. The compiler must indicate the type Object

. This leads to the same problem (and solution) as before.

However, it Class

is a generic type and can be parameterized. On the next change, the last method call works without explicit casting:

Class<int[]> int_array_class = int[].class;
test_function(int_array_class.cast(a));

      

+7


source


test_function expects int [] as an argument, you pass it an object reference (Object a). Unsurprisingly, it doesn't compile.



0


source


Your three commented functions require compiling explicit commands for int[]

. Like this,

test_function((int[]) a);
test_function((int[]) a_class.cast(a));
test_function((int[]) int_array_class.cast(a));

      

They worked without exception when I tested them in Java 8.

0


source







All Articles