- 元註解:負責註解其他的註解,Java定義了4個標準的meta-annotation型別
@Target:用於描述註解的適用範圍
@Retention:表示需要再什麼級別儲存該註解資訊,用於描述註解的生命週期(source<class<runtime)
@Document:該註解江北包含在javadoc中
@Inherited:說明子類可以繼承父類中的註解
- 自定義註解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation {
//型別 引數名() 預設值
String value() default "";
}
- 動態語言:就是在執行程式碼時可以根據某些條件改變自身結構
靜態語言:執行是結構不可變,如java,c++
但java有一定的動態性,可以利用反射機制獲得類似動態語言的特性,使程式設計更加靈活
- 獲取Class物件的三種方式
//一個Person類
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
}
//透過三種方式獲得Class物件
import domain.Person;
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
//1.Class.forName("全類名")
Class cls0 = Class.forName("domain.Person");
System.out.println(cls0);
//2.類名.class
Class cls1 = Person.class;
System.out.println(cls1);
//3.物件.getClass()
Person p = new Person();
Class cls2 = p.getClass();
System.out.println(cls2);
}
}
- class,interface,[],enum,annotation,primitive type,void都有Class物件
- 類載入分為三個部分:載入,連線,初始化
載入:將.class檔案的二進位制位元組流讀入記憶體,並在堆記憶體中為之建立Class物件,作為.class進入記憶體後的資料的訪問入口。
為何取消方法區?
方法區儲存類的後設資料資訊,我們不清楚一個程式到底有多少類需要被載入,且方法區位於JVM記憶體,我們不清楚需要給方法區分配多大記憶體,太小容易PermGen OOM,太大,在觸發Full GC時又極其影響效能,同時還存在一些記憶體洩露的問題
連線:分為三個階段,驗證,準備,解析
驗證:為了保證載入進來的位元組流符合JVM的規範,不會對JVM有安全性問題。
準備:準備階段的主要任務是為類的類變數開闢空間並賦預設值。
解析:該階段的主要職責為將Class在常量池中的符號引用轉變為直接引用,此處針對的是靜態方法及屬性和私有方法與屬性。
初始化:該階段主要是為類的類變數初始化值的,在宣告類變數時,直接給變數賦值或者在靜態初始化塊為類變數賦值
- 反射的作用:動態建立物件,動態操作屬性,動態呼叫方法
- Class類的常用方法:
getFields()—— 獲得類的public型別的屬性;getDeclaredFields()—— 獲得類的所有屬性;getField(String name)—— 獲得類的指定屬性;
getMethods()—— 獲得類的public型別的方法;getMethod (String name,Class [] args)—— 獲得類的指定方法;
getConstrutors()—— 獲得類的public型別的構造方法;getConstrutor(Class[] args)—— 獲得類的特定構造方法;
newInstance()—— 透過類的無參構造方法建立物件;
getName()—— 獲得類的完整名字;
getPackage()—— 獲取此類所屬的包;
getSuperclass()—— 獲得此類的父類對應的Class物件