Java重点:反射机制的使用

本文涉及的产品
可观测可视化 Grafana 版,10个用户账号 1个月
应用实时监控服务-应用监控,每月50GB免费额度
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
简介: J2EE中的反射(Reflection)是指在程序运行期间访问、检测和修改自身的状态或行为。通过反射,可以动态地获取一个类的所有成员变量、方法、构造函数等信息,并且可以在运行时调用这些成员。在J2EE中,反射可以地,以及其他能的应用程序。什么是反射?反射(Reflection)是一种在运行时动态地获取和操作对象的能力,它允许程序通过对象的类类型来了解对象的成员和方法,并且可以在运行时调用这些成员和方法。


一、概念

J2EE中的反射(Reflection)是指在程序运行期间访问、检测和修改自身的状态或行为。通过反射,可以动态地获取一个类的所有成员变量、方法、构造函数等信息,并且可以在运行时调用这些成员。在J2EE中,反射可以方便实现一些框架ORM工具,以及其他动态性要求的应用程序。

什么是反射?

反射(Reflection)是一种在运行时动态地获取和操作对象的能力,它允许程序通过对象的类类型来了解对象的成员和方法,并且可以在运行时调用这些成员和方法。反射可以用于许多目的,例如在运行时动态加载类、实例化对象、查看和修改对象的属性和方法、调用私有方法和构造函数,等等。在Java中,反射通过java.lang.reflect包中的类和接口来实现。反射的优点是可以使我们的代码更加灵活和动态,但是反射的开销比较大,因此在性能要求较高的情况下,应该谨慎使用。

总的来说:反射Java语言中的一种机制,通过这种机制可以动态的实例化对象、读写属性、调用方法

二、类类

在Java反射(reflection)中,Class类被称为“类类”(class of class),因为它代表了JVM中的一个类。每个Java类在内存中都有一个对应的Class类实例对象,可以通过Java的反射机制获取。通过这个实例,我们可以动态地获取创建操作一个类的各种元数据(如属性、方法、注解等),并可以在程序运行时动态地创建、修改该类的对象。通过反射,我们可以实现更加灵活和动态的编程方式,可以在编码阶段不确定访问的类和方法,直到运行时才确定需要获取和调用的类和方法。

1、类类的获取方式

1. Object类中的getClass()方法:可以获取一个对象所属的类。

2. 类名.class:直接通过类名这种语法形式获取一个类的Class实例对象

3. Class.forName(String className):过类的全限定名获取Class实例对象,需要处理ClassNotFoundException异常。

这些方式均可以获得一个Java类的Class实例对象,从而可以利用反射机制获取该类的一系列信息,如属性、方法、构造方法、注解等。

1)类名.Class

在开始示例的前期准备工作我们写一个类(Class)

package com.tgq.reflect;
/**
 * 一个类
 * 
 * @author tgq
 *
 */
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) {
    System.out.println("调用Student类私有的构造方法创建一个学生对象");
    this.age = age;
  }
  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());
  }
}

image.gif

编写好一个类之后我们开始调用方法进行拿去:代码示例

package com.tgq.reflect;
/**
 * 类类的获取方式: 1、类名.Class 2、对象.getClass(); 3、Class.forName();
 * 
 * @author tgq
 *
 */
public class Demo_01 {
  @SuppressWarnings("rawtypes")
  public static void main(String[] args) throws Exception {
    // 1、类名.Class
    Class c1 = Student.class;
    System.out.println(c1);
  }
}

image.gif

输出结果:

image.gif编辑

2)对象.getClass()

package com.tgq.reflect;
/**
 * 类类的获取方式: 1、类名.Class 2、对象.getClass(); 3、Class.forName();
 * 
 * @author tgq
 *
 */
public class Demo_01 {
  @SuppressWarnings("rawtypes")
  public static void main(String[] args) throws Exception {
    // 1、类名.Class
    // Class c1 = Student.class;
    // System.out.println(c1);
    // 2、对象.getClass();
    Student student = new Student();
    Class c2 = student.getClass();
    System.out.println(c2);
  }
}

