Java学习路线-31:反射与简单Java类

简介: Java学习路线-31:反射与简单Java类

第24 章 : 反射与简单Java类

109 传统属性赋值弊端

简单Java类,setter,getter过多,代码重复

通过反射(Object类直接操作属性或方法)实现相同功能类的重复操作的抽象处理

110 属性自动赋值实现思路

类设计的基本机构:

应该由一个专门的ClassInstanceFactory类负责反射处理

接收反射对象与要设置的属性内容,同时可以获取指定类的实例化对象

class ClassInstanceFactory{
    private ClassInstanceFactory(){}
    /**
     * 实例化对象的创建方法,该对象可以根据传入的字符串结构“属性:内容|属性:内容”
     * @param clazz 要进行反射实例化的Class对象,有Class就可以反射实例化对象
     * @param value 要设置给对象的属性内容
     * @return 一个已经配置好属性内容的Java类对象
     */
    public static <T> T getInstance(Class clazz, String value){
        return null;
    }
}

111 单级属性赋值

完成2项内容:

1、通过反射进行指定类对象的实例化处理

2、进行内容设置 Field Method


必须要有无参构造


处理流程

Class<?>
    -Field 
    -Method 调用setter
Utils
    -BeanUtils   获取类型,属性设置
    -StringUtils 首字母大写
ClassInstanceFactory<T> 对象实例化并设置属性
main 测试类

即使类中的属性再多,也可以实现属性赋值

StringUtil.java

package util;
class StringUtil{
    /**
     * 首字母大写
     */
    public static String capitalize(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);
        }
    }
}

BeanUtil.java

package util;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class BeanUtil {
    /**
     * 对象属性赋值
     * @param obj
     * @param value 数据结构"key:value|key:value"
     */
    public static void setValue(Object obj, String value){
        String[] attrs = value.split("\\|");
        // System.out.println(Arrays.toString(attrs));
        for(String attr : attrs){
            String[] keyValue = attr.split(":");
            String key = keyValue[0];
            String val = keyValue[1];
            String setName = "set" + StringUtil.capitalize(key);
            // System.out.println(key + val + setName);
            try{
                Field field = obj.getClass().getDeclaredField(key);
                Method method = obj.getClass().getDeclaredMethod(setName, field.getType());
                method.setAccessible(true);
                method.invoke(obj, val);
            } catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

Demo.java

import util.BeanUtil;
class Person{
    private String name;
    public Person() {
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}
/**
 * 属性赋值工厂类
 */
class ClassInstanceFactory{
    private ClassInstanceFactory(){}
    public static <T> T getInstance(Class<T> clazz, String value) {
        try {
            Object obj = clazz.getDeclaredConstructor().newInstance();
            BeanUtil.setValue(obj, value);
            return (T) obj;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }
}
class Demo{
    public static void main(String[] args) {
        Person person = ClassInstanceFactory.getInstance(Person.class, "name:Tom");
        System.out.println(person);
        // Person{name='Tom'}
    }
}

112 设置多种数据类型

简单Java类中属性类型

long(Long)

int(Integer)

double(Double)

String


在 BeanUtil.java中添加类型转换方法

package util;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class BeanUtil {
    public static void setValue(Object obj, String value){
        String[] attrs = value.split("\\|");        
        for(String attr : attrs){
            String[] keyValue = attr.split(":");
            String key = keyValue[0];
            String val = keyValue[1];
            String setName = "set" + StringUtil.capitalize(key);
            try{
                Field field = obj.getClass().getDeclaredField(key);
                Method method = obj.getClass().getDeclaredMethod(setName, field.getType());
                method.setAccessible(true);
                Object convertVal = convertValue(field.getType().getName(), val);
                method.invoke(obj, convertVal);
            } catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    public static Object convertValue(String type, String value){
        if ("java.lang.String".equals(type)){
            return value;
        } else if("int".equals(type)){
            return Integer.parseInt(value);
        } else{
            return null;
        }
    }
}

Person类添加int类型的age属性,和修改测试Demo类传入参数

import util.BeanUtil;
class Person{
    private String name;
    private int age;
    public void setAge(int age) {
        this.age = age;
    }
    public Person() {
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
class Demo{
    public static void main(String[] args) {
        Person person = ClassInstanceFactory.getInstance(Person.class, "name:Tom|age:23");
        System.out.println(person);
        // Person{name='Tom', age=23}
    }
}

如果要做一个完整的产品,需要考虑所有可能的类型

113 级联对象实例化

例如:

一个员工属于一个部门,一个部门属于一个公司


约定使用.作为级联关系

eg:

company.dept.dname:财务部

考虑代码简洁性

114 级联属性赋值

完整代码

StringUtil.java

package util;
class StringUtil{
    /**
     * 首字母大写
     */
    public static String capitalize(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);
        }
    }
}

BeanUtil.java

package util;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class BeanUtil {
    /**
     * 对象属性赋值
     *
     * @param values 数据结构"key:value|key.subKey.subKey:value"
     */
    public static void setValues(Object obj, String values) {
        String[] attrs = values.split("\\|");
        for (String attr : attrs) {
            String[] keyValue = attr.split(":");
            String key = keyValue[0];
            String val = keyValue[1];
            try {
                // 级联关系,通过点. 分隔 eg: company.name
                if (key.contains(".")) {
                    String[] objKeys = key.split("\\.");
                    Object currentObject = obj;
                    // 对象链
                    for (int i = 0; i < objKeys.length - 1; i++) {
                        String objKey = objKeys[i];
                        Object tempObject = getValue(currentObject, objKey);
                        // 没有实例化
                        if (tempObject == null) {
                            tempObject = getFieldInstance(currentObject, objKey);
                            setValue(currentObject, objKey, tempObject);
                        }
                        currentObject = tempObject;
                    }
                    // 最后一个就是属性
                    String attrKey = objKeys[objKeys.length - 1];
                    setValue(currentObject, attrKey, convertFieldValue(currentObject, attrKey, val));
                }
                // 单级关系
                else {
                    setValue(obj, key, convertFieldValue(obj, key, val));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 给对象设置属性值
     */
    public static void setValue(Object obj, String key, Object value) {
        try {
            Field field = obj.getClass().getDeclaredField(key);
            String setName = "set" + StringUtil.capitalize(key);
            Method method = obj.getClass().getDeclaredMethod(setName, field.getType());
            method.setAccessible(true);
            method.invoke(obj, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 获取对象属性值
     */
    public static Object getValue(Object obj, String key) {
        Object value = null;
        try {
            String getName = "get" + StringUtil.capitalize(key);
            Method getMethod = obj.getClass().getDeclaredMethod(getName);
            getMethod.setAccessible(true);
            value = getMethod.invoke(obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return value;
    }
    /**
     * 获取对象属性对应类的实例化对象
     */
    public static Object getFieldInstance(Object obj, String key) {
        Object fieldObj = null;
        try {
            Field field = obj.getClass().getDeclaredField(key);
            Constructor constructor = field.getType().getConstructor();
            constructor.setAccessible(true);
            fieldObj = constructor.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return fieldObj;
    }
    /**
     * 转换字符串为对应类型的值
     */
    public static Object convertValue(String type, String value) {
        if ("java.lang.String".equals(type)) {
            return value;
        } else if ("int".equals(type)) {
            return Integer.parseInt(value);
        } else {
            return null;
        }
    }
    public static Object convertFieldValue(Object obj, String key, String value) {
        Object val = null;
        try {
            Field field = obj.getClass().getDeclaredField(key);
            val = convertValue(field.getType().getName(), value);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return val;
    }
}

Demo.java

import util.BeanUtil;
class Person {
    private String name;
    private int age;
    private Company company;
    public Person() {
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Company getCompany() {
        return company;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setCompany(Company company) {
        this.company = company;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", company=" + company +
                '}';
    }
}
class Dept {
    private String name;
    public Dept() {
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Dept{" +
                "name='" + name + '\'' +
                '}';
    }
}
class Company {
    private String name;
    private Dept dept;
    public Company() {
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setDept(Dept dept) {
        this.dept = dept;
    }
    public Dept getDept() {
        return dept;
    }
    @Override
    public String toString() {
        return "Company{" +
                "name='" + name + '\'' +
                ", dept=" + dept +
                '}';
    }
}
/**
 * 属性赋值工厂类
 */
class ClassInstanceFactory {
    private ClassInstanceFactory() {
    }
    public static <T> T getInstance(Class<T> clazz, String values) {
        try {
            Object obj = clazz.getDeclaredConstructor().newInstance();
            BeanUtil.setValues(obj, values);
            return (T) obj;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
class Demo {
    public static void main(String[] args) {
        String values = "name:Tom|age:23|company.name:Tech|company.dept.name:law";
        Person person = ClassInstanceFactory.getInstance(Person.class, values);
        System.out.println(person);
        // Person{name='Tom', age=23, company=Company{name='Tech', dept=Dept{name='law'}}}
    }
}


相关文章
|
2月前
|
IDE Java 关系型数据库
Java 初学者学习路线(含代码示例)
本教程为Java初学者设计,涵盖基础语法、面向对象、集合、异常处理、文件操作、多线程、JDBC、Servlet及MyBatis等内容,每阶段配核心代码示例,强调动手实践,助你循序渐进掌握Java编程。
327 3
|
2月前
|
SQL Java 数据库
2025 年 Java 从零基础小白到编程高手的详细学习路线攻略
2025年Java学习路线涵盖基础语法、面向对象、数据库、JavaWeb、Spring全家桶、分布式、云原生与高并发技术,结合实战项目与源码分析,助力零基础学员系统掌握Java开发技能,从入门到精通,全面提升竞争力,顺利进阶编程高手。
448 0
|
3月前
|
安全 Java 数据库连接
2025 年最新 Java 学习路线图含实操指南助你高效入门 Java 编程掌握核心技能
2025年最新Java学习路线图,涵盖基础环境搭建、核心特性(如密封类、虚拟线程)、模块化开发、响应式编程、主流框架(Spring Boot 3、Spring Security 6)、数据库操作(JPA + Hibernate 6)及微服务实战,助你掌握企业级开发技能。
492 3
|
5月前
|
前端开发 JavaScript Java
Java 学习路线规划及项目案例中的技术栈应用解析
内容包括:**Java 17核心特性**(如sealed class、record)与模块化开发;Spring Boot 3 + Spring Cloud微服务架构,涉及响应式编程(WebFlux)、多数据库持久化(JPA、R2DBC、MongoDB);云原生技术**如Docker、Kubernetes及CI/CD流程;性能优化(GraalVM Native Image、JVM调优);以及前后端分离开发(Vue 3、Spring Boot集成)。通过全栈电商平台项目实战,掌握从后端服务(用户、商品、订单)到前端应用(Vue 3、React Native)的全流程开发。
233 9
|
5月前
|
消息中间件 Java 微服务
2025 版 Java 学习路线实战指南从入门到精通
《Java学习路线实战指南(2025版)》是一份全面的Java开发学习手册,涵盖基础环境搭建、核心语法与新特性、数据结构与算法、微服务架构、云原生技术栈、AI融合及项目实战。内容包括JDK安装配置、IntelliJ IDEA设置、Records类与模式匹配增强、LeetCode题解、Spring Cloud微服务开发、Kubernetes部署、OpenAI API调用等。结合在线商城系统案例,采用Vue 3、Spring Boot 3.5、MySQL、Elasticsearch等技术,提供从理论到实践的完整路径,助力开发者掌握2025年最新趋势与最佳实践。
405 4
|
2月前
|
SQL 算法 Java
零基础到精通的史上最强 Java 学习路线图推荐
史上最全Java学习路线图,涵盖基础语法、面向对象、数据结构与算法、多线程、JVM、Spring框架、数据库及项目实战,助你从零基础到精通Java开发,附完整代码与工具推荐。
204 3
零基础到精通的史上最强 Java 学习路线图推荐
|
2月前
|
NoSQL Java 关系型数据库
超全 Java 学习路线,帮你系统掌握编程的超详细 Java 学习路线
本文为超全Java学习路线,涵盖基础语法、面向对象编程、数据结构与算法、多线程、JVM原理、主流框架(如Spring Boot)、数据库(MySQL、Redis)及项目实战等内容,助力从零基础到企业级开发高手的进阶之路。
236 1
|
2月前
|
前端开发 Java 数据库连接
帮助新手快速上手的 JAVA 学习路线最详细版涵盖从入门到进阶的 JAVA 学习路线
本Java学习路线涵盖从基础语法、面向对象、异常处理到高级框架、微服务、JVM调优等内容,适合新手入门到进阶,助力掌握企业级开发技能,快速成为合格Java开发者。
448 3
|
3月前
|
算法 Java 测试技术
适合新手小白的史上最强 Java 学习路线图从基础到进阶全程指南
本Java学习路线图涵盖从基础语法、面向对象、集合框架到进阶编程、JVM原理、Spring Boot框架,再到数据库操作与实战项目开发,内容系统全面,适合零基础新手入门与进阶提升,助力掌握Java全栈开发技能。
302 4
|
3月前
|
Java 数据库连接 微服务
零基础自学 Java 全栈必备最全学习路线及知识清单方向指引
本文为零基础学习者提供完整的Java全栈学习路线,涵盖Java基础、进阶、框架、项目实战及拓展方向,助你系统掌握全栈开发技能,快速成长为优秀Java工程师。
441 6