首页 > 编程语言 >JAVA反射是什么(反射的作用)

JAVA反射是什么(反射的作用)

时间:2024-10-12 10:22:16浏览次数:9  
标签:反射 JAVA String Person age person Class 作用 name

反射概述

反射是什么

反射 (Reflection) 是 Java 的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性。

Oracle 官方对反射的解释是:

Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to use reflected fields, methods, and constructors to operate on their underlying counterparts, within security restrictions. The API accommodates applications that need access to either the public members of a target object (based on its runtime class) or the members declared by a given class. It also allows programs to suppress default reflective access control.

简而言之,通过反射,我们可以在运行时获得程序或程序中每一个类型的成员和成员的信息。程序中一般的对象的类型都是在编译期就确定下来的,而 Java 反射机制可以动态地创建对象并调用其属性,这样的对象的类型在编译期是未知的。所以我们可以通过反射机制直接创建对象,即使这个对象的类型在编译期是未知的。

反射的核心是 JVM 在运行时才动态加载类或调用方法/访问属性,它不需要事先(写代码的时候或编译期)知道运行对象是谁。

反射的作用

  • 运行时判断任意一个对象所属的类;

  • 运行时创建任意一个类的对象;

  • 运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法);

  • 运行时调用任意一个对象的方法。

反射的使用

获取Class

Java的对象模型中:

  1. 所有的类都是Class类的实例,Object是类,那么Object也是Class类的一个实例。

  2. 所有的类都最终继承自Object类,Class是类,那么Class也继承自Object。

首先创建Person类:

package entity;

public class Person {
    private String name;
    public int age;

    public Person() {
    }

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

    public Person(int age) {
        this.age = age;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    private void playGame(){
        System.out.println("playing……");
    }

}

获取Class的方法有三种:

  1. 直接获取某个类的class

    Class<Person> personClass = Person.class;

  2. 调用某个对象的getClass()方法

    Person person = new Person();
    Class<? extends Person> personClass = person.getClass();

  3. 调用Class类的forName()静态方法

    Class<?> personClass = Class.forName("entity.Person");

生成实例对象

  1. 调用Class对象的newInstance()方法

    Person person = personClass.newInstance();

  2. 通过获取类的构造方法进行实例化

    • 无参构造

      Constructor<Person> constructor = personClass.getConstructor();
      Person person = constructor.newInstance();

    • 有参构造

      Constructor<Person> constructor = personClass.getConstructor(String.class, int.class);
      Person person = constructor.newInstance("tom", 18);

访问属性

  1. 访问公有属性

    // 获取age属性
    Field ageField = personClass.getField("age");
    // 获取person对象的age属性值
    Object age = ageField.get(person);
    System.out.println(age);
    ​
    ​
    //将person对象的age属性值设置为20
    ageField.set(person,20);
    System.out.println(person.age);

  2. 访问私有属性

    // 获取私有的name属性
    Field nameField = personClass.getDeclaredField("name");
    // 将name属性的可访问性设置为true
    nameField.setAccessible(true);
    // 获取person对象的name属性值
    Object name = nameField.get(person);
    System.out.println(name);
    ​
    // 将person对象的name属性值设置为jerry
    nameField.set(person,"jerry");
    System.out.println(person.getName());

调用方法

  1. 访问公有方法

    // 获取getName()方法
    Method getName = personClass.getMethod("getName");//getMethod(方法名,参数列表)
    // 通过person对象调用getName()方法,并获取执行结果
    Object name = getName.invoke(person);
    System.out.println(name);
    ​
    ​
    // 获取setName()方法
    Method setName = personClass.getMethod("setName", String.class);
    // 通过person对象调用setName()方法,并传递参数
    setName.invoke(person,"trump");
    System.out.println(person.getName());

  2. 访问私有方法

// 获取私有的playGame()方法
Method playGame = personClass.getDeclaredMethod("playGame");
// 将playGame()方法的可访问性设置为true
playGame.setAccessible(true);
// 通过person对象调用playGame()方法
playGame.invoke(person);

反射的应用

反射封装JDBC框架

传统写法:
 /**
     * 传统jdbc 写法
     *
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        //注册驱动
        Class.forName("com.mysql.jdbc.Driver");// 这句话可以省略 驱动自动加载

        Connection connection =
                DriverManager.getConnection("jdbc:mysql:///db01", "root", "root1234");
        // 如果换一张表  student代码就需要改变,下面的赋值 都需要改变 代码写死了 需要灵活
        //虽然我不知道 未来是那个实体类,可以利用反射 在运行时拿到book表对应实体类的信息
        PreparedStatement ps = connection.prepareStatement("insert into student(id,name) values(?,?)");
        ps.setInt(1, 1);
        ps.setString(2, "张三");
        int i = ps.executeUpdate();
        System.out.println(i > 0 ? "成功" : "失败");
        connection.close();
        //把可变的东西 改为灵活的
    }
//问题:每次需要写sql语句 而且sql语句的表名 每次都要换,参数数量不确定。封装一个insert方法
Guava
<dependency>
  <groupId>com.google.guava</groupId>
  <artifactId>guava</artifactId>
  <version>31.1-jre</version>
</dependency>
				//驼峰转下划线
        String tableName = "PersonDog";
        String to = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, tableName);
        System.out.println(to);//person_dog

        //下划线转驼峰
        String tableName = "person_dog";
        String to = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableName);
        System.out.println(to);//PersonDog

自定义注解

package com.codingfuture.annotation;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Id {
    String value = "";
}


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableName {
    String value();
}
  • Target

    • FIELD:表示"被标注的注解"只能出现在属性上。

    • TYPE:表示"被标注的注解"只能出现在类上。

    • METHOD:表示"被标注的注解"只能出现在方法上。

    • PARAMETER:表示"被标注的注解"只能出现在参数上。

    • CONSTRUCTOR:表示"被标注的注解"只能出现在构造上。

  • Retention

    • 这个Retention注解用来标注"被标注的注解"最终保存在哪里。 @Retention(RetentionPolicy.SOURCE):表示该注解只能被保留在java源文件中。 @Retention(RetentionPolicy.CLASS):表示该注解被保存在class文件中。 @Retention(RetentionPolicy.RUNTIME):表示该注解被保存在class文件中,并且可以被反射机制所读取。

  • 获取指定类型是否加参数

标签:反射,JAVA,String,Person,age,person,Class,作用,name
From: https://blog.csdn.net/2401_86518012/article/details/142871143

相关文章

  • Java日总结---JDBC
    JDBC就是使用java语言操作关系型数据库的一种API1.JDBAAPI---DriverManager(两个作用)注册驱动:在mysql8.0后是ClassforName("com.mysql.cj.jdbc.Driver");来实现的查看源码后发现是由Driver类中静态代码块,底层是由DriverManager中的registerDriver方法来做的提示:在mysql5......
  • JavaScript 第4章:函数与作用域
    在JavaScript中,函数是程序设计中的重要组成部分,它们用于封装一段代码以执行特定的任务。下面我们将逐一探讨第4章提到的各个概念。1.函数声明vs函数表达式函数声明(FunctionDeclaration)是使用function关键字定义一个函数,并给它命名的一种方式。这种方式定义的函数会......
  • 微信公众号推送每日天气(Java版)
    准备工作公众号必须经过企业认证,个人公众号的无法使用这是获取到微信公众号的appId、secret网址贴这儿了:https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index还有测试的模板申请每日一言,我这里使用的彩虹屁,地址:https://www.tianapi.com/......
  • Java在图片上写字生成新图片的代码实现
    引言在图像处理领域,有时我们需要在图片上添加文字,以生成带有特定信息的新图片。Java作为一种功能强大的编程语言,提供了多种库和工具来实现这一需求。本文将详细介绍如何使用Java在图片上写字,并生成一张新的图片。准备工作在开始编写代码之前,我们需要确保已经安装了Java开......
  • taozige/Java语言的Netty框架+云快充协议1.5+充电桩系统+新能源汽车充电桩系统源码
    云快充协议+云快充1.5协议+云快充1.6+云快充协议开源代码+云快充底层协议+云快充桩直连+桩直连协议+充电桩协议+云快充源码介绍云快充协议+云快充1.5协议+云快充1.6+云快充协议开源代码+云快充底层协议+云快充桩直连+桩直连协议+充电桩协议+云快充源码软件架构1、提供云快......
  • 【Java】创建对象的几种方式
    【Java】创建对象的几种方式合集-Java基础(11)1.【Java】Integer包装类缓存(cache)05-092.【java】Java之关于基本数据类型和引用数据类型的存放位置05-093.【java】ArrayList和LinkedList的区别05-104.【java】【集合类】HashMap与HashTable的区别05-105.【Java】的四种引用......
  • java计算机毕业设计管易tms运输智能监控管理系统(开题+程序+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在现代物流行业中,运输管理系统的智能化与高效化已成为提升企业竞争力的关键因素之一。随着电子商务和快递业务的迅猛发展,货物运输量急剧增加,传统的人......
  • java计算机毕业设计电子导游系统(开题+程序+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着旅游业的蓬勃发展,人们对于旅游体验的需求日益多样化和个性化。传统的导游方式已难以满足现代游客对于信息获取、行程规划及互动体验的需求。在此......
  • java计算机毕业设计M站内容管理系统(开题+程序+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着互联网技术的飞速发展,各类在线服务平台应运而生,为用户提供便捷、高效的服务体验。M站内容管理系统作为一种专门为管理网站内容设计的系统,其重要......
  • java+vue计算机毕设高教教师考核系统【源码+程序+论文+开题】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在当今高等教育快速发展的背景下,高校教师作为知识传授与科研创新的重要力量,其工作表现与贡献评估显得尤为关键。传统的高校教师考核方式往往依赖于纸......