JAva反射技術のケースの汎用消去

15548 ワード

汎用消去
汎用概念を正しく理解する第一の前提は、タイプ消去を理解することである.(type erasure).Javaにおける汎用は基本的にコンパイラという階層で実現されている.生成されたJavaバイトコードには汎用中のタイプ情報は含まれていない.汎用を使用する際に付けられたタイプパラメータは、コンパイラによってコンパイル時に削除される.このプロセスをタイプ消去と呼ぶ.コードに定義されたListやListなどのタイプは、コンパイル時に削除される後はリストになります.JVMが見ているのはListだけであり、汎用的に付加されたタイプ情報はJVMには見えない.Javaコンパイラは、コンパイル時にエラーが発生する可能性のある場所をできるだけ発見しますが、実行時にタイプ変換異常が発生することは避けられません.タイプ消去もJavaの汎用実装方式とC++テンプレートメカニズム実装方式の重要な違いである.
 
多くの汎用的な奇妙な特性は、このタイプの消去の存在に関連しています.
 
汎用クラスには独自のクラスオブジェクトはありません.例えばリストは存在しない.classまたはList.class、リストのみ.class.
静的変数は、汎用クラスのすべてのインスタンスによって共有されます.MyClassとして宣言されたクラスに対して、その中の静的変数にアクセスする方法は依然としてMyClassである.myStaticVar.new MyClassで作成されたオブジェクトもnew MyClassで作成されたオブジェクトも、静的変数を共有します.
汎用タイプパラメータはJava例外処理のcatch文では使用できません.異常処理はJVMの実行時刻に行われるためである.タイプ情報が消去されるため、JVMは2つの例外タイプMyExceptionとMyExceptionを区別できません.JVMの場合、これらはすべてMyExceptionタイプです.例外に対応するcatch文も実行できません.
タイプ消去の基本手順も簡単です.まず、タイプパラメータを置き換えるための特定のクラスを見つけます.この具体的なクラスは一般にObjectである.タイプパラメータの上界が指定されている場合は、この上界が使用されます.コードのタイプパラメータを特定のクラスに置き換えます.同時に表示されるタイプ宣言を削除します.すなわち、<>の内容を削除します.例えばT get()メソッド宣言はObject get()になります.リストはリストになります.次に、ブリッジメソッド(bridge method)を生成する必要がある場合があります.これは、タイプを消去したクラスに必要なメソッドが欠けている可能性があります.
コードケース:
 
    
  1. package com.lemon.test;
  2. import java.lang.reflect.Method;
  3. import java.util.ArrayList;
  4. /**
  5. * ( ):
  6. * , ArrayList , ?
  7. * , .class ,
  8. * 。 , , ,
  9. * @author Lemon
  10. *
  11. */
  12. public class ReflexTest01 {
  13. public static void main(String[] args) throws ReflectiveOperationException {
  14. // ArrayList
  15. ArrayList<Integer> array = new ArrayList<>();
  16. array.add(10);
  17. array.add(20);
  18. array.add(30);
  19. array.add(40);
  20. // array.add(" , ");
  21. // ArrayList<> Class
  22. Class extends ArrayList> arrayClass = array.getClass();
  23. // add
  24. Method addMethod = arrayClass.getMethod("add", Object.class);
  25. addMethod.invoke(array, " 666, !");
  26. System.out.println(array);
  27. }
  28. }
 
    
  1. [10, 20, 30, 40, 666, !]