注解
注解聲明
聲明一個(gè)注解類型
java中的所有的注解优炬,默認(rèn)實(shí)現(xiàn)Annotation接口:
聲明一個(gè)"class"不同的是授嘀,注解的聲明使用@interface關(guān)鍵字旷赖。一個(gè)注解的聲明如下:
public @interface Lance{
}? ? ?
元注解
在定義注解時(shí)给郊,注解類也能夠使用其他的注解聲明菩浙。對注解類型進(jìn)行注解類,我們稱之為 meta-annotation(元注解)睬愤,一般片仿,我們在定義自定義注解時(shí),需要指定的元注解有兩個(gè):
@Target
注解標(biāo)記標(biāo)記另一個(gè)注解尤辱,以限制可以應(yīng)用注解的java元素類型砂豌。目標(biāo)注解指定以下元素類型之一作為其值:
@Retention
注解指定標(biāo)記注解的存儲(chǔ)方式:
RetentionPolicy.SOURCE - 標(biāo)記的注解僅保留在源碼級別中厢岂,并被編譯器忽略。
RetentionPolicy.CLASS - 標(biāo)記的注解在編譯時(shí)由編譯器保留阳距,但Java虛擬機(jī)(JVM)會(huì)忽略
RetentionPolicy.RUNTIME - 標(biāo)記的注解由JVM保留塔粒,因此運(yùn)行時(shí)環(huán)境可以使用它。
@Retention三個(gè)值中SOURCE < CLASS < RUNTIME ,即CLASS包含了SOURCE,RUNTIME包含SOURCE筐摘、CLASS卒茬。下文會(huì)接介紹他們的不同應(yīng)用場景。
注解類型元素
在上文元注解中咖熟,允許在使用注解時(shí)傳遞參數(shù)圃酵。我們也能讓自定義注解的主體包含annotation type element(注解類型元素)聲明,它們看起來很像方法馍管,可以定義可選的默認(rèn)值郭赐。
了解反射
反射之中包含了一個(gè)【反】字,所以了解反射我們先從【正】開始罗捎,
一般情況下我們使用某個(gè)類時(shí)必定知道它是什么類观谦,是用來做什么的。于是我們直接對這個(gè)類進(jìn)行實(shí)例話桨菜,之后使用這個(gè)類對象進(jìn)行操作豁状。
Shap shap = new Shap();
shap.geCorlor();
反射是開始并不知道我們要初始化的對象是什么,自然也無法使用new關(guān)鍵字來創(chuàng)建對象了雷激。這時(shí)候,我們使用JDK提供的反射API進(jìn)行反射調(diào)用告私。
Class shapeClass = Class.forName("com.example.use.Shape");
Shape shapeInst = (Shape) shapeClass.newInstance();
Log.i("TAG","init: "+shapeInst.toString());
舉例:通過反射獲取類的幾種方式
Date date =new Date();
Class da = date.getClass();
Class da2 = Date.class;
Class da3 = Class.forName("java.util.Date");
Date da4 = (Date) da3.newInstance();
da4.setDate(1);
反射就是在運(yùn)行時(shí)才知道要操作的類是什么屎暇,并且可以在運(yùn)行時(shí)獲取類的完整構(gòu)造,并調(diào)用對應(yīng)的方法驻粟。
// 獲取類所有構(gòu)造方法
Constructor[] constructors = da.getConstructors();
for (Constructor c : constructors){
Log.i("constructors","獲取類所有構(gòu)造方法: "+c);
}
//? ? ? 獲取某指定構(gòu)造方法
Constructor constructor = da.getConstructor(int.class,int.class,int.class);
Log.i("constructors","獲取某指定構(gòu)造方法:--- "+constructor);
try {
Date date1 = constructor.newInstance(1,2,3);
Log.i("constructors","time:--- "+date1.getTime());
}catch (InvocationTargetException e) {
e.printStackTrace();
}
反射獲取構(gòu)造方法根悼,并設(shè)置值
Method[] methods = date.getDeclaredMethods();
for (int i =0; i < methods.length; i++) {
Log.i("intMethod","intMethod: "+methods[i].getName());
}
Method setYear = date.getDeclaredMethod("setYear",int.class);
Date date1 = (Date) date.newInstance();
setYear.invoke(date1,1000);
Log.i("intMethod","intMethod: "+setYear+"---"+date1.getYear());
反射修改成員變量的值
public class Person {
private int age;
private Stringname;
public Person() {
}
public Person(int age) {
this.age = age;
}
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public Person(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Person person =new Person(333,"我");
Class cl = person.getClass();
Field fiAge = cl.getDeclaredField("age");
fiAge.setAccessible(true);
Object o = fiAge.get(person);
fiAge.set(person,222);//私有方法必須先設(shè)置為true
Log.i("person","setfield: "+person.getAge());
2022-10-09 00:48:40.872 3893-3893/com.example.myapplication I/person: setfield: 222