赞
踩
有这样的需求,在不改变源码的情况下,通过修改配置文件来扩展功能(设计模式中的OCP原则,也叫开闭原则)。
Java反射机制可以完成
这些类在java.lang.reflect中:
package com.reflection.question; import java.io.FileInputStream; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Properties; /** * @author Albert * @version 1.0 * @date 2023/12/1-11:18 * @describe */ public class Reflection01 { public static void main(String[] args) throws Exception{ //使用Properties类,可以读写配置文件 Properties properties = new Properties(); properties.load(new FileInputStream("src\\re.properties")); String classfullpath = properties.get("classfullpath").toString(); String methodName = properties.get("method").toString(); System.out.println("classfullpath=" + classfullpath); System.out.println("method=" + methodName); //使用反射 //1.加载类,返回class类型的对象cls Class cls = Class.forName(classfullpath); //2.通过cls得到加载的类com.Cat的对象实例 Object o = cls.newInstance(); System.out.println("o的运行类型=" + o.getClass()); //3.通过cls得到你加载的类com.Cat的methodName的“hi”的方法对象 Method method1 = cls.getMethod(methodName); //4.通过method1调用方法,即通过方法对象来实现调用方法 System.out.println("========================="); method1.invoke(o); //Java.lang.reflect.Field:代表类的成员变量,Field对象表示某个类的成员变量 //得到name字段 //getField不能得到私有的属性 Field nameField = cls.getField("age"); System.out.println(nameField.get(o)); //Java.lang.reflect.Constructor:代表类的构造方法,Constructor对象表示构造器 Constructor constructor = cls.getConstructor();//返回无参构造器 System.out.println(constructor); Constructor constructor2 = cls.getConstructor(String.class);//这里传入的String.class就是String类的Class对象 System.out.println(constructor2); } }
优点: 可以动态的创建和使用对象(也是框架底层核心),使用灵活,没有反射机制,框架技术就失去底层支撑。
缺点: 使用反射基本是解释执行,对执行速度有影响
package com.reflection.question; import com.Cat; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.lang.reflect.Method; import java.util.Properties; /** * @author Albert * @version 1.0 * @date 2023/12/1-11:55 * @describe 测试反射调用的性能和优化方案 */ public class Reflection02 { public static void main(String[] args) throws Exception { m1(); m2(); m3(); } public static void m1(){//传统方法 Cat cat = new Cat(); long start = System.currentTimeMillis(); for(int i = 0; i < 9000000; i++){ cat.hi(); } long end = System.currentTimeMillis(); System.out.println("传统方法调用hi()耗时= " + (end - start)); } public static void m2() throws Exception {//反射 //使用反射 //1.加载类,返回class类型的对象cls Class cls = Class.forName("com.Cat"); //2.通过cls得到加载的类com.Cat的对象实例 Object o = cls.newInstance(); //3.通过cls得到你加载的类com.Cat的methodName的“hi”的方法对象 Method method1 = cls.getMethod("hi"); //4.通过method1调用方法,即通过方法对象来实现调用方法 long start = System.currentTimeMillis(); for(int i = 0; i < 9000000; i++){ method1.invoke(o); } long end = System.currentTimeMillis(); System.out.println("传统方法调用hi()耗时= " + (end - start)); } public static void m3() throws Exception {//优化的反射 //使用反射 //1.加载类,返回class类型的对象cls Class cls = Class.forName("com.Cat"); //2.通过cls得到加载的类com.Cat的对象实例 Object o = cls.newInstance(); //3.通过cls得到你加载的类com.Cat的methodName的“hi”的方法对象 Method method1 = cls.getMethod("hi"); method1.setAccessible(true);//取消访问检查, //4.通过method1调用方法,即通过方法对象来实现调用方法 long start = System.currentTimeMillis(); for(int i = 0; i < 9000000; i++){ method1.invoke(o); } long end = System.currentTimeMillis(); System.out.println("传统方法调用hi()耗时= " + (end - start)); } }
package com.class_; import com.Car; import java.lang.reflect.Field; /** * @author Albert * @version 1.0 * @date 2023/12/1-19:52 * @describe 演示类的常用方法 */ public class Class02 { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException { //1.获取Car类对应的Class对象 //<?>表示不确定的Java类型 Class<?> cls = Class.forName("com.Car"); //2.输出cls System.out.println(cls);//显示cls对象,是哪个类的Class对象 com.Car System.out.println(cls.getClass());//输出cls运行类型java.lang.Class //3.得到包名 System.out.println(cls.getPackage().getName());//com //4.得到全类名 System.out.println(cls.getName());//com.Car //5.通过cls创建对象实例 Car car = (Car) cls.newInstance(); System.out.println(car);//Car{brand='宝马', price=50000, color='白色'} //6.通过反射获得属性brand(注意,无法获取私有属性) Field brand = cls.getField("brand"); System.out.println(brand.get(car));//宝马 //7.通过反射给属性赋值 brand.set(car, "奔驰"); System.out.println(brand.get(car));//奔驰 //8.通过遍历得到所有的字段 Field[] fields = cls.getFields(); System.out.println("所有字段如下:"); for (Field field :fields) { System.out.println(field.getName() + " " + field.get(car)); } } }
如何获取Class类对象
package com.class_; import com.Car; /** * @author Albert * @version 1.0 * @date 2023/12/1-20:27 * @describe 演示如何获取Class对象(总共6种方式) */ public class GetClass { public static void main(String[] args) throws ClassNotFoundException { //1.class.forName 应用场景:通过配置文件读取类的路径,再从路径中找到并加载Class对象 String classAllPath = "com.Car";//一般通过读取配置文件获取 Class<?> cls1 = Class.forName(classAllPath); System.out.println(cls1); //2.类名.class 应用场景:用于参数传递 Class cls2 = Car.class;//例如,cls2可以作为匹配对应构造器时的参数 System.out.println(cls2); //3.对象.getClass() 应用场景:有对象实例 Car car = new Car(); Class cls3 = car.getClass(); System.out.println(cls3); //4.通过类加载器【4种】来获取类的Class对象 //(1)先得到类加载器 car ClassLoader classLoader = car.getClass().getClassLoader(); //(2)通过类加载器获得Class对象 Class cls4 = classLoader.loadClass(classAllPath); System.out.println(cls4); //hasCode一样,说明这些对象都是同一个 System.out.println(cls1.hashCode()); System.out.println(cls2.hashCode()); System.out.println(cls3.hashCode()); System.out.println(cls4.hashCode()); //5.基本数据类型(int, char, boolean, float, double, long, shout)按如下方式得到class类的对象 Class<Integer> cls5 = int.class; System.out.println(cls5); //6.基本数据类型的包装类 Class<Integer> cls6 = Integer.TYPE; System.out.println(cls6); //hasCode一样,说明这些对象都是同一个 System.out.println(cls5.hashCode()); System.out.println(cls6.hashCode()); } }
反射机制是java实现动态语言的关键,也就是通过反射实现类动态加载。
类加载的时机:
JVM 在该阶段的主要目的是将字节码从不同的数据源(可能是 class 文件、也可能是jar 包,甚至网络)转化为二进制字节流加载到内存中,并生成一个代表该类的java.lang.Class 对象。
JVM 会在该阶段对静态变量,分配内存并默认初始化 对应数据类型的默认初始值,如 0、0L、null、false 等)。这些变量所使用的内存都将在方法区中进行分配。
虚拟机将常量池内的符号引用替换为直接引用的过程。
package com.reflection; import org.junit.jupiter.api.Test; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; /** * @author Albert * @version 1.0 * @date 2023/12/2-9:32 * @describe 演示如何通过反射获取类的结构信息 */ public class ReflectionUtils { public static void main(String[] args) { } //第一组方法 @Test public void api_01() throws ClassNotFoundException { //得到class对象 Class<?> cls = Class.forName("com.reflection.Person"); //getName:获取全类名 System.out.println(cls.getName());//com.reflection.Person //getSimpleName:获取简单类名 System.out.println(cls.getSimpleName());//Person // getFieLds:获取所有public修饰的属性,包含本类以及父类的 Field[] fields = cls.getFields(); for(int i = 0; i < fields.length; i++){ System.out.println(fields[i].toString());//public java.lang.String com.reflection.Person.name //public java.lang.String com.reflection.A.hobby } // getDeclaredFields:获取本类中所有属性(不包括父类的属性) Field[] fields2 = cls.getDeclaredFields(); for(int i = 0; i < fields2.length; i++){ System.out.println(fields2[i].getName()); } // getMethods:获取所有public修饰的方法,包含本类以及父类的 Method[] methods = cls.getMethods(); for (Method method :methods) { System.out.println(method.getName()); } // getDeclaredMethods:获取本类中所有方法(不包括父类的方法) Method[] methods2 = cls.getDeclaredMethods(); for (Method method :methods2) { System.out.println(method.getName()); } // getConstructors: 获取本类public修饰的构造器(不包括父类的) Constructor[] constructors = cls.getConstructors(); for (Constructor constructor :constructors) { System.out.println(constructor.getName()); } // getDeclaredConstructors:获取本类中所有构造器 Constructor[] constructors2 = cls.getDeclaredConstructors(); for (Constructor constructor :constructors2) { System.out.println(constructor.getName()); } // getPackage:以Package形式返回包信息 Package p = cls.getPackage(); System.out.println(p); // getSuperCLass:以CLass形式返回父类信息 Class c = cls.getSuperclass(); System.out.println(c); // getInterfaces:以CLass[]形式返回接口信息 Class[] classes = cls.getInterfaces(); for (Class aClass :classes) { System.out.println(aClass.getName()); } // getAnnotations:以Annotation[] 形式返回注解信息 Annotation[] annotations = cls.getAnnotations(); for (Annotation annotation :annotations) { System.out.println(annotation); } } //第二组方法 @Test public void api_02() throws ClassNotFoundException { //得到class对象 Class<?> cls = Class.forName("com.reflection.Person"); // getDeclaredMethods:获取本类中所有方法(不包括父类的方法) // getModifiers:以int形式返回修饰符[说明: 默认修饰符 是0,public 是1 ,private 是2 ,protected 是 4,static 是8 ,final 是 16] // getReturnType:以Class形式获取返回类型 // getName:返回方法名 // getParameterTypes:以Class[]返回参数类型数组 Method[] methods2 = cls.getDeclaredMethods(); for (Method method :methods2) { System.out.println(method.getName()); System.out.println(method.getModifiers()); System.out.println(method.getReturnType()); Class<?>[] classes = method.getParameterTypes(); for (Class aClass :classes) { System.out.println(aClass); } } } //第三组方法 @Test public void api_03() throws ClassNotFoundException { //得到class对象 Class<?> cls = Class.forName("com.reflection.Person"); // getDeclaredFields:获取本类中所有属性(不包括父类的属性) //getModifiers: 以int形式返回修饰符[说明: 默认修饰符 是0,public 是1,private 是 2,protected 是4static 是8 ,final 是 16] , public(1) + static (8) = 9 //getType:以Class形式返回类型 // getName:返回属性名 Field[] fields2 = cls.getDeclaredFields(); for(int i = 0; i < fields2.length; i++){ System.out.println(fields2[i].getName()); System.out.println(fields2[i].getModifiers()); System.out.println(fields2[i].getType()); } } //第四组方法 @Test public void api_04() throws ClassNotFoundException { //得到class对象 Class<?> cls = Class.forName("com.reflection.Person"); // getDeclaredConstructors:获取本类中所有构造器 // getModifiers: 以int形式返回修饰符 // getName:返回构造器名 (全类名) // getParameterTypes:以Class[]返回参数类型数组 Constructor[] constructors2 = cls.getDeclaredConstructors(); for (Constructor constructor :constructors2) { System.out.println(constructor.getName()); System.out.println(constructor.getModifiers()); Class[] classes = constructor.getParameterTypes(); for (Class aClass :classes) { System.out.println(aClass.getName()); } } } } interface IA{} interface IB{} class A{ public String hobby; public void hi(){} public A(){} } @Deprecated class Person extends A implements IA, IB{ //属性 public String name; protected static int age; String job; private double sal; public Person(){} public Person(String name){} private Person(String name, int age){} //方法 public void m1(String name, int age, double sal){} protected void m2(){} void m3(){} private void m4(){} }
方式一:调用类中的public修饰的无参构造器
方式二:调用类中的指定构造器
Class类相关方法——newlnstance : 调用类中的无参构造器,获取对应类的对象;getConstructor(Class…clazz):根据参数列表,获取对应的public构造器对象;getDecalaredConstructor(Class…clazz):根据参数列表,获取对应的所有构造器对象
Constructor类相关方法——setAccessible:暴破;newlnstance(Object…obj):调用构造器
package com.reflection; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; /** * @author Albert * @version 1.0 * @date 2023/12/2-10:49 * @describe 演示通过反射机制创建实例 */ public class ReflectCreateInstance { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { //1.先获取User类的Class对象 Class<?> userClass = Class.forName("com.reflection.User"); //2.通过public的无参构造器创建实例 Object o = userClass.newInstance(); System.out.println(o); //3.通过public的有参构造器创建实例 Constructor userConstructor = userClass.getConstructor(String.class); Object mary = userConstructor.newInstance("mary"); System.out.println(mary); //2.通过private的有参构造器创建实例 Constructor userConstructor2 = userClass.getDeclaredConstructor(int.class, String.class); userConstructor2.setAccessible(true);//关闭安全检查,允许访问私有构造器 Object rich = userConstructor2.newInstance(20, "rich"); System.out.println(rich); } } class User{ private int age = 10; private String name = "jack"; public User(){//公有无参构造器 } public User(String name){//公有有参构造器 this.name = name; } private User(int age, String name){//私有有参构造器 this.age = age; this.name = name; } @Override public String toString() { return "User{" + "age=" + age + ", name='" + name + '\'' + '}'; } }
package com.reflection; import java.lang.reflect.Field; /** * @author Albert * @version 1.0 * @date 2023/12/2-11:12 * @describe 演示反射操作属性 */ public class ReflectAccessProperty { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException { //1.得到Student类对应的 cLass对象 Class<?> stuClass = Class.forName("com.reflection.Student"); //2.创建对象 Object o = stuClass.newInstance();//o 的运行类型就是Student System.out.println(o.getClass());//student // 3.使用反射得到age 属性对象 Field age = stuClass.getField("age"); age.set(o, 88);//通过反射来操作属性 System.out.println(o);// System.out.println(age.get(o));//返回age属性的值 //4.使用反射操作name 属性 Field name = stuClass.getDeclaredField("name"); //对name 进行暴破,可以操作private 属性 name.setAccessible(true); name.set(o, "jack"); //name.set(null,"老韩~");//因为name是static属性,因此 o 也可以写成null System.out.println(o); System.out.println(name.get(o)); System.out.println(name.get(null));//因为name是静态才可以这么写 } } class Student { public int age; private static String name; public Student() { } public String toString() { return "Student [age=" + age + ", name=" + name + "]"; } }
package com.reflection; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * @author Albert * @version 1.0 * @date 2023/12/2-11:28 * @describe 演示通过反射调用方法 */ public class ReflectAccessMethod { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { //1.得到Student类对应的 cLass对象 Class<?> bossClass = Class.forName("com.reflection.Boss"); //2.创建对象 Object o = bossClass.newInstance(); //3.调用public的hi方法 //Method method = bossClass.getMethod("hi", String.class);//OK Method method = bossClass.getDeclaredMethod("hi", String.class);//OK method.invoke(o, "jack"); //4.调用private static的hi方法 Method method2 = bossClass.getDeclaredMethod("say", int.class, String.class, char.class); method2.setAccessible(true); System.out.println(method2.invoke(o, 100, "jack", 'M')); System.out.println(method2.invoke(null, 500, "rich", 'W'));//因为是静态方法,可以这样写 //5.通过反射执行的方法返回值是使用Object来接收,但是返回值的运行类型还是方法所定义的返回值类型 Object s = method2.invoke(null, 300, "Man", 'W'); System.out.println(s.getClass()); } } class Boss{ public int age; private static String name; public Boss() { } private static String say(int n, String s, char c){ return n + " " + s + " " + c; } public void hi(String s){ System.out.println("hi " + s); } }
package com.Homework; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * @author Albert * @version 1.0 * @date 2023/12/2-11:45 * @describe 通过反射修改私有成员变量。定义PrivateTest类,有私有name属性,并且属性值为hellokitty * 提供getName的公有方法 * 创建PrivateTest的类,利用Class类得到私有的name属性,修改私有的name属性值 * 并调用getName()的方法打印name属性值 */ public class H01 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { Class<?> c = Class.forName("com.Homework.PrivateTest"); //PrivateTest test = (PrivateTest) c.newInstance(); Object test = c.newInstance(); Method getName = c.getDeclaredMethod("getName"); System.out.println("修改前 name = " + getName.invoke(test)); Field name = c.getDeclaredField("name"); name.setAccessible(true); name.set(test, "albert"); System.out.println("修改后 name = " + getName.invoke(test)); } } class PrivateTest{ private String name = "helllokitty"; public String getName(){ return name; } }
package com.Homework; import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * @author Albert * @version 1.0 * @date 2023/12/2-11:59 * @describe 练习2利用反射和File完成以下功能: * 利用Class类的forName方法得到File类的class对象 * 在控制台打印File类的所有构造器 * 通过newInstance的方法创建File对象,并创建E:\mynew.txt文件 */ public class H02 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { Class<?> fileClass = Class.forName("java.io.File"); Constructor[] constructors = fileClass.getDeclaredConstructors(); for (Constructor constructor :constructors) { System.out.println(constructor); } Constructor constructor = fileClass.getConstructor(String.class); Object file = constructor.newInstance("e:\\mynew.txt"); Method method = fileClass.getMethod("createNewFile"); method.invoke(file); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。