Java中的注解和反射實例詳解
一、注解
注解(Annotation): 從jdk5.0開始引進(jìn),可以對程序進(jìn)行解釋或被其他程序讀取。
注解格式:"@注釋名",并可以添加一些參數(shù)。
例:@MyAnnotation(value=‘value')
1、內(nèi)置注解
@override: 用于修飾方法,表示該方法聲明是重寫或?qū)崿F(xiàn)一個父類的方法
@Deprecated: 用于修飾方法、屬性、類,表示已過時不建議使用的
@SuppressWarnings: 用于抑制編譯時的警告信息
2、元注解
作用:用于注解其他注解
@Target: 用于描述注解的適用范圍
例:@Target(ElementType.ANNOTATION_TYPE) 適用范圍為注解定義
@retention: 表示需要在什么級別保存該注解信息
SOURCE - 源碼級別
CLASS - class級別
RUNTIME - 運(yùn)行級別
SOURCE < CLASS < RUNTIME
例:@Retention(RetentionPolicy.RUNTIME) 此注解運(yùn)行時有效
@Documented: 表示是否將注解生成在Javadoc中
@Inherited: 表示子類可以繼承父類的注解
3、自定義注解
注解定義:@interface+注解名
@Target(ElementType.METHOD)//作用在方法上
@Retention(RetentionPolicy.RUNTIME)//運(yùn)行時有效
@interface Myannotation1{
//注解的參數(shù):參數(shù)類型 + 參數(shù)名();
String Parameter1() ;
int Parameter2() default -1; //默認(rèn)值為-1代表不存在
}
@Target(ElementType.METHOD)//作用在方法上
@Retention(RetentionPolicy.SOURCE )//源碼中有效
@interface Myannotation2{
String Value() ;//只有一個參數(shù)時,參數(shù)名用Value
}
測試:
//有默認(rèn)值的參數(shù)可以不填沒有默認(rèn)值的參數(shù)必填,并且參數(shù)填寫沒有順序
@Myannotation1(Parameter1 = "Parameter1 ")
//參數(shù)定義為Value時,前面的"Value = "可以省略
@Myannotation2("Value")
public void test01(){
}
二、反射
反射(Reflection)是java被視為動態(tài)語言的關(guān)鍵,反射機(jī)制允許程序在執(zhí)行期借助于Reflection API取得任何類的內(nèi)部信息,并能直接操作任意對象的內(nèi)部屬性及方法。
優(yōu)缺點(diǎn):具有靈活性但是效率較低。
Class c = Class.forName(java.lang.String)
1、Class類
某個類的屬性、方法和構(gòu)造器、某個類實現(xiàn)了哪些接口,JRE都為其保留了一個不變的Class類型的對象,同一個類的所有對象共享同一個Class對象。
Class類具有以下特點(diǎn):
- Class本身也是一個類
- Class對象只能由系統(tǒng)建立對象
- 一個加載的類在JVM中只會有一個Class實例
- 一個Class對象對應(yīng)的是一個加載到JVM中的一個class文件
- 每個類的實例都會記得自己是由哪個Class實例所生成
- 通過Class可以完整地得到一個類中的所有被加載結(jié)構(gòu)
- Class類是Reflection的根源,針對任何想動態(tài)加載、運(yùn)行的類,唯有先獲得相應(yīng)的Class對象
Class類的常用方法:
| 方法名 | 功能說明 |
|---|---|
| static Class.forName(String name) | 返回指定類名name的Class對象 |
| Object newInstance() | 調(diào)用缺省構(gòu)造函數(shù),返回Class對象的一個實例 |
| getName() | 返回此Class對象所表示的實體(類、接口、數(shù)組類或void)的名稱 |
| Class getSuperClass() | 返回當(dāng)前Class對象的父類Class對象 |
| Class[] getinterfaces() | 返回當(dāng)前Class對象的接口 |
| Class Loader getClassLoader() | 返回該類的類加載器 |
| Constructor[] getConstructors() | 返回一個包含某些Constructor對象的數(shù)組 |
| Method getMethod(String name ,Class T) | 返回一個Method對象,此對象的形參類型為paramType |
| Field[] getDeclaredFields | 返回Field對象的一個數(shù)組 |
2、通過反射獲取Class對象:
所有的類都可以通過反射獲取其Class對象。
下面通過例子列舉獲取類的Class對象的三種方式:
//新建Person類
class Person{
String name;
int age;
int id;
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;
}
}
//測試
public class test02 {
public static void main(String[] args) throws ClassNotFoundException {
Person person = new Person();
//方式一、通過包名獲取
Class class1 = Class.forName("com.reflection.Person");
System.out.println(class1.hashCode());
//方式二、通過對象獲取
Class class2 = person.getClass();
System.out.println(class3.hashCode());
//方式三、通過類獲取
Class class3 = Person.class;
System.out.println(class3.hashCode());
}
}
輸出結(jié)果:

