簡體   English   中英

Java:編譯時Object的隱式轉換不起作用,但可以使用反射

[英]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_classint_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM