Java二次複習筆記(1)

Java二次複習筆記(1)

  1. Java採用的默認字元編碼集是Unicode。
  2. byte=byte+byte報錯,值為int,而byte+=byte不報錯。同樣short = short+short報錯,值為int;short += short不報錯。
  3. float和double小數計算有時會出現誤差,原因是電腦底層為二進位,有些小數無法用二進位準確表示。如:0.5可以用2的-1次表示,0.3則無法用二進位表示。
  4. static方法是類級別的;非static方法是對象級別的。
    對象可以 -> new一個對象後,對象.static方法()或對象.非static方法()
    類只能 -> 類名.static方法
class Sta{
    public static void test01(){
        System.out.println("用類名直接調用static方法!");
    }
    public static void test02(){
        System.out.println("new一個對象後調用static方法!");
    }
}
public class Test {
    public static void test(){
        System.out.println("本類直接調用static方法!");
    }
    public static void main(String[] args) {
        test();
        Sta.test01();
        new Sta().test02();
    }
}

運行結果:

本類直接調用static方法!
用類名直接調用static方法!
new一個對象後調用static方法!
  1. 對於非基本類型(也叫對象類型或引用類型):
    只定義,不new:默認值為null。例如 Person p; String s; 其中p和s都為null。
    new實例化:Xxx xx = new Xxx(); xx值不是null,xx內部的屬性值全部是數據類型的默認值。例如 String s = new String(); s為””,Person p = new Person(); p對象里的屬性name為null,age為0,stature為0.0。
  2. 字元串。如果直接使用字面量(String s = "abc";),則從常量池中找;如果使用new(String s = new String("abc");),則從堆中找,而堆又會從常量池中找,如果常量池中不存在,則在常量池中創建,並引用該常量池中的字元串。
    ①問:String s = new String("hello");創建了多少個對象?答:如果之前常量池中不存在「hello」字元串,創建了兩個對象(堆中+常量池中)+一個引用。如果之前常量池中存在「hello」字元串,則創建了一個對象(堆中)+一個引用。
    ②問:如果常量池為空,String s = new String("a"+"b");創建了多少個對象?答:創建了4個對象(堆中new的東西+常量池中”a”、”b”、”ab”)。
  3. . String中的inter()方法,可以讓引用直接指向常量池。例String s1="a"; String s2=new String("a"); 此時s1==s2為false,當s2=s2.inter();s1==s2為true。
  4. 字元串分割。split()方法有些符號(. | + 等等)是無法直接分割的,需要加兩個轉義字元\;也可以使用StringTokenizer token = new StringTokenizer(要分割的字元串,分割的符號);然後迭代while(token.hasMoreElements()) {System.out.println(token.nextElement());}實現分割。
import java.util.StringTokenizer;
public class Test {
    public static void main(String[] args) {
        String s = "abc+def";
        String[] splits = s.split("\\+");
        System.out.println(splits[0]+"\t"+splits[1]);
        
        StringTokenizer tokenizer = new StringTokenizer(s,"+"); 
        while (tokenizer.hasMoreElements()){    
            System.out.println(tokenizer.nextElement()); 
        } 
    }
}

運行結果:

abc def
abc
def
  1. 構造方法。如果類中沒有構造方法,則系統自動提供一個無參構造方法,如果類中存在了任何構造方法,系統不再提供無參構造方法。this();調用本類構造,super();調用父類構造,只能放在第一行。建議:如果給類中編寫構造方法,提前寫一個無參構造防止報錯。
  2. 子類繼承父類。private、構造方法是不能被繼承的,但是子類可以顯示調用父類構造->super(); 。
class F{
    private int age = 10;
    public F(){
        System.out.println(age);
        ff();
    }
    private void ff(){
        System.out.println("ff");
    }
    public void tt(){
        System.out.println("tt");
    }
}
class S extends F{
    public S(){
        super();
    }
}
public class Test {
    public static void main(String[] args) {
        new S().tt();
    }
}

運行結果:

10
ff
tt
  1. 實例化。當new Xxx();時經歷了以下過程:測試類static靜態程式碼塊->父類static靜態程式碼塊->子類static靜態程式碼塊->父類普通程式碼塊->父類無參->子類普通程式碼塊->子類無參…
    靜態程式碼塊(static{ }):第一次執行且永遠只執行一次。
    普通程式碼塊({ }):每次執行無參構造之前執行。
class F{
    static {
        System.out.println("父類靜態程式碼塊");
    }
    {
        System.out.println("父類普通程式碼塊");
    }
    public F(){
        System.out.println("父類構造方法");
    }
}
class S extends F{
    static {
        System.out.println("子類靜態程式碼塊");
    }
    {
        System.out.println("子類普通程式碼塊");
    }
    public S(){
        System.out.println("子類構造方法");
    }
}
public class Test {
    static {
        System.out.println("測試類靜態程式碼塊");
    }
    {
        System.out.println("測試類普通程式碼塊");
    }
    public static void main(String[] args) {
        new S();
        new S();
    }
}

運行結果:

測試類靜態程式碼塊
父類靜態程式碼塊
子類靜態程式碼塊
父類普通程式碼塊
父類構造方法
子類普通程式碼塊
子類構造方法
父類普通程式碼塊
父類構造方法
子類普通程式碼塊
子類構造方法
  1. 構造方法不能被重寫(原因:重寫必須是子類重寫父類,構造方法不能被繼承,所以不存在重寫)。
    | | 位置 | 方法名 | 參數列表 | 返回值 | 訪問修飾符 |
    | — | — | — | — | — | — |
    | 方法重寫 | 子類 | 相同 | 相同 | 相同或子類 | 不能比父類更嚴格 |
    | 方法重載 | 同類或子類 | 相同 | 不相同 | 無關 | 無關 |
  2. 抽象類不能實例化,原因:抽象類中可能存在抽象方法,而抽象方法沒有方法體。
  3. final關鍵字。final修飾的類不能被繼承,final修飾的方法不能被重寫,final修飾的變數、屬性不能被修改。
  4. 多態。打:打籃球、打水、打架…
    多態:父類引用指向子類對象;引用在棧空間中,子類對象在堆空間中。
父類 引用對象名字 = new 子類();
Pet pet = new Dog();//多態
Pet pet = new Cat();//多態
double d = 10;//double = int(大範圍類型 = 小範圍類型)
  1. 繼承: 子類 is a 父類 ->狗是一個寵物(狗是子類,寵物是父類)
    介面: 類 has a 介面 ->門有鎖的功能(門是類,鎖是介面)
  2. 介面。介面中沒有方法體,且方法都默認為「public abstract」,屬性都默認為「static final」。介面和抽象類一樣,不能實例化。
  3. 子類必須重寫父類中的所有抽象方法;實現類必須實現介面中的所有抽象方法。
  4. 包裝類。
public class BZL {
    public static void main(String[] args) {
        int i = 10;
        Integer j = new Integer(20);
        i = j;  //自動裝箱  底層使用的是intValue()
        j = i;  //自動裝箱  底層使用的是valueOf()
        /*valueOf()該方法中有一個緩衝區【-128,127】,如果裝箱的數字不在此範圍內,要重新new一個對象*/
        Integer a = 100;
        Integer b = 100;
        Integer c = 1000;
        Integer d = 1000;
        System.out.println("a與b比較:"+ (a==b));
        System.out.println("c與d比較:"+ (c==d));
    }
}

運行結果:

a與b比較:true
c與d比較:false
  1. 集合。
    Collection 存儲的數據 不唯一,無序,是List的父類,Collection介面的父類是Iterable介面。
package collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionTest {
    public static void main(String[] args) {
        Collection col = new ArrayList<>();
        Collection col1 = new ArrayList();
        //col.add();  添加元素
        col.add("a");
        col.add("b");
        col.add("c");
        System.out.println("col"+col);
        col1.add(1);
        col1.add(2);
        col1.add("3");
        System.out.println("col1"+col1);
        //迭代
        Iterator it = col.iterator();
        while (it.hasNext()) {
            String s = (String) it.next();
            System.out.println(s);
        }
        //col.addAll();  添加一個集合所包含的全部元素
        col.addAll(col1);
        System.out.println("col:"+col);
        //col.toArray();  將集合轉換為數組
        Object[] os = col.toArray();
        System.out.print("集合轉數組:");
        for (int i = 0; i < os.length; ++i) {
            System.out.print(os[i]+"\t");
            if (i==os.length-1){
                System.out.println();
            }
        }
        //col.remove(Object o); 移除
        col.remove("b");
        System.out.println("移除後 col:"+col);
        //col.removeAll();  移除一個集合所包含的全部元素
        col.removeAll(col1);
        System.out.println("移除"+col1+"後col:"+col);
        col.addAll(col1);
        System.out.println("col:"+col);
        //col.retainAll();  只剩一個集合所包含的全部元素
        col.retainAll(col1);
        System.out.println("retainAll"+col1+"後col:"+col);
        //col.contain();  判斷是否包含該元素
        System.out.println(col.contains("2"));
        System.out.println(col.contains(2));
        //col.containAll();  判斷是否包含該集合
        System.out.println(col.containsAll(col1));
        System.out.println("判斷集合是否為空:"+col.isEmpty());
        System.out.println("返回集合長度:"+col.size());
        System.out.println("返回集合哈希值:"+col.hashCode());
        //清空集合
        col.clear();
        System.out.println("col:"+col);
    }
}

運行結果:

col[a, b, c]
col1[1, 2, 3]
a
b
c
col:[a, b, c, 1, 2, 3]
集合轉數組:a b c 1 2 3 
移除後 col:[a, c, 1, 2, 3]
移除[1, 2, 3]後col:[a, c]
col:[a, c, 1, 2, 3]
retainAll[1, 2, 3]後col:[1, 2, 3]
false
true
true
判斷集合是否為空:false
返回集合長度:3
返回集合哈希值:30865
col:[]

List(ArrayList,LinkList)存儲的數據是不唯一的,有序的(按存入順序排),可以通過索引增刪改查元素。

package collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
//List介面擁有Collection介面的所有功能
public class ListTest {
   public static void main(String[] args) {
       ArrayList list = new ArrayList();
       list.add("a");
       list.add("b");
       System.out.println("list:"+list);
       //add(int index,Object element);  index位置插入元素element
       list.add(0,"A");
       System.out.println("list:"+list);
       List list1 = new ArrayList();
       list1.add("F");
       list1.add("f");
       list1.add("B");
       //add(int index,Collection c);  index位置插入集合c
       list.addAll(1,list1);
       System.out.println("將集合"+list1+"插入1位置後list:"+list);
       //get();  返回某位置元素
       System.out.println("位置3的元素為:"+list.get(3));
       //indexOf(); 返回某元素首次出現的位置
       //lastIndexOf(); 返回某元素最後出現的位置
       System.out.println("b元素的位置:"+list.indexOf("b"));
       //remove(int index);  刪除指定位置的元素
       list.remove(2);
       System.out.println("刪除位置2處的元素後list:"+list);
       //set(int index,Object element);  index位置元素替換為元素element
       list.set(0,"OK");
       System.out.println("0位置元素替換為OK後,list:"+list);
       //subList(int fromIndex,int toIndex);  截取集合元素[fromIndex,toIndex)
       ArrayList list3 = new ArrayList(list.subList(1,3));
       System.out.println("截取list的[1,3):"+list3);
       LinkedList link = new LinkedList();
       link.add("a");
       link.add("b");
       link.addFirst("頭");
       link.addLast("尾");
       System.out.println("link:"+link);
       //普通for循環遍歷
       System.out.println("普通for循環遍歷");
       for (int i=0;i<link.size();i++){
           System.out.println(link.get(i));
       }
       //增強for循環遍歷
       System.out.println("增強for循環遍歷");
       for (Object o:link){
           String s = (String)o;
           System.out.println(s);
       }
       //迭代器
       System.out.println("迭代器");
       Iterator iterator = link.iterator();
       while (iterator.hasNext()){
           String s = (String)iterator.next();
           System.out.println(s);
       }
   }
}

