Java反射詳解

1.三種形式獲取Class對象

Class<?>clazz = Class.forName("com.test.Test01");//根據名稱獲取
Class clazz1 = Test01.class;
Class clazz2 =new Test01().getClass();

//在同一個虛擬機中運行的類只能有一個class,所以打印結果是一樣的
System.out.println(clazz1.hashCode()+","+clazz.hashCode()+","+clazz2.hashCode());

2.四種方式創建實例

2.1 通過Class創建實例
Studentstu1 = (Student)clazz.newInstance();

2.2 通過構造方法創建實例
Constructor con[]=clazz.getConstructors();
for(Constructor cons:con){
try {
Student stu1 = (Student)cons.newInstance();
} catch (Exceptione) {
e.printStackTrace();
}
}

2.3 克隆的方式
Student stu2 =Studentstu.clone(); 

2.4 序列化和反序列化
Studentstu =new Student();
stu.setAge(1);
stu.setName("1");
Filefile =new File("d:\\student.txt");
//序列化過程
FileOutputStreamfos =new FileOutputStream(file);
ObjectOutputStreamoos =new ObjectOutputStream(fos);
oos.writeObject(stu);
//反序列化過程
FileInputStreamfis =new FileInputStream(file);
ObjectInputStreamois =new ObjectInputStream(fis);
Studentstu1 = (Student)ois.readObject();
System.out.println(stu1);


3.常用api
clazz.getDeclaredClasses()返回所有的內部類
getInterfaces()返回所有接口Class數組
getSuperClass()返回父類的Class實例,如果當前類是基本數據類型,或者void,或者Object,就返回null
getModifiers()獲得修飾符 返回int 右移加上取模的方式
isMemberClass()是不是內部類
isInterface()是不是接口
isArray()是不是數組

4.屬性(java.lang.reflect.Field)

4.1 基本操作
getFields() 獲取當前類以及父類裏面所有public屬性
getField(String fieldName)根據屬性名稱,獲取Field實例。如果獲取的屬性超出getFields()這個範圍,會拋出NoSuchFieldException異常。
getDeclaredFields()獲取當前類的所有屬性,包含private,protected,缺省的。但不包括其父類或者接口裏面的任何屬性.
getDeclaredField(String fieldName)根據屬性名稱,獲取Field實例。如果獲取的屬性超出getDeclaredFields ()這個範圍,會拋出NoSuchFieldException異常。

4.2 注意

在操作私有屬性時需要調用這個方法
field.setAccessible(true);//跳過安全檢測,並且效率快,不然操作私有屬性會拋出SecurityException異常

注意獲取屬性只能獲取本類的屬性,下面這個封裝可以遞歸獲取父類的屬性
private FieldgetFieldByFieldName(Class<?>clazz,StringfieldName){
try {
return clazz.getDeclaredField(fieldName);
} catch (NoSuchFieldExceptione) {
return getFieldByFieldName(clazz,fieldName);
} catch (SecurityExceptione) {
}
return null;
}

4.3 屬性賦值和獲取
public void getField()throws IllegalArgumentException, IllegalAccessException{
User user =new User("張三","18");
Field[] fields = User.class.getDeclaredFields();
for (Fieldfield :fields) {
field.setAccessible(true);
field.set(user,"李四");//設置屬性值
Object value =field.get(user);//獲取屬性值
System.out.println(value);
}
}





5.方法(java.lang.reflect.Method)

5.1基本操作
getMethods()能獲取本身及其所有父類的public方法。
getMethod (StringmethodName,Class paramaterTypes)根據方法和參數列表名稱,獲取Method實例。如果獲取的方法超出getMethods()這個範圍,會拋出NoSuchMethodException異常。
 
getDeclaredMethods()能獲取本身所有方法。包含private,protected,缺省的所有方法。但不包括父類的任何方法。
getDeclaredMethod(String fieldName,Class paramaterTypes)根據方法和參數列表名稱,獲取Method實例。如果獲取的方法超出getDeclaredMethods ()這個範圍,會拋出NoSuchMethodException異常。

5.2 調用方法
Class<?>clazz = User.class;
Methodmethod =clazz.getDeclaredMethod("getName",null);//參數名,參數類型,如果無參就傳空
Methodmethod2 =clazz.getDeclaredMethod("setName", String.class);
method2.setAccessible(true);
//調用方法
method2.invoke(clazz.newInstance(),"張三");//類的實例,參數值

