第一句子网 - 唯美句子、句子迷、好句子大全
第一句子网 > Java基础篇:反射机制详解

Java基础篇:反射机制详解

时间:2021-07-31 10:20:37

相关推荐

Java基础篇:反射机制详解

反射机制

反射机制、反射含义1.利用反射获取类对象的三种方法2.利用反射获取类对象的类名、方法、属性3.利用反射获取类对象中的构造器、构造器参数类型、实例化构造器实例化重点类的加载方式不同所调用的构造方法不尽相同执行效率不同4.利用反射获取类对象中的方法的包装类5.通过反射获取运行配置文件内容(Properties)6.利用反射和properties实现获取配置文件中的内容(类路径、方法名,然后反射实现 实例化、回调方法)6.2.String 的 endsWith() 方法7.在不更改源代码的前提下通过更改配置文件实现程序功能的扩展8.使用反射的小结

反射机制、反射含义

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象, 都能够调用它的任意方法和属性;

这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制

帮助理解:就是我们可以通过代码获取到类中的所有属性和所有方法

简而言之:自己找到自己,俗称“照镜子”

1.利用反射获取类对象的三种方法

方法一:对象.getClass()方法方法二:类.clss属性方法三:Class.forName()

代码块

public class Test {public static void main(String[] args) throws Exception {//Student类的实例化Student student01= new Student(); //方法一:通过getclass()Class<? extends Student> s1 = student01.getClass();System.out.println(s1);//方法二:通过class属性Class<Student> s2 = Student.class;System.out.println(s2);//方法三:通过Class.forname()System.out.println(Class.forName("com.Li.reflex01.Student"));}}

2.利用反射获取类对象的类名、方法、属性

stu.getClass();

stu.getClass().getFields().getName() & field.getType() //属性名 和 属性类型

stu.getClass().getMethods().getName() & method.getReturnType() //类方法 和 方法返回值

/*** @Description: 测试类:测试获取类对象中的类名、方法和属性* @auther:Li Ya Hui* @Time:4月19日下午1:33:00*/public class Test {public static void main(String[] args) {//1.student类的实例化Student stu = new Student();//2.获取student的类对象 classClass<? extends Student> student = stu.getClass();System.out.println("类的class:\t"+student);System.out.println("类的全称:"+stu.getClass().getSimpleName());System.out.println("类的简称:"+stu.getClass().getName());//3使用增强for遍历学生类的属性 属性名,属性类型Field[] stufiled = stu.getClass().getFields();for (Field field : stufiled) {System.out.println("属性名:"+field.getName()+"\t\t属性的数据类型:"+field.getType());}//4.获取类中的方法Method[] stumethods = stu.getClass().getMethods();for (Method method : stumethods) {System.out.println("类的方法"+method.getName()+"\t类的方法的返回值类型"+method.getReturnType());}}}

3.利用反射获取类对象中的构造器、构造器参数类型、实例化构造器

package com.Li.reflex03;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;public class Test {public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {//获取类对象Class<?> stu = Class.forName("com.Li.reflex03.Student");//获取所有的公有构造方法(前提 类是用public修饰的)Constructor<?>[] stuConstru = stu.getConstructors();for (Constructor<?> constructor : stuConstru) {System.out.println("构造器:\t"+constructor);//构造器执行 (参数 类型 个数 不对会导致出错)//System.out.println("构造器执行:\t:"+constructor.newInstance(""));//等价于Student student = new Student(); 相当于类的初始化//获取构造器中的参数类型Class<?>[] parameterTypes = constructor.getParameterTypes();//遍历各个构造器参数类型for (Class<?> parameter : parameterTypes) {System.out.println("构造器中的参数类型:\t"+parameter.getName());}System.out.println();}}}

实例化重点

类的加载方式不同

​ 在执行Class.forName(“a.class.Name”)时,JVM会在classapth中去找对应的类并加载,这时JVM会执行该类的静态代码段。在使用newInstance()方法的时候,必须保证这个类已经加载并且已经连接了,而这可以通过Class的静态方法forName()来完成的。

​ 使用关键字new创建一个类的时候,这个类可以没有被加载,一般也不需要该类在classpath中设定,但可能需要通过classlaoder来加载。

所调用的构造方法不尽相同

​ new关键字能调用任何构造方法。

​ newInstance()只能调用无参构造方法。

执行效率不同

​ new关键字是强类型的,效率相对较高。

​ newInstance()是弱类型的,效率相对较低。

4.利用反射获取类对象中的方法的包装类

/*** @Description:测试类,测试利用反射获取类的方法的包装类Method* @auther:Li Ya Hui* @Time:4月19日下午8:57:13*/public class Test {public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {//1.获取类对象Class<Student> ownerClass = Student.class; //2.Student类的实例化Student student = ownerClass.newInstance();//3.通过类对象获取method类 方法名方法返回值类型 需是类Method method = ownerClass.getMethod("sayHi", String.class);//多个参数时//Method method = ownerClass.getMethod("sayHi", String.class, String.class);//4.invoke() 是method类中的方法,起作用是回调类中的方法 //invoke 参数讲解: 1.回调那个实例化对象中的方法 2.传入的参数的值String result = (String) method.invoke(student, "LiYaHui");//多个参数时// String result = (String) method.invoke(student, "LiYaHui","李亚辉");System.out.println(result); }}

5.通过反射获取运行配置文件内容(Properties)

properties位于java.util.properties,是Java语言的配置文件所使用的类

/*** @Description: 利用properties获取配置文件中的内容* @auther:Li Ya Hui* @Time:4月20日上午9:14:52*/public class Test {public static void main(String[] args) throws IOException {//实例properties类Properties properties = new Properties();//创建读取对象FileReader fileReader = new FileReader("dbconfig.txt");//加载读取对象properties.load(fileReader);//获取username属性String username = properties.getProperty("username");//打印username的值System.out.println(username);//打印 root}}自己写的配置文件//dbconfig.txtusername=rootpassword=rootdrivername=com.mysql.jdbc.driverurl=127.0.01:3306

6.利用反射和properties实现获取配置文件中的内容(类路径、方法名,然后反射实现 实例化、回调方法)

package com.Li.reflex05;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.ObjectInputStream.GetField;import java.lang.reflect.Constructor;import java.lang.reflect.Method;import java.util.Properties;/*** @Description: 利用反射和properties实现获取配置文件中的内容* @auther:Li Ya Hui* @Time:4月20日上午9:39:51*/public class Test {public static void main(String[] args) throws Exception {//1.propertie类的初始化Properties properties = new Properties();//2.加载配置文件哎FileReader fileReader = new FileReader("playerList.txt");//3.properties加载配置文件properties.load(fileReader);//4.利用properties获取配置文件中的内容//当前的配置文件中的className的属性值, 得到应用类的路径String className = properties.getProperty("className"); System.out.println("获取到的类的路径名:\t"+className);//当前的配置文件中的methodName的属性值, 得到类的方法名String methodName = properties.getProperty("methodName");System.out.println("获取到的类中方法的名字:\t"+methodName);//得到类的classClass<?> heroclass = Class.forName(className);//得到构造器Constructor constructor = heroclass.getConstructor();//初始化构造器,其作用相当于是new ,目前是实例化类Object hero = constructor.newInstance();//调用方法getMethod使用类对象来调用的,所以不能用hero对象Method method = heroclass.getMethod(methodName, String.class);//通过类对象获取到方法的包装类Method,且同时指出本次执行的方法是run,且该方法的传入参数为String//回调hero类中的run方法method.invoke(hero,"ss枪手");}}//hero类/*** @Description: 英雄类* @auther:Li Ya Hui* @Time:4月20日上午9:36:45*/public class Hero {public void run(String attribute){if (attribute.endsWith("肉盾")) {System.out.println("肉盾!可以慢跑");}else if(attribute.endsWith("枪手")){System.out.println("枪手可以边打边跑");}else {System.out.println("可以正常跑!");}}}//配置文件//playerList.txtclassName=com.Li.reflex05.HeromethodName=run

6.2.String 的 endsWith() 方法

(上面例子的hero英雄类中有应用场景)

endwith和equals方法有些相似,但是不同的是endwith判断是否以指定字符结尾,有点正则表达式的意思

7.在不更改源代码的前提下通过更改配置文件实现程序功能的扩展

package com.Li.reflex07;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.ObjectInputStream.GetField;import java.lang.reflect.Constructor;import java.lang.reflect.Method;import java.util.Properties;/*** @Description: 在不更改源代码的前提下通过更改配置文件实现程序功能的扩展* @auther:Li Ya Hui* @Time:4月20日上午9:39:51*/public class Test {public static void main(String[] args) throws Exception {//1.propertie类的初始化Properties properties = new Properties();//2.加载配置文件哎FileReader fileReader = new FileReader("playerList2.txt");//3.properties加载配置文件properties.load(fileReader);//4.利用properties获取配置文件中的内容//当前的配置文件中的className的属性值, 得到应用类的路径String className = properties.getProperty("className"); System.out.println("获取到的类的路径名:\t"+className);//当前的配置文件中的methodName的属性值, 得到类的方法名String methodName = properties.getProperty("methodName");System.out.println("获取到的类中方法的名字:\t"+methodName);//得到类的classClass<?> heroclass = Class.forName(className);//得到构造器Constructor constructor = heroclass.getConstructor();//初始化构造器,其作用相当于是new ,目前是实例化类Object hero = constructor.newInstance();//调用方法getMethod使用类对象来调用的,所以不能用hero对象Method method = heroclass.getMethod(methodName, String.class);//通过类对象获取到方法的包装类Method,且同时指出本次执行的方法是run,且该方法的传入参数为String//以上代码没有更改,封装后可实现多次扩展实例代码//回调hero类中的run方法method.invoke(hero,"boss"); //只需在调用时换参数即可}}//妖怪类(Devil)package com.Li.reflex07;/*** @Description: 妖怪类* @auther:Li Ya Hui* @Time:4月20日上午9:36:45*/public class Devil {public void run(String attribute){if (attribute.endsWith("boss")) {System.out.println("boss!可以慢跑");}else if(attribute.endsWith("littleboss")){System.out.println("littleboss可以稍微快点跑");}else {System.out.println("可以正常跑!");}}}//配置文件//playerList2.txtclassName=com.Li.reflex07.DevilmethodName=run

8.使用反射的小结

​ 1.可以在任何地方通过反射获取到类中的属性和方法和构造器还有实例化

​ 2.因为可以获取到构造器,当然也可以实例化==(通过newInstance()方法即可实现)==

​ 3.经常被应用在框架中,例如Struts,Soring框架

​ 要点:newInstance这个方法勉强等同于news这个关键字

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。