首页 > 编程语言 >Java内省

Java内省

时间:2022-12-16 15:56:36浏览次数:54  
标签:map java String student 内省 Student import Java

Introspector

Java JDK Introspector

在开发框架的时候经常会用到Java类的 get/set方法设置或者获取值,但是每次都是用反射来完成此类操作或与麻烦,JDK提供了 一套API,专门操作Java对象的属性。内省专门操作Java对象的属性。

在Java中private int id 这种叫做字段field,而get/set方法才被叫做属性property

Java中的属性是指设置和读取字段的方法。
属性名称就是去掉get/set后面的部分

package cn.pickle.entity;

import lombok.Data;

/**
 * @author Pickle
 * @version V1.0
 * @date13:53 2022/12/14
 */
@Data	//该注解自动生成 get/set 方法
public class Student {
    private Long id;	//field 字段
    private String password;	//field 字段
    private Integer classNumber;//field 字段
    
    
    public String getTest(){
    return "TEST";
}

测试函数

package cn.pickle.introspector;

import cn.pickle.entity.Student;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;

/**
 * @author Pickle
 * @version V1.0
 * @date 2022/12/16 14:11
 */
public class demo {
    public static void main(String[] args) throws IntrospectionException {
        //获得Student属性封装到beanInfo中
        final BeanInfo beanInfo = Introspector.getBeanInfo(Student.class);

        //得到类中的所有属性描述器
        final PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();

        System.out.println("属性的个数为" + propertyDescriptors.length);

        for (PropertyDescriptor pd :
                propertyDescriptors) {
            System.out.println("属性" + pd.getName());
        }
    }
}

结果

image-20221216142346813

属性test可以看出获得的属性和字段并没有关系,而属性class则是父类的getClass()方法

PropertyDescriptor

propertyDescriptor通过反射快速操作JavaBean的getter/setter方法。

PropertyDescriptor获取get/set方法的API

image-20221216142901158

实例

package cn.pickle.introspector;

import cn.pickle.entity.Student;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;

/**
 * @author Pickle
 * @version V1.0
 * @date 2022/12/16 14:11
 */
public class demo {
    public static void main(String[] args) {
        try {
            //获取描述Student的Class实例
            final Class<?> stuClass = Class.forName("cn.pickle.entity.Student");

            final Student student = (Student)stuClass.newInstance();

            //获取id的属性描述器
            final PropertyDescriptor pd = new PropertyDescriptor("id", Student.class);
            
            //setId()
            final Method writeId = pd.getWriteMethod();

            //getId()
            final Method readId = pd.getReadMethod();

            System.out.println(student.toString());

            writeId.invoke(student,1L);

            System.out.println(student.toString());

            System.out.println("利用属性描述器获取的get方法读取id的值为:" + readId.invoke(student,null));

        }catch (Exception error){
            System.out.println("没有找到该类" + error.getMessage());
        }
    }
}

输出

image-20221216145024057

Apache BeanUtils

更高效的内省框架

       <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.9.4</version>
        </dependency>

简单使用

package cn.pickle.introspector;

import cn.pickle.entity.Student;
import org.apache.commons.beanutils.BeanUtils;

import java.beans.*;
import java.lang.reflect.InvocationTargetException;

/**
 * @author Pickle
 * @version V1.0
 * @date 2022/12/16 14:11
 */
public class demo {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        Student student = new Student();
        final String id = BeanUtils.getProperty(student, "id");
        System.out.println("BeanUtils 获取的 id 为: " + id);

        BeanUtils.setProperty(student,"id",1L);
        System.out.println("BeanUtils 设置后的Student" + student.toString());
    }
}

输出

image-20221216150221257

ConvertUtils

实现非基本类型的自定义转换封装

将Map属性批量封装到Bean中

package cn.pickle.introspector;

import cn.pickle.entity.Student;
import org.apache.commons.beanutils.BeanUtils;

import java.beans.*;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Pickle
 * @version V1.0
 * @date 2022/12/16 14:11
 */
public class demo {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        Student student = new Student();
        Map<String,String> map = new HashMap<>();
        map.put("id","1");
        map.put("classNumber","1");
        map.put("password","1");
        BeanUtils.populate(student,map);
        System.out.println(student);
    }
}

输出

image-20221216151316562

但是如果里面包含不是基本类型,我们在原来的基础上给Student加上一个Date字段

image-20221216151414430

package cn.pickle.introspector;

import cn.pickle.entity.Student;
import org.apache.commons.beanutils.BeanUtils;

import java.beans.*;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Pickle
 * @version V1.0
 * @date 2022/12/16 14:11
 */
public class demo {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        Student student = new Student();
        Map<String,String> map = new HashMap<>();
        map.put("id","1");
        map.put("classNumber","1");
        map.put("password","1");
        map.put("birthday","2001-01-01");
        BeanUtils.populate(student,map);
        System.out.println(student);
    }
}

直接报错

image-20221216151551286

意思就是DateConverter不支持默认的String到Date转换,有两种解决方案。

  • 自定义转换器然后用ConvertUtils注册。