image.gif

输出结果:

image.gif编辑

3)Class.forName()

package com.tgq.reflect;
/**
 * 类类的获取方式: 1、类名.Class 2、对象.getClass(); 3、Class.forName();
 * 
 * @author tgq
 *
 */
public class Demo_01 {
  @SuppressWarnings("rawtypes")
  public static void main(String[] args) throws Exception {
    // 1、类名.Class
    // Class c1 = Student.class;
    // System.out.println(c1);
    // 2、对象.getClass();
    // Student student = new Student();
    // Class c2 = student.getClass();
    // System.out.println(c2);
    // 3、Class.forName();
    Class c3 = Class.forName("com.tgq.reflect.Student");
    System.out.println(c3);
  }
}

image.gif

输出结果:

image.gif编辑

三、反射实例化

在Java中,可以使用反射来实例化一个类。具体实现可以通过Class类的newInstance()方法或者Constructor类的newInstance()方法来实现。

三个常用的方法:getConstructor ()getDeclaredConstructor ()newInstance()

一切的反射从类类开始

1、调用一个公有的无参构造方法

public class Demo_02 {
  @SuppressWarnings("rawtypes")
  public static void main(String[] args) throws Exception {
    // 一切反射从类类开始
    // 不管是哪一种获取类类的方法都是可以的
    // Class c1 = Class.forName("com.tgq.reflect.Student");
    // Student student = new Student();
    // Class c1 = student.getClass();
    Class c1 = Student.class;
    /*
     * 1、调用一个无参构造器反射实例化: 如果没有无参构造器是会报错的
     */
    Student stu1 = (Student) c1.newInstance();
    System.out.println(stu1);
  }
}

image.gif

输出结果:

image.gif编辑

2、调用一个公有的一个参构造方法

public class Demo_02 {
  @SuppressWarnings("rawtypes")
  public static void main(String[] args) throws Exception {
    // 一切反射从类类开始
    // 不管是哪一种获取类类的方法都是可以的
    // Class c1 = Class.forName("com.tgq.reflect.Student");
    // Student student = new Student();
    // Class c1 = student.getClass();
    Class c1 = Student.class;
    /*
     * 1、调用一个无参构造器反射实例化: 如果没有无参构造器是会报错的
     */
    Student stu1 = (Student) c1.newInstance();
    System.out.println(stu1);
    /*
     * 调用有参构造器必须要实例化构造器对象 2、调用一个有一个参数的构造器:getConstructor == 获取构造器对象
     * 
     * parameterTypes:代表了参数的类别Class
     */
    Constructor con1 = c1.getConstructor(String.class);
    Student stu2 = (Student) con1.newInstance("s1");
    System.out.println(stu2);
  }
}

image.gif

输出结果:

image.gif编辑

3、调用一个公有的两个参构造方法

public class Demo_02 {
  @SuppressWarnings("rawtypes")
  public static void main(String[] args) throws Exception {
    // 一切反射从类类开始
    // 不管是哪一种获取类类的方法都是可以的
    // Class c1 = Class.forName("com.tgq.reflect.Student");
    // Student student = new Student();
    // Class c1 = student.getClass();
    Class c1 = Student.class;
    /*
     * 1、调用一个无参构造器反射实例化: 如果没有无参构造器是会报错的
     */
    Student stu1 = (Student) c1.newInstance();
    System.out.println(stu1);
    /*
     * 调用有参构造器必须要实例化构造器对象 2、调用一个有一个参数的构造器:getConstructor == 获取构造器对象
     * 
     * parameterTypes:代表了参数的类别Class
     */
    Constructor con1 = c1.getConstructor(String.class);
    Student stu2 = (Student) con1.newInstance("s1");
    System.out.println(stu2);
    /*
     * 3、调用两个参数的构造器实例化
     */
    Constructor con2 = c1.getConstructor(String.class, String.class);
    Student stu3 = (Student) con2.newInstance("s1", "sb");
    System.out.println(stu3);
  }
}

image.gif

输出结果:

image.gif编辑

4、调用一个私有的一个参构造方法

public class Demo_02 {
  @SuppressWarnings("rawtypes")
  public static void main(String[] args) throws Exception {
    // 一切反射从类类开始
    // 不管是哪一种获取类类的方法都是可以的
    // Class c1 = Class.forName("com.tgq.reflect.Student");
    // Student student = new Student();
    // Class c1 = student.getClass();
    Class c1 = Student.class;
    /*
     * 1、调用一个无参构造器反射实例化: 如果没有无参构造器是会报错的
     */
    Student stu1 = (Student) c1.newInstance();
    System.out.println(stu1);
    /*
     * 调用有参构造器必须要实例化构造器对象 2、调用一个有一个参数的构造器:getConstructor == 获取构造器对象
     * 
     * parameterTypes:代表了参数的类别Class
     */
    Constructor con1 = c1.getConstructor(String.class);
    Student stu2 = (Student) con1.newInstance("s1");
    System.out.println(stu2);
    /*
     * 3、调用两个参数的构造器实例化
     */
    Constructor con2 = c1.getConstructor(String.class, String.class);
    Student stu3 = (Student) con2.newInstance("s1", "sb");
    System.out.println(stu3);
    /*
     * 4、调用一个私有的带一个参数的构造器实例化: getConstructor只能获取公有的构造器对象
     *
     * getDeclaredConstructor:获取私有的构造器对象
     */
    Constructor con3 = c1.getDeclaredConstructor(Integer.class);
    // 打开私有的访问权限
    con3.setAccessible(true);
    Student stu4 = (Student) con3.newInstance(1);
    System.out.println(stu4);
  }
}

image.gif

输出结果:

image.gif编辑

四、反射:方法调用

1、公有无参

public class Demo_03 {
  public static void main(String[] args) throws Exception {
    Class c = Student.class;
    // 1、反射调用 无参方法
    Student s = (Student) c.newInstance();
    // 反射调用无参方法,先获取到方法对象
    // name:方法名
    // parameterTypes:调用这个方法要传的参数类型
    Method m1 = c.getMethod("hello");
    // invoke:方法的返回值
    // obj:类示例
    // args:参数值
    Object invoke = m1.invoke(s);
    System.out.println(invoke);
  }
}

image.gif

输出结果:

image.gif编辑

2、公有有参

public class Demo_03 {
  public static void main(String[] args) throws Exception {
    Class c = Student.class;
    // 1、反射调用 无参方法
    Student s = (Student) c.newInstance();
    // 反射调用无参方法,先获取到方法对象
    // name:方法名
    // parameterTypes:调用这个方法要传的参数类型
    Method m1 = c.getMethod("hello");
    // invoke:方法的返回值
    // obj:类示例
    // args:参数值
    Object invoke = m1.invoke(s);
    System.out.println(invoke);
    // 2、调用有参方法
    Method m2 = c.getMethod("hello", String.class);
    Object invoke2 = m2.invoke(s, "asdfghjk");
    System.out.println(invoke2);
  }
}

image.gif

输出结果:

image.gif编辑

3、私有有参

public class Demo_03 {
  public static void main(String[] args) throws Exception {
    Class c = Student.class;
    // 1、反射调用 无参方法
    Student s = (Student) c.newInstance();
    // 反射调用无参方法,先获取到方法对象
    // name:方法名
    // parameterTypes:调用这个方法要传的参数类型
    Method m1 = c.getMethod("hello");
    // invoke:方法的返回值
    // obj:类示例
    // args:参数值
    Object invoke = m1.invoke(s);
    System.out.println(invoke);
    // 2、调用有参方法
    Method m2 = c.getMethod("hello", String.class);
    Object invoke2 = m2.invoke(s, "asdfghjk");
    System.out.println(invoke2);
    // 3、调用有参私有的方法
    Method m3 = c.getDeclaredMethod("add", Integer.class, Integer.class);
    // 打开私有权限
    m3.setAccessible(true);
    Object invoke3 = m3.invoke(s, 1, 2);
    System.out.println(invoke3);
  }
}

image.gif

输出结果:

image.gif编辑

完整代码:

package com.tgq.reflect;
import java.lang.reflect.Method;
/**
 * 反射动态方法的调用
 * 
 * @author tgq
 *
 */
public class Demo_03 {
  public static void main(String[] args) throws Exception {
    Class c = Student.class;
    // 1、反射调用 无参方法
    Student s = (Student) c.newInstance();
    // 反射调用无参方法,先获取到方法对象
    // name:方法名
    // parameterTypes:调用这个方法要传的参数类型
    Method m1 = c.getMethod("hello");
    // invoke:方法的返回值
    // obj:类示例
    // args:参数值
    Object invoke = m1.invoke(s);
    System.out.println(invoke);
    // 2、调用有参方法
    Method m2 = c.getMethod("hello", String.class);
    Object invoke2 = m2.invoke(s, "asdfghjk");
    System.out.println(invoke2);
    // 3、调用有参私有的方法
    Method m3 = c.getDeclaredMethod("add", Integer.class, Integer.class);
    // 打开私有权限
    m3.setAccessible(true);
    Object invoke3 = m3.invoke(s, 1, 2);
    System.out.println(invoke3);
  }
}

image.gif

五、反射:读写属性

通过Field类的get()set()方法来实现。

拿到我们所有的属性:

public class Demo_04 {
  public static void main(String[] args) throws Exception {
    Class c = Student.class;
    Student stu = new Student("1", "1A");
    // 我们把age设置一个值
    stu.age = 18;
    // System.out.println(stu.getSid());
    // 获取对象中全部的属性
    Field[] fields = c.getDeclaredFields();
    // 遍历
    for (Field f : fields) {
      // 因为sid、sname是私有的,所以我们要打开私有权限
      f.setAccessible(true);
      // 获取所有属性
      System.out.println(f.getName() + ":" + f.get(stu));
    }
  }
}

image.gif

输出结果:

image.gif编辑

我们进行设置属性值:

public class Demo_04 {
  public static void main(String[] args) throws Exception {
    Class c = Student.class;
    Student stu = new Student("1", "1A");
    // 我们把age设置一个值
    stu.age = 18;
    // System.out.println(stu.getSid());
    // 拿到属性
    Field snamefield = c.getDeclaredField("sname");
    // 打开权限
    snamefield.setAccessible(true);
    // 进行设置
    snamefield.set(stu, "2B");
    // 获取对象中全部的属性
    Field[] fields = c.getDeclaredFields();
    // 遍历
    for (Field f : fields) {
      // 因为sid、sname是私有的,所以我们要打开私有权限
      f.setAccessible(true);
      // 获取所有属性
      System.out.println(f.getName() + ":" + f.get(stu));
    }
  }
}

image.gif

输出结果:

image.gif编辑

完整代码:

package com.tgq.reflect;
import java.lang.reflect.Field;
/**
 * 反射:读写属性
 * 
 * @author tgq
 *
 */
public class Demo_04 {
  public static void main(String[] args) throws Exception {
    Class c = Student.class;
    Student stu = new Student("1", "1A");
    // 我们把age设置一个值
    stu.age = 18;
    // System.out.println(stu.getSid());
    // 拿到属性
    Field snamefield = c.getDeclaredField("sname");
    // 打开权限
    snamefield.setAccessible(true);
    // 进行设置
    snamefield.set(stu, "2B");
    // 获取对象中全部的属性
    Field[] fields = c.getDeclaredFields();
    // 遍历
    for (Field f : fields) {
      // 因为sid、sname是私有的,所以我们要打开私有权限
      f.setAccessible(true);
      // 获取所有属性
      System.out.println(f.getName() + ":" + f.get(stu));
    }
  }
}

image.gif


相关文章
|
23天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
61 2
|
27天前
|
Java 编译器
探索Java中的异常处理机制
【10月更文挑战第35天】在Java的世界中,异常是程序运行过程中不可避免的一部分。本文将通过通俗易懂的语言和生动的比喻,带你了解Java中的异常处理机制,包括异常的类型、如何捕获和处理异常,以及如何在代码中有效地利用异常处理来提升程序的健壮性。让我们一起走进Java的异常世界,学习如何优雅地面对和解决问题吧!
|
1月前
|
XML 安全 Java
Java反射机制:解锁代码的无限可能
Java 反射(Reflection)是Java 的特征之一,它允许程序在运行时动态地访问和操作类的信息,包括类的属性、方法和构造函数。 反射机制能够使程序具备更大的灵活性和扩展性
43 5
Java反射机制:解锁代码的无限可能
|
26天前
|
Java 数据库连接 开发者
Java中的异常处理机制及其最佳实践####
在本文中,我们将探讨Java编程语言中的异常处理机制。通过深入分析try-catch语句、throws关键字以及自定义异常的创建与使用,我们旨在揭示如何有效地管理和响应程序运行中的错误和异常情况。此外,本文还将讨论一些最佳实践,以帮助开发者编写更加健壮和易于维护的代码。 ####
|
1月前
|
安全 IDE Java
Java反射Reflect机制详解
Java反射(Reflection)机制是Java语言的重要特性之一,允许程序在运行时动态地获取类的信息,并对类进行操作,如创建实例、调用方法、访问字段等。反射机制极大地提高了Java程序的灵活性和动态性,但也带来了性能和安全方面的挑战。本文将详细介绍Java反射机制的基本概念、常用操作、应用场景以及其优缺点。 ## 基本概念 ### 什么是反射 反射是一种在程序运行时动态获取类的信息,并对类进行操作的机制。通过反射,程序可以在运行时获得类的字段、方法、构造函数等信息,并可以动态调用方法、创建实例和访问字段。 ### 反射的核心类 Java反射机制主要由以下几个类和接口组成,这些类
60 2
|
1月前
|
存储 缓存 安全
🌟Java零基础:深入解析Java序列化机制
【10月更文挑战第20天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
29 3
|
1月前
|
安全 Java UED
深入理解Java中的异常处理机制
【10月更文挑战第25天】在编程世界中,错误和意外是不可避免的。Java作为一种广泛使用的编程语言,其异常处理机制是确保程序健壮性和可靠性的关键。本文通过浅显易懂的语言和实际示例,引导读者了解Java异常处理的基本概念、分类以及如何有效地使用try-catch-finally语句来处理异常情况。我们将从一个简单的例子开始,逐步深入到异常处理的最佳实践,旨在帮助初学者和有经验的开发者更好地掌握这一重要技能。
28 2
|
1月前
|
Java 数据库连接 开发者
Java中的异常处理机制####
本文深入探讨了Java语言中异常处理的核心概念,通过实例解析了try-catch语句的工作原理,并讨论了finally块和throws关键字的使用场景。我们将了解如何在Java程序中有效地管理错误,提高代码的健壮性和可维护性。 ####
|
1月前
|
Java
Java中的反射机制与应用实例
【10月更文挑战第22天】Java作为一门面向对象的编程语言,提供了丰富的特性来支持对象的创建、操作和交互。其中,反射机制是Java的一项核心特性,它允许程序在运行时动态地获取类的信息、创建对象、调用方法、访问属性等。本文将从三个部分探讨Java中的反射机制及其应用实例:一是反射机制的基本概念和原理;二是反射机制在Java中的应用场景;三是通过实例深入理解反射机制的使用方法和技巧。
24 4
|
2月前
|
安全 Java 程序员
深入浅出Java中的异常处理机制
【10月更文挑战第20天】本文将带你一探Java的异常处理世界,通过浅显易懂的语言和生动的比喻,让你在轻松阅读中掌握Java异常处理的核心概念。我们将一起学习如何优雅地处理代码中不可预见的错误,确保程序的健壮性和稳定性。准备好了吗?让我们一起踏上这段旅程吧!
28 6