级联对象实例化 | 带你学《Java语言高级特性》之九十三

简介: 本节需要掌握实现级联对象实例化以及实现对象的级联属性设置。

上一篇::设置多种数据类型 | 带你学《Java语言高级特性》之九十二
【本节目标】
本节需要掌握实现级联对象实例化以及实现对象的级联属性设置。

级联对象实例化

如果现在给定的类对象中存在有其它的引用的级联关系的情况下,称为多级设置。例如:一个雇员属于一个部门,一个部分属于一个公司,所以这时对于简单Java类的基本关系定义如下:
Company:

class Company{
    private String name;
    private Date createdate;
}

Dept:

class Dept{
    private String dname;
    private String loc;
    private Company company;
}

Emp:

class Emp{
    private Long empno;
    private String ename;
    private String job;
    private double salary;
    private Date hireDate;
    private Dept dept;
}

如果要通过Emp进行操作,则应该使用“.”作为级联关系的处理:

dept.dname:财务部 Emp类实例化对象.getDept().setDname("财务部")
dept.company.name:MLDN Emp类实例化对象.getDept()..getCompany().setName("MLDN")

考虑到代码的简洁性,所以应该考虑可以通过级联的配置自动实现类中属性的实例化。

String value="empno:7369|ename:Smith|job:Clerk|salary:750.00|hiredate:1989-10-10" + "dept.dname:财务部|dept.company.name:MLDN";

现在的属性存在有多级的关系,那么对于多级的关系就必须与单级的配置区分开

import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class JavaAPIDemo {
    public static void main(String[] args)throws Exception{
        String value="empno:7369|ename:Smith|job:Clerk|salary:750.00|hiredate:1989-10-10" + "dept.dname:财务部|dept.company.name:MLDN";
        Emp emp = ClassInstanceFactory.create(Emp.class, value);
        System.out.println("雇员编号:" + emp.getEmpno() + "、姓名:" + emp.getEname() + "、职位:" + emp.getJob() + "、基本工资:" + emp.getSalary() + "、受雇日期:" + emp.getHiredate());
        System.out.println(emp.getDept());
        System.out.println(emp.getDept().getCompany());
    }
}
class ClassInstanceFactory{
    private ClassInstanceFactory(){}

    /**
     * 实例化对象的创建方法,该对象可以根据传入的字符串结构:"属性:内容|属性:内容"
     * @param clazz 要进行反射实例化的Class对象,有Class就可以反射实例化对象
     * @param value 要设置给对象的属性内容
     * @return 一个已经配置好属性内容的Java对象
     */
    public static <T> T create(Class<?> clazz,String value){
        // 如果要想采用反射进行简单Java类对象属性设置的时候,类中必须要有无参构造
        try {
            Object obj = clazz.getDeclaredConstructor().newInstance();
            BeanUtils.setValue();   //通过反射设置属性
            return (T) obj; //返回对象
        }catch (Exception e) {
            e.printStackTrace();  //如果此时真的出现了错误,本质上抛出异常也没用
            return null;
        }    
    }
}
class StringUtils {
    public static String initcap(String str) {
        if (str == null || "".equals(str)) {
            return str;
        }
        if (str.length() == 1) {
            return str.toUpperCase();
        }else {
        return str.substring(0, 1).toUpperCase() + str.substring(1);
        }
    }
}
class BeanUtils{   //进行Bean处理的类
    private BeanUtils(){}
    /**
     * 实现指定对象的属性设置
     * @param obj 要进行反射操作的实例化对象
     * @param value 包含有指定内容的字符串,格式"属性:内容|属性:内容"
     */
    public static void setValue(Object obj,String value){
        String results [] = value.split("\\|");//按照"|"进行每一组属性的拆分
        for (int x = 0; x < results.length; x ++) {   //循环设置属性内容
            //attval [0]保存的是属性名称,attval [1]保存的是属性内容
            String attval [] = results[x].split(":");   //获取“属性名称”和内容
            try {
                if (attval[0].contains(".")) {   //多级配置
                    String temp [] = attval[0].split("\\.");
                    Object currentObject = obj;
                    // 最后一位肯定是指定类中的属性名称,所以不在本次实例化处理的范畴之内
                    for (int y = 0 ; y < temp.length - 1 ; y ++) {  // 实例化
                        // 调用了相应的getter方法,如果getter方法返回了null,表示该对象未实例化
                        Method getMethod = obj.getClass().getDeclaredMethod("get" + StringUtils.initcap(temp[y]));
                        Object tempObject = getMethod.invoke(currentObject); 
                        if (tempObject == null) {    //该对象现在并没有实例化
                            Field field = currentObject.getClass().getDeclaredField(temp[y]);  //获取属性类型
                            Method method = currentObject.getClass().getDeclaredMethod("set" + StringUtils.initcap(temp[y]), field.getType());
                            Object newObject = field.getType().getDeclaredConstructor().newInstance();
                            method.invoke(currentObject, newObject);
                            currentObject = newObject;
                        }else {
                            currentObject = tempObject;
                        }
                        System.out.println(temp[y] + "--" + currentObject);
                    }
                }else {
                    Field field = obj.getClass().getDeclaredField(attval[0]);  //获取成员
                    Method setMethod = obj.getClass().getDeclaredMethod("set" + StringUtils.initcap(attval [0]), field.getType());
                    Object convertValue = BeanUtils.convertAttributeValue(field.getType().getName(), attval[1]);
                    setMethod.invoke(obj, convertValue);  //调用setter方法设置内容
                }
            }catch (Exception e) {}
        }
    }
    /**
     * 实现属性类型转换处理
     * @param type 属性类型,通过Field获取
     * @param value 属性的内容,传入的都是字符串,需要将其变为指定类型
     * @return 转换后的数据类型
     */
    private static Object convertAttributeValue(String type, String value) {
        if ("long".equals(type) || "java.lang.Long".equals(type)) {    //长整型
            return Long.parseLong(value);
        }else if ("int".equals(type) || "java.lang.int".equals(type)) {
            return Integer.parseInt(value);
        }else if ("double".equals(type) || "java.lang.double".equals(type)) {
            return Integer.parseDouble(value);
        }else if ("java.util.Date".equals(type)) {
            SimpleDateFormat sdf = null;
            if (value.matches("\\d{4}-\\d{2}-\\d{2}") {  //日期类型
                sdf = new SimpleDateFormat("yyyy-MM-dd");
            } else if (value.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}") {
                sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            }else {
                return new Date() ;   //当前日期
            }
            try {
                return sdf.parse(value);
            } catch(ParseException e) {
                return new Date() ;   //当前日期
            }
        }else {
            return value;
        }
    }
}
class Company{
    private String name;
    private Date createdate;
    public String getName() {
        return name;
    }
    public void setname(String name) {
        this.name = name;
    }   
    public Date getCreatedate() {
        return createdate;
    }
    public void setCreatedate(Date createdate) {
        this.createdate = createdate;
    }         
}
class Dept{
    private String dname;
    private String loc;
    private Company company;
    public String getDname() {
        return dname;
    }
    public void setDname(String dname) {
        this.dname = dname;
    }    
    public String getLoc() {
        return loc;
    }
    public void setLoc(String loc) {
        this.loc = loc;
    } 
    public Company getCompany() {
        return company;
    }
    public void setCompany(Company company) {
        this.company = company;
    }       
}
class Emp{
    private long empno;
    private String ename;
    private String job;
    private double salary;
    private Date hiredate;
    private Dept dept;
    public Dept getDept() {
        return dept;
    }
    public void setDept(Dept dept) {
        this.dept = dept;
    }
    public void setEname(String ename) {
        this.ename = ename;
    }
    public void setJob(String job) {
        this.job = job;
    }
    public String getEname() {
        return ename;
    }
    public String getJob() {
        return job;
    }
    public long getEmpno() {
        return empno;
    }
    public void setEmpno(Long empno) {
        this.empno = empno;
    }
    public double getSalary() {
        return salary;
    }
    public void setSalary(double salary) {
        this.salary = salary;
    }
    public Date getHiredate() {
        return hiredate;
    }
    public void setHiredate(Date hiredate) {
        this.hiredate = hiredate;
    }
}

image.png

这些自动的级联配置的实例化处理操作,在以后进行项目的编写之中一定会使用到。

级联属性设置

现在已经成功的实现级联的对象实例化处理,那么随后就需要去考虑级联的属性的设置了,在之前考虑级联对象实例化处理时,循环时都是少了一位的。

for (int y = 0 ; y < temp.length - 1 ; y ++) {  // 实例化
    // 调用了相应的getter方法,如果getter方法返回了null,表示该对象未实例化
    Method getMethod = obj.getClass().getDeclaredMethod("get" + StringUtils.initcap(temp[y]));
    Object tempObject = getMethod.invoke(currentObject); 
    if (tempObject == null) {    //该对象现在并没有实例化
        Field field = currentObject.getClass().getDeclaredField(temp[y]);  //获取属性类型
        Method method = currentObject.getClass().getDeclaredMethod("set" + StringUtils.initcap(temp[y]), field.getType());
        Object newObject = field.getType().getDeclaredConstructor().newInstance();
        method.invoke(currentObject, newObject);
        currentObject = newObject;
    }else {
        currentObject = tempObject;
    }
}

当此时代码循环处理完成之后,currentObject表示的就是可以进行setter方法调用的对象了,并且理论上该对象一定不可能为null,随后就可以按照我们之前的方式利用对象进行setter方法调用。

范例:实现对象的级联属性设置

//进行属性内容的设置
Field field = currentObject.getClass().getDeclaredField(temp[temp.length - 1]);  //获取成员
Method setMethod = currentObject.getClass().getDeclaredMethod("set" + StringUtils.initcap(temp[temp.length - 1]), field.getType());
Object convertValue = BeanUtils.convertAttributeValue(field.getType().getName(), attval[1]);
setMethod.invoke(currentObject, convertValue);  //调用setter方法设置内容

image.png

在以后的开发中简单Java类的赋值处理将不再重复调用setter操作完成,而这种处理形式是在正规开发中普遍采用的方式。

想学习更多的Java的课程吗?从小白到大神,从入门到精通,更多精彩不容错过!免费为您提供更多的学习资源。
本内容视频来源于阿里云大学

下一篇:ClassLoader类加载器 | 带你学《Java语言高级特性》之九十四
更多Java面向对象编程文章查看此处

相关文章
|
19天前
|
存储 缓存 Java
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
71 3
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
|
5月前
|
存储 安全 Java
Java Map新玩法:探索HashMap和TreeMap的高级特性,让你的代码更强大!
【10月更文挑战第17天】Java Map新玩法:探索HashMap和TreeMap的高级特性,让你的代码更强大!
109 2
|
4月前
|
监控 Java API
如何使用Java语言快速开发一套智慧工地系统
使用Java开发智慧工地系统,采用Spring Cloud微服务架构和前后端分离设计,结合MySQL、MongoDB数据库及RESTful API,集成人脸识别、视频监控、设备与环境监测等功能模块,运用Spark/Flink处理大数据,ECharts/AntV G2实现数据可视化,确保系统安全与性能,采用敏捷开发模式,提供详尽文档与用户培训,支持云部署与容器化管理,快速构建高效、灵活的智慧工地解决方案。
|
2月前
|
Oracle Java 关系型数据库
Java基础(一):语言概述
Java基础(一):语言概述
61 15
Java基础(一):语言概述
|
19天前
|
缓存 Java 应用服务中间件
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
66 5
|
20天前
|
存储 Java
Java中判断一个对象是否是空内容
在 Java 中,不同类型的对象其“空内容”的定义和判断方式各异。对于基本数据类型的包装类,空指对象引用为 null;字符串的空包括 null、长度为 0 或仅含空白字符,可通过 length() 和 trim() 判断;集合类通过 isEmpty() 方法检查是否无元素;数组的空则指引用为 null 或长度为 0。
|
2月前
|
Java
Java快速入门之类、对象、方法
本文简要介绍了Java快速入门中的类、对象和方法。首先,解释了类和对象的概念,类是对象的抽象,对象是类的具体实例。接着,阐述了类的定义和组成,包括属性和行为,并展示了如何创建和使用对象。然后,讨论了成员变量与局部变量的区别,强调了封装的重要性,通过`private`关键字隐藏数据并提供`get/set`方法访问。最后,介绍了构造方法的定义和重载,以及标准类的制作规范,帮助初学者理解如何构建完整的Java类。
|
2月前
|
安全 Java
Object取值转java对象
通过本文的介绍,我们了解了几种将 `Object`类型转换为Java对象的方法,包括强制类型转换、使用 `instanceof`检查类型和泛型方法等。此外,还探讨了在集合、反射和序列化等常见场景中的应用。掌握这些方法和技巧,有助于编写更健壮和类型安全的Java代码。
50 17
|
2月前
|
Java
java代码优化:判断内聚到实体对象中和构造上下文对象传递参数
通过两个常见的java后端实例场景探讨代码优化,代码不是优化出来的,而是设计出来的,我们永远不可能有专门的时间去做代码优化,优化和设计在平时
38 15
|
2月前
|
存储 监控 算法
探秘局域网桌面监控:深入剖析 Java 语言核心算法
在数字化办公时代,局域网桌面监控如同企业的“智慧鹰眼”,确保工作效率与数据安全。本文以Java为载体,揭示哈希表在监控中的关键应用。通过高效的数据结构和算法,哈希表能快速索引设备连接信息,大幅提升监控的时效性和响应速度。代码示例展示了如何用Java实现设备网络连接监控,结合未来技术如AI、大数据,展望更智能的监控体系,助力企业在数字化浪潮中稳健前行。

热门文章

最新文章