6.構造方法 (java.lang.reflect.Constructor)

6.1 基本操作
getConstructors() 能取得所有public的構造方法
getDeclaredConstructors()能取得所有的構造方法,包含private,protected,缺省的。
newInstance(paramaterTypes)調用相應的public構造方法,生成實例
如果要訪問private的構造方法,設置constructor.setAccessable(true)來解決。

6.2 構成方法賦值
Constructor<User>constructor = User.class.getDeclaredConstructor(String.class,String.class);
constructor.setAccessible(true);
Useruser =constructor.newInstance("張三","18");

7.調用靜態方法
//調用靜態的方法
Methodmethod = User.class.getMethod("test",String.class);
method.invoke(null,"張三");//靜態方法不需要實例
//調用靜態屬性
Fieldfield = User.class.getField("WIDTH");
Objectwidth =field.get(null);//不需要實例
field.set(null, 600);
System.out.println(width+","+field.get(null));

8.性能測試
Useruser =new User();
long start = System.currentTimeMillis();
for (int i = 0; i < 1000000;i++) {
user.setName("張三");
}
long end = System.currentTimeMillis();
System.out.println("普通調用耗時"+(end-start)+"毫秒");
Class clazz = User.class;
start = System.currentTimeMillis();
Fieldfield =null;
for (int i = 0; i < 1000000;i++) {
field =clazz.getField("name");
field.set(user,"張三");
}
end = System.currentTimeMillis();
System.out.println("反射調用,沒有跳過安全檢測耗時"+(end-start)+"毫秒");
start = System.currentTimeMillis();
for (int i = 0; i < 1000000;i++) {
field =clazz.getField("name");
field.setAccessible(true);
field.set(user,"張三");
}
end = System.currentTimeMillis();
System.out.println("反射調用,跳過安全檢測耗時"+(end-start)+"毫秒");

9.操作泛型(java.lang.reflect.Type)

9.1基本操作
ParameterizedType 表示參數化類型,如 Collection<String>。
GenericArrayType 表示一種數組類型,其組件類型爲參數化類型或類型變量。
TypeVariable 是各種類型變量的公共高級接口。
WildcardType 表示一個通配符類型表達式,如?? extends Number? super Integer

9.2 獲取方法上的註解
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 void getType()throws Exception{
System.out.println("------獲取方法參數的泛型-------");
Class clazz =this.getClass();
Method method =clazz.getMethod("test01", Map.class,List.class);
Type[] types =method.getGenericParameterTypes();//獲取方法參數的泛型
for (TypeparamType :types) {
System.out.println("#"+paramType);
if (paramType instanceof ParameterizedType) {
Type[] typeArguments = ((ParameterizedType)paramType).getActualTypeArguments();
for (TypetypeArgument :typeArguments) {
System.out.println(typeArgument);//獲取具體的泛型
}
}
}
System.out.println("------獲取方法返回的泛型-------");
Method method2 =clazz.getMethod("test02",null);
Type returnType =method2.getGenericReturnType();//獲取方法返回的泛型
if (returnType instanceof ParameterizedType) {
Type[] typeArguments = ((ParameterizedType)returnType).getActualTypeArguments();
System.out.println("#"+returnType);
for (TypetypeArgument :typeArguments) {
System.out.println(typeArgument);//獲取具體的泛型
}
}
}
9.3 獲取當前類上泛型的類型(針對Hibernate)
只要XxxDao繼承了BaseDao那麼增刪改查一個都不需要寫。
public class BaseDao<T> {
//獲取
public T get(Serializableid){
Session session = SessionFactoryUtil.getSessionFactory().openSession();
session.getTransaction().begin();
T obj =(T)session.get(getModleClass(),id);
session.getTransaction().commit();
session.close();
return obj;
}
//增加
//刪除
//修改
public Class getModleClass(){
//獲取當前的T的類型
ParameterizedType pt = (ParameterizedType)this.getClass().getGenericSuperclass();
Class<T> clazz =(Class<T>)pt.getActualTypeArguments()[0] ;
return clazz;
}
}
public class StudentDaoextends BaseDao<StudentBean> {
}
發佈了26 篇原創文章 · 獲贊 8 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章