1. 程式人生 > 其它 >反射全紀錄(-)

反射全紀錄(-)

Java正射,即為通過例項物件訪問class物件;Java反射,即是通過class訪問物件的屬性和方法。

本篇文章,是反射的第一部分,筆者主要分享如下內容:

  • 反射獲取本類的私有屬性
  • 反射獲取父類的私有屬性
  • 反射獲取本類中非基本型別的私有屬性
  • 反射獲取泛型類的私有屬性
  • 反射獲取內部類的私有屬性

接下來,我們詳細介紹每個部分的內容:

  • 反射獲取本類的私有屬性

使用者類User是我們此次研究的主要物件,根據不同的場景,我們將其命名為User1,User2,User3...
根據本次場景,User1是單獨的類,相關程式碼如下:
`import lombok.Data;

@Data
public class User1 {
private Long id;
private String name;
private String descr;
}
`
其訪問測試方法如下:

`
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;

@Slf4j
public class ReflectClass {

public void reflectClass(Object object,Class clazz){
    try {
        for (Field field:clazz.getDeclaredFields()){
            //設定可訪問屬性
            field.setAccessible(true);
            Object fieldValue = field.get(object);
            log.info("fieldName:{},fieldValue:{}",field.getName(),fieldValue);
        }
    }catch (Exception e){
        e.printStackTrace();
    }

}

public static void main(String[] args) {
    User1 user1 = new User1();
    user1.setId(1L);
    user1.setName("perry");
    user1.setDescr("描述");
    ReflectClass reflectClass = new ReflectClass();
    reflectClass.reflectClass(user1, User1.class);
}

}
在測試方法中,clazz.getDeclaredFields() 獲取該類的所有宣告的屬性,包括public,private,protected等等.如果僅僅需要訪問private屬性, 可以通過field.getModifiers()`,進行區分,private在該方法下值為2,public為1,protected為4,static為8,final為16,synchronized為32,volatile為64,transient為128。

接下來,進入下個專題:

  • 反射獲取父類的私有屬性

我們常常會將很多實體類繼承一個基類,基類儲存相關審計欄位,比如createDate,createUser,updateDate,updateUser.
`import lombok.Data;
import java.util.Date;

@Data
public class BaseObject {
private Date createDate;
private Date updateDate;
private String createUser;
private String updateUser;
}
User類修改如下,import lombok.Data;

@Data
public class User2 extends BaseObject{
private Long id;
private String name;
private String descr;
}`

其實現方法如下:

public void reflectSuperClass(Object object,Class clazz){ try { clazz = clazz.getSuperclass(); if (clazz != null){ reflectClass(object,clazz); } }catch (Exception e){ e.printStackTrace(); } }

  • 反射獲取本類中非基本型別的私有屬性

本次,我們重構下之前的reflectClass()方法,如果其屬性不是基本型別,則遞迴獲取其值
本場景下,使用者持有Department屬性,相實體物件如下:
`import lombok.Data;

@Data
public class Department {
private Long id;
private Long pid;
private String name;
private String descr;
}
`
使用者類如下:

`
import lombok.Data;

@Data
public class User3 {
private Long id;
private String name;
private String descr;

private Department department;

}
其實現訪問類如下:public void reflectClass(Object object,Class clazz){
try {
for (Field field:clazz.getDeclaredFields()){
//設定可訪問屬性
field.setAccessible(true);
// log.info("modifier:{}",field.getModifiers());
Object fieldValue = field.get(object);
if (fieldValue != null && !isBaseType(fieldValue)){
reflectClass(fieldValue,fieldValue.getClass());
}
log.info("fieldName:{},fieldValue:{}",field.getName(),fieldValue);
}
}catch (Exception e){
e.printStackTrace();
}
}
private boolean isBaseType(Object object) {
if (object instanceof String
|| object instanceof Boolean
|| object instanceof Integer
|| object instanceof Double
|| object instanceof Date) {
return true;
}
return false;
}`

  • 反射獲取泛型類的私有屬性

實現同 獲取本類中非基本型別的私有屬性。只不過其使用者類定義如下:
`import lombok.Data;
@Data
public class User4 {
private Long id;
private String name;
private String descr;

private T data;

}
`

測試方法如下:
private static void testUser4(){ log.info("test 反射獲取泛型類的私有屬性 start .."); User4<Department> user4 = new User4<>(); user4.setName("perry"); Department department = new Department(); department.setName("技術部"); user4.setData(department); ReflectClass reflectClass = new ReflectClass(); reflectClass.reflectClass(user4, User4.class); log.info("test 反射獲取泛型類的私有屬性 end .."); }

  • 反射獲取內部類的私有屬性

內部類獲取屬性的方法,同獲取本類中私有屬性的方法。只不過測試方式上有區別:
因為內部類存在下列特徵:

  1. 在內部類中可以隨意使用外部類的成員方法以及成員變數。
    2.要在外部類中例項化內部類物件的引用。
    3.使用this關鍵字獲取內部類與外部類物件的引用。

也就是說,呼叫的時候,傳遞的時內部類的物件,而非外部類物件,如果是外部類物件,它就找不到內部類物件了。

該場景下使用者類如下宣告:

`import lombok.Data;

@Data
public class User5 {
private Long id;
private String name;
private String descr;

@Data
class Role {
    private String roleName;
}

}
`

其測試方法如下:

`private static void testUser5(){
log.info("test 反射獲取內部類的私有屬性 start ..");
User5 user5 = new User5();
user5.setName("perry");
//內部類
User5.Role role = user5.new Role();
role.setRoleName("管理員");

    ReflectClass reflectClass = new ReflectClass();
    //注意呼叫物件
    reflectClass.reflectClassWithInnderClass(role, User5.Role.class);
    log.info("test 反射獲取內部類的私有屬性 end ..");
}

`

以上介紹了關於反射的一些場景,以及一些通用的獲取屬性的方法,相關程式碼比較詳細。
如有需要全部程式碼,可與我留言。