運行結果:

list:[a, b]
list:[A, a, b]
將集合[F, f, B]插入1位置後list:[A, F, f, B, a, b]
位置3的元素為:B
b元素的位置:5
刪除位置2處的元素後list:[A, F, B, a, b]
0位置元素替換為OK後,list:[OK, F, B, a, b]
截取list的[1,3):[F, B]
link:[頭, a, b, 尾]
普通for循環遍歷
頭
a
b
尾
增強for循環遍歷
頭
a
b
尾
迭代器
頭
a
b
尾

Set(HashMap,TreeMap)存儲的數據是唯一的,無序的。因為無序,所以無法通過索引 增刪改查 元素。

package collection;
import java.util.HashSet;
import java.util.Iterator;
//Set接介面擁有Collection介面的所有功能
public class SetTest {
    public static void main(String[] args) {
        HashSet set = new HashSet();
        set.add("a");
        set.add("b");
        set.add("A");
        set.add("B");
        set.add("a");
        System.out.println(set);
        //增強for循環遍歷
        System.out.println("增強for循環遍歷");
        for (Object o :set) {
            String s = (String)o;
            System.out.println(s);
        }
        //迭代器遍歷
        System.out.println("迭代器遍歷");
        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
            String s = (String)iterator.next();
            System.out.println(s);
        }
    }
}

運行結果:

[a, A, b, B]
增強for循環遍歷
a
A
b
B
迭代器遍歷
a
A
b
B

Map(HashMap,TreeMap)無序的,key值是唯一的,value值不唯一。

package map;
import java.util.*;
//HashMap介面擁有Map介面的所有功能
//無序的:與存儲順序無關
public class MapTest {
    public static void main(String[] args) {
        HashMap map = new HashMap();
        map.put("2","張三");
        map.put("1","李四");
        map.put("3","王五");
        map.put("A1","哈哈");
        System.out.println(map);
        //根據key找value
        System.out.println("key值為2的value值:"+map.get(2));
        System.out.println("集合長度:"+map.size());
        System.out.println("判斷是否包含指定的key:"+map.containsKey(1));
        System.out.println("判斷是否包含指定的value:"+map.containsValue("王五"));
        //轉為只含key的單值集合(key值唯一,所以用Set)
        Set set = map.keySet();
        System.out.println(set);
        //轉為只含value的單值集合(value值不唯一,所以用Collection)
        Collection coll = map.values();
        System.out.println(coll);
        //remove(key);  根據key刪除元素,返回值為value
        map.remove(2);
        System.out.println("刪除key值為2的元素:"+map);
        //增強for循環遍歷--通過entry遍歷
        System.out.println("增強for循環遍歷--通過entry遍歷");
        Set entries = map.entrySet();
        for(Object o:entries){
            Map.Entry et = (Map.Entry) o;
            Object k = et.getKey();
            Object v = et.getValue();
            System.out.println("key:"+k+"--"+"value:"+v);
        }
        //迭代器
        System.out.println("迭代器");
        Set keySet = map.keySet();
        Iterator iterator = keySet.iterator();
        while(iterator.hasNext()){
            Object k = iterator.next();
            Object v = map.get(k);
            String sk = (String)k;
            String sv = (String)v;
            System.out.println("key:"+sk+"--"+"value:"+sv);
        }
    }
}

運行結果:

