Java反射

简介: Java反射

前言

框架通常借助设计模式、反射和配置文件等技术实现灵活的开发和可扩展性。今天我们就来了解反射这项技术。

一、反射概述

1.1 概念

Java中的反射是指在程序运行时检查、访问、修改变量、方法、调用构造函数的机制

Java中反射机制主要是由java.lang.Class类及其相关方法以及java.lang.reflect包中的Field、Method、Constructor类和访问控制相关类构成的。

1.2 作用

(1)可以在运行时动态地获取类、接口、方法、属性等对象的信息,实现了代码和数据的分离,增加了程序的灵活性和可扩展性。

(2)可以在运行时动态地创建对象、调用方法、操作属性,尤其使用在框架的开发中,可以通过反射机制灵活的使用已经存在的类库、组件库等。

(3)可以实现一些基于注解的编程技术,例如通过注解定义一些特定的属性信息,然后可以使用反射机制在程序运行时动态地读取和处理这些注解信息。

(4)反射机制可以实现一些基本Java中无法实现的特殊操作,例如通过反射机制访问私有成员,执行私有方法,实现单例模式等。

二、类类

Java中的类类是指java.lang.Class类,是Java反射机制的核心类之一。类类表示Java程序中的一个类或接口。

2.1常用方法

方法 描述
getName() 返回类的名称,包括包名
getSimpleName() 返回类的简单名称,不包括包名
getModifiers() 返回类的修饰符,例如public、private、static等
getPackage() 返回类所在的包
getFields() 返回类或接口的public字段
getDeclaredFields() 返回类或接口声明的所有字段,包括私有字段
getMethods() 返回类或接口的public方法
getDeclaredMethods() 返回类或接口声明的所有方法,包括私有方法
getConstructors() 返回类的public构造器
getDeclaredConstructors() 返回类声明的所有构造器,包括私有构造器

2.2实例化类类

这里有个Student类

package com.xqx.reflect;
public class Student {
  private String sid;
  private String sname;
  public Integer age;
  static {
    System.out.println("加载进jvm中!");
  }
  public Student() {
    super();
    System.out.println("调用无参构造方法创建了一个学生对象");
  }
  public Student(String sid) {
    super();
    this.sid = sid;
    System.out.println("调用带一个参数的构造方法创建了一个学生对象");
  }
  public Student(String sid, String sname) {
    super();
    this.sid = sid;
    this.sname = sname;
    System.out.println("调用带二个参数的构造方法创建了一个学生对象");
  }
  @SuppressWarnings("unused")
  private Student(Integer age,String sname) {
    System.out.println("调用Student类私且多参的构造方法创建一个学生对象");
    this.age = age;
    this.sname = sname;
  }
  public String getSid() {
    return sid;
  }
  public void setSid(String sid) {
    this.sid = sid;
  }
  public String getSname() {
    return sname;
  }
  public void setSname(String sname) {
    this.sname = sname;
  }
  public void hello() {
    System.out.println("你好!我是" + this.sname);
  }
  public void hello(String name) {
    System.out.println(name + "你好!我是" + this.sname);
  }
  @SuppressWarnings("unused")
  private Integer add(Integer a, Integer b) {
    return new Integer(a.intValue() + b.intValue());
  }
}

2.2.1Class.forName()

这个方法可以根据给定的类名获取对应的Class对象

Class c = Class.forName("com.xqx.reflect.Student");

2.2.2getClass()

该方法可以返回当前对象的类的Class对象。例如

Student stu=new Student();
      Class class1 = stu.getClass();

2.2.3类名.class

Class c1=Student.class;
System.out.println(c);
      System.out.println(c1);
      System.out.println(class1);

打印结果:

class com.xqx.reflect.Student
class com.xqx.reflect.Student
class com.xqx.reflect.Student

2.2.4创建类实例

获取了类的Class对象之后,就可以使用Class.newInstance()方法来创建类实例:

//一切反射从类类开始
    Class c = Class.forName("com.xqx.reflect.Student");
    //创建类实例 无参实例化
    Student stu = (Student) c.newInstance();

需要注意的是,newInstance()方法只能创建无参构造函数的类对象,如果存在有参构造函数,则需要使用Constructor类来创建类实例。同时,在Java 9中,newInstance()方法已被废弃,建议使用Class.getDeclaredConstructor()方法代替。

