反射
私は解剖学のクラスファイルは、一連の操作を実行するために反映されます理解しています。
Classクラス
クラスクラスのインスタンスを取得するための3つの方法:
- .classクラス名
- .getClassオブジェクト()
static Class forName(String className)
クラスのClassオブジェクトのクラス名を取得するためによると(ここではclassNameは、クラスの完全な名前でなければなりません)
第3の実施形態は、一般のGet Classオブジェクトを使用しています。
一般的なメンバー方法:
Field getField(String name)
オブジェクトのメンバ変数のクラスを取得しますString getName()
パッケージ名、クラス名:クラスの完全な名前を取得します。String getSimpleName()
クラス名:クラスと呼ぶの取得String getPackageName()
パッケージ名を取得します。Field getField(String name)
パブリックメンバ変数のオブジェクトへのアクセスMethod getMethod(String name, Class<?>... parameterTypes)
パブリックメンバ関数は、クラスを取得するには、オブジェクトConstructor<T> getConstructor(Class<?>... parameterTypes)
公共Objectクラスのコンストラクタを取得します。newInstance()
(JDK 9がインスタンス化clazz.getDeclaredConstructor()。NewInstanceメソッドを()を使用して、有効期限が切れている)のような取得の例
静的:
forName(String className)
ロードクラス
前記記述するために使用されるメンバ変数、メンバ関数、過度の要素コンストラクタ、独立したクラス:
カテゴリ | 説明 |
---|---|
フィールド | メンバ変数 |
方法 | メンバー方法 |
コンストラクタ | コンストラクタ |
事前定義されたオブジェクト:8つの基本タイプと空隙が、それは独自のクラスオブジェクトであります
コンストラクタ、メソッド、フィールド
コンストラクタ
newInstance(Object... initargs)
インスタンスを取得します。setAccessible(boolean)
あなたは検査の私権を超えて、つまり、暴力それにアクセスすることができます
setAccessible(boolean)
親クラスのメソッド、フィールド、メソッドはコンストラクタの暴力がプライベートメソッド/変数にアクセスするように設定することが可能です。
方法
Object invoke(Object obj, Object... args)
メソッド呼び出し、メソッドの戻り値の戻り値(ボイドメソッドがnullを返す)、最初のパラメータは、オブジェクトの呼び出しでは、第2のパラメータは、メソッドのパラメータであります
クラスローダ
一般的なクラスローダが3、各クラスローダは異なる場所クラスのロードを担当しています
|説明ローダーを
- | | - |
ブートストラップのルートクラスローダを|ブートストラップは、トップクラスローダです。これは、クラスファイルは、このようなようにシステム、文字列やなどのJavaコアクラスの担当で、私たち自身の書き込みではありませんロードします。メモリにロードされたすべてのクラスのみ、我々が使用することができます。(ブートストラップが自動的にロード)
ExtClassLoader拡張クラスローダーを| ExtClassLoader拡張クラスローダー、負荷がクラスを拡張することで、社内ではありません、自分の使用ををjdkています。(ExtClassLoaderクラスがロードされたブートストラップ)
AppClassLoaderシステム/アプリケーション・クラス・ローダー| AppClassLoaderシステム/アプリケーション・クラス・ローダーは、私たちがクラスパスを設定しない場合はクラスパス、クラスパスは、その後、ストレージ・クラス・パスを示す指定されたすべてのjarファイルまたはディレクトリをロードするために使用されます現在のフォルダを表し、アイデアでCLASSPATH環境は、ディレクトリの外にあります。カタログ・ストアでAppClassLoaderクラスローダは、私たちのディレクトリに書き出されたクラスファイルをロードするために使用されていることを、私たちの書き込みのクラスファイルの外にあります。(AppClassLoaderクラスがロードされExtClassLoader)
相対デフォルトのディレクトリ(ファイルパス)がプロジェクトディレクトリからの相対で、srcとローダー相対ディレクトリ
コメント
一般的なJDKの注:
コメント | 使用 |
---|---|
@Override |
リライト |
@SuppressWarnings() |
警告を抑制します |
@FunctionalInterface |
機能インタフェース |
@SuppressWarnings()
パラメータキーワードのリスト:
パラメータ | 説明 |
---|---|
すべて | すべての警告を抑制するために(すべての警告を抑制) |
ボクシング | ボクシング/アンボクシング操作(阻害パッキング、アンボクシング警告時間)に対する警告を抑制することができます |
キャスト | 操作を鋳造する相対警告を抑制すること(マッピング関連警告の阻害) |
DEPイン | 非推奨の注釈に対する警告を抑制するために(警告が有効コメントを抑制する) |
廃止 | 廃止に対して警告を抑制することができる(抑制が警告期限切れ) |
フォールスルー | (スイッチにおける阻害正しい削除警告休憩)switch文で休憩を逃しに対する警告を抑制するために、 |
最後に | (最終的にはモジュールが戻らない警告を抑制するために)返さないブロック最終的に相対的な警告を抑制するために、 |
隠蔽 | (変数を隠す地元に対して警告を抑制するために) |
不完全なスイッチ | switch文(列挙型の場合)には欠落しているエントリに対する警告を抑制するために(完全なswitch文ではありません無視) |
NLS | 非NLSに対して警告を抑制するために、文字列リテラル(無視非NLS文字形式) |
ヌル | ヌル分析に対して警告を抑制する(ヌル動作をスキップ) |
rawtypes | クラスのparamsにジェネリックを使用する場合、未特定のタイプに対して警告を抑制するために(ジェネリックを指定された対応するタイプなしで使用する場合は無視) |
制限 | 落胆や禁断の参照の使用に対する警告を抑制するために、 |
シリアル | 直列化可能クラスのserialVersionUIDフィールドが欠落に対する警告を抑制するために(serialVersionUIDの変数を無視し、シリアライズクラスで宣言されていません) |
スタティックアクセス | 誤ったスタティックアクセス(正しい静的方法警告を阻害しないアクセス)に対して警告を抑制することができます |
合成・アクセス | 内部クラス(サブクラスが内部クラスにアクセスするための最適な方法によれば、警告を阻害しない)からの最適化されていないアクセスに対して警告を抑制するために |
未チェック | 未チェックの操作(NO阻害アラート型チェック動作)に対する警告を抑制することができます |
修飾されていないフィールド・アクセス | 修飾されていないフィールドアクセスに対する警告を抑制するために(警告の抑制は、アクセスドメインを持っていません) |
未使用 | 未使用コードに対して警告を抑制するために(コードが警告を抑制するために使用されていません) |
カスタム注釈
声明の注釈
カスタムアノテーションを使用して@interface
ステートメント
属性することができ、その中:public abstract 属性类型 属性名() default 属性的默认值;
注釈はpublic abstract
省略することができ、かつ唯一の属性タイプをしている:基本类型
、、 、、String
1つまたは複数の一次元配列型、属性はデフォルト値はありませんすることができます。注釈の使用括弧内に属性を割り当てる必要がある場合、注釈は、属性をすることができない、デフォルト値が割り当てられないことができています。同じ方法で同じノートは一度だけ使用することができます。Class
注解
カスタムアノテーションを解析します
元注解
元注解是用来标记注解的注解。
一共有四种:
@Target
用于确定被修饰的注解使用的位置(主要)@Retention
用于确定被修饰的自定义注解生命周期(主要)@Documented
将此注解包含在Javadoc中@Inherited
允许子类继承父类中的注解
@Target
:表示该注解可以用于什么地方。可能的ElementType参数包括:CONSTRUCTOR
:构造器的生命FIELD
:域声明(包括enum实例)LOCAL_VARIABLE
:局部变量声明METHOD
:方法声明PACKAGE
:包声明PARAMETER
:参数声明TYPE
:类、接口(包括注解类型)和enum声明ANNOTATION_TYPE
:注解声明(与TYPE的区别?专门用在注解上的TYPE)TYPE_PARAMETER
:Java8TYPE_USE
:Java8
@Retention
:
表示需要在什么级别保存该注解信息。可选的RetentionPolicy参数包括:SOURCE
:注解将在编译器丢弃CLASS
:注解在class文件中可用,但会被VM丢弃RUNTIME
:VM将在运行期也保留注解,因此可以通过反射机制读取注解的信息
可以通过反射拿到方法,然后拿到注解,通过拿到的注解便可以拿到注解中的值。
代理
静态代理
代理:代理对象主要用来拦截目标业务对象的访问
- 代理对象要持有真实业务对象。(在代理类中创建被代理类的对象。)
- 代理对象要和真实业务对象,具备相同的行为方法。实现同一个接口。
- 代理对象拦截对真实对象的访问,可以修改访问的参数、返回值,甚至拦截访问。
静态代理使用较少。
动态代理
动态代理:就是在程序运行的过程中,动态的生成一个类,这个类要代理目标业务对象,并且可以动态生成这个代理类的对象。
在Java中当某个类需要被代理的时候,要求这个类中的被代理的方法必须抽取到一个接口中,然后这个类需要实现那个接口,只有在这个接口中的方法,代理类才能代理它。
Proxy类
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
:
获得代理类实例,参数:
ClassLoader loader
类加载器,一般给被代理对象的类加载器即可
Class<?>[] interfaces
被代理对象的所有的接口数组
InvocationHandler h
调用处理器,是一个接口。
InvocationHandler
接口有一个静态方法:public Object invoke(Object proxy, Method method, Object[] args)
第一个参数是代理本身,第二个参数是调用的方法,第三个参数是调用方法的参数(在方法中this
是这个接口的实现类,proxy
才是代理本身,通过返回代理本身可以实现链式调用,参考这里)
上个栗子:
@Test
public void proxyTest() throws Exception {
//获取自定义类的Class对象
Class clazz = Class.forName("org.junit.sh.n1.Person");
//获取该类的类加载器
ClassLoader loader = clazz.getClassLoader();
//获取接口数组
Class[] interfaces = clazz.getInterfaces();
// @SuppressWarnings("all")//clazz.newInstance()方法在JDK9中过期了,懒得改了,注解一下
//实例化一个对象作为调用者
Person p = (Person) clazz.newInstance();
//使用Lambda实现InvocationHandler
InvocationHandler h = (proxy, method, args) -> {
if ("show".equals(method.getName())) {
System.out.println("修改方法");
return method.invoke(p, args);
}
return null;
};
//自定义类实现的接口
Showable theProxy = (Showable) Proxy.newProxyInstance(loader, interfaces, h);
//调用方法
theProxy.show();
}
真正理解反射和注解还是得结合框架(。・∀・)ノ