当前位置: 首页 > news >正文

初级程序员必会的java反射教程

目录

 🍏1. 创建一个Person实体类🍏

🍎 2. 反射获取Class类对象的三种方法🍎

🍎 2.1 通过全类名的方式获取

🍎 2.2 类名.class

🍎 2.3 实例对象.getClass() 

🍎 2.4 总结

 🍒 3. 反射获取属性变量 🍒

🍒 3.1 获取所有public修饰符的成员变量

🍒 3.2 获取指定字段并赋值

 🍒 3.3 获取所有的成员变量(不考虑修饰符)

🍒 3.4 获取私有的变量(利用暴力反射)

🍔 4.反射获取构造方法 🍔

 🍔 4.1有参构造

🍔 4.2无参构造

 🍔 4.3无参构造简便写法

🍓 5.反射获取成员方法 🍓

 🍓 5.1无参方法     

 🍓 5.2 有参方法

 🍓 5.3 获取所有方法(包含Object的方法)

项目源码下载地址 : https://download.csdn.net/download/qq_45481709/86708493


 🍏1. 创建一个Person实体类🍏

在后续的反射演示中我们都会拿Person类中的类名, 属性, 方法做演示

package com.learning.java.fanshe.domain;


import lombok.Data;

/**
 * 拓展 :
 * 1.构造器必须与类同名(如果一个源文件中有多个类,那么构造器必须与公共类同名)
 * 2.每个类可以有一个以上的构造器
 * 3.构造器可以有0个、1个或1个以上的参数
 * 4.构造器没有返回值
 * 5.构造器总是伴随着new操作一起调用
 */
@Data
public class Person {
    private String name;
    private Integer age;

    public String sex;

    public Person() {
    }
    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public void walk() {
        System.out.println("我在走路");
    }
    public void walk(String name) {
        System.out.println(name + "在走路");
    }
    private void a() {

    }


}

🍎 2. 反射获取Class类对象的三种方法🍎

🍎 2.1 通过全类名的方式获取

Class<?> a = Class.forName("com.learning.java.fanshe.domain.Person");
System.out.println(a);

首先这里的全类名可以理解为类的包路径

Class.forName的作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的静态代码段
输出结果 : 
class com.learning.java.fanshe.domain.Person

🍎 2.2 类名.class

Class<Person> b = Person.class;
System.out.println(b);

用Class.类名的方法, jvm把类加载进内存但不进行初始化,返回Class对象

输出结果 : 
class com.learning.java.fanshe.domain.Person

🍎 2.3 实例对象.getClass() 

Class<? extends Person> c = new Person().getClass();
System.out.println(c);

对类进行静态初始化、非静态初始化,返回引用是运行时真正所指对象(向上转型)所属类的Class对象

输出结果 : 
class com.learning.java.fanshe.domain.Person

🍎 2.4 总结

在完成上面三种获取class类对象后, 不难发现最后输出的结果是一样的, 这里我们再用代码证实一下

    public static void main(String[] args) throws Exception {
        Class<?> a = Class.forName("com.learning.java.fanshe.domain.Person");
        System.out.println(a);

        Class<Person> b = Person.class;
        System.out.println(b);

        Class<? extends Person> c = new Person().getClass();
        System.out.println(c);
        
        System.out.println(a == b);
        System.out.println(b == c);
        
    }
输出结果 : 
true
true

结论:

同一个字节码文件(*,c1ass)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的class对象都是同一个

 🍒 3. 反射获取属性变量 🍒

🍒 3.1 获取所有public修饰符的成员变量

Class<Person> persionClass = Person.class;
 Field[] fields = persionClass.getFields();
        for (Field field : fields) {
            //注: 这里只能获取public修饰的变量
            System.out.println(field);
        }
输出结果:
public java.lang.String com.learning.java.fanshe.domain.Person.sex

🍒 3.2 获取指定字段并赋值

Field sex = persionClass.getField("sex");
        //获取成员变量sex的值
        Person person = new Person();
        //设置a的值
        sex.set(person, "张安");
        Object o = sex.get(person);
        System.out.println(o);
输出结果: 
张安

 🍒 3.3 获取所有的成员变量(不考虑修饰符)

  for (Field declaredField : persionClass.getDeclaredFields()) {
            System.out.println(declaredField);
        }
输出结果:
private java.lang.String com.learning.java.fanshe.domain.Person.name
private java.lang.Integer com.learning.java.fanshe.domain.Person.age
public java.lang.String com.learning.java.fanshe.domain.Person.sex

🍒 3.4 获取私有的变量(利用暴力反射)

之前我们的属性name是私有属性 private String name 如果想获取就需要暴力setAccessible(true)

 //获取私有的变量
        Field name = persionClass.getDeclaredField("name");
        //忽略访问权限修饰符的安全检查(暴力反射)
        name.setAccessible(true);
        Object o1 = name.get(person);
        System.out.println(o1);

 这里因为并未给该变量赋值所以输出为null

输出结果:
null


🍔 4.反射获取构造方法 🍔

 🍔 4.1有参构造

        //创建有参
        Constructor<Person> constructor = persionClass.getConstructor(String.class, Integer.class);
        System.out.println(constructor);
        //创建对象
        Person person1 = constructor.newInstance("张三", 12);
        System.out.println(person1);
输出结果:
public com.learning.java.fanshe.domain.Person(java.lang.String,java.lang.Integer)
Person(name=张三, age=12, sex=null)

🍔 4.2无参构造

 //创建无参构造
        Constructor<Person> constructor1 = persionClass.getConstructor();
        System.out.println(constructor1);
        //创建对象
        Person person2 = constructor1.newInstance();
        System.out.println(person2);