結(jié)論:三種方式獲取的Class對象為同一個。
3、獲取類的運(yùn)行時結(jié)構(gòu)
public class test03 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class c1 = Class.forName("com.reflection.Person");
//獲得類的名字
String name = c1.getName();//獲得包名加類名
String simpleName = c1.getSimpleName();//獲得類名
//獲得類的屬性
Field[] fields = c1.getFields();//獲得類的所有公有屬性
Field[] declaredFields = c1.getDeclaredFields();//獲得類的所有屬性
Field field = c1.getField(name);//獲得類的指定公有屬性
Field declaredField = c1.getDeclaredField(name);//獲得類的指定屬性(所有類型均可)
//獲得類的方法
Method[] method = c1.getMethods();//獲得本類及其父類的所有公有方法
Method[] declaredMethods = c1.getDeclaredMethods();//獲得本類的所有方法
Method getName = c1.getMethod("getName", null);//獲取指定方法(本類及其父類的所有公有方法)
Method setName = c1.getDeclaredMethod("setName", String.class);//獲取指定方法(本類的所有方法)
//獲得類的構(gòu)造器
Constructor[] constructors = c1.getConstructors();//獲取所有公有構(gòu)造器
Constructor[] declaredConstructors = c1.getDeclaredConstructors();//獲取所有構(gòu)造器
Constructor constructor = c1.getConstructor(String.class, int.class);//獲取指定公有構(gòu)造器
Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class);//獲取指定構(gòu)造器
}
}
4、通過反射構(gòu)造對象
public class Test04 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//獲得Class對象
Class c1 = Class.forName("com.reflection.Person");
//通過反射創(chuàng)建對象
Person person = (Person)c1.newInstance();//本質(zhì)上是調(diào)用了無參構(gòu)造器
Constructor constructor = c1.getDeclaredConstructor(String.class,int.class);//獲取有參構(gòu)造器
Person person2 = (Person) constructor.newInstance("name",18);//調(diào)用有參構(gòu)造器創(chuàng)建對象
//通過反射調(diào)用普通方法
Method setName = c1.getDeclaredMethod("setName", String.class);//獲取方法
setName.invoke(person,"name");//通過invoke調(diào)用方法
//通過反射操作屬性
Field name = c1.getDeclaredField("name");//獲取name屬性
name.setAccessible(true);//關(guān)閉安全檢測,關(guān)閉后可以訪問私有屬性(true為關(guān)閉,false為打開,默認(rèn)是false)
name.set(person,"lalala");//設(shè)置屬性的值
}
}
5、通過反射獲取注解的信息
創(chuàng)建類和注解
@Testclass("db_Student2")//類注解
//創(chuàng)建學(xué)生類
class Student2{
@Testfield(columnname = "name",type = "varchar",length = 20)//屬性注解
String name;
@Testfield(columnname = "age",type = "int",length = 3)
int age;
@Testfield(columnname = "ID",type = "int",length = 10)
int ID;
public Student2() {
}
public Student2(String name, int age, int ID) {
this.name = name;
this.age = age;
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 int getID() {
return ID;
}
public void setID(int ID) {
this.ID = ID;
}
}
//類的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Testclass{
String value();
}
//屬性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Testfield{
String columnname();
String type();
int length();
}
測試
public class test05 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("com.zjrcu.reflection.Student2");
//通過反射獲得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//通過反射獲得注解value的值
Testclass testclass = (Testclass)c1.getAnnotation(Testclass.class);
String value = testclass.value();
System.out.println(value);
//獲取類中指定注解的value值
Field f = c1.getDeclaredField("name");
Testfield testfield = (Testfield) f.getAnnotation(Testfield.class);
System.out.println(testfield.columnname());
System.out.println(testfield.length());
System.out.println(testfield.type());
}
}
總結(jié)
到此這篇關(guān)于Java中的注解和反射的文章就介紹到這了,更多相關(guān)Java注解和反射內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
spring security登錄成功后跳轉(zhuǎn)回登錄前的頁面
這篇文章主要介紹了spring security登錄成功后跳轉(zhuǎn)回登錄前的頁面,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09
Java數(shù)據(jù)結(jié)構(gòu)之二叉查找樹的實現(xiàn)
二叉查找樹(亦稱二叉搜索樹、二叉排序樹)是一棵二叉樹,且各結(jié)點(diǎn)關(guān)鍵詞互異,其中根序列按其關(guān)鍵詞遞增排列。本文將通過示例詳細(xì)講解二叉查找樹,感興趣的可以了解一下2022-03-03

