欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

java学习笔记【反射以及反射的简单应用】

时间:2023-06-08
文章目录

1.什么是反射?---描述类的编译阶段

1.1 如何获取Person类的字节码文件对象呢?1.2 如何通过字节文件对象获取构造器对象Constructor,创建类的实例!1.3 如何通过反射的方式,获取带参数的构造方法,创建当前类的实例!1.4 如何通过类的字节码文件对象获取成员变量所在的Field类对象,并对成员属性赋值! 2.反射的应用

2.1 有一个ArrayList集合,ArrayList,里面添加一些字符串元素 如何给ArrayList添加Integer类型的元素?2.2 已知两个类Student/Worker类,里面都有一个love()方法 在测试类Test2中,测试的时候,当需要学生类的时候,调用love->爱学习,爱生活,啥都爱!" 1.什么是反射?—描述类的编译阶段

反射:
通过获取类或者接口的字节码文件对象,(正在运行的类)Class类对象,
然后获取类中构造方法所在的对象java.lang.reflect.Constructor,创建当前类实例
然后还可以获取类中的成员方法所在的java.lang.reflect.Field对象,然后去给成员变量赋值
还可以获取类中的成员方法所在的java.lang.reflect.Method对象,可以调用成员方法了!

1.1 如何获取Person类的字节码文件对象呢?

Object类的getClass()方法;

任意Java类型的class属性

在Class类中有一个静态功能(使用居多:参数为String类型–>可以放在配置文件中)
public static Class<?> forName(String className) throws ClassNotFoundException
​ 参数是所需类的全限定名称(包名.类名)

public class PersonDemo { public static void main(String[] args) throws ClassNotFoundException { Person p1 = new Person() ; System.out.println(p1); Person p2 = new Person() ; System.out.println(p2); System.out.println(p1 == p2); //false,都需要在堆内存中开辟空间 System.out.println("==========================================="); //方法1:Object类的getClass()方法 Class c1 = p1.getClass(); System.out.println(c1); Class c2 = p2.getClass() ; System.out.println(c2); System.out.println(c1 == c2); System.out.println("============================================"); //方法2:任意Java类型的class属性(最直接的) Class c3 = Person.class ; System.out.println(c3); System.out.println(c1 == c3); System.out.println(c2 == c3); System.out.println("==========================================="); //方法3: //forName()所需类的完全限定名称(包名.类名) Class c4 = Class.forName("com.qf.reflect.Person") ; System.out.println(c4);//class com.qf.reflect.Person System.out.println(c1 == c4); System.out.println("============================================="); //public String getName();获取字节码文件对象中的全限定名称 String name = c4.getName() ; System.out.println(name);//com.qf.reflect.Person }}

1.2 如何通过字节文件对象获取构造器对象Constructor,创建类的实例!

之前的写法:
创建一个Person类对象,无参构造方法公共的 类名 对象名 = new 类名() ;
现在:

使用反射的方式来创建Person类的实例1)获取Person类的字节码文件对象Class2)获取构造方法Constructor类对象 getConstructors() :获取类中所有的公共的构造方法的类对象 getDeclaredConstructors() :获取当前类中所有的构造方法的类对象(包括私有)3)通过构造方法Construcotr类对象来创建当前类的实例!4)输出对象名称

import java.lang.reflect.Constructor;public class ReflectDemo { public static void main(String[] args) throws Exception { //之前的写法 Person p = new Person() ;//Person{name='null', age=0, gender='null'} System.out.println(p); System.out.println("====================="); //1)获取字节码文件对象 Class c = Class.forName("com.qf.reflect.Person") ; //2)获取指定的公共的无参构造方法 Constructor constructor = c.getConstructor() ; //3) 通过构造方法Constructor类对象来创建当前类的实例! //public T newInstance(Object..、initargs):创建当前类的实例 ,参数可变参数, 描述给构造方法的实际参数 Object obj = constructor.newInstance(); System.out.println(obj); //obj---->相当上面的p对象 }}

1.3 如何通过反射的方式,获取带参数的构造方法,创建当前类的实例!

import java.lang.reflect.Constructor;public class ReflectDemo2 { public static void main(String[] args) throws Exception { //1)获取Person类的字节码文件对象 Class personClazz = Class.forName("com.qf.reflect.Person") ; //2)获取指定的构造方法的类对象Constructor //获取指定的构造方法,参数是参数类型的字节码文件对象 // private Person(String name,int age) Constructor constructor = personClazz.getDeclaredConstructor(String.class,int.class,String.class) ; //参数为true,取消java语言访问检查 constructor.setAccessible(true); Object obj = constructor.newInstance("张三",23,"女") ; System.out.println(obj); //Person{name='张三', age=23, gender='女'} } }

1.4 如何通过类的字节码文件对象获取成员变量所在的Field类对象,并对成员属性赋值!

import java.lang.reflect.Constructor;import java.lang.reflect.Field;public class ReflectDemo3 { public static void main(String[] args) throws Exception{ //1)获取字节码文件对象 Class clazz = Class.forName("com.qf.reflect.Person") ; //通过字节码文件对象获取公共的空参构造方法类对象 Constructor con = clazz.getConstructor() ; //通过con构造方法类对象创建当前类实例(Person) Object obj = con.newInstance();// //System.out.println(obj); //2)通过字节码文件对象获取指定的公共的字段的类对象Field Field nameField = clazz.getField("name"); //field的特有的方法-->给成员变量赋值 //参数1:当前指定的实例 //参数2:给成员变量实际参数 nameField.set(obj,"高圆圆"); //获取指定的字段类对象(包括私有,受保护的,默认的修饰符) //getDeclaredField(String name) Field ageField = clazz.getDeclaredField("age"); //取消java语言访问检查 ageField.setAccessible(true); //赋值 ageField.set(obj,43) ; System.out.println(obj); }}

2.反射的应用 2.1 有一个ArrayList集合,ArrayList,里面添加一些字符串元素 如何给ArrayList添加Integer类型的元素?

import java.lang.reflect.Method;import java.util.ArrayList;public class ReflectArrayListDemo { public static void main(String[] args) throws Exception { //创建一个ArrayList ArrayList arrayList = new ArrayList<>() ; arrayList.add("hello") ; arrayList.add("world") ; arrayList.add("javaEE") ; System.out.println(arrayList); //通过反射获取ArrayList集合的字节码文件对象 //一共三种方式 Class clazz = arrayList.getClass() ; System.out.println(clazz); //获取当前的这个成员方法所在Method类对象 Method m = clazz.getMethod("add",Object.class) ; //调用方法 m.invoke(arrayList,100) ; m.invoke(arrayList,200) ; System.out.println(arrayList); }}

2.2 已知两个类Student/Worker类,里面都有一个love()方法 在测试类Test2中,测试的时候,当需要学生类的时候,调用love->爱学习,爱生活,啥都爱!"

//学生类public class Student { public void love(){ System.out.println("爱学习,爱生活,啥都爱!"); }}// 工人类public class Worker { public void love(){ System.out.println("爱生活,爱java"); }}//classname.properties文件className=com.qf.reflect_02.WorkermethodName=love//测试类import java.io.InputStream;import java.lang.reflect.Method;import java.util.Properties;public class Test2 { public static void main(String[] args) throws Exception { //1)读取src下面的配置文件classname.properties ---->获取src类路径下的资源文件所在的输入流 InputStream inputStream = Test2.class.getClassLoader() .getResourceAsStream("classname.properties") ; //2) 创建一个属性列表集合类对象:Properties Properties prop = new Properties() ; //将配置文件中的内容加载到属性列列表集合中 prop.load(inputStream); //3)获取className键对应的值 String className = prop.getProperty("className") ; String methodName = prop.getProperty("methodName") ; //4)获取当前className键对应的类型的字节码文件对象 Class clazz = Class.forName(className); //直接创建当前类的实例 Object obj = clazz.newInstance(); //5)通过字节码文件对象获取成员方法Method对象 Method method = clazz.getMethod(methodName); //6)调用方法 method.invoke(obj) ; }}

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。