{A1=哈哈, 1=李四, 2=張三, 3=王五}
key值為2的value值:null
集合長度:4
判斷是否包含指定的key:false
判斷是否包含指定的value:true
[A1, 1, 2, 3]
[哈哈, 李四, 張三, 王五]
刪除key值為2的元素:{A1=哈哈, 1=李四, 2=張三, 3=王五}
增強for循環遍歷--通過entry遍歷
key:A1--value:哈哈
key:1--value:李四
key:2--value:張三
key:3--value:王五
迭代器
key:A1--value:哈哈
key:1--value:李四
key:2--value:張三
key:3--value:王五

泛型:

package generic;
import java.util.*;
class Person{
    private int id;
    private String name;
    private int age;
    private double height;
    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", height=" + height +
                '}';
    }
    public Person(){}
    public Person(int id, String name, int age, double height) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.height = height;
    }
    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 int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public double getHeight() {
        return height;
    }
    public void setHeight(double height) {
        this.height = height;
    }
}
public class Demo {
    public static void main(String[] args) {
        Map<Integer,String> map = new HashMap<>();
        map.put(1,"張三");
        map.put(3,"王五");
        map.put(2,"李四");
        Set<Map.Entry<Integer, String>> entries = map.entrySet();
        for (Map.Entry<Integer,String> entry:entries){
            System.out.println("key = "+entry.getKey());
            System.out.println("value = "+entry.getValue());
        }
        List<Person> list = new ArrayList<>();
        Person p1 = new Person(1,"張三",20,1.78);
        Person p2 = new Person(3,"王五",25,1.69);
        Person p3 = new Person(2,"李四",22,1.88);
        list.add(p1);
        list.add(p2);
        list.add(p3);
        Iterator<Person> iterator = list.iterator();
        while (iterator.hasNext()){
            Person p = iterator.next();
            System.out.println(p);
        }
    }
}

運行結果:

key = 1
value = 張三
key = 2
value = 李四
key = 3
value = 王五
Person{id=1, name='張三', age=20, height=1.78}
Person{id=3, name='王五', age=25, height=1.69}
Person{id=2, name='李四', age=22, height=1.88}
  1. 集合刪除(remove()):
    Collection中的類(List、Set),刪除的返回值是boolean;
    Map中的類,是根據key刪除,返回值是value。
  2. 工具類。(Arrays、Collections)
    數組工具類:
import java.util.Arrays;
public class ArraysTest {
    public static void getArr(int[] arr){
        for (int i=0;i<arr.length;i++){
            System.out.print(arr[i]+"\t");
        }
        System.out.println();
    }
    public static void main(String[] args) {
        int[] arr = {5,8,9,11,6,2,7,9};
        System.out.println("原數組:");
        getArr(arr);
        Arrays.sort(arr);
        System.out.println("數組排序:");
        getArr(arr);
        //二分查法, 必須先排序再二分查
        System.out.println("9的位置:"+Arrays.binarySearch(arr,9));
        Arrays.fill(arr,5);
        System.out.println("填充全部:");
        getArr(arr);
    }
}

運行結果:

原數組:
5 8 9 11 6 2 7 9 
數組排序:
2 5 6 7 8 9 9 11 
9的位置:5
填充全部:
5 5 5 5 5 5 5 5 

集合工具類:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CollectionsTest {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("java");
        list.add("mysql");
        list.add("html");
        list.add("php");
        list.add("python");
        System.out.println(list);
        Collections.sort(list);
        System.out.println("字典排序:"+ list);
        System.out.println("最大值:"+Collections.max(list));
        System.out.println("最小值:"+Collections.min(list));
        //二分法查(使用前,必須保證集合元素是 自然有序的)
        System.out.println("\"php\"位置:"+Collections.binarySearch(list,"php"));
        Collections.shuffle(list);
        System.out.println("洗牌後:"+list);
        Collections.reverse(list);
        System.out.println("反轉後:" + list);
        Collections.swap(list,1,2);
        System.out.println("1位置與2位置元素交換:" + list);
        Collections.replaceAll(list,"php","c++");
        System.out.println("新元素替換所有舊元素" + list);
        Collections.fill(list,"hello");
        System.out.println("填充全部:" + list);
    }
}

