首页 > 编程语言 >Java反射详解

Java反射详解

时间:2023-10-20 16:31:46浏览次数:34  
标签:lang 反射 Java String Class Person 详解 java public

目录


一、概述


1、框架


2、反射


好处:


二、获取字节码class对象的方法


1、第一阶段——Source源代码阶段


2、第二阶段——Class类对象阶段


3、第三阶段——Runtime运行时阶段


4、代码演示


结论:


三、Class对象功能概述


1、获取成员变量


Field[] getFields()(获取所有公共成员变量)


Field getField(String name)(获取指定公共成员变量)


Field[] getDeclaredFields()(获取所有成员变量)


Field getDeclaredField(String name)(获取指定成员变量)


代码演示:


2、获取构造方法


Constructor[] getConstructors()(获取所有公共构造方法)


Constructor getConstructor(Class... parameterTypes)(获取所有指定公共构造方法)


Constructor[] getDeclaredConstructors()(获取所有构造方法)


Constructor getDeclaredConstructor(Class... parameterTypes)(获取指定构造方法)


代码演示:


3、获取成员方法


Method[] getMethods()(获取所有公共方法,包括继承自Object的)


Method getMethod(String name, Class... parameterTypes)(获取所有指定公共方法)


Method[] getDeclaredMethods()(获取所有方法,不包括继承自Object的)


Method getDeclaredMethod(String name, Class... parameterTypes)(获取指定方法)


代码演示:


4、获取类名


String getName()


代码演示:


四、案例


1、需求


2、实现分析


3、实现步骤


4、代码演示


学生类:


测试类:


一、概述

反射——框架设计的灵魂


1、框架

①半成品软件;


②可以在框架的基础上进行软件开发,简化代码;


③使用框架不需要会反射,但自己要开发框架就需要会反射;



2、反射

将类的各个组成部分封装为其他对象,这就是反射机制;


好处:

①可以在程序运行的过程中操作这些对象;


②可以解耦,提高程序的可扩展性;



二、获取字节码class对象的方法

1、第一阶段——Source源代码阶段

Class.forName("全类名"):将字节码文件加载到内存,返回Class对象;


多用于配置文件,将类名定义在配置文件中。读取文件,加载类;


2、第二阶段——Class类对象阶段

类名.class:通过类名的属性class获取;


多用于参数的传递;


3、第三阶段——Runtime运行时阶段

对象.getClass():getClass()定义在Object类中;


多用于对象获取字节码的方式;


4、代码演示

package study.reflect;
 
import study.method_references.Person;
 
public class Reflect {
    public static void main(String[] args) throws ClassNotFoundException {
        //1、第一阶段——Source源代码阶段
        //Class.forName("全类名"):将字节码文件加载到内存,返回Class对象;
        Class c1 = Class.forName("study.method_references.Person");
        System.out.println(c1);
        //2、第二阶段——Class类对象阶段
        //类名.class:通过类名的属性class获取;
        Class c2 = Person.class;
        System.out.println(c2);
        //3、第三阶段——Runtime运行时阶段
        //对象.getClass():getClass()定义在Object类中;
        Person person = new Person();
        Class c3 = person.getClass();
        System.out.println(c3);
        //这三个class都是同一个
        System.out.println(c1==c2);
        System.out.println(c1==c3);
        //true
        //true
    }
}

结论:

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



三、Class对象功能概述

别忘了,先获取类,再通过类获取;


1、获取成员变量

Field[] getFields()(获取所有公共成员变量)

返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共(public修饰的)字段;


Field getField(String name)(获取指定公共成员变量)

返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共(public修饰的)成员字段;


Field[] getDeclaredFields()(获取所有成员变量)

返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段;


Field getDeclaredField(String name)(获取指定成员变量)

返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段;


代码演示:

package study.reflect;
 
import study.method_references.Person;
 
import java.lang.reflect.Field;
 
public class GetFieldTest {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        //1、获取所有公共成员变量
        Person person = new Person();
        Class c = person.getClass();
        Field[] fields = c.getFields();
        for (Field field : fields) {
            System.out.println(field);
            //public java.lang.String study.method_references.Person.name
        }
        //2、获取指定公共成员变量
        Field field = c.getField("name");
        System.out.println(field);
        //public java.lang.String study.method_references.Person.name
        //3、获取指定的成员变量(不关乎修饰符)
        Field field1 = c.getDeclaredField("name");
        System.out.println(field1);
        //public java.lang.String study.method_references.Person.name
        Field field2 = c.getDeclaredField("name1");
        System.out.println(field2);
        //private java.lang.String study.method_references.Person.name1
        //4、获取所有成员变量(不关乎修饰符)
        Field[] fields1 = c.getDeclaredFields();
        for (Field field11 : fields1) {
            System.out.println(field11);
            //private java.lang.String study.method_references.Person.name1
            //public java.lang.String study.method_references.Person.name
        }
        //5、对获取的变量进行操作
        //获取值
        Person p1 = new Person();
        Object value1 = field.get(p1);
        System.out.println(value1);
        //设置值
        field.set(p1,"大哥");
        Object value2 = field.get(p1);
        System.out.println(value2);//大哥
    }
}


2、获取构造方法

Constructor<?>[] getConstructors()(获取所有公共构造方法)

返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共(public修饰的)构造方法;


Constructor<T> getConstructor(Class<?>... parameterTypes)(获取所有指定公共构造方法)

返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共(public修饰的)构造方法;


Constructor<?>[] getDeclaredConstructors()(获取所有构造方法)

返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法;


Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)(获取指定构造方法)

返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法;


代码演示:

package study.reflect;
 
import study.method_references.Person;
 
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
 
public class GetConstructorsTest {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //0、获取类
        Person person = new Person();
        Class c = person.getClass();
        //1、获取所有公共构造方法
        Constructor[] constructors = c.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
            //public study.method_references.Person(java.lang.String)
            //public study.method_references.Person()
        }
        //2、获取所有指定公共构造方法
        Constructor constructor = c.getConstructor(String.class);
        System.out.println(constructor);
        //public study.method_references.Person(java.lang.String)
        //3、获取所有构造方法
        Constructor[] constructors1 = c.getDeclaredConstructors();
        for (Constructor constructor1 : constructors1) {
            System.out.println(constructor1);
            //private study.method_references.Person(java.lang.String,java.lang.String)
            //public study.method_references.Person(java.lang.String)
            //public study.method_references.Person()
        }
        //4、获取指定构造方法
        Constructor constructor1 = c.getDeclaredConstructor(String.class,String.class);
        System.out.println(constructor1);
        //private study.method_references.Person(java.lang.String,java.lang.String)
        //5、使用构造方法创建对象
        Object p1 = constructor.newInstance("大哥");
        Person p2 = (Person)p1;
        System.out.println(p2.getName());//大哥
        p2.setName("大哥pro");
        System.out.println(p2.getName());//大哥pro
    }
}


3、获取成员方法

Method[] getMethods()(获取所有公共方法,包括继承自Object的)

返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共(public修饰的) member 方法;


Method getMethod(String name, Class<?>... parameterTypes)(获取所有指定公共方法)

返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共(public修饰的)成员方法;


Method[] getDeclaredMethods()(获取所有方法,不包括继承自Object的)

返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法;


Method getDeclaredMethod(String name, Class<?>... parameterTypes)(获取指定方法)

返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法;


代码演示:

package study.reflect;
 
import study.method_references.Person;
 
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
 
public class getMethodsTest {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //0、获取类
        Person person = new Person();
        Class c = person.getClass();
        //1、获取所有公共方法
        Method[] methods = c.getMethods();
        for (Method method : methods) {
            System.out.println(method);
            //public java.lang.String study.method_references.Person.getName()
            //public void study.method_references.Person.setName(java.lang.String)
            //public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
            //public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
            //public final void java.lang.Object.wait() throws java.lang.InterruptedException
            //public boolean java.lang.Object.equals(java.lang.Object)
            //public java.lang.String java.lang.Object.toString()
            //public native int java.lang.Object.hashCode()
            //public final native java.lang.Class java.lang.Object.getClass()
            //public final native void java.lang.Object.notify()
            //public final native void java.lang.Object.notifyAll()
        }
        //2、获取所有指定公共方法
        Method method = c.getMethod("getName");
        System.out.println(method);
        //public java.lang.String study.method_references.Person.getName()
        System.out.println("===============================");
        //3、获取所有方法
        Method[] methods1 = c.getDeclaredMethods();
        for (Method method1 : methods1) {
            System.out.println(method1);
            //public java.lang.String study.method_references.Person.getName()
            //public void study.method_references.Person.setName(java.lang.String)
            //private java.lang.String study.method_references.Person.getName1()
            //private void study.method_references.Person.setName1(java.lang.String)
        }
        //4、获取指定方法
        Method method1 = c.getDeclaredMethod("getName1");
        System.out.println(method1);
        //private java.lang.String study.method_references.Person.getName1()
        //5、调用方法
        Person p = new Person();
        //私有方法,可采用暴力反射
        method1.setAccessible(true);
        method1.invoke(p);//getName1被执行了……
    }
}

4、获取类名

String getName()

以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称;


代码演示:

package study.reflect;
 
import study.method_references.Person;
 
public class getNameTest {
    public static void main(String[] args) {
        //0、获取类
        Person person = new Person();
        Class c = person.getClass();
        //1、获取类名
        String className = c.getName();
        System.out.println(className);//study.method_references.Person
    }
}

四、案例

1、需求

写一个“框架”,在不改变类的代码的情况下,可以创建任意类,并调用其中的任意方法;



2、实现分析

配置文件+反射;



3、实现步骤

①将需要创建对象的全类名和需要执行的方法定义在配置文件中;


②在程序中加载配置文件;


③使用反射技术来加载类文件进内存;


④创建对象;


⑤执行方法;



4、代码演示

Java反射详解_System


学生类:

package study.reflect;
 
public class Student {
    public void study(){
        System.out.println("学习啦……");
    }
    public void sleep(){
        System.out.println("睡觉啦……");
    }
}

测试类:

package study.reflect;
 
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
 
public class DemoTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //①将需要创建对象的全类名和需要执行的方法定义在配置文件中;
 
        //②在程序中加载配置文件;
        //创建Properties
        Properties properties = new Properties();
        //获取类加载器
        ClassLoader classLoader = DemoTest.class.getClassLoader();
        //使用类加载器读取配置文件
        InputStream inputStream = classLoader.getResourceAsStream("pro.properties");
        //将配置文件转换为一个Properties集合
        properties.load(inputStream);
        //③使用反射技术来加载类文件进内存;
        String className = properties.getProperty("className");
        String methodName = properties.getProperty("methodName");
        Class c = Class.forName(className);
        //④创建对象;
        Object o = c.getDeclaredConstructor().newInstance();
        //⑤执行方法;
        Method method = c.getMethod(methodName);
        method.invoke(o);
        //睡觉啦……
    }
}



标签:lang,反射,Java,String,Class,Person,详解,java,public
From: https://blog.51cto.com/u_13272819/7956123

相关文章

  • xxl-job执行java任务报错: unable to find valid certification path to requested tar
    1、错误:xxl-job调用https接口显示证书验证失败[错误信息:sun.security.validator.ValidatorException:PKIXpathbuildingfailed:sun.security.provider.certpath.SunCertPathBuilderException:unabletofindvalidcertificationpathtorequestedtarget]2023-10-2015......
  • 【从零学习python 】02. 开发工具介绍及交互式编程及注释详解
    编写Python代码根据我们之前介绍的知识,我们知道,所谓代码其实就是将一段普通文本按照一定的规范编写,然后交给电脑解析并且执行。那既然是一段文本,那我们是否可以直接使用文本编辑器来编码呢?答案是肯定的,但是这样开发起来,效率会很低。一、常见的代码编辑工具实际上,在我们实际工作......
  • 79基于java的在线家政预约服务系统设计与实现(配套lun文,可参考做bi设)
    本章节给大家带来一个基于java在线家政预约服务系统设计与实现,可适用于java家政服务系统,java预约家政系统,java在线家政系统,在线服务系统,社会家政系统,家政管理系统,家政服务平台,家政更加服务平台系统,家政管理系统等等;项目背景现代社会,由于经济不断发展,家政服务的数量也在不断的......
  • Java 命名
    命名规范可用下划线但是不能用空格但因为Java是一个区分大小写的语言,所以使用驼峰原则会省下一个下划线的空间取名要简单易懂包名多单词全小写表名、列名不区分大小写,这个时候驼峰就不好使了,就全大/小写,然后下划线分割开类名、接口名首字母大写(大驼峰)变量名、方法名......
  • Maven中的dependencyManagement 详解
    1.作用:在Maven中dependencyManagement的作用其实相当于一个对所依赖jar包进行版本管理的管理器。2.pom.xml文件中,jar的版本判断的两种途径:(1)如果dependencies里的dependency自己没有声明version元素,那么maven就会到dependencyManagement里面去找有没有对该artifactId和groupI......
  • Java对接科大讯飞星火大模型实战
    Java对接讯飞认知大模型教程,先注册账号领取免费测试额度获取个人免费额度个人免费购买星火认知大模型V2.0获取秘钥平台地址:讯飞开放平台pom.xml文件<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>s......
  • 在Java中,可以使用`java.nio.file`包中的`Files`类来进行文件搜索。以下是一种模糊搜索
    在Java中,可以使用`java.nio.file`包中的`Files`类来进行文件搜索。以下是一种模糊搜索文件的方法:```javaimportjava.io.IOException;importjava.nio.file.*;importjava.nio.file.attribute.BasicFileAttributes;publicclassFileSearch{publicstaticvoidmain(String......
  • 00-开源离线同步工具DataX3.0重磅详解!
    1概览DataX是一个异构数据源离线同步工具,致力于实现包括关系型数据库(MySQL、Oracle等)、HDFS、Hive、ODPS、HBase、FTP等各种异构数据源之间稳定高效的数据同步功能。1.1设计理念为了解决异构数据源同步问题,DataX将复杂的网状的同步链路变成了星型数据链路,DataX作为中间传......
  • Java拾贝第七天——包装类、BigInteger、BigDecimal
    Java拾贝不建议作为0基础学习,都是本人想到什么写什么基本数据类型怎么变化引用数据类型(对象)Java为每种基本类型都提供了对应的包装类型:基本数据类型包装类intIntegercharCharactershortShortlongLongfloatFloatdoubleDoublebooleanBoolean......
  • Java基础的转义符、数据类型和标识符
    1.转义符把字符转义成特殊含义或原来意思,这就是转义符的作用例如:1publicclassDemo{2publicstaticvoidmain(String[]args){3//\":因为在Java中双引号(")是有特殊含义的双引号是成双成对出现的4//当你想打印一个双引号时,就需要运用转义......