タイプ情報(反射、RTTI)

情報の種類

オブジェクトとクラスを特定する方法について1.javaのランタイム情報

  • 「伝統的な」RTTI実行時型識別、我々はすでに、すべてのタイプ、オープンコンパイル時に知っていて、コンパイル時の.classファイルを確認することを前提としてい

  • リフレクション、実行時にクラスを使用して、発見情報を可能にする、ファイルを開くと、実行時にチェックされた.class

実行時型情報あなたは、プログラムの実行の種類についての情報を見つけて使用できるように

2.Classオブジェクト

クラスはに関する情報が含まれ、この特定のオブジェクトクラスのオブジェクト
の各クラスをコンパイルして、同じ名前の.classファイルのファイルに保存された、Classオブジェクトを持っています

名詞

クラスローダサブシステム

ネイティブクラスローダ

すべてのクラスは、彼らの最初の時間使用されているあなたが最初のプログラムの作成時に、動的にJVMにロードされ、クラスの静的メンバーの参照を、彼らはクラスをロードします

コンストラクタは、新しいオブジェクトクラスの作成時に新しい静的メソッドは、クラスの静的メンバへの参照として扱われます

Javaランタイムではなく、すべてのクラスが完全にロードされますが、必要なときにのみロード

静的初期化時のクラスのロードが行われます。

あなたは実行時型情報で使用したいときはいつでも、あなたはまず、適切なクラスのオブジェクト参照を取得する必要があります

Classオブジェクトへの参照を取得する方法は?

  • 、そのタイプのホールドオブジェクトにする必要はありませんClass.forNameの(「クラス名」)は、オブジェクトを取得することができます

  • T.class、クラスリテラル(注、このメソッドのクラスオブジェクトへの参照を作成し、自動的にクラスオブジェクトを初期化しません)

  • Object.getClass()は、オブジェクトの種類を有し、ダイレクトを得るための方法を使用します

  • getSuperclass()は、クラスのオブジェクト、ベースクラスへの直接アクセスを持っています

実際の作業ステップのクラス

  • ロード、クラスローダが実行
  • リンク、クラスのバイトコード検証、ストレージ容量ドメインの静的割り当て
  • 、スーパークラスの初期化を初期化し、ブロック初期静的初期化スタティックを行います

初期化は、静的メソッドまで遅延(コンストラクタが静的である)、または初めて非定数静的フィールドは、実行前に引用されています

import java.util.Random;
/**
 * ClassInitialization
 * @@author thinking in java
 * @@version 1.1
 */
class Initable{
    // 编译器常量
    static final int staticFinal=1;
    // 不是编译器常量
    static final int staticFinal2=ClassInitialization.rand.nextInt(1000);
    static{
        System.out.println("initializing Initable");
    }
}
class Initable2{
    static int staticNonFinal=2;
    static{
        System.out.println("initializing Initable2");
    }
}
class Initable3{
    static int staticNonFinal=3;
    static{
        System.out.println("initializing Initable3");
    }
}
public class ClassInitialization{

    public static Random rand=new Random(47);

    public static void main(String[] args) throws Exception{
        //  使用.class获得类的引用不会引发初始化
        Class initable=Initable.class;
        System.out.println("after creating initable ref");
        //  static final 编译器常量,可以不对类进行初始化就可进行读取
        System.out.println(Initable.staticFinal);
        // 触发类的初始化
        System.out.println(Initable.staticFinal2);
        // static 或 final 在读取前必须进行链接(分配存储空间)和初始化(初始化存储空间)
        System.out.println(Initable2.staticNonFinal);
        // Class.forName() 立即进行初始化
        Class initable3=Class.forName("Initable3");
        System.out.println("after creating initable3 ref");
        System.out.println(Initable3.staticNonFinal);

    }
}
/*output:
after creating initable ref
1
initializing Initable
258
initializing Initable2
2
initializing Initable3
after creating initable3 ref
3
*///:~

