はしごを登る:注釈と反射圧縮

学習リソースは以下から編成されます:ステーションB「クレイジーゴッドトーク」

注釈

JDK5.0から使用

  • 注釈の役割

    • プログラム自体ではありませんが、プログラムを説明することができます(コメントと同様、説明に使用されます)
    • 他のプログラム(コンパイラーなど)で読み取ることができます。
  • 注釈フォーマット

    • @noteという名前の注釈が存在し、パラメータを持つことができます
  • 一般的なアプリケーションのシナリオ

    • パッケージ、クラス、メソッド、フィールドなどにアタッチして、これらの要素に追加の補助情報を追加できます。この情報は、リフレクションメカニズムを通じて取得できます。

メタ注釈

  • メタ注釈の機能は、他の注釈に注釈を付けることです。Javaは4つの標準メタ注釈タイプを定義し、これらを使用して他の注釈タイプの説明を提供します。

  • これらの型とそれらがサポートするクラスは、java.lang.annotationパッケージにあります。

    • @Target:注釈のスコープを説明するために使用されます(注釈を使用できる場所を説明します)
    • @Retention:アノテーション情報を保存する必要があるレベルを示し、アノテーションのライフサイクルを説明します
      • (SOURCE <CLASS <RUNTIME)
    • @Document:アノテーションがjavadocに含まれることを説明する
    • @Inherited:サブクラスが親クラスのアノテーションを継承できることを示します、アノテーションの継承

カスタム注釈

  • @interface宣言アノテーション、パブリック@interface name {}を使用します
  • java.lang.annotation.Annotationインターフェースを自動的に継承する
  • 各メソッドは実際に構成パラメーターを宣言し、メソッド名はパラメーター名、戻り値の型はパラメーターの型です(戻り値は基本型、クラス、文字列、列挙型のみです)
  • パラメータのデフォルト値はデフォルトで宣言できます
  • パラメーターメンバーが1つしかない場合、通常は値の名前が付けられます
  • アノテーション要素には値が必要ですが、アノテーション要素を定義するときは、デフォルト値として空の文字列0を使用することがよくあります。
    ここに画像の説明を挿入

反射

リフレクションの概要

  • リフレクションは、Javaが動的言語と見なされるための鍵です。リフレクションメカニズムにより、プログラムは実行中にリフレクションAPIをキャッチしてクラスの内部情報を取得し、オブジェクトの内部プロパティとメソッドを直接操作できます。
  • クラスをロードした後、タイプClassのオブジェクトがヒープメモリのメソッド領域に生成されます。このオブジェクトにはクラスの完全な構造情報が含まれているため、このオブジェクトを通じてクラスの構造を確認できます。このオブジェクトは鏡のようなものなので、反射と呼ばれます。

プライベートに変更されたクラスとメソッドを読み取ることができます。

Javaリフレクションメカニズムによって提供される関数:

  • 実行時にオブジェクトのクラスを決定する
  • 実行時に任意のクラスのオブジェクトを構築します
  • 実行時に任意のクラスのメンバー変数とメソッドを判断する
  • 実行時に一般的な情報を取得する
  • 実行時に任意のオブジェクトのメンバー変数とメソッドを呼び出す
  • 実行時の注釈の処理
  • 動的プロキシを生成する

Javaリフレクションの利点:

  • 動的なコンパイルとオブジェクトの作成を実現し、優れた柔軟性を反映します。

Javaリフレクションの欠点:

  • パフォーマンスに影響を与えます。リフレクションの使用は基本的に解釈操作であり、このタイプの操作は同じ操作を直接実行するよりも常に低速です。

クラスクラスとクラスインスタンスの取得

  • クラス自体もクラスです
  • クラスオブジェクトはシステムによってのみ作成できます
  • ロードされたクラスは、JVMに1つのClassインスタンスのみを持ちます
  • Classオブジェクトは、JVMにロードされた.classファイルに対応します
  • クラスを通じて、クラスに読み込まれたすべての構造を完全に取得できます。
  • ClassクラスはReflectionのルートです。動的にロードして実行するクラスでは、まず対応するClassオブジェクトを取得する必要があります。

クラスの一般的なメソッド

メソッド名 説明
static Class.forName(String name) 指定されたクラス名のClassオブジェクトを取得します
オブジェクトnewInstance() パラメーターなしのコンストラクターを呼び出して、Classオブジェクトのインスタンスを作成します。
getName() このClassオブジェクトが表すエンティティ(クラス、インターフェース、配列クラス、またはvoid)の名前を返します。
クラスgetSuperClass() 現在のClassオブジェクトの親クラスのClassオブジェクトを返します
Class [] getInterfaces() 現在のClassオブジェクトのインターフェースのClass配列を取得します
ClassLoader getClassLoader() このクラスを返すクラスローダー
コンストラクター[] getConstructors() 現在のClassオブジェクトのコンストラクタ配列を取得します
メソッドgetMothed(String name、Class…T) 仮パラメータタイプがparamTypeであるMethodオブジェクトを返します。
Field [] getDeclaredFields() 現在のClassオブジェクトのフィールド配列を取得します

クラスクラスを取得するメソッド:

  • クラス名に従って直接取得
Class clazz = Person.class;
  • 例によって取得されます:
Class calzz = sutdent.getClass();
  • クラスのパスによると:
Class clazz = Class.forName("com.ssx.People");
  • 組み込みの基本データ型を直接使用できます。
  • ClassLoaderから取得できます

完全型クラス

ここに画像の説明を挿入

クラスローディングとClassLoader

プログラムがメモリにロードされていないクラスをアクティブに使用すると、システムは次の3つの手順でクラスを初期化します
ここに画像の説明を挿入

JVMを参照して振り返ると、より明確になります。

ブートクラスローダー:rt.jar

ここに画像の説明を挿入
クラスローディングのデモ
ここに画像の説明を挿入ここに画像の説明を挿入

リフレクションでジェネリックを取得する

  • Javaはジェネリック消去のメカニズムを使用してジェネリックを導入します。Javaのジェネリックは、コンパイラーjavacによってのみ使用され、データのセキュリティを確保し、強制的な型変換の問題を回避しますが、コンパイルが完了すると、イントロスペクションに関連するすべての型すべて消去
  • リフレクションを通じてこれらの型を操作するために、JavaはParameterizedType、GenericArrayType、TypeVariable、およびWildcardTypeを追加して、クラスクラスに分類できないが、元の型と同じ名前を持つ型を表します。
  • ParameterizedType:次のようなパラメーター化されたタイプ:Collection
  • GenericArrayType:要素の型がパラメーター化された型または型変数である配列型
  • TypeVariable:さまざまなタイプの変数のパブリック親インターフェースです
  • WildcardType:ワイルドカードタイプの式を表します

ここに画像の説明を挿入

リフレクションによって注釈を取得する

Annotation annotation = clazz.getAnnotations();//获取全部注解
clazz.getAnnotation(anno.class);
annotation.value()

概要

おすすめ

転載: blog.csdn.net/qq845484236/article/details/107924393