首頁>技術>

一.註解Annotation

1.什麼是註解

註解是以“@註釋名”在程式碼中存在。

程式碼中的特殊標記,這些標記可以在編譯、類載入、執行時被讀取,並執行相對應的處理。

減少了配置,大量減少了程式碼量,透過反射機制實現對這些元資料(為其他資料提供資訊的資料)的訪問。

在開發中使用也是比較常見的,比如:@Controller、@Param、@Data等,Java原生(標記&檢查)有@Overried、@Deprecated、@Functional

2.基本內建註解

@Override 表示這個方法重寫了父類的方法

@Deprecated 表示這個方法已經過期,不建議開發者使用

@SuppressWarnings 表示忽略警告資訊

3.自定義註解

利用反射讀取註解

public class Test3 {     public static void main(String[] args) {        try {            // 1.反射            Class clazz = Class.forName("com.annotation.Student");            // 2.獲得這個類的註解            Annotation[] annotations = clazz.getAnnotations();            for (Annotation annotation:annotations){                System.out.println(annotation);            }            // 3.獲得類的註解value的值            TableKuang table = (TableKuang)clazz.getAnnotation(TableKuang.class);            System.out.println(table.value());             // 4.獲得類指定註解的值            Field name = clazz.getDeclaredField("name");            FieldKuang fieldKuang = name.getAnnotation(FieldKuang.class);            System.out.println(fieldKuang.columnName()+"-->"+fieldKuang.type()+"-->"+fieldKuang.length());          } catch (ClassNotFoundException | NoSuchFieldException e) {            e.printStackTrace();        }    }  }@TableKuang("db_student")class Student{     @FieldKuang(columnName = "db_id",type="int",length = 10)    private int id;    @FieldKuang(columnName = "db_name",type="varchar",length = 10)    private String name;    @FieldKuang(columnName = "db_age",type="int",length = 3)    private int age;     ......} // 表名註解@Target(value = {ElementType.TYPE})@Retention(value = RetentionPolicy.RUNTIME)@interface TableKuang{    String value();} // 屬性註解@Target(value = {ElementType.FIELD})@Retention(value = RetentionPolicy.RUNTIME)@interface FieldKuang{    String columnName(); // 列名    String type(); // 型別    int length();  // 長度}

4.元註解

元註解的作用就是負責註解其他註解

@Tartget:用於描述註解的使用範圍(Type修飾類、介面或列舉型別;Filed成員變數;Method方法;)

@Retention:表示生命週期(source<class<runtime)

@Inherited:表示子類可以繼承父類的註解

@Ducumented:表示註解將被包含在javadoc中

二.反射

這裡講一下 「 執行時 」,.java檔案經過javac編譯變成.class檔案,class檔案會被JVM裝載執行。

我記得在工作中,我有一個需求是主系統對使用者表、部門表等增量變化的同時要求去增量同步子系統對應的使用者表、部門表資料。增量同步的這個工具類就有用到了反射技術。一個好的工具就要相容各種情況(使用者、部門等)。

還有就是SpringMVC中在方法寫上物件,傳入的引數就會封裝到物件上。

這些例子都有涉及到反射:約定大於配置,配置大於硬編碼。

2.1 什麼是反射

反射是Java被視為動態語言的關鍵,反射機制允許程式在執行期藉助於反射API得到類的內部資訊,並能直接操作任意物件的內部屬性以及方法。

載入類之後,在堆記憶體的方法區就產生了一個Class型別的物件,這個物件就包含了完整的類的結構資訊。

優點:可以實現動態建立物件和編譯,體現出很大的靈活性。

缺點:對效能有影響,慢於直接執行相同的操作。

2.2 類的載入過程

2.2.1 載入

將class檔案位元組碼內容載入到記憶體,並將這些靜態資料轉換成方法區的執行時資料結構,然後生成一個代表這個類的java.lang.Class物件

2.2.2 連結

將Java類的二進位制程式碼合併到JVM的執行狀態之中的過程

驗證:確保載入的類資訊符合JVM規範

準備:正式為類變數分配記憶體並設定類變數預設初始值的階段(方法區)

解析:虛擬機器常量池內的符號引用替換為直接引用的過程

2.2.3 初始化

執行類構造器方法的過程

當初始化一個類的時候,如果發現其父類還沒有初始化,則需要先觸發其父類的初始化

虛擬機器會保證一個類的方法在多執行緒環境中被正確加鎖和同步

2.3 類的載入器

類載入器的作用是將class檔案位元組碼內容載入記憶體中,並將靜態資料轉換成方法資料結構,然後在堆中生成一個代表這個類的java.lang.class物件,作為方法區中類資料的訪問入口

2.4 獲取類物件

wistchen.getClass()Class.forName("包名+類名")Wistchen.classClassLoader classLoader = this.getClass().getClassLoader(); classLoader.loadClass(className);

2.5 類物件的常用方法

static ClassforName(String name) 返回指定類名name的class物件

Object newInstance() 呼叫預設建構函式,返回Class物件的一個例項

getName() 返回此Class物件所表示的實體的名稱

Class getSuperClass() 返回當前CLass物件的父類的Class物件

Class[] getinterfaces() 獲取當前Class物件的介面

ClassLoader getClassLoader() 返回該類的類載入器

Constructor[] getConstructors() 返回一個包含某些Constructor物件的陣列

Method getMethed(String name,Class T) 返回一個Method物件

Field getDeclaredFields() 可以獲取本類所有的欄位,包括private的,但是不能獲取繼承來的欄位。 (注: 這裡只能獲取到private的欄位,但並不能訪問該private欄位的值,除非加上 setAccessible(true))

Field getField 只能獲取public的,包括從父類繼承來的欄位。

2.5 建立物件

Class pClass = Class.forName(className); 類物件

Constructor c = pClass.getConstructor();構造器

c.newInstance() 透過構造器例項化

2.6 訪問屬性

public class TestReflection {    public static void main(String[] args) {        Hero hero = new Hero();        hero.name = "garen";         try{            Field f1 = hero.getClass().getDeclaredField(("name"));            f1.set(hero,"teemo");            System.out.println(hero.name);        } catch (NoSuchFieldException | IllegalAccessException e) {            e.printStackTrace();        }    }} class Hero{    public String name; //為了訪問屬性,把name修改為public    public float hp;    public  int damage;    public int id;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Hero(){     }    public Hero(String string) {        name =string;    }     @Override    public String toString() {        return "Hero [name=" + name + "]";    }    public boolean isDead() {        // TODO Auto-generated method stub        return false;    }    public void attackHero(Hero h2) {        System.out.println(this.name+ " 正在攻擊 " + h2.getName());    }}

2.7 呼叫方法

public class TestReflection2 {    public static void main(String[] args) {        Hero1 hero1 = new Hero1();         try{           // 獲取這個名字叫做setName,引數型別是String的方法            Method m = hero1.getClass().getMethod("setName", String.class);           // 對h物件,呼叫這個方法                        m.invoke(hero1,"wistchen");            System.out.println(hero1.getName());        } catch (Exception e) {            e.printStackTrace();        }    } }class Hero1 {    public String name;    public float hp;    public int damage;    public int id;     public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Hero1(){     }    public Hero1(String string) {        name =string;    }     @Override    public String toString() {        return "Hero1 [name=" + name + "]";    }    public boolean isDead() {        // TODO Auto-generated method stub        return false;    }    public void attackHero(Hero h2) {        // TODO Auto-generated method stub     } }

學習參考來自:

B站狂神說

HOW2J.CN

4
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • web前端HTML高頻面試題