1. 程式人生 > 其它 >註解、反射

註解、反射

註解

Annotation(註解)

(1)作用:可以被其他程式(比如:編譯器)讀取

(2)格式:“@註釋名”。在程式碼中存在的,還可新增一些引數值

如:@SuppressWarnings(value=”unchecked”) -- 壓制警告

(3)可以附加在package(包),class(類),method(方法),field等上面。可以通過反射機制實現對這些元資料的訪問

內建註釋---(常見)

(1)@Override(方法重寫)

(2)@SuppressWarnings(壓制警告)

(3)Deprecated(過時)

元註釋

(1)元註釋作用:負責註解其他註解

@Target

:用於描述註解的使用範圍

@Retention:表示註釋在什麼地方還有效,用於描述註解的生命週期(有三個值:SOURCE<CLASS<RUNTIME)

@Document:說明該註解將包含在javadoc中

@Inherited:說明子類可以繼承父類中的註解

範例:(註解)

package collection;
import java.lang.annotation.*;
// 測試元註解
public class Demo11 {

@MyAnnotation // 使用註解
public void text(){}
}

// @Target 表示註解可以用在什麼地方,METHOD(方法),TYPE(類)
@Target(value = {ElementType.METHOD,ElementType.TYPE})

// @Retention 表示註解在什麼地方有效(有三個值RUNTIME,CLASS,SOURCE)
@Retention(value = RetentionPolicy.RUNTIME)

// @Document 表示是否將註解生成JAVAdoc中
@Documented

// @Inherited 子類可以繼承父類的註解
@Inherited

// 定義一個註解
@interface MyAnnotation{}

自定義註解

(1)使用@Interface自定義註解,自動繼承java.lang.annotation.Annotation介面

格式:@interface 註解名{定義內容}

(2)返回值型別就是引數的型別(返回值只能是基本資料,Class,String,enum)

(3)註解引數:引數型別 引數名();

(4)如果註解只有一個引數,建議引數名使用value,呼叫註解時,可不用寫引數名,直接寫引數

範例:(自定義註解)
package text;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

public class Text3 {
// 註解可以顯示賦值,如果沒有預設值,必須給註解賦值
@MyAnnotation2(school = {"南昌大學,北京大學"})
public void text(){}

@MyAnnotation3("小輝")
public void text2(){}
}

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
// 註解的引數:引數型別+引數名();
String name() default "" ; //預設值
int age() default 0;
int id() default -1; //如果預設值為-1,表示不存在
String[] school();
}

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation3{
// 如果註解只有一個引數,建議引數名使用value,呼叫註解時,可不用寫引數名,直接寫引數
String value() ;
}

反射

(1)只要元素型別與維度一樣,就是同一個Class

範例:
package collection;
import java.lang.annotation.ElementType;

public class Deom13 {
public static void main(String[] args) {
Class c1 = Object.class; //類
Class c2 = Comparable.class; //介面
Class c3 = String[].class; //一維陣列
Class c4 = int[][].class; //二維陣列
Class c5 = Override.class; //註解
Class c6 = ElementType.class; //列舉
Class c7 = Integer.class; //基本資料型別
Class c8 = void.class; //void
Class c9 = Class.class; //Class
}
}

類載入與ClassLoader

(1)載入——連結——初始化

注:通過反射獲取執行時類的完整結構

Field、Method、Constructor、Superclass、Interface、Annotation

注:不能直接操作私有屬性或方法,操作私有屬性或方法時,需要關閉程式的安全檢測屬性或方法setAccessible(true)

setAccessible

(1)Method和Filed、Constructor物件都有setAccessible()方法

(2)setAccessible作用是啟動和禁用安全檢查的開頭

(3)引數值為true,表示原本無法訪問的私有成員也可以訪問

範例:
package collection;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Demo14 {
public static void main(String[] args) throws Exception {
Class c1 = Class.forName("collection.Son");
Object obj=c1.newInstance();
Field name = c1.getDeclaredField("name");

// 不能直接操作私有屬性,需要關閉程式的安全檢測,屬性或方法setAccessible(true)
name.setAccessible(true);
name.set(obj,"小藍");
System.out.println(name.get(obj));
}
}

class Son{
private String name;
private int age;
public Son() { }
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}

獲取泛型資訊

(1)ParameterizedType:表示一種引數化型別

(2)GenericArrayType:表示一種元素型別是引數型別或型別變數的陣列型別

(3)TypeVariable:是各種型別變數的公共父介面

(4)WildcardType:代表一種萬用字元型別表示式

getGenericExceptionTypes(); // 獲得泛型異常資訊 getGenericParameterTypes(); // 獲得泛型引數資訊 getGenericReturnType(); // 獲得泛型返回值資訊

範例:
package collection;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

public class Demo15 {
public void test01(Map<String,Integer> map, List<String> list){
System.out.println("test01");
}

public Map<String,Integer> test02(){
System.out.println("test02");
return null;
}




public static void main(String[] args) throws NoSuchMethodException {
Method method = Demo15.class.getDeclaredMethod("test01", Map.class, List.class);
Type[] getGenericParameterTypes =method.getGenericParameterTypes();
// 獲得泛型引數資訊

for (Type getGenericParameterType : getGenericParameterTypes) {
System.out.println("## "+getGenericParameterType);
// 獲得泛型引數資訊

if (getGenericParameterType instanceof ParameterizedType){
// 判斷泛型引數是否是引數化型別
Type[] actualTypeArguments = ((ParameterizedType) getGenericParameterType).getActualTypeArguments(); // 取得真實引數型別
// 強轉為引數化型別
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
System.out.println("=====================");
method=Demo15.class.getMethod("test02");
Type genericReturnType = method.getGenericReturnType();
// 取得返回值引數型別
if (genericReturnType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
}

獲取註解資訊

(1)獲得註解:Class類物件.getAnnotations()

(2)獲得指定的註解:Class類物件.getAnnotation(註解名.class)

範例:(通過反射獲得註解)
package collection;
import java.lang.annotation.*;
public class Demo16 {
public static void main(String[] args) throws Exception {
Class c1 = Class.forName("collection.Student");

// 通過反射獲得註解
Annotation[] annotations=c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation); //@collection.Table(value=db_student)
}

// 獲得註解的value的值
Table table = (Table) c1.getAnnotation(Table.class);// 獲得類指定的註解
String value = table.value();
System.out.println(value); // db_student

// 獲得類指定的註解
java.lang.reflect.Field name = c1.getDeclaredField("name");
Field annotation = name.getAnnotation(Field.class); // 獲得指定的註解
System.out.println(annotation.columnName()); //db_name
System.out.println(annotation.type()); //varchar
System.out.println(annotation.length()); //3
}
}








@Table("db_student")
class Student{
@Field(columnName = "db_id",type ="int",length = 10)
private int id;
@Field(columnName = "db_age",type ="int",length = 10)
private int age;
@Field(columnName = "db_name",type ="varchar",length = 3)
private String name;

public Student() { }
}

// 類名的註解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Table{
String value();
}

// 屬性的註解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Field{
String columnName();
String type();
int length();
}