一、注解
注解(Annotation): 從jdk5.0開始引進,可以對程式進行解釋或被其他程式讀取,
注解格式:"@注釋名",并可以添加一些引數,
例:@MyAnnotation(value=‘value’)
1、內置注解
@override: 用于修飾方法,表示該方法宣告是重寫或實作一個父類的方法
@Deprecated: 用于修飾方法、屬性、類,表示已過時不建議使用的
@SuppressWarnings: 用于抑制編譯時的警告資訊
2、元注解
作用:用于注解其他注解
@Target: 用于描述注解的適用范圍
例:@Target(ElementType.ANNOTATION_TYPE) 適用范圍為注解定義
@retention: 表示需要在什么級別保存該注解資訊
SOURCE - 原始碼級別
CLASS - class級別
RUNTIME - 運行級別
SOURCE < CLASS < RUNTIME
例:@Retention(RetentionPolicy.RUNTIME) 此注解運行時有效
@Documented: 表示是否將注解生成在Javadoc中
@Inherited: 表示子類可以繼承父類的注解
3、自定義注解
注解定義:@interface+注解名
@Target(ElementType.METHOD)//作用在方法上
@Retention(RetentionPolicy.RUNTIME)//運行時有效
@interface Myannotation1{
//注解的引數:引數型別 + 引數名();
String Parameter1() ;
int Parameter2() default -1; //默認值為-1代表不存在
}
@Target(ElementType.METHOD)//作用在方法上
@Retention(RetentionPolicy.SOURCE )//原始碼中有效
@interface Myannotation2{
String Value() ;//只有一個引數時,引數名用Value
}
測驗:
//有默認值的引數可以不填沒有默認值的引數必填,并且引數填寫沒有順序
@Myannotation1(Parameter1 = "Parameter1 ")
//引數定義為Value時,前面的"Value = "可以省略
@Myannotation2("Value")
public void test01(){
}
二、反射
反射(Reflection)是java被視為動態語言的關鍵,反射機制允許程式在執行期借助于Reflection API取得任何類的內部資訊,并能直接操作任意物件的內部屬性及方法,
優缺點:具有靈活性但是效率較低,
Class c = Class.forName(java.lang.String)
1、Class類
某個類的屬性、方法和構造器、某個類實作了哪些介面,JRE都為其保留了一個不變的Class型別的物件,同一個類的所有物件共享同一個Class物件,
Class類具有以下特點:
- Class本身也是一個類
- Class物件只能由系統建立物件
- 一個加載的類在JVM中只會有一個Class實體
- 一個Class物件對應的是一個加載到JVM中的一個class檔案
- 每個類的實體都會記得自己是由哪個Class實體所生成
- 通過Class可以完整地得到一個類中的所有被加載結構
- Class類是Reflection的根源,針對任何想動態加載、運行的類,唯有先獲得相應的Class物件
Class類的常用方法:
| 方法名 | 功能說明 |
|---|---|
| static Class.forName(String name) | 回傳指定類名name的Class物件 |
| Object newInstance() | 呼叫預設建構式,回傳Class物件的一個實體 |
| getName() | 回傳此Class物件所表示的物體(類、介面、陣列類或void)的名稱 |
| Class getSuperClass() | 回傳當前Class物件的父類Class物件 |
| Class[] getinterfaces() | 回傳當前Class物件的介面 |
| Class Loader getClassLoader() | 回傳該類的類加載器 |
| Constructor[] getConstructors() | 回傳一個包含某些Constructor物件的陣列 |
| Method getMethod(String name ,Class T) | 回傳一個Method物件,此物件的形參型別為paramType |
| Field[] getDeclaredFields | 回傳Field物件的一個陣列 |
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());
}
}
輸出結果:

結論:三種方式獲取的Class物件為同一個,
3、獲取類的運行時結構
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);//獲取指定方法(本類的所有方法)
//獲得類的構造器
Constructor[] constructors = c1.getConstructors();//獲取所有公有構造器
Constructor[] declaredConstructors = c1.getDeclaredConstructors();//獲取所有構造器
Constructor constructor = c1.getConstructor(String.class, int.class);//獲取指定公有構造器
Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class);//獲取指定構造器
}
}
4、通過反射構造物件
public class Test04 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//獲得Class物件
Class c1 = Class.forName("com.reflection.Person");
//通過反射創建物件
Person person = (Person)c1.newInstance();//本質上是呼叫了無參構造器
Constructor constructor = c1.getDeclaredConstructor(String.class,int.class);//獲取有參構造器
Person person2 = (Person) constructor.newInstance("name",18);//呼叫有參構造器創建物件
//通過反射呼叫普通方法
Method setName = c1.getDeclaredMethod("setName", String.class);//獲取方法
setName.invoke(person,"name");//通過invoke呼叫方法
//通過反射操作屬性
Field name = c1.getDeclaredField("name");//獲取name屬性
name.setAccessible(true);//關閉安全檢測,關閉后可以訪問私有屬性(true為關閉,false為打開,默認是false)
name.set(person,"lalala");//設定屬性的值
}
}
5、通過反射獲取注解的資訊
創建類和注解
@Testclass("db_Student2")//類注解
//創建學生類
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());
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/265836.html
標籤:AI
