Java反射、注解和BeanUtils工具类的使用

一、反射

  • 概述:反射是一种机制,利用该机制可以在程序运行过程中对类进行解剖并操作类中的
    属性构造方法等成员
  • 使用反射机制解剖类需要先获得字节码文件对象(Class类型对象),那为什么要获得这个类呢?
    在这里插入图片描述
    • 默认情况下:每创建一个类,内存中对应一个Class对象
    • 获得Class的三种方法:
      //方式一:类名.class
      Class userClazz1 = User.class;
      
      //方式二:对象名.getClass();
      User user=new User();
      Class userClazz2 = user.getClass();
      
      //方式三:Class.forName("类的全限定名")  全限定名:包名+类名
      Class userClazz3 = Class.forName("zongjie.User");
      
    • 创建此Class对象所表示的类的一个新实例,依赖的是无参构造:
      Object obj = userClazz3.newInstance();
      
  • 获得字节码对象之后有什么用?
    在这里插入图片描述
    user.java
public class User{

    public String username;
    public String password;
    private Integer age;
    private String sex;

    public User() {

    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public User(String username, String password, Integer age, String sex) {

        this.username = username;
        this.password = password;
        this.age = age;
        this.sex = sex;
    }

    private User(Integer age, String sex) {
        this.age = age;
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "Useraa{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }

    public void study(String username){

    }

    public void sleep(){

    }
}
  • Constructor对象、Filed对象、Method对象分别代表什么?
    • Constructor对象:类中的每一个构造方法都是Constructor对象
      在这里插入图片描述
    • Constructor对象中的方法
      	User user = new User();
          //Constructor演示
          Class userClazz = User.class;
      
          //1.获得所有public类型的构造方法
          Constructor[] constructors = userClazz.getConstructors();//length:3
      
          //2.获得所有构造方法(包含私有的)
          Method[] declaredMethods = userClazz.getDeclaredMethods();//length:4
      
          //3.userClazz.getConstructor(参数类型...);//获得指定参数列表public类型的构造方法
          //3.1 获得public Useraa(String username, String password)构造方法的Constructor对象
          Constructor constructor = userClazz.getConstructor(String.class, String.class);
      
          //4.clazz.getDeclaredConstructor(参数类型...);//获得指定参数列表构造方法(包含私有)
          //4.1 获得private Useraa(Integer age, String sex)构造方法的Constructor对象
          Constructor constructor1 = userClazz.getDeclaredConstructor(Integer.class, String.class);
      
          //5.根据构造方法创建一个对象
          //5.1 当构造方法为private修饰时,需要暴力反射才能使用该构造方法
          constructor1.setAccessible(true);
          //5.2 public T newInstance(Object ... initargs) 参数:要什么构造方法,就根据构造方法参数列表进行传参
          User man = (User)constructor1.newInstance(100, "男");
          System.out.println(man);
      
    • Filed对象:类中的每一个字段(成员变量)都是Field对象
      在这里插入图片描述
    • Filde对象中的方法:
      	Class userClazz = User.class;
      
          //1.获得所有public类型的字段(包括父类的)
          Field[] fields = userClazz.getFields();//length:2
          System.out.println(fields.length);
      
         //2.获得所有字段(包括私有的,不包括父类的)
          Field[] declaredFields = userClazz.getDeclaredFields();//length:4
      
          //3.获得指定public类型的字段 public String username
          Field username = userClazz.getField("username");
      
          //4.获得指定字段(包括私有的) private String sex;
          Field sexField = userClazz.getDeclaredField("sex");
          //4.1当字段被private修饰时,需要暴力反射才能使用该字段
          sexField.setAccessible(true);
          //4.2赋值  参数1:Class对象对应的类的对象 参数2:要赋的值
          sexField.set(user,"女");;
          //4.3获取值  参数:Class对象对应的类的对象
          Object sexStr= sexField.get(user);
          System.out.println(sexStr);
      
    • Method:类中的每一个方法都是Method对象
      在这里插入图片描述
    • Method对象中的方法:
      	Class userClazz = User.class;
      
          //1.获得所有public类型的方法(包括父类的)
          Method[] methods = userClazz.getMethods();
      
          //2.获得所有方法(包括私有的,不包括父类)
          Method[] declaredMethods = userClazz.getDeclaredMethods();
      
          //3.获得指定public类型的方法 public void Study(String username)  参数1:方法名  参数2:方法名中的参数类型
          Method method = userClazz.getMethod("study", String.class);
      
          //4.获得指定方法(包括私有的) private void eat(String[] username)参数1:方法名  参数2:方法名中的参数类型
          Method eat = userClazz.getDeclaredMethod("eat", String[].class);
          //4.1当方法被private修饰时,需要暴力反射才能使用该方法
          eat.setAccessible(true);
          //4.2调用方法  参数1:调用方法的对象   参数2:可变参数会把数据解析成多个参数,
          // 传递到eat()方法中的new String[]{"张三", "李四"}实际上是 "张三" ,"李四"这两个参数,所以需要强转
          // ps:如果不需要调用方法的对象(main方法)则传null
          Object obj = eat.invoke(user, (Object) new String[]{"张三", "李四"});
          System.out.println(obj);
      

二、注解

  • 什么是注解:供编译器或JVM使用,可以根据注解完成对应的功能

  • 作用的位置:包,类,字段,方法,方法参数以及局部变量上

  • 作用

    • 编译见检查:@Override
    • 框架的配置:
  • 创建格式public @interface 注解名(){}

  • 注解中可以定义注解属性

    	public @interface 注解名(){
    		类型 属性名();//没有默认值c
    		类型 属性名 default 值;//设置默认值
    	}
    
    • 类型可以为:
      • 基本类型(四类8种)
      • String
      • 枚举类型
      • 注解类型
      • Class类型
      • 以上类型的一维数组类型
  • 使用注解@注解名(属性名=值,属性名2=值2) //没有默认值的必须要赋值,有默认值可以不用赋值

    Anno.java

    	@Target({ElementType.METHOD})
    	@Retention(RetentionPolicy.RUNTIME)
    	public @interface Anno {
    	    String username();
    	    String[] str();
    	}
    	
    	@Target(ElementType.METHOD)
    	@Retention(RetentionPolicy.RUNTIME)
    	@interface Anno1{
    	    String value();
    	}
    	
    	@Target(ElementType.METHOD)
    	@Retention(RetentionPolicy.RUNTIME)
    	@interface Anno2{
    	    String[] value();
    	}
    
    	@Anno(username = "张三",str={"str1","str2","str3"})
        public void method1(){
    
        }
    
        //当注解属性只有一个且名为value可以省略名
        @Anno1("张三")
        public void method2(){
    
        }
    
        //注解只有一个String数组名为value且只存一个值
        @Anno2("李四")
        public void method3(){
    
        }
    
  • 元注解:定义注解的注解

    • @Target:定义该注解作用在什么上面(位置),默认是任何位置

      • @Target(ElementType.METHOD):定义在方法上
      • @Target(ElementType.TYPE):定义在类上
      • @Target(ElementType.FIELD):定义在属性上
      • @Target(ElementType.CONSTRUCTOR):定义在构造方法上
    • @Retention:定义该注解保留到那个代码阶段,默认只在源码阶段保留

      • @Retention(RetentionPolicy.SOURCE):只在源码上保留(默认)
        *@Retention(RetentionPolicy.CLASS):在源码和字节码上保留
      • @Retention(RetentionPolicy.RUNTIME):在所有的阶段都保留
  • 注解解析

    //获得clazz对象
        Class clazz = Test2.class;
    
        //通过clazz对象获得method对象
        Method method = clazz.getMethod("method1");
    
        //判断是否方法上是否有注解
        if (method.isAnnotationPresent(Anno.class)) {
            //通过method对象获得方法上的注解对象
            Anno anno = method.getAnnotation(Anno.class);
            String[] str = anno.str();
            String username = anno.username();
            System.out.println(Arrays.toString(str));
            System.out.println(username);
        }
    

    三、BeanUtils工具类

  • 作用

    • 对JavaBean的属性进行赋值和取值。
    • 将一个JavaBean所有属性赋值给另一个JavaBean对象中。
    • 将一个Map集合的数据封装到一个JavaBean对象中。
  • JavaBean:

    • 类必须使用public修饰。
    • 提供无参数的构造器。
    • 提供getter和setter方法访问属性。
    • 实现序列化接口(一般不写)

注意:字段:就是成员变量,字段名就是成员变量名。
属性:属性名通过setter/getter方法去掉set/get前缀,首字母小写获得

  • 使用
    在这里插入图片描述
    	    //把Map中的值封装到javaBean中
            HashMap<String,String> map=new HashMap<>();
    
            //key需和属性相同(不是字段),value会把"18"尝试转换为18,转换失败有默认值0
            //配合Map<String, String[]> parameterMap = request.getParameterMap();使用
            map.put("username","张三");
            map.put("age","18a");
            map.put("sex","男");
            User1 user1 = new User1();
    
            //封装的方法
            BeanUtils.populate(user1,map);
            System.out.println(user1);
    
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值