通过反射和缓存区对一个类中的私有属性,私有方法进行设值,取值操作

来源:互联网 发布:惠州网络英才网 编辑:程序博客网 时间:2024/06/07 00:15

今天做项目的时候遇到一个问题,当实体类User里属性和get,set方法全是私有的,我们要怎么对其中的属性,和方法进行操作。我们知道一般的new对象是肯定行不通的。

        现有两种方法来解决这个问题,其中一种方法是我们熟悉的反射操作,还有一个方法便是利用缓存区StringBuilder或者StringBuffer配合构造方法来实现。

/** * 用户表 * @author Aaron * */public class User {private Integer userId;   //用户编号private String name;     //真实姓名private String passWord; //密码private Integer id;   //密保编号private String passWordQuestion;  //密保问题答案private String idCard;  //身份证private String phoneNumber;  //手机号private String email;  //邮箱private String birthday;  //生日private String sex;  //性别private String url;  //用户头像private String personAddress;  //个人地址private String workAddress;  //工作地址private Integer Status;  //账号状态private Integer roleId;  //角色编号public User() {    }public User(User user, StringBuilder sb, String[] flag) {    for (int i = 0; i < flag.length; i++) {            if("id".equals(flag[i])) {                sb.append(user.userId + ";");            }else if("name".equals(flag[i])) {                sb.append(user.name + ";");            }else if("password".equals(flag[i])) {                sb.append(user.passWord);            }else {                sb.append("");            }        }}public User(Integer userId, String name, String passWord) {        super();        this.userId = userId;        this.name = name;        this.passWord = passWord;    }    private Integer getUserId() {return userId;}private void setUserId(Integer userId) {this.userId = userId;}private String getName() {return name;}private void setName(String name) {this.name = name;}private String getPassWord() {return passWord;}private void setPassWord(String passWord) {this.passWord = passWord;}private Integer getId() {return id;}private void setId(Integer id) {this.id = id;}private String getPassWordQuestion() {return passWordQuestion;}private void setPassWordQuestion(String passWordQuestion) {this.passWordQuestion = passWordQuestion;}private String getIdCard() {return idCard;}private void setIdCard(String idCard) {this.idCard = idCard;}private String getPhoneNumber() {return phoneNumber;}private void setPhoneNumber(String phoneNumber) {this.phoneNumber = phoneNumber;}private String getEmail() {return email;}private void setEmail(String email) {this.email = email;}private String getBirthday() {return birthday;}private void setBirthday(String birthday) {this.birthday = birthday;}private String getSex() {return sex;}private void setSex(String sex) {this.sex = sex;}private String getUrl() {return url;}private void setUrl(String url) {this.url = url;}private String getPersonAddress() {return personAddress;}private void setPersonAddress(String personAddress) {this.personAddress = personAddress;}private String getWorkAddress() {return workAddress;}private void setWorkAddress(String workAddress) {this.workAddress = workAddress;}private Integer getStatus() {return Status;}private void setStatus(Integer status) {Status = status;}private Integer getRoleId() {return roleId;}private void setRoleId(Integer roleId) {this.roleId = roleId;}}

一、利用缓存区StringBuilder或者StringBuffer来实现

1,首先因为我们的属性,方法全是私有的,所有我们在外部不能对其进行赋值操作,所以我们利用构造方法对其进行传参。
2,然后创建缓存区,用来临时存储想要取出的值,刚开始想用String字符串来保存,但是String对象中不存在存取的方法,所以不能用它来存取值,于是想到用缓存区StringBuilder或者StringBuffer来存取,其中有存数值的append方法和取数值的toString方法。
3,先在User实体类中创建含有userID,name,password的构造方法,对其属性进行赋值。
4,在main方法中创建User类,传递值。
5,创建缓存区对象StringBuilder,用来存储我们要取出的值
6,创建一个字符串数组用来标识我们传进去的值对应的属性。
7,通过new User(user, sb, flag),把User对象,缓存区,和标识通过构造函数进行传递,在构造函数里面进行操作,把值全部通过append方法保存到缓存区中。
8,最后我们只要通过toString方法得到userID,name,和password,我们看通过split方法把他们分别拿到。


public class Main {    public static void main(String[] args) {           User user = new User(1, "zcl", "123");           StringBuilder sb = new StringBuilder();           String[] flag = {"id", "name", "password"};           new User(user, sb, flag);           String[] str = sb.toString().split(";");           for (String string : str) {               System.out.println(string);        }    }} 

二、通过反射实现
     反射应用在一些通用性比较高的代码中,框架大多用反射实现,在框架开发中,都是基于配置文件开发:在配置
文件中配置了类,可以通过反射得到类中所有内容,可以让类中的某个方法来执行。
     1,反射的原理:
首先把.java文件保存到本地硬盘.java
编译java文件,生成.class文件
使用jvm,把class文件通过类加载到内存中
当使用反射的时候,首先需要获取到class类,得到这个类之后,就可以得到class文件里面的所有内容。
属性通过一个类File获得
构造方法通过一个类Constructor获得
普通方法通过一个类Method获得
     
     2,使用反射操作类里面的属性
*首先获取到class类(三种方法)
Class clazz1 = User.class;
Class clazz2 = new User().getClass();
Class clazz3 = Class.forName("要获取的类的路径");

     3,操作无参构造函数
a,得到Class
 Class clazz = Class.forName("cn.zclong.bean.User");
b,得到User类的实例
 User user = (User)clazz.newInstance();
c,设置值
 user.setName("zcl");
 system.out.println(user.getName());


     4,操作有参构造函数
a,得到Class
 Class clazz = Class.forName("cn.zclong.bean.User");
b,获取有参构造方法,传递的是有参构造方法里面的参数类型,类型使用的是Class形式传递
 Constructor cs = clazz.getConstructor(Integer.class, String.class, String.class);
c,通过有参数的构造方法创建User实例并设置值
 User user = (User)cs.newInstance(1, "zcl", 123);
 system.out.println(user.getUserID()+":"+user.getName()+":"+user.getPassword);


    5,操作属性
a,得到Class
 Class clazz = Class.forName("cn.zclong.bean.User");
b,得到User类的实例
 User user = (User)clazz.newInstance();
c,获得要操作的属性,参数是属性的名称
 Filed f1 = clazz.getDeclaredFiled("name");
d,若操作的是私有属性,不然操作,需要设置可以操作私有属性
 f1.setAccessible(true);
  e,设置name的set方法,两个参数:第一个参数是类的实例,第二个参数是设置的值
 f1.set(user, "zcl");//相当于 user.name = "zcl";


     6,操作普通方法(解决属性和方法都为private的情况)

public static void main(String[] args) {        //反射实现操作私有方法                try {          //1,得到Class类           //Class c = Class.forName("cn.edu.jxau.bluedot.po.User");           //Class c = User.class;           Class c = new User().getClass();                     //2,得到User实例           User user = (User)c.newInstance();                    //3,得到普通方法,传递两个参数,第一个参数为方法名称,第二个参数为通过方法设置的值           Method m = c.getDeclaredMethod("setName", String.class);                      //4,若操作的方法是私有的,需要设置值true           m.setAccessible(true);                      //让setName方法去执行invoke()设置值,传递两个参数,           //第一个参数为User实例,第二个参数为设置的值           m.invoke(user, "zcl");                      //取得name的值           //1,得到getName方法           m = c.getDeclaredMethod("getName", null);                    //2,若操作的方法是私有的,需要设置值true           m.setAccessible(true);                      //3,执行invoke()方法           String str = (String) m.invoke(user, null);           System.out.println(str);                    } catch (Exception e) {            e.printStackTrace();        }    }   

***注意:当操作的方法是静态方法时,因为静态方法调用的方式是:类名.方法名,不需要类的实例,使用反射操作静
态方法的时候,也不需要实例,在invoke()方法的第一个参数里面写null:m.invoke(null,  "zcl");


以上便是解决这个问题的两种方式,最重要的还是反射知识,这个非常重要。希望这篇文章可以帮到有需要的同学。

阅读全文
2 0
原创粉丝点击