输出结果:
public com.learning.java.fanshe.domain.Person()
Person(name=null, age=null, sex=null)

 🍔 4.3无参构造简便写法

 //无参构造的简便写法
        Person person3 = persionClass.newInstance();
        System.out.println(person3);
输出结果:
Person(name=null, age=null, sex=null)

🍓 5.反射获取成员方法 🍓

 🍓 5.1无参方法     

Method walk = persionClass.getMethod("walk");
        Person person4 = new Person();
        //执行方法
        walk.invoke(person4);
输出结果:
我在走路

 🍓 5.2 有参方法

Method walk1 = persionClass.getMethod("walk", String.class);
        walk1.invoke(person4,"张三");
输出结果:
张三在走路

 🍓 5.3 获取所有方法(包含Object的方法)

Method[] methods = persionClass.getMethods();
        for (Method method : methods) {
            method.setAccessible(true);
            //获取方法名称
            System.out.println(method.getName());
            System.out.println(method);
        }
equals
public boolean com.learning.java.fanshe.domain.Person.equals(java.lang.Object)
toString
public java.lang.String com.learning.java.fanshe.domain.Person.toString()
hashCode
public int com.learning.java.fanshe.domain.Person.hashCode()
getName
public java.lang.String com.learning.java.fanshe.domain.Person.getName()
setName
public void com.learning.java.fanshe.domain.Person.setName(java.lang.String)
walk
public void com.learning.java.fanshe.domain.Person.walk()
walk
public void com.learning.java.fanshe.domain.Person.walk(java.lang.String)
getAge
public java.lang.Integer com.learning.java.fanshe.domain.Person.getAge()
setAge
public void com.learning.java.fanshe.domain.Person.setAge(java.lang.Integer)
setSex
public void com.learning.java.fanshe.domain.Person.setSex(java.lang.String)
getSex
public java.lang.String com.learning.java.fanshe.domain.Person.getSex()
wait
public final void java.lang.Object.wait() throws java.lang.InterruptedException
wait
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
wait
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
getClass
public final native java.lang.Class java.lang.Object.getClass()
notify
public final native void java.lang.Object.notify()
notifyAll
public final native void java.lang.Object.notifyAll()
我在走路

相关文章:

  • JS学习762~780(注册事件+删除事件+DOM事件流+事件对象+阻止事件冒泡+事件委托鼠标事件+键盘事件)
  • 【华为机试真题Java】滑动窗口最大值
  • Triton测试
  • 监控文件事件
  • 【Node.js】官网学习笔记
  • 番茄ToDo语句精选
  • 树状数组。 数组修改某个元素的数值/求出前n个元素的和,需要在一百毫秒处理上百万个数字
  • 【操作系统】第一章 计算机系统概述
  • 【Vue】Vue的Mustache插值语法、v-bind指令
  • Android7.1.1系统,Toast的Exception: android.view.WindowManager$BadTokenException解决
  • TiKV 监控指标详解
  • 嵌入式系统开发笔记92:感受开源之美
  • VLC 编译安装 [for android, linux, windows]
  • 字节内部私藏的数据结构与算法刷题笔记,太顶了熬夜刷上头
  • 前端性能优化方法与实战开篇词 开启刻意练习之路,进阶前端性能技术专家
  • 2017-09-12 前端日报
  • 2019.2.20 c++ 知识梳理
  • Cookie 在前端中的实践
  • css属性的继承、初识值、计算值、当前值、应用值
  • gops —— Go 程序诊断分析工具
  • HomeBrew常规使用教程
  • JAVA之继承和多态
  • Java知识点总结(JavaIO-打印流)
  • k8s如何管理Pod
  • vue从入门到进阶:计算属性computed与侦听器watch(三)
  • windows下如何用phpstorm同步测试服务器
  • 给Prometheus造假数据的方法
  • 将 Measurements 和 Units 应用到物理学
  • 力扣(LeetCode)357
  • 深入浏览器事件循环的本质
  • 树莓派 - 使用须知
  • 思维导图—你不知道的JavaScript中卷
  • 跳前端坑前,先看看这个!!
  • 译米田引理
  • “十年磨一剑”--有赞的HBase平台实践和应用之路 ...
  • #define,static,const,三种常量的区别
  • #微信小程序(布局、渲染层基础知识)
  • (01)ORB-SLAM2源码无死角解析-(66) BA优化(g2o)→闭环线程:Optimizer::GlobalBundleAdjustemnt→全局优化
  • (day 2)JavaScript学习笔记(基础之变量、常量和注释)
  • (webRTC、RecordRTC):navigator.mediaDevices undefined
  • (编译到47%失败)to be deleted
  • (附程序)AD采集中的10种经典软件滤波程序优缺点分析
  • (附源码)php投票系统 毕业设计 121500
  • (附源码)springboot家庭装修管理系统 毕业设计 613205
  • (附源码)springboot美食分享系统 毕业设计 612231
  • (机器学习-深度学习快速入门)第一章第一节:Python环境和数据分析
  • (免费领源码)python#django#mysql公交线路查询系统85021- 计算机毕业设计项目选题推荐
  • (原)本想说脏话,奈何已放下
  • (转)Google的Objective-C编码规范
  • (转)visual stdio 书签功能介绍
  • .Net Core webapi RestFul 统一接口数据返回格式
  • .NET Core引入性能分析引导优化
  • .Net 访问电子邮箱-LumiSoft.Net,好用
  • .NET/C# 使用 #if 和 Conditional 特性来按条件编译代码的不同原理和适用场景
  • .NET/C# 异常处理:写一个空的 try 块代码,而把重要代码写到 finally 中(Constrained Execution Regions)