二、Java高級特性(註解與反射)

一、前言

註解可以理解成標記,打標籤。單獨的一個註解是沒用的,需要搭配使用,例如搭配反射等等。我們需要通過使用註解上的值來做相應的操作。

二、自定義一個註解

package com.example.myapplication;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定義一個註解
 * InjectAnnotation
 * 註解可以理解成標記,打標籤,
 * 1、設置Retention註解,表示定義註解的級別、也可以理解爲註解的生命週期
 * (1)RetentionPolicy.SOURCE源碼上
 * 表示註解存在源碼中,當通過JAVAC編譯成字節碼之後,註解便不存在。此類型註解可以用在我們的註解處理中
 * 因爲註解處理器的方法執行在編譯器,我們可以在註解處理器的方法執行時候獲取我們的註解內容,做相應的一些操作,例如生成一些我們需要的輔助類
 * 比如Arouter框架。也可以用於源代碼的檢查。例如當我們的方法希望傳遞指定的類型的時候,可以使用註解來限制。
 * (2)RetentionPolicy.CLASS字節碼上
 * 此類型註解表示註解在字節碼中存在,即源碼編譯成字節碼,註解一直存在。可以用在字節碼增強、插裝的一些實現。
 * 也就是在字節碼中獲取註解內容,針對原有字節碼進行一些修改,而達到字節碼增強的效果。例如我們的熱修復
 * <p>
 * (3)RetentionPolicy.RUNTIME 運行期間,也叫運行行註解
 * 運行時註解,也就是從編譯到運行,註解一直存在,在程序運行的時候,我們可以使用我們的註解。例如:我們程序運行的時候,我們可以通過獲取註解+反射來實現一些功能,例如
 * 實現view.findId
 * <p>
 * <p>
 * 2、設置註解作用目標的對象
 * 常用的有
 * (1)TYPE 作用在類上
 * (2)FIELD  變量上
 * (3)METHOD 方法上
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ValueAnnotation {
    
    String value();
    
    DataType dataType();


}

自定義註解使用@interface關鍵字,並在註解上使用@Retention註解和@Target註解

  • 1、設置Retention註解,表示定義註解的級別、也可以理解爲註解的生命週期

(1)RetentionPolicy.SOURCE源碼上
表示註解存在源碼中,當通過JAVAC編譯成字節碼之後,註解便不存在。此類型註解可以用在我們的註解處理中
因爲註解處理器的方法執行在編譯器,我們可以在註解處理器的方法執行時候獲取我們的註解內容,做相應的一些操作,例如生成一些我們需要的輔助類。比如Aruter框架。也可以用於源代碼的檢查。例如當我們的方法希望傳遞指定的類型的時候,可以使用註解來限制。

(2)RetentionPolicy.CLASS字節碼上
此類型註解表示註解在字節碼中存在,即源碼編譯成字節碼,註解一直存在。可以用在字節碼增強、插裝的一些實現。 也就是在字節碼中獲取註解內容,針對原有字節碼進行一些修改,而達到字節碼增強的效果。例如我們的熱修復。

(3)RetentionPolicy.RUNTIME 運行期間上的註解
也叫運行時註解,運行時註解,也就是從編譯到運行,註解一直存在,在程序運行的時候,我們可以使用我們的註解。例如:我們程序運行的時候,我們可以通過獲取註解+反射來實現一些功能,例如: 實現findById

  • 2、設置註解作用目標的對象(Target註解)
    常用的有:
    (1)TYPE 作用在類上
    (2)FIELD 變量上
    (3)METHOD 方法上
  • 3、設置註解的值
    例如代碼中的,value和dataType,註解值可以有多個

三、註解結合反射實現Android中Activity頁面跳轉Intent值的獲取

1、自定義一個註解,也就是上面的註解
2、創建一個工具類
主要功能就是通過反射獲取Activity中的成員屬性,並且是獲取帶有我們自定義註解的屬性成員。然後獲取註解上的值,註解上設置了兩個值:字符串參數名和枚舉類型的數據類型。
根據數據類型和參數名,通過activity.getIntent()來獲取Intent上的值,拿到值之後,給成員賦值即可

package com.example.myapplication;

import java.lang.reflect.Field;

import androidx.appcompat.app.AppCompatActivity;

public class InjectUtils {

    public static void init(AppCompatActivity activity) {
        //1、通過actibity對象獲取class對象
        Class<? extends AppCompatActivity> activityClass = activity.getClass();
        //2.獲取該類的所有成員
        Field[] fields = activityClass.getDeclaredFields();
        //3.遍歷獲取:有打上ValueAnnotation註解的成員
        for (int i = 0; i < fields.length; i++) {
            if (fields[i].isAnnotationPresent(ValueAnnotation.class)) {
                try {
                    //4、給成員設置訪問權限、
                    fields[i].setAccessible(true);//也就是當成員是private的時候,允許訪問
                    //5、獲取成員上的註解的值
                    ValueAnnotation valueAnnotations = fields[i].getAnnotation(ValueAnnotation.class);
                    String value = valueAnnotations.value();
                    DataType dataType = valueAnnotations.dataType();
                    //6、判斷數據類型,設置值
                    if (dataType == DataType.IntegerData) {
                        Integer result = activity.getIntent().getIntExtra(value, 0);
                        fields[i].set(activity, result);
                    }
                    if (dataType == DataType.StringData) {
                        String result = activity.getIntent().getStringExtra(value);
                        fields[i].set(activity, result);
                    }

                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }


            }


        }

    }

}

在Activity上使用

package com.example.myapplication;

import android.os.Bundle;
import android.util.Log;

import java.lang.reflect.Type;

import androidx.appcompat.app.AppCompatActivity;

public class ResultActivity extends AppCompatActivity {
    @ValueAnnotation(value = "result", dataType = DataType.StringData)
    private String result;
    @ValueAnnotation(value = "age", dataType = DataType.IntegerData)
    private Integer age;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        InjectUtils.init(this);
        Log.e("ResultActivity", "result =  " + result);
        Log.e("ResultActivity", "age =  " + age);

//        //通過反射獲取泛型類型
//        //通過匿名內部類來實現,獲取泛型的類型
//        TypeClass<String> typeClass = new TypeClass<String>() {
//        };
//        Log.e("ResultActivity", "getType =  "+typeClass.getType());


    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章