運行結果:

[java, mysql, html, php, python]
字典排序:[html, java, mysql, php, python]
最大值:python
最小值:html
"php"位置:3
洗牌後:[mysql, html, php, java, python]
反轉後:[python, java, php, html, mysql]
1位置與2位置元素交換:[python, php, java, html, mysql]
新元素替換所有舊元素[python, c++, java, html, mysql]
填充全部:[hello, hello, hello, hello, hello]
  1. 異常。
    try{ }catch{ } 自己(當前方法)能夠處理,使用try catch;
package exception;
public class ExceptionTest {
    public static void test01(){
        try{
            Object obj = null;
            obj.equals(""); //會出現空指針異常
        }catch (NullPointerException e){
            System.out.println("發生了空指針異常!");
        }catch (Exception e){
           e.printStackTrace();
        }finally{
            System.out.println("最終都會執行的地方!");
        }
    }
    public static int test02(){
        try{
           int[] i = new int[1];
//            System.exit(1);     //關閉虛擬機,直接終止,下面都不會運行
           i[1] = 5; //發生數組越界異常
            return 0;
        }
        //捕獲時,先寫範圍小的類型,後寫範圍大的類型
        catch (NullPointerException e){
            System.out.println("發生了空指針異常!");
            return 1;
        }catch (Exception e){
            System.out.println("上面catch沒捕獲到後用這個捕獲!");
            return 2;
        }finally {
            System.out.println("最終都會執行的地方!");
            //return 3;
        }
    }
    public static void main(String[] args) {
        test01();
        System.out.println("返回值是:"+test02());
    }
}

運行結果:

發生了空指針異常!
最終都會執行的地方!
上面catch沒捕獲到後用這個捕獲!
最終都會執行的地方!
返回值是:2

throws 自己(當前方法)不能處理,上交個上級(方法調用處)處理,使用throws。
自定義異常:MyException.java

package exception;
public class MyException extends Exception {
   public MyException(String message){
       super(message);
   }
}

ThrowTest.java

package exception;
public class ThrowTest {
   //1.利用try catch處理異常
   public static void test01(){
       int age = 188;
       //約定年齡範圍(0,120]
       if (age<=0 || age>120){
           try {
               throw new MyException("年齡不符!");
           } catch (MyException e) {
               e.printStackTrace();
           }
       }
   }
   //2.利用throws拋出異常
   public static void test02() throws MyException {
       int age = 188;
       //約定年齡範圍(0,120]
       if (age<=0 || age>120){
           throw new MyException("年齡不符!");
       }
   }
   public static void main(String[] args) {
       test01();
       //對於用throws拋出異常的方法,調用時要麼try catch,要麼繼續throws拋出
       try {
           test02();
       }catch (MyException e){
           e.printStackTrace();
       }
   }
}

運行結果:

exception.MyException: 年齡不符!
 at exception.ThrowTest.test01(ThrowTest.java:15)
 at exception.ThrowTest.main(ThrowTest.java:31)   ...
exception.MyException: 年齡不符!
 at exception.ThrowTest.test02(ThrowTest.java:26)
 at exception.ThrowTest.main(ThrowTest.java:34)   ...
  1. 內置註解
    @Override:可以確保重寫的方法的確存在於父類或者介面中,可以有效的避免單詞拼錯等情況。
    @Deprecated:用於提示,該方法由於安全、性能問題等已經不推薦使用了。此外,在版本升級時,如果要計劃刪除一些方法,也通常會在下一個版本中將該方法加上@Deprecated,然後再在後續版本中刪除。
    @SuppressWarnings(value=”unchecked”):壓制警告(一般不建議使用)。value值有unchecked,deprecation(忽略一些過期的API),unused(是否未被使用),fallthrough(switch是否一直往下執行而沒有break),path(忽略堆路徑不存在的檢查),serialVersionUID(忽略一個類可以被序列化,但沒有序列化的警告),all(忽略一切警告)。
  2. 元註解(修飾註解的註解)
    @Target:限制註解使用的位置(屬性、方法、類),如果一個註解沒有@Target描述,則該註解可以修飾任何類型的元素,如果有@Target修飾。該註解就只能用於被@Target修飾的地方。
