1. 程式人生 > >Java 泛型,反射,註解釋義

Java 泛型,反射,註解釋義

導言:由於Android熱門框架Retrofit,Eventbus,BufferKinfe原始碼不同程度的使用泛型,反射和註解,所以有必要對最基礎的知識進行記錄,別有時還暈乎乎,一句話總結,泛型解決型別轉換,反射動態獲取類所有資訊並設定,註解告訴編譯器如何執行程式

泛型:

定義:
實質是型別引數化,在編譯時免去強制型別轉換的麻煩,在執行時由具體的型別來替換這個泛型引數,也就是避免型別轉換出現異常的東西

例項:

//能檢查編譯時型別的錯誤
public void test1() throws Exception {
        List<String> list = new ArrayList<>();
        list.add("aaaa");
//      list.add(1);// 編譯時期報錯
        String str = list.get(1); 
    }

//泛型正確和錯誤寫法
public void test2() throws Exception {
        // 宣告泛型集合,四種正確寫法
        List<Object> list1 = new ArrayList<Object>();
        List<String> list2 = new ArrayList<String>();
        List list3 = new ArrayList<String>();
        List<Integer> list4 = new ArrayList();
        
        // 錯誤,頭大腳輕
        //List<Object> list5 = new ArrayList<String>();
        // 錯誤: 泛型型別必須是引用型別,不能為基本型別
        //List<int> list6 = new ArrayList<int>();
    }

//泛型類
public class Demo1<T> {
    // 定義泛型方法
    public <K> T aile(T t,K k) {
        return null;
    }
    // 測試方法
    public void test() throws Exception {
        //在建立泛型類物件的時候,確定型別
        Demo1<String> demo = new Demo1<String>();
        demo.aile("test", 1);
    }
}

//泛型方法
public class Demo2 {
    // 定義泛型方法
    public <K,T> T aile(T t,K k) {
        return null;
    }
    // 測試方法
    public void test() throws Exception {
        //在使用泛型方法的時候,確定泛型型別
        aile(1.0f, 1);
    }
}

//泛型介面
public interface IDao<T> {
    void aile(T t );
    void ware(T t );
}
//實現泛型介面1
public class Dao<T> implements IDao<T> {}
//實現泛型介面2
public class AnimalDao implements IDao<Animal>{}

//泛型關鍵字
? : 只接收值 
extends: 元素的型別必須繼承指定類
super: 元素的型別必須是指定類的父類

//? 的使用
public class test1 {
    public void aile(List<?> list) {
        // 只能獲取、迭代list,不能編輯list,比如列印列印資料,一般在方法引數中用
        for (Object o : list) {
         Log.i("info",o+"");
     }
    }
}

//extends 的使用,必須是Number的子類
public class test2 {
    public void aile(List<? extends Number> list) {
    }
    public void test() throws Exception {
        List<Double> list1 = new ArrayList<Double>();
        List<Float> list2 = new ArrayList<Float>();
        List<Integer> list3 = new ArrayList<Integer>();
        List<String> list4 = new ArrayList<String>();
        //呼叫
        aile(list1);
        aile(list2);
        aile(list3);
	    //報錯
        //aile(list4);
    }
}

//super 的使用,必須是String的父類
public class test3{
    public void aile(List<? super String> list) {
    }
    public void test() throws Exception {
        List<Object> list1 = new ArrayList<Object>();
        List<String> list2 = new ArrayList<String>();
        List<Integer> list3 = new ArrayList<Integer>();
        aile(list1);
        aile(list2);
        //報錯
        //aile(list3);
    }
}

反射:

定義:
對於任意一個類,可以動態的獲取類、屬性、方法的資訊,也能構造物件並控制物件的屬性和行為

例項:

public class Bean {
    // 屬性
    private int id = 1000;
    private String name = "aaaa";
    // 無參構造器
    public Bean(){
        System.out.println("Bean");
    }
    // 帶參構造器
    public Bean(String name){
        System.out.println("Bean" + name);
    }
    // 方法
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
// 反射使用
public class test {
    //獲取類建立例項
    public void testClass() throws Exception {
        // 類全名
        String className = "cn.aile.Bean";
        // 得到類位元組碼
        Class<?> clazz = Class.forName(className);
        // 建立無參物件
        //Bean bean = (Bean) clazz.newInstance();
        // 建立含參物件
        Constructor<?> constructor = clazz.getDeclaredConstructor(String.class);
        Bean bean = (Bean) constructor.newInstance("Jack");
    }
    //獲取屬性名稱、值
    public void testField() throws Exception {
        //類全名
        String className = "cn.aile.Bean";
        //得到類位元組碼
        Class<?> clazz = Class.forName(className);
        // 物件
        Bean bean =  (Bean) clazz.newInstance();
        //獲取所有的屬性名稱
        Field[]  fs =  clazz.getDeclaredFields();
        // 遍歷:輸出每一個屬性名稱、值
        for (Field f : fs) {
            //設定強制訪問
            f.setAccessible(true);
            //名稱
            String name = f.getName();
            //獲取值
            Object value = f.get(bean);
	    //設定值
	    f.set(bean,"bbbb");
        }
    }
    //獲取方法
    public void testMethod() throws Exception {
        //類全名
        String className = "cn.aile.Bean";
        //得到類位元組碼
        Class<?> clazz = Class.forName(className);
        //物件
        Bean bean =  (Bean) clazz.newInstance();
        //獲取方法物件
        Method m = clazz.getDeclaredMethod("getId");
        //呼叫方法
        Object r_value = m.invoke(bean);
    }
}

註解:

定義:
註解:告訴編譯器如何執行程式,有java內建(@Override,@Deprecated,@SuppressWarnings)和自定義的註解
註釋, 給程式設計師閱讀的描述資訊
元註解:修飾註解的註解

例項:
1:java內建註解

   //重寫父類的方法
    @Override
    public String toString() {
        return super.toString();
    }
    //抑制編譯器警告
    @SuppressWarnings({"unused","unchecked"})
    private void aile1() {
        List list = null;
    }
    //標記方法過時
    @Deprecated
    private void aile2() {
    }

2:自定義註解,可以給類、欄位、方法上新增描述資訊

   //註解格式
    public @interface Info {
    String name();
    int age();
    }
    //使用
    @Info(name = "aaa", age = 18)
    public void aile() {
    }

3:元註解
@Target:指定註解的可用範圍
TYPE, 類
FIELD, 欄位
METHOD, 方法
PARAMETER, 引數
CONSTRUCTOR, 構造器
LOCAL_VARIABLE 區域性變數

@Retention:指定註解的宣告週期
RetentionPolicy.SOURCE 在原始碼時有效
RetentionPolicy.CLASS 在位元組碼時有效
RetentionPolicy.RUNTIME 在執行時有效

@Target({TYPE}) //指定該註解在類上使用
@Retention(RetentionPolicy.RUNTIME)  //在執行時有效
public @interface Aile {
    String info();
}

好了,算是複習了一遍基礎知識,結束.