instanceofは

これは、オブジェクトが特定の型のインスタンスではないことを教えてくれるブール値を返します。

メソッドのクラスもあります

public boolean isInstance(Object obj);

反射

RTTIの制限は、オブジェクトの正確な型を知りたいのですが、限界があり、このタイプはコンパイル時に知られなければなりません

プログラムにおける基準空間ではなく、Class.forNameの(「com.mysql.cj.DriverManger」)を取得するステップと、
またはネットワークから得られた、ディスク・クラスの代表のバイト

クラスとクラスライブラリは、全体の完全なサポートjava.lang.reflectの反射の概念を

  • GETを使用して、提出し、関連するフィールドのフィールドを変更するように設定
  • 達成するための方法、呼出し()メソッドの呼び出し
  • コンストラクタ、新しいオブジェクトの建設

反射は、他の特性をサポートするために使用される動的なコードを作成するために使用される(シリアライズ、たjavaBean)

インスタンスの反射を作成します

// Class的newInstance()
Class<?> c=String.class;
Object str=c.newInstance();

// Class的Constructor对象,可以指定构造器来实现
Class<?> c=String.class;
Constructor constructor=c.getConstructor(String.class);
Object obj=constructor.newInstance("456");

構成情報取得
クラスクラスコンストラクタクラスのインスタンスを取得するためにgetConstructor法
とのnewInstanceコンストラクタクラスは、オブジェクトのインスタンスを作成する方法を有しています

// 类的所有公有构造器
public Constructor[] getConstructors()

// 类的所有构造器
public Constructor[] getDeclareConstructors()

取得方法
クラスオブジェクトのメソッドのコレクションを取得します

// 返回类的公有方法,包含继承的公有方法数组
public Method[] getMethods() throws SecurityException

// 返回类的所有方法,不包括由超类继承的方法
public Method[] getDeclareMethods() throws SecurityException

// 返回一个特定的方法

public Method getMethod(String name,Class<?>...parameterTypes);

フィールド情報の取得

// 返回一个字段域,记录了类和超类的公有域
public Filed[] getFields()

// 记录类的全部域,以声明的成员变量,不能得到父类的成员变量
public Field[] getDeclareFields()

メソッドを呼び出します

// 函数原型
public Object invoke(Object obj,Object ...args)
              throws IllegalAccessException, IllegalArgumentException,InvocationTargetException


// 一个测试用例
public class test1 {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class<?> klass = methodClass.class;
        //创建methodClass的实例
        Object obj = klass.newInstance();
        //获取methodClass类的add方法
        Method method = klass.getMethod("add",int.class,int.class);
        //调用method对应的方法 => add(1,4)
        Object result = method.invoke(obj,1,4);
        System.out.println(result);
    }
}
class methodClass {
    public final int fuck = 3;
    public int add(int a,int b) {
        return a+b;
    }
    public int sub(int a,int b) {
        return a+b;
    }
}

長所と短所の反射

あなたが完了する反射機能を持っていない場合は、リフレクションを使用していません

利点:

  • スケーラビリティ、完全修飾名は、外部からのカスタムクラスを使用して、拡張することができるオブジェクトのインスタンスを作成するために使用することができます

  • クラスブラウザとビジュアル開発ツール、アイデア、escipse表示プロンプトクラス、反映されているアプリケーション

  • デバッグおよびテストツール、

短所:

  • パフォーマンス・オーバーヘッド、ダイナミック型解像度、JVMは、コード、低反射効率を最適化することができません

  • セキュリティ上の制限は、あなたが環境にセキュリティ制限のない実行する必要があります

  • 内部被ばく、抽象反射コードが弱体化させます

参考:

ベーシック(sczyh30) - Javaのリフレクション(1)の深さ分析
Javaで思考
のJavaのコア技術(音量- )
技術のインタビュー不可欠-CyC2018

おすすめ

転載: www.cnblogs.com/GeekDanny/p/11829475.html