三、反射属性

通过Field类来获取对象的属性,也可以获取到私有属性,还可以设置属性的值。

3.1公有属性的获取与赋值

getDeclaredField()方法获取属性、get()方法打印获取到属性的值、set()方法为熟悉赋值

Student student = new Student();
    student.setSid("s001");
    student.setSname("xqx");
    student.age=18;
    //一切反射从类类开始
    Class<? extends Student> c = student.getClass();
    //获取到公有属性age
    Field ageField = c.getDeclaredField("age"); 
    System.out.println("修改前:"+ageField.get(student));
    ageField.set(student, 16);
    System.out.println("修改后:"+ageField.get(student));

打印结果:

加载进jvm中!
调用无参构造方法创建了一个学生对象
修改前:18
修改后:16

3.2私有属性的获取与赋值

获取与赋值方法跟公有属性一致,但必须打开权限setAccessible才可调用,否则报错

//拿到私有属性
    Field idField = c.getDeclaredField("sid");
    Field nameField = c.getDeclaredField("sname");
    //打开私有属性访问权限
    idField.setAccessible(true);
    nameField.setAccessible(true);
    System.out.println("修改前:"+idField.get(student));
    //修改
    idField.set(student, "s110");
    System.out.println("修改后:"+idField.get(student));
    System.out.println("修改前:"+nameField.get(student));
    nameField.set(student, "nb");
    System.out.println("修改后:"+nameField.get(student));

打印结果:

修改前:s001
修改后:s110
修改前:xqx
修改后:nb

3.3 获取所有属性

//拿到所有字段
    Field[] fields = c.getDeclaredFields();
    for (Field field : fields) {
      field.setAccessible(true);
      //拿到所有字段名、值
      System.out.println(field.getName() + ":" + field.get(student));
    }

打印结果:

sid:s110
sname:nb
age:16

3.4获取修饰符

Class类的getModifiers()方法可以返回一个int类型的修饰符,这个修饰符是由多个常量值通过位运算组合而成的。获取修饰符可以帮助我们更方便地了解一个类的特性,从而更好地理解并使用该类。

//拿到所有字段
    Field[] fields = c.getDeclaredFields();
    for (Field field : fields) {
      field.setAccessible(true);
      int modifiers = field.getModifiers();
      if (Modifier.isPublic(modifiers)) {
        System.out.println("public:"+field.getName());
        System.out.println("public修饰符的常量值:"+modifiers);
      }
      if (Modifier.isPrivate(modifiers)) {
        System.out.println("private:"+field.getName());
        System.out.println("private修饰符的常量值:"+modifiers);
      }
    }

打印结果:

private:sid
private修饰符的常量值:2
private:sname
private修饰符的常量值:2
public:age
public修饰符的常量值:1

四、反射方法

4.1 获取公有无参方法

// 一切反射从类类开始
    Class<Student> c = Student.class;
    // 创建类实例
    Student stu = (Student) c.newInstance();
    //获取无参方法  hello是方法名
    Method m = c.getMethod("hello");
    //调用方法
    Object invoke = m.invoke(stu);
    System.out.println(invoke);

打印结果:

加载进jvm中!
调用无参构造方法创建了一个学生对象
你好!我是null
null

4.2 获取公有一参方法

//获取有参方法  hello是方法名 String.class是参数类型
    Method m2 = c.getMethod("hello", String.class);
    //调用方法 stu是类实例  "nb"是要传的参数
    Object invoke2 = m2.invoke(stu, "nb");
    System.out.println(invoke2);

打印结果:

nb你好!我是null
null

4.3 获取私有多参方法

跟调用私有属性一样,必须打开访问权限setAccessible

//获取私有多参方法  add是方法名 Integer.class是参数类型
    Method m3 = c.getDeclaredMethod("add", Integer.class, Integer.class);
    // 打开访问权限
    m3.setAccessible(true);
    //调用方法 stu是类实例  22、33是要传的参数
    Object invoke3 = m3.invoke(stu, 22, 33);
    System.out.println(invoke3);

打印结果:

55

五、反射构造函数

5.1获取无参

//一切反射从类类开始
    Class c = Class.forName("com.xqx.reflect.Student");
    //创建类实例 无参实例化
    Student stu = (Student) c.newInstance();
    System.out.println(stu);

打印结果:

加载进jvm中!
调用无参构造方法创建了一个学生对象
com.xqx.reflect.Student@33909752

5.2 获取公有有参

//获取有参构造
    Constructor c1 =c.getConstructor(String.class);
    Student stu2 = (Student)c1.newInstance("s001");
    System.out.println(stu2);

打印结果:

调用带一个参数的构造方法创建了一个学生对象
com.xqx.reflect.Student@55f96302

5.3获取私有多参

//私有
    Constructor c3 =c.getDeclaredConstructor(Integer.class,String.class);
    //打开访问权限
    c3.setAccessible(true);
    Student stu4 = (Student)c3.newInstance(120,"xqx");
    System.out.println(stu4);

打印结果:

调用Student类私且多参的构造方法创建一个学生对象
com.xqx.reflect.Student@42a57993

六、总结

反射机制的基本步骤如下:

(1)获取Class对象。可以通过多种方式来获取Class对象,比如Class.forName()、Object.getClass()以及类字面常量等。

(2)创建实例对象。获取Class对象后,可以使用Class.newInstance()方法来创建类实例对象。

(3)获取或设置对象的属性。通过Field类来获取对象的属性,可以获取私有属性,也可以设置属性的值。

(4)调用对象的方法。通过Method类来获取对象的方法,可以获取私有方法,也可以调用方法。

(5)调用对象的构造函数。通过Constructor类来调用对象的构造函数。

好啦,今天的分享就到此为止!希望你看完本篇文章有所收获,祝你变得更强、未来出“粽”!!!

目录
相关文章
|
12天前
|
安全 Java 索引
Java——反射&枚举
本文介绍了Java反射机制及其应用,包括获取Class对象、构造方法、成员变量和成员方法。反射允许在运行时动态操作类和对象,例如创建对象、调用方法和访问字段。文章详细解释了不同方法的使用方式及其注意事项,并展示了如何通过反射获取类的各种信息。此外,还介绍了枚举类型的特点和使用方法,包括枚举的构造方法及其在反射中的特殊处理。
36 9
Java——反射&枚举
|
19天前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
25天前
|
Java 程序员 编译器
Java的反射技术reflect
Java的反射技术允许程序在运行时动态加载和操作类,基于字节码文件构建中间语言代码,进而生成机器码在JVM上执行,实现了“一次编译,到处运行”。此技术虽需更多运行时间,但广泛应用于Spring框架的持续集成、动态配置及三大特性(IOC、DI、AOP)中,支持企业级应用的迭代升级和灵活配置管理,适用于集群部署与数据同步场景。
|
9天前
|
存储 安全 Java
扫盲java基础-反射(一)
扫盲java基础-反射(一)
|
9天前
|
Java
扫盲java基础-反射(二)
扫盲java基础-反射(二)
|
3月前
|
安全 Java 测试技术
day26:Java零基础 - 反射
【7月更文挑战第26天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
30 5
|
2月前
|
缓存 安全 Java
【Java 第十篇章】反射
Java 反射技术让程序能在运行时动态获取类信息并操作对象,极大提升了灵活性与扩展性。本文将介绍反射的基本概念、原理及应用,包括如何使用 `Class`、`Field`、`Method` 和 `Constructor` 类进行动态操作。此外,还将探讨反射在动态加载、框架开发与代码测试中的应用场景,并提醒开发者注意性能与安全方面的问题,帮助你更合理地运用这一强大工具。
18 0
|
3月前
|
IDE Java 测试技术
Java进阶之反射
【7月更文挑战第14天】Java反射机制允许在运行时动态获取类信息、创建对象及调用其方法。它基于`Class`类,让我们能访问类的属性、方法、构造器。例如,通过`Class.forName()`加载类,`Class.newInstance()`创建对象,`Method.invoke()`执行方法。反射广泛应用于动态代理、单元测试、序列化及框架中,提供灵活性但牺牲了性能,且可破坏封装性。IDE的代码补全也是反射的应用之一。在使用时需谨慎,避免对私有成员的不当访问。
31 1
|
3月前
|
Java 程序员 测试技术
解析Java中的反射机制及其应用场景
解析Java中的反射机制及其应用场景
|
3月前
|
开发框架 Java Android开发
Java中的类反射与动态代理详解
Java中的类反射与动态代理详解
下一篇
无影云桌面