public enum ElementType {
    /**  類,介面(包括注釋類型)或枚舉聲明 */
   
    TYPE,
    /** 欄位聲明(包括枚舉常量) */
    FIELD,
    /** 方法聲明 */
    METHOD,
    /** 形式參數聲明 */
    PARAMETER,
    /** 構造函數聲明 */
    CONSTRUCTOR,
    /** 局部變數聲明 */
    LOCAL_VARIABLE,
    /** 注釋類型聲明 */
    ANNOTATION_TYPE,
    /** 包聲明 */
    PACKAGE,
    /**
     * 類型參數聲明
     *
     * @since 1.8
     */
    TYPE_PARAMETER,
    /**
     * 使用類型
     *
     * @since 1.8
     */
    TYPE_USE,
    /**
     * 模組聲明.
     *
     * @since 9
     */
    MODULE
}

@Retention:限制註解的生命周期

public enum RetentionPolicy {
    /**
     * 批註將被編譯器丟棄。
     jvm直接將該註解丟棄
     */
    SOURCE,
    /**
     * 注釋將由編譯器記錄在類文件中,但不必在運行時由VM保留。這是默認的行為。
     .java -> .class
     程式在編譯時會使用註解,在運行時不會使用
     */
    CLASS,
    /**
     * 注釋由編譯器記錄在類文件中,並在運行時由VM保留,因此可以通過反射方式讀取它們。
     *
     * @see java.lang.reflect.AnnotatedElement
     程式在編譯以及運行時。都會使用註解
     */
    RUNTIME
}

@Document:
默認情況下,javadoc不包含註解的解釋,如果想在javadoc文檔中也包含註解的說明,則需要使用@Document標註。
@Inherited:繼承。如果A類有一個註解,B類繼承A類時,默認不會繼承該註解;如果該註解用@Inherited修飾,則就可以繼承註解。


接下來舉個例子:
先自定義一個註解

package annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(value = {ElementType.FIELD,ElementType.METHOD}) //修飾註解,只能在屬性、方法上使用
@Retention(RetentionPolicy.RUNTIME) //修飾註解,編譯運行時都會使用註解
public @interface MyAnnotation {
    //String value(); //用定義方法的形式,定義了一個屬性value
    //String[] value(); //數組形式
    String value() default "Hello"; //default指定了value默認值為H ello
    int age() default 24;
}

測試一下

package annotation;
import java.lang.annotation.Annotation;
public class AnnotationTest {
    @MyAnnotation
    @Deprecated
    public static void test() throws Exception {
        //獲取  「類名」 的 「方法」 的 「註解」
        Annotation[] annotations = Class.forName("annotation.AnnotationTest").getMethod("test").getAnnotations();
        for (Annotation a: annotations) {
        /*註:如果元註解@Retention的值不為RetentionPolicy.RUNTIME,則會直接執行下面的else結果*/
            if (a instanceof MyAnnotation){ 
                System.out.println("獲取自定義註解的value值:" + ((MyAnnotation)a).value() );
                System.out.println("獲取自定義註解得到age值:" + ((MyAnnotation)a).age() );
            }else{
                System.out.println("@Deprecated");
            }
        }
    }
    public static void main(String[] args) throws Exception {
        test();
    }
}

運行結果:

獲取自定義註解的value值:Hello
獲取自定義註解得到age值:24
@Deprecated
Tags: