15-基础加强-1-类加载器反射
文章目录
- 1.类加载器
- 1.1类加载器【理解】
- 1.2类加载的过程【理解】
- 1.3类加载的分类【理解】
- 1.4双亲委派模型【理解】
- 1.5ClassLoader 中的两个方法【应用】
- 2.反射
- 2.1反射的概述【理解】
- 2.2获取Class类对象的三种方式【应用】 第1步:获取类的Class对象
- 2.3反射获取构造方法并使用【应用】第2.1步:利用Class类获取对象方法
- 2.3.1Class类获取构造方法对象的方法
- 2.3.2Constructor类用于创建对象的方法 (构造方法获取到了,接下来第3步:利用构造方法创建对象了)
- 2.3.3小结
- 2.4反射获取成员变量并使用【应用】
- 2.4.1Class类获取成员变量对象的方法 (第2步:获取成员变量 (第1步已经获取了Class类对象了))
- 2.4.2Field类用于给成员变量赋值的方法 (第3步:使用成员变量 (前面已经获取到了成员变量对象了))
- 2.5反射获取成员方法并使用【应用】
- 2.5.1Class类获取成员方法对象的方法 (第2步:用Class类对象获取成员方法)
- 2.5.2Method类用于执行方法的方法 (第3步:前面已经获取了成员方法,这里该执行成员方法了)
- 小结:反射根据配置文件动态创建对象并执行方法
- LX 再手敲一遍,读取配置文件,动态创建类对象,获取方法并执行
1.类加载器
1.1类加载器【理解】
-
作用
负责将.class文件(存储的物理文件)加载在到内存中

1.2类加载的过程【理解】
-
类加载时机
- 创建类的实例(对象)
- 调用类的类方法
- 访问类或者接口的类变量,或者为该类变量赋值
- 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
- 初始化某个类的子类
- 直接使用java.exe命令来运行某个主类
-
类加载过程
-
加载
- 通过包名 + 类名,获取这个类,准备用流进行传输
- 将这个类加载到内存中
- 加载完毕创建一个class对象 类在内存中不能随便乱放,得为每个类创建一个Class对象来存放这个类的信息
-

-
链接
-
验证
确保Class文件字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身安全
(文件中的信息是否符合虚拟机规范有没有安全隐患)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HzUSJvbX-1676707016232)(.\img\03_类加载过程验证.png)]](https://img-blog.csdnimg.cn/4ec0cb922b7b40e2ae0988d19b5a04e8.png)
-
准备
负责为类的类变量(被static修饰的变量)分配内存,并设置默认初始化值
(初始化静态变量) 静态变量有默认的初始化值 开辟空间 赋值为null 注意只为static修饰的静态变量赋初值
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VrfQ087y-1676707016234)(.\img\04_类加载过程准备.png)]](https://img-blog.csdnimg.cn/c963a7a572ad4a5f8b0ba6f9f839ad00.png)
-
解析
将类的二进制数据流中的符号引用替换为直接引用
(本类中如果用到了其他类,此时就需要找到对应的类)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B12DVgn5-1676707016235)(.\img\05_类加载过程解析.png)]](https://img-blog.csdnimg.cn/f59c894982de4c479bc58cfe8ee4205c.png)

-
“将类的二进制数据流中的符号引用替换为直接引用”:
加载好了类Student,但是其成员name是引用类型,对应的String类到底有没有被加载呀,加载了在哪呀? 所以String先是符号引用
----内存中找到String类------ 就变成了 直接引用(String类型)
-
初始化
根据程序员通过程序制定的主观计划去初始化类变量和其他资源
(静态变量赋值以及初始化其他资源)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dxugFrGa-1676707016235)(.\img\06_类加载过程初始化.png)]](https://img-blog.csdnimg.cn/6b8b187cbaf049b88662426bca1a93b9.png)
-
小结
- 当一个类被使用的时候,才会加载到内存
- 类加载的过程: 加载、验证、准备、解析、初始化
1.3类加载的分类【理解】
-
分类
- Bootstrap class loader:虚拟机的内置类加载器,通常表示为null ,并且没有父null
- Platform class loader:平台类加载器,负责加载JDK中一些特殊的模块
- System class loader:系统类加载器(应用程序类加载器),负责加载用户类路径上所指定的类库
-
类加载器的继承关系
- System的父加载器为Platform
- Platform的父加载器为Bootstrap
1.4双亲委派模型【理解】
-
介绍
如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器,如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是双亲委派模式
是逻辑上的父子关系,不是extends的继承父子关系。 就是把类加载任务委托给‘父亲’去加载
某个父亲加载不了就返回,直到最后没办法,自己才去加载
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yyyPYrfH-1676709561222)(.\img\07_双亲委派模型.png)]](https://img-blog.csdnimg.cn/9e92b5140ff8402a90633cf6b09afd98.png)
1.5ClassLoader 中的两个方法【应用】
-
方法介绍
方法名 说明 public static ClassLoader getSystemClassLoader() 获取系统类加载器 public InputStream getResourceAsStream(String name) 加载某一个资源文件 public class ClassLoaderDemo1 {public static void main(String[] args) {//获得系统类加载器ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();//获得系统类加载器的父加载器 --- 平台类加载器ClassLoader platformClassLoader = systemClassLoader.getParent();//获得平台类加载器的父加载器 --- 启动类加载器ClassLoader bootstrapClassLoader = platformClassLoader.getParent();System.out.println("系统类加载器"+systemClassLoader);System.out.println("平台类加载器"+platformClassLoader);System.out.println("启动类加载器"+bootstrapClassLoader);} }
-
LX 读取properties文件
- prop.properties
name=zhangsan age=13- ClassLoaderDemo2.java
public class ClassLoaderDemo2 {public static void main(String[] args) throws IOException {//static ClassLoader getSystemClassLoader() 获取系统类加载器//InputStream getResourceAsStream(String name) 加载某一个资源文件//获取系统类加载器ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();//利用加载器去加载一个指定的文件//参数:文件的路径(放在src的根目录下,默认去那里加载)//返回值:字节流。InputStream is = systemClassLoader.getResourceAsStream("prop.properties");Properties prop = new Properties();prop.load(is);System.out.println(prop);is.close();} }
- ClassLoaderDemo2.java 整理后很简单
public class ClassLoaderDemo2_1 {public static void main(String[] args) throws IOException {// 获得系统类加载器ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();// 利用加载器加载一个指定文件 返回字节流InputStream is = systemClassLoader.getResourceAsStream("prop.properties");Properties prop = new Properties();prop.load(is);System.out.println("prop = " + prop);is.close();} }
2.反射
2.1反射的概述【理解】
-
反射机制
是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意属性和方法;
这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。
2.2获取Class类对象的三种方式【应用】 第1步:获取类的Class对象
-
三种方式分类
-
类名.class属性
-
对象名.getClass()方法
-
Class.forName(全类名)方法
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sADuhDGD-1676715280381)(.\img\08_获取Class对象的三种方式.png)]](https://img-blog.csdnimg.cn/43cddb01d05c4b4b8e6137836e3c4615.png)
-
-
示例代码
Student.java
package cn.whu.myreflect1;public class Student {private String name;private int age;//空参构造,全参构造,toString,所有get/setpublic void study(){System.out.println("学生在学习");}
}
ReflectDemo1.java
/*** 各种获取类的Class对象的方法*/
public class ReflectDemo1 {public static void main(String[] args) throws ClassNotFoundException {//方法1.Class类中的静态方法forName("全类名") //所谓全类名: 包名.类名Class clazz = Class.forName("cn.whu.myreflect1.Student");System.out.println(clazz);//class cn.whu.myreflect1.Student//方法2.通过class属性来获取Class clazz2 = Student.class;System.out.println(clazz2);//class cn.whu.myreflect1.Student//方法3.利用对象的getClass方法来获取class对象//getClass方法是定义在Object类中的,所以任何对象都有Student stu = new Student();Class clazz3 = stu.getClass();System.out.println(clazz3);//class cn.whu.myreflect1.StudentSystem.out.println(clazz == clazz2);//trueSystem.out.println(clazz2 == clazz3);//true}
}

无视修饰符: 无视private还是public
有了Class对象可以干嘛,可以获取类的所有信息,主要也就三类:构造器、普通方法、成员变量
Class对象组成如下:

2.3反射获取构造方法并使用【应用】第2.1步:利用Class类获取对象方法
2.3.1Class类获取构造方法对象的方法
-
方法介绍
方法名 说明 Constructor<?>[] getConstructors() 返回所有公共构造方法对象的数组 Constructor<?>[] getDeclaredConstructors() 返回所有构造方法对象的数组 Constructor getConstructor(Class<?>… parameterTypes) 返回单个公共构造方法对象 Constructor getDeclaredConstructor(Class<?>… parameterTypes) 返回单个构造方法对象
- Student.java
package cn.whu.myreflect2;public class Student {private String name;private int age;//私有的有参构造private Student(String name){System.out.println("name值为:"+name);System.out.println("private Student 有参构造方法");}//公共无参构造public Student() {System.out.println("public Student 无参构造方法");}//公共有参构造public Student(String name,int age){System.out.println("name值为:"+name+" age值为:"+age);System.out.println("public Student 有参构造方法");}
}
- Constructor<?>[] getConstructors() 返回所有公共构造方法对象的数组
public static void main(String[] args) throws ClassNotFoundException {//1.不管那种获取方法 第一步都得先获取Class对象啊Class<?> clazz = Class.forName("cn.whu.myreflect2.Student");//2. Constructor<?>[] getConstructors() 返回所有公共构造方法对象的数组Constructor<?>[] constructors = clazz.getConstructors();for (Constructor<?> constructor : constructors) {System.out.println(constructor);}}

- Constructor<?>[] getDeclaredConstructors() 返回所有构造方法对象的数组
public static void main(String[] args) throws ClassNotFoundException {//1.不管那种获取方法 第一步都得先获取Class对象啊Class<?> clazz = Class.forName("cn.whu.myreflect2.Student");//2. Constructor<?>[] getDeclaredConstructors() 返回所有构造方法对象的数组Constructor<?>[] declaredAnnotations = clazz.getDeclaredConstructors();for (Constructor declaredAnnotation : declaredAnnotations) {System.out.println(declaredAnnotation);}

- Constructor getConstructor(Class<?>… parameterTypes) 返回单个公共构造方法对象
参数就写构造方法的形式参数类型对应的Class类
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {//1.不管那种获取方法 第一步都得先获取Class对象啊Class<?> clazz = Class.forName("cn.whu.myreflect2.Student");//2. Constructor getConstructor(Class<?>… parameterTypes) 返回单个公共构造方法对象Constructor<?> constructor1 = clazz.getConstructor();System.out.println(constructor1);//public cn.whu.myreflect2.Student() 公共空参构造Constructor<?> constructor2 = clazz.getConstructor(String.class, int.class);//参数类型就写构造方法的形参类型和顺序System.out.println(constructor2);//public cn.whu.myreflect2.Student(java.lang.String,int) //string,int参构造方法//Constructor<?> constructor3 = clazz.getConstructor(int.class);//报错 并没有一个参数为(int)的构造方法}

- Constructor getDeclaredConstructor(Class<?>… parameterTypes) 返回单个构造方法对象
私有的也可以获取到
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {//1.不管那种获取方法 第一步都得先获取Class对象啊Class<?> clazz = Class.forName("cn.whu.myreflect2.Student");//2. Constructor getDeclaredConstructor(Class<?>… parameterTypes) 返回单个构造方法对象// 私有的也可以获取到Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(String.class);System.out.println(declaredConstructor);}

2.3.2Constructor类用于创建对象的方法 (构造方法获取到了,接下来第3步:利用构造方法创建对象了)
-
方法介绍
方法名 说明 T newInstance(Object…initargs) 根据指定的构造方法创建对象 setAccessible(boolean flag) 设置为true,表示取消访问检查
- T newInstance(Object…initargs) 根据指定的构造方法创建对象
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {//1. 第一步永远都是先获取Class对象Class<?> clazz = Class.forName("cn.whu.myreflect2.Student");//2.获取构造方法对象Constructor<?> constructor = clazz.getConstructor(String.class, int.class);//3.利用newInstance 创建Student对象Student student = (Student) constructor.newInstance("张三",23); // 当然创建对象时的实参值得这时候传递了// 此时,构造方法会自动执行System.out.println("student = " + student);}

类似的调用空参构造
public static void main(String[] args) throws Exception {//1. 第一步永远都是先获取Class对象Class<?> clazz = Class.forName("cn.whu.myreflect2.Student");//2.获取构造方法对象Constructor<?> constructor = clazz.getConstructor();//3.利用newInstance 创建Student对象Student student = (Student) constructor.newInstance(); // 当然创建对象时的实参值得这时候传递了// 此时,构造方法会自动执行System.out.println("student = " + student);}

空参构造还有个简写方式(过时方法 了解即可)
public static void main(String[] args) throws Exception { // 反射调用空参创建对象简写格式//1. 第一步永远都是先获取Class对象Class<?> clazz = Class.forName("cn.whu.myreflect2.Student");//2. 在Class类中,有一个newInstance方法,可以利用空参直接创建一个对象 (直接跳过了获得构造对象那一步)Student student = (Student) clazz.newInstance(); // 该方法已经过时 了解即可System.out.println(student);}

- setAccessible(boolean flag) 设置为true,表示取消访问检查(可以临时使用私有成员了)
★获取一个私有的构造方法,创建对象★
多一步,临时取消访问检查
public static void main(String[] args) throws Exception {//1. 第一步永远都是先获取Class对象Class<?> clazz = Class.forName("cn.whu.myreflect2.Student");//2.获取构造私有方法对象Constructor<?> constructor = clazz.getDeclaredConstructor(String.class);//直接创建对象会报错 毕竟私有,直接调用私有构造方法肯定不妥//也即:被private修饰的成员,不能直接使用//如果用反射强行获取并使用,需要临时取消访问检查constructor.setAccessible(true);//临时取消(私有)访问检查//3.利用newInstance 创建Student对象Student student = (Student) constructor.newInstance("张三"); // 当然创建对象时的实参值得这时候传递了// 此时,构造方法会自动执行System.out.println("student = " + student);}

反射可以强行获取私有方法,并强行用其获取对象
2.3.3小结
-
获取class对象
三种方式: Class.forName(“全类名”), 类名.class, 对象名.getClass()
-
获取里面的构造方法对象
getConstructor (Class<?>... parameterTypes) getDeclaredConstructor (Class<?>… parameterTypes)
-
如果是public的,直接创建对象
newInstance(Object… initargs)
-
如果是非public的,需要临时取消检查,然后再创建对象
setAccessible(boolean) 暴力反射

2.4反射获取成员变量并使用【应用】
2.4.1Class类获取成员变量对象的方法 (第2步:获取成员变量 (第1步已经获取了Class类对象了))
-
方法分类
方法名 说明 Field[] getFields() 返回所有公共成员变量对象的数组 Field[] getDeclaredFields() 返回所有成员变量对象的数组 Field getField(String name) 返回单个公共成员变量对象 Field getDeclaredField(String name) 返回单个成员变量对象
公共成员变量:仅仅public修饰的成员变量
所有成员变量:public、private、protect… 修饰的成员变量
- Student.java
public class Student {public String name;public int age;public String gender;private int money = 300;//3个public 仅仅int money一个private
}
- Field[] getFields() 返回所有公共成员变量对象的数组 (仅仅public)
public static void main(String[] args) throws Exception {//Field[] getFields() 返回所有公共成员变量对象的数组//1.第一步永远还是获取对呀类的Class对象Class clazz = Class.forName("cn.whu.myreflect3.Student");//2.第二步:获取Field对象Field[] fields = clazz.getFields();for (Field field : fields) {System.out.println(field); //所有public成员变量}}

- Field[] getDeclaredFields() 返回所有成员变量对象的数组 (包括私有)
public static void main(String[] args) throws Exception {//Field[] getDeclaredFields() 返回所有成员变量对象的数组 (包括私有)//1.第一步永远还是获取对呀类的Class对象Class clazz = Class.forName("cn.whu.myreflect3.Student");//2.第二步:获取Field对象Field[] declaredFields = clazz.getDeclaredFields();for (Field declaredField : declaredFields) {System.out.println(declaredField);}}

- Field getField(String name) 返回单个公共成员变量对象 (仅仅public)
public static void main(String[] args) throws Exception {//Field getField(String name) 返回单个公共成员变量对象//1.第一步永远还是获取对呀类的Class对象Class clazz = Class.forName("cn.whu.myreflect3.Student");//2.第二步:获取Field对象Field age = clazz.getField("age"); //传入变量名即可//Field age = clazz.getField("age1"); //倘若没有这个变量 则会报错//Field money = clazz.getField("money"); //私有的也会报错System.out.println(age);}

- Field getDeclaredField(String name) 返回单个成员变量对象 (包括私有)
public static void main(String[] args) throws Exception { //Field getDeclaredField(String name) 返回单个成员变量对象//1.第一步永远还是获取对呀类的Class对象Class clazz = Class.forName("cn.whu.myreflect3.Student");//2.第二步:获取Field对象Field age = clazz.getDeclaredField("age"); // 传入变量名 获取公有变量Field money = clazz.getDeclaredField("money"); // 私有的也可以获取System.out.println(age);System.out.println(money);}

2.4.2Field类用于给成员变量赋值的方法 (第3步:使用成员变量 (前面已经获取到了成员变量对象了))
-
方法介绍
方法名 说明 void set(Object obj, Object value) 赋值 Object get(Object obj) 获取值
第一个参数就是要赋值或者获取值的 具体对象 (一个类好多对象 到底赋值给哪个对象,肯定要说明一下的)
- 示例代码
- void set(Object obj, Object value) 赋值
public static void main(String[] args) throws Exception {//void set(Object obj, Object value) 赋值//1.第一步永远还是获取对呀类的Class对象Class clazz = Class.forName("cn.whu.myreflect3.Student");//2.获取age这个Filed对象Field age = clazz.getField("age");//3.利用set方法进行赋值//3.1先创建一个Student对象 (不然赋值给谁呢?)Student student = (Student) clazz.newInstance();//空参的简写形式(跳过了获取构造方法那步)//3.2有了对象才可以给指定对象进行赋值age.set(student,18); //给student对象的age属性赋值18System.out.println(student.age);//18}

-
Object get(Object obj) 获取值
访问私有成员,都必须取消访问检查
public static void main(String[] args) throws Exception {//Object get(Object obj) 获取值//1.第一步永远还是获取对呀类的Class对象Class clazz = Class.forName("cn.whu.myreflect3.Student");//2.获取age这个Filed对象Field money = clazz.getDeclaredField("money");//直接获取一个私有的//3.☆想再下面访问私有成员,都必须取消访问检查money.setAccessible(true);//4.调用get方法,获取money值//4.1 还是得提前创建实际对象Student student = (Student) clazz.newInstance();//4.2 获取指定对象的money值Object val = money.get(student);System.out.println(val);//300}

2.5反射获取成员方法并使用【应用】
2.5.1Class类获取成员方法对象的方法 (第2步:用Class类对象获取成员方法)
-
方法分类
方法名 说明 Method[] getMethods() 返回所有公共成员方法对象的数组,包括继承的 Method[] getDeclaredMethods() 返回所有成员方法对象的数组,不包括继承的 Method getMethod(String name, Class<?>… parameterTypes) 返回单个公共成员方法对象 Method getDeclaredMethod(String name, Class<?>… parameterTypes) 返回单个成员方法对象 -
示例代码
-
Student.java
public class Student {// 私有,无参,无返回值private void fun(){System.out.println("私有的show方法,无参,无返回值");}// 公共,无参,无返回值public void fun1(){System.out.println("公共的fun1方法,无参,无返回值");}// 公共,有参,无返回值public void fun2(String name){System.out.println("公共的fun2方法,有参,无返回值, 参数为:"+name);}// 公共,无参,有返回值public String fun3(){System.out.println("公共的fun3方法,无参,有返回值, 参数为:");return "zhangsan";}// 公共,有参,有返回值public String fun4(String name){System.out.println("公共的fun4方法,有参,有返回值, 参数为:"+name);return "zhangsan";}
}
- Method[] getMethods() 返回所有公共成员方法对象的数组,包括继承的
public static void main(String[] args) throws Exception {//Method[] getMethods() 返回所有公共成员方法对象的数组,包括继承的//1.第一步永远是先获取Class对象Class clazz = Class.forName("cn.whu.myreflect4.Student");//2.获取成员方法对象Method[] methods = clazz.getMethods();//所有公共成员方法for (Method method : methods) {System.out.println(method); // 所有public都打印出来了 (包括一大堆从Object里继承的)}}

- Method[] getDeclaredMethods() 返回所有成员方法对象的数组,不包括继承的
public static void main(String[] args) throws Exception {//extracted1();//Method[] getDeclaredMethods() 返回所有成员方法对象的数组,不包括继承的//1.第一步永远是先获取Class对象Class clazz = Class.forName("cn.whu.myreflect4.Student");//2.获取成员方法对象Method[] declaredMethods = clazz.getDeclaredMethods();//所有方法,包括私有 (但继承的就获取不到了 (私有的也不会被继承))for (Method declaredMethod : declaredMethods) {System.out.println(declaredMethod);}}

- Method getMethod(String name, Class<?>… parameterTypes) 返回单个公共成员方法对象
public static void main(String[] args) throws Exception {//Method getMethod(String name, Class<?>… parameterTypes) 返回单个公共成员方法对象//1.第一步永远是先获取Class对象Class clazz = Class.forName("cn.whu.myreflect4.Student");//2.获取成员方法对象Method fun1 = clazz.getMethod("fun1");//第一个参数方法名,该方法本身有参数就接着写在后面System.out.println(fun1); // public void cn.whu.myreflect4.Student.fun1()//获取有形参的方法Method fun2 = clazz.getMethod("fun2", String.class); // 方法名,形参1.class,形参2.class ....System.out.println(fun2); // public void cn.whu.myreflect4.Student.fun2(java.lang.String)}
- Method getDeclaredMethod(String name, Class<?>… parameterTypes) 返回单个成员方法对象 (主要用来获取私有成员)
public static void main(String[] args) throws Exception {//Method getDeclaredMethod(String name, Class<?>… parameterTypes) 返回单个成员方法对象//1.第一步永远是先获取Class对象Class clazz = Class.forName("cn.whu.myreflect4.Student");//2.获取成员方法对象 私有fun方法Method fun = clazz.getDeclaredMethod("fun");System.out.println(fun);//只是看一下 完全可以(不必取消访问检查)}

2.5.2Method类用于执行方法的方法 (第3步:前面已经获取了成员方法,这里该执行成员方法了)
-
方法介绍
方法名 说明 Object invoke(Object obj, Object… args) 运行方法 参数一: 用obj对象调用该方法
参数二: 调用方法的传递的实际参数(如果没有就不写)
返回值: 方法的返回值(如果没有就不写)
-
示例代码
public static void main(String[] args) throws Exception {//Object invoke(Object obj, Object… args) 运行方法//参数一: 用obj对象调用该方法//参数二: 调用方法的传递的实际参数(如果没有就不写)//返回值: 方法的返回值(如果没有就不写)//1. 第一步永远是先获取Class对象Class clazz = Class.forName("cn.whu.myreflect4.Student");//2. 获取里面的Method对象, fun4 (最难的,有参,有返回值)Method fun4 = clazz.getMethod("fun4", String.class);//要指定方法参数类型//3. 运行方法//3.1 先得创建实际对象,作为方法的调用者(对象调用方法运行嘛)Student student = (Student) clazz.newInstance();//又是简写形式(跳过了获取构造器的一步)//3.2 有了对象,就可以在该对象上执行方法了Object ret = fun4.invoke(student,"myname"); //实参 依次写在后面 有返回值就直接接收就行了System.out.println(ret);}

小结:反射根据配置文件动态创建对象并执行方法
小结:
1、获取Class对象
Class clazz = Class.forName("cn.whu.myreflect1.Student");
Class clazz2 = Student.class;
Class clazz3 = new Student().getClass();2、通过Class对象获取三类成员
Constructor constructor = clazz.getConstructor(); // 获取构造器 (详细介绍了多种方式)
Method method = clazz.getMethod("name"); //获取方法 (详细介绍了多种方式)
Field field clazz.getField(String name) // 获取变量名 (详细介绍了多种方式)3、通过获取的构造器创建对象
Object o = constructor.newInstance();4、通过对象和方法,执行对应方法
method.invoke(o);//学生在学习
反射可以根据配置文件,动态创建对象,并调用对象的方法

ReflectDemo2.java
package cn.whu.myreflect1;import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;/*** 根据配置文件创建对象,并执行对象方法*/
public class ReflectDemo2 {public static void main(String[] args) throws ClassNotFoundException, IOException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {//获取系统类加载器,加载prop.properties文件InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("prop.properties");//得先创建一个Properties集合Properties prop = new Properties();//将文件中的数据读取到集合中prop.load(is);is.close();//---- 下面利用【反射】创建对象并调用方法 ----// 死步骤 能看懂 最好是记住//获取字节码文件对象Class clazz = Class.forName(prop.getProperty("className"));//配置文件里className配置好的全路径名//(通过类Class对象)获取构造器对象Constructor constructor = clazz.getConstructor();//利用构造器创建一个对象Object o = constructor.newInstance();//获取方法对象Method method = clazz.getMethod(prop.getProperty("methodName"));//配置文件里配置好的方法名//运行方法method.invoke(o);//学生在学习}
}
prop.properties
className=cn.whu.myreflect1.Worker
methodName=work

LX 再手敲一遍,读取配置文件,动态创建类对象,获取方法并执行
propLX.properties
className=cn.whu.LX.Worker
methodName=show
Worker.java
package cn.whu.LX;public class Worker {private String name;private int age;public Worker() {}public Worker(String name, int age) {this.name = name;this.age = age;}public String show(){System.out.println("我叫"+name+" 我今年"+age+"岁啦");//成员变量 类内部可以随便访问return "明年就"+(age+1)+"岁啦";}}
myreflectLX.java
package cn.whu.LX;import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;public class myreflectLX {public static void main(String[] args) throws Exception {// 1.类加载器获取输入流 读取Property配置文件 获取配置信息InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("propLX.properties");Properties prop = new Properties();prop.load(is);is.close();System.out.println("prop = "+prop);String className = prop.getProperty("className");String methodName = prop.getProperty("methodName");System.out.println("className = "+className);System.out.println("methodName = "+methodName);//2.反射 动态根据(类名className)和(其方法名methodName) 创建对象 并用对象调用该方法//2.1 获取Class对象Class clazz = Class.forName(className);//有了Class对象 啥都能获取了//2.2 获取有参数构造并创建对象Constructor constructor = clazz.getConstructor(String.class, int.class);Worker worker = (Worker) constructor.newInstance("紫英", 24);//2.3 获取方法Method method = clazz.getMethod(methodName);//2.4 用对象调用方法Object ret = method.invoke(worker);//该方法有返回值就接收System.out.println(ret);}
}

相关文章:
15-基础加强-1-类加载器反射
文章目录1.类加载器1.1类加载器【理解】1.2类加载的过程【理解】1.3类加载的分类【理解】1.4双亲委派模型【理解】1.5ClassLoader 中的两个方法【应用】2.反射2.1反射的概述【理解】2.2获取Class类对象的三种方式【应用】 第1步:获取类的Class对象2.3反射获取构造方…...
基于SSM,Spring, BootStrap 毕业设计管理系统的设计与实现
目录 一.前言介绍 二、主要技术 2.1 SSM框架介绍 2.2 MYSQL数据库 2.3 持久层框架MyBatis 2.4 前端框架BootStrap 三. 系统设计 3.1 系统架构设计 3.2 系统功能模块 3.2.1 学生模块 3.2.2 教师模块 3.2.3 管理员模块 四、数据库设计 4.1 数据分析 4.2 概念设计 …...
一招鉴别真假ChatGPT,并简要介绍ChatGPT、GPT、GPT2和GPT3模型之间的区别和联系
以下内容除红色字体部分之外,其他均来源于ChatGPT自动撰写。 ChatGPT是基于GPT模型的对话生成模型,旨在通过对话模拟实现自然语言交互。它是为了改善人机对话体验而设计的,主要应用于聊天机器人、智能客服等场景。 与GPT模型相比,…...
华为OD机试 - 特异性双端队列(JS)
特异性双端队列 题目 有一个特异性的双端队列,该队列可以从头部到尾部添加数据,但是只能从头部移除数据。 小A一次执行 2n 个指令往队列中添加数据和移除数据, 其中 n 个指令是添加数据(可能从头部也可以从尾部添加) 依次添加 1 到 n , n 个指令是移出数据 现在要求移除数…...
Nginx自动封禁可疑Ip
文章目录一、Nginx封禁ip1、简介2、nignx 禁止IP访问2.1 方法一2.2 方法二3、关于 deny 的使用二、脚本自动封禁Ip1、流程介绍2、脚本实战2.1 核心脚本解释2.2 编写shell脚本2.3 crontab定时一、Nginx封禁ip 1、简介 在网站维护过程中,有时候我们需要对一些IP地址…...
分布式事务--理论基础
1、事务基础 1.1、什么是事务 事务可以看做是一次大的活动,它由不同的小活动组成,这些活动要么全部成功,要么全部失败。 1.2、本地事务 在同一个进程内,控制同一数据源的事务,称为本地事务。例如数据库事务。 在计…...
Matlab数学建模常用算法及论文插图绘制模板资源合集
最近有很多朋友咨询我关于Matlab论文插图绘制方面的问题。 问了一下,这些朋友中,除了写博士论文的,大部分都是要参加美赛的。 这让我突然想起,自己曾经为了水论文,购买过一批Matlab数学建模的资料。 想了想…...
C语言【动态内存管理 后篇】
动态内存管理 后篇🫅经典例题🤦♂️题目1🤦♂️题目2🤦♂️题目3🤦♂️题目4🫅C/C程序的内存开辟前面的一篇文章动态内存管理 前篇,我们已经了解过了动态内存管理的相关信息,…...
四大步骤,教你彻底关闭Win10自动更新
文章目录一、禁用Windows Update服务二、在组策略里关闭Win10自动更新相关服务三、禁用任务计划里边的Win10自动更新四、在注册表中关闭Win10自动更新参考资料一、禁用Windows Update服务 1、同时按下键盘 Win R,打开运行对话框,然后输入命令 services…...
通信算法之一百零四:QPSK完整收发仿真链路
1.发射机物理层基带仿真链路 1.1 % Generates the data to be transmitted [transmittedBin, ~] BitGenerator(); 2.2 % Modulates the bits into QPSK symbols modulatedData QPSKModulator(transmittedBin); 2.3 % Square root Raised Cosine Transmit Filter %comm…...
时间复杂度(超详解+例题)
全文目录引言如何衡量一个算法的好坏时间复杂度时间复杂度的定义时间复杂度的大O表示法实例test1test2test3test4test5总结引言 如何衡量一个算法的好坏 我们在写算法的时候,对于实现同样的作用的不同算法,我们如何判断这个算法的好坏呢? …...
【Java面试总结】Maven篇
【Java面试总结】Maven篇1.Maven坐标是啥2.Maven常见的依赖范围有哪些?3.多模块如何聚合4.对于一个多模块项目,如果管理项目依赖的版本5.maven怎么解决版本冲突6.Maven常用命令有哪些?1.Maven坐标是啥 一般maven使用groupID,artifactId&…...
【每日一题Day123】LC1792最大平均通过率 | 堆
最大平均通过率【LC1792】 一所学校里有一些班级,每个班级里有一些学生,现在每个班都会进行一场期末考试。给你一个二维数组 classes ,其中 classes[i] [passi, totali] ,表示你提前知道了第 i 个班级总共有 totali 个学生&#…...
[安装之5] Mac pro更换大内存固态硬盘实践教程
近由于mac电脑内存吃紧,安装大的软件,是不是要提示一下内存不够,内心非常的不爽。作为一款A1502版的mac,128G固态硬盘通常被称为“乞丐版”。提前做好准备工作后,我周末花了一天的时间搞定这件事,为了能够帮…...
04 Python变量的声明与使用
基本上,在所有的计算机编程语言中,都会用到变量,变量将数据存储在计算机内存中。 变量是指存储数据的内存地址,通过变量名,我们可以找到这个变量名对应的内容。 命名变量时不允许使用数字、特殊字符、连字符开头。 变量可以有一个短名称(如 x、y、z),但强烈建议使用更具…...
LeetCode 2418. 按身高排序
给你一个字符串数组 names ,和一个由 互不相同 的正整数组成的数组 heights 。两个数组的长度均为 n 。 对于每个下标 i,names[i] 和 heights[i] 表示第 i 个人的名字和身高。 请按身高 降序 顺序返回对应的名字数组 names 。 示例 1: 输…...
一文了解Hotspot虚拟机下JAVA对象从创建到回收的生命周期
Java虚拟机是Java的核心和基础,他是Java编译器和操作系统平台之间处理器,能实现跨平台运行Java程序。本文主要讲解的是虚拟机如何管理对象,即Java对象在JVM虚拟机中被创建到回收的流程 Java对象从创建到回收的生命周期对象创建流程1.类加载检…...
【Java基础】Java对象创建的几种方式
先上关键内容,所用到的代码请参考文末示例代码。一、使用new关键字创建对象这是一种最常用的创建对象的方式。Student student1 new Student();二、使用Class的newInstance()方法创建对象需要有一个无参构造方法,这个newInstance()方法调用无参的构造函…...
社保缴费满15年就可以不缴了?6个很多人最关心的问题权威解答来了
一、社保缴费满15年就可以不缴了? 上海市政府新闻办公室2022年在微信号发文表示,社会保险是由国家通过立法强制建立的社会保障制度,用人单位和劳动者都必须依法参加社会保险。即使职工与用人单位商议签订了不参加社保的所谓“协议”…...
关于HDFS
目录 一、HDFS概述 二、HDFS架构与工作机制 三、HDFS的Shell操作 四、Hdfs的API操作 一、HDFS概述 HDFS:Hadoop Distributed File System;一种分布式文件管理系统,通过目录树定位文件。使用场景:一次写入,多次读出…...
日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
通过MicroSip配置自己的freeswitch服务器进行调试记录
之前用docker安装的freeswitch的,启动是正常的, 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...
