Java反射详解(一)-Field

Reflection

一 反射的应用场景

1.1 场景一:JDBC封装的工具类DBUtils组件

  • 问题:写DBUtils在前,我们使用在后,那么当时作者在写DBUtils时候,作者是否知道后面我们使用时,需要查询返回某个类型的对象?

例如:Student stu =qr.query(sql,new BeanHandler(),xxx);
作者在写queryRunning时时怎么知道我们需要Student这种实体类的返回类型的呢?

结论:在DBUtils源码中一定有一段在运行期动态的根据传入的类型创建指定类型对象的代码

1.2 场景二:JAVAWEB中的Servlet

  • 问题:Tomcat容器管理Servlet,Tomcat的代码先实现,我们写Servlet在后,那么问题就来了,先实现的Tomcat怎么管理后面写的Servlet类的呢?

说白了Tomcat为什么会认识我们后面运行期才写的Servlet?

结论:在Tomcat中servlet容器实现的过程中也有一段在运行期根据web.xml或者注解的配置动态创建Servlet的对象的代码

1.3 场景三:MyBatis

  • 问题:
    Sql:<insert id ="add" parameterType="stu">insert into stu(name,age)values(#{name},#{age})</insert>

session.insert(“add”,stu);

Mybatis 实现在前,使用Mybatis添加Student对象在后

结论:Mybatis中也有一段在运行期根据属性名字到执行对象中执行getter方法的代码

二 反射的概念

Reflection反射是Java语言提供的一套在运行期动态获得四大类中信息的API

四大类:编译后都会生成.Class文件
类 class
接口 interface
枚举:enum
注解:@interface

它是可以分析后面使用使用反射技术的框架的这个类的一种技术

三 反射的基础类(平台类)java.lang.Class

  • 我们编译上述的四大类后后产生的.class文件,也可以用一个Class类来描述,那么一个Class对象代表的就是一份某一份具体的.class文件

在这里插入图片描述
而Class类内部,每一个Class对象对应一个四大类的.class文件,大概就像下面这样👇
在这里插入图片描述

  • Class类没有公共的构造方法,它只能通过JVM调用类加载后生成的.class文件自动在内存堆区构造存放该类的信息 [我们不能new]
    在这里插入图片描述

四 通过Class获得实体类的信息

1.有实体类 用类名字.class (固定形式)

Class cls = Student.class//cls里面装的是Student这个类的所有属性和方法
Class clas1 = User.class//同理

2.有实体类的对象 用.getClass()

Class cls = stu.getClass()//这个stu是Student这个类的对象,通过这种方法也可以拿到"Class类"的对象

3.字符串类名字

//例如
Class cla =Class.forName("java.util.ArrayList");//包名+类名

这三种途径得到的都是一个实体类

五 反射的应用

5.1 数组

int set1[] ={1,2,3,4};
int set2[] ={11,22,33,44};
System.out.println(set1.getClass()==set2.getClass());//true

数组而言,类型和维数相同则他们对应的class对象就一样

5.2 实体类

举个String的例子

        String str =new String("ET");
        String str1 =new String("122331");
        System.out.println(str.getClass()==str1.getClass());//true

对于实体类而言只要是一个类,所有对象都对应一个class对象

5.3 通过Class创建对象

还是String来举例子:

 Class cls =String.class;
 String str4=(String) cls.newInstance();

newInstance() 就相当于调用实体类的空参构造方法,倘若实体类中没有空参构造方法则直接报错 比如:👇

 Class cla = Student.class;
 Student stu =(Student) cla.newInstance();

实体类的构造方法:👇

 public Student(int a) {
        System.out.println("....");
   }

运行报错:
在这里插入图片描述

5.4 通过Class拿实体类属性

Class clas =Student.class;
        Field[] fs =clas.getDeclaredFields();
        for (Field f : fs) {
            String name =f.getName();//属性名
            Class clsType =f.getType();//返回类型也可获得一个class对象
            String ftype =clsType.getSimpleName();//得到返回类型去掉包名的名称
            String mod = Modifier.toString(f.getModifiers());//getModifiers返回一个int代表修饰符的16进制的数字 toString可以把这个数字转成String类型
            System.out.println(mod+"\t"+ftype+"\t"+name);
        }

实体类中我们自己写的属性👇

  private String username;
  public String password;

运行👇
在这里插入图片描述
这里需要提一嘴 我们这里用的getDeclaredFields(),拿到的就是这个当下这个类的属性 如果用getFields()则会拿到本类public的属性和直接父类public的属性

5.5 通过拿到的属性,来拿对象的属性值

  Student stu =new Student();
      stu.setUsername("shang");
        Class cla =stu.getClass();
        Field f =cla.getDeclaredField("username");//拿指定名称的属性
        f.setAccessible(true);//破封装
        String str =(String) f.get(stu);//类似常用的没封装属性时候的stu.username
        System.out.println(str);

运行👇
在这里插入图片描述

5.6 通过主方法传值(args[])的方式来获得所有传入对象的所有属性

首先封装个方法👇

 public static void testFields(Class cls)throws Exception{
        System.out.println(cls.getSimpleName());//得到除去包名的类名
        Field[] fd=cls.getDeclaredFields();//得到所有属性
        for (Field f : fd) {
            String name =f.getName();//属性名
            Class clsType =f.getType();
            String fType =clsType.getSimpleName();//返回类型名
            String mod =Modifier.toString(f.getModifiers());//修饰符
            System.out.println(mod+" "+fType+" "+name);
        }
    }

主方法👇

testFields(Class.forName(args[0]));

通过IDEA传值,因为笔者开发工具用的IDEA👇
我这里拿java.util.ArrayList举例子 尝试拿它所有属性
首先main方法是测试类
在这里插入图片描述
打开后传参👇
在这里插入图片描述
运行👇
在这里插入图片描述
ok,ArrayList中所有的属性我们就展现出来了


总结

关于反射今天先说这么多,下一篇详细介绍以下反射里面的Method反射中的Method详解,纯原创,喜欢记得点赞+关注哦~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

商朝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值