package cn.pickle.introspector;

import cn.pickle.entity.Student;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;

import java.lang.reflect.InvocationTargetException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Pickle
 * @version V1.0
 * @date 2022/12/16 14:11
 */
@SuppressWarnings("unchecked")
public class demo {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        Student student = new Student();
        Map<String,String> map = new HashMap<>();
        map.put("id","1");
        map.put("classNumber","1");
        map.put("password","1");
        map.put("birthday","2001-01-01");

        ConvertUtils.register(new Converter() {
            /**
             * @param <T>
             * @param aClass 目标类型
             * @param o      当前传入的值
             * @return
             */
            @Override
            public <T> T convert(Class<T> aClass, Object o) {
                DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
                if(o instanceof String){// String -> Date
                    String date = (String) o;
                    try {
                        final Date parse = df.parse(date);
                        return (T) parse;
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                }else{//Date -> String
                    final String format = df.format((Date) o);
                    return (T) format;
                }
                return null;
            }
        }, Date.class);

        BeanUtils.populate(student,map);
        System.out.println(student);
    }
}

结果

image-20221216154348750

  • 使用提供的转换器
package cn.pickle.introspector;

import cn.pickle.entity.Student;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;

import java.lang.reflect.InvocationTargetException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Pickle
 * @version V1.0
 * @date 2022/12/16 14:11
 */
@SuppressWarnings("unchecked")
public class demo {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        Student student = new Student();
        Map<String,String> map = new HashMap<>();
        map.put("id","1");
        map.put("classNumber","1");
        map.put("password","1");
        map.put("birthday","2001-01-01");

//        ConvertUtils.register(new Converter() {
//            /**
//             * @param <T>
//             * @param aClass 目标类型
//             * @param o      当前传入的值
//             * @return
//             */
//            @Override
//            public <T> T convert(Class<T> aClass, Object o) {
//                DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
//                if(o instanceof String){// String -> Date
//                    String date = (String) o;
//                    try {
//                        final Date parse = df.parse(date);
//                        return (T) parse;
//                    } catch (ParseException e) {
//                        e.printStackTrace();
//                    }
//                }else{//Date -> String
//                    final String format = df.format((Date) o);
//                    return (T) format;
//                }
//                return null;
//            }
//        }, Date.class);
        ConvertUtils.register(new DateLocaleConverter(),Date.class);
        BeanUtils.populate(student,map);
        System.out.println(student);
    }
}

image-20221216154534508

标签:map,java,String,student,内省,Student,import,Java
From: https://www.cnblogs.com/poteitoutou/p/16987571.html

相关文章

  • java相关学习资料收集
    springboot学习资料springboot系列教程 spingboot系列教程2 javaspringboot学习application.properties全部配置项   ​​点击查看SpringBoot所有配置......
  • 18 Java内存模型与线程_JVM同步机制和锁类库实现线程安全
    目录1线程安全定义2Java数据与线程安全2.1不可变2.2绝对线程安全2.3相对线程安全2.4线程兼容2.5线程对立3Java线程安全支持3.1互斥同步3.1.1synchronized互斥同......
  • java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11Graphi
    公司项目windows迁移到linux系统,导出Excel报错误,解决办法:配置Tomcat中的catalina.sh在JAVA_OPTS中添加-Djava.awt.headless=true这样的代码,在末尾加上-Djava.awt.hea......
  • 【转载】完美解决 java: 无效的目标发行版: 11
    在使用IDEA编译程序时出现下面的错误信息:java:无效的目标发行版:11问题描述经过研究才发现,这是因为作者使用了jdk8进行编译,而试图使用jdk11的功能,这就必然会导致版本问......
  • 基于Java实现数据脱敏
    用法Jdk版本大于等于1.8maven依赖<dependency><groupId>red.zyc</groupId><artifactId>desensitization</artifactId><version>2.4.6</version></d......
  • 一文带你搞懂java中的变量的定义是什么意思
    前言在之前的文章中,壹哥给大家讲解了Java的第一个案例HelloWorld,并详细给大家介绍了Java的标识符,而且现在我们也已经知道该使用什么样的工具进行Java开发。那么接下来,壹哥......
  • 0基础→自动化测试框架实现:java + testng + httpclient + allure
    必备基础java基础配置文件解析(properties)fastjson的使用(处理json字符串、json数组)jsonpath的使用java操作excel(通过POIHttpClient的使用(get、post请求)TestNG用法 自动化测......
  • java面向对象面试题(2)
    1)给定如下java代码程序片断:      classA{             publicA(){                    System.out.println(“A”);   ......
  • Java多线程详解(通俗易懂)
    一、线程简介1.什么是进程?电脑中会有很多单独运行的程序,每个程序有一个独立的进程,而进程之间是相互独立存在的。例如图中的微信、酷狗音乐、电脑管家等等。2.什么是......
  • JAVA8自带TreeUtils
        tree.json{"code":200,"msg":"操作成功","data":[{"id":"310000","name":"电子商务","parentId":"000000"}......