鄂州正规网站建设,学大教育一对一收费价格表,贵阳市网站建设,wordpress v电影目录
基本概念
定义
用途
反射相关的类
反射基本原理
Class 类中的相关方法
常用获得类相关的方法
常用获得类中属性相关的方法
常用获得类中构造器相关的方法
常用获得类中方法相关的方法
实例理解
反射优缺点 基本概念 定义 Java 的反射#xff08;reflectionreflection机制是一种强大功能它可以让我们在运行时动态地获取和操作 类 或 对象 的信息 实例理解 我们可以通过反射机制来创建一个类的对象而不需要使用 new 关键字我们也可以通过反射机制来访问或修改一个对象的私有属性或方法而不需要遵循封装原则我们还可以通过反射机制来调用一个对象的任意方法而不需要知道它的参数类型或返回值类型 用途 典型用途一 在开发第三方应用时我们可能会遇到一些类的成员变量、方法或属性是私有的或者只对系统应用开放这就意味着我们不能直接访问这些成员或方法这时我们便可以在运行时 通过 Java 的反射机制 来动态地访问和操作类的内部成员包括私有成员和方法 典型用途二 反射在开发通用框架 Spring 中起着重要的作用在Spring 框架中所有类Bean都由 Spring 容器进行管理这些 Bean 可以通过 XML 配置或注解来配置当我们从容器中获取Bean 以进行依赖注入时容器会读取配置信息这些配置信息包含了类的信息比如类的名称、属性、方法等Spring根据这些信息 动态地创建这些类的实例这个过程就是所谓的 依赖注入该过程中反射起到了关键作用Spring 使用反射来动态地创建类的实例调用方法以及设置属性值 反射相关的类 反射基本原理 Java 的反射机制是基于 java.lang.Class 类实现的当我们编译一个 Java 文件时会生成一个 .class 文件当 JVM 加载这个 .class 文件时会将其解析为一个 java.lang.Class 类的对象在程序运行时每个 Java 文件都会被 JVM 解析为一个 Class 类的实例这个 Class 类的实例包含了该 Java 文件中所定义类的所有信息包括类的名称、属性、方法等我们可以通过 Java 的反射机制来操作这个 Class 类的实例具体来说我们可以使用反射来获取类的属性和方法甚至可以添加或修改类的属性和方法这使得我们可以在运行时动态地操作类使其成为一个 动态的类 类名用途Class 类代表类的实体在运行的 Java 应用程序中表示类和接口Field 类代表类的成员变量、类的属性Method 类代表类的方法Constructor 类代表类的构造方法 Class 类中的相关方法 常用获得类相关的方法 方法用途getClassLoader()获得类的加载器getDeclaredClasses()返回一个数组数组中包含该类中所有类和接口类的对象(包括私有的)forName(String className)根据类名返回类的对象newInstance()创建类的实例getName()获得类的完整路径名字 常用获得类中属性相关的方法 方法用途getField(String name)获得某个公有的属性对象getFields()获得所有公有的属性对象getDeclaredField(String name)获得某个属性对象getDeclaredFields()获得所有属性对象 常用获得类中构造器相关的方法 方法用途getConstructor(Class ? parameterTypes)获得该类中与参数类型匹配的公有构造方法getConstructors()获得该类的所有公有构造方法getDeclaredConstructor(Class ? parameterTypes)获得该类中与参数类型匹配的构造方法getDeclaredConstructors()获得该类所有构造方法 常用获得类中方法相关的方法 方法用途getMethod(String name, Class ? parameterTypes) 获得该类某个公有的方法getMethods()获得该类所有公有的方法getDeclaredMethod(String name, Class ? parameterTypes) 获得该类某个方法getDeclaredMethods()获得该类所有方法 实例理解 此处我们先创建一个 Student 类 class Student{//私有属性nameprivate String name master;//公有属性agepublic int age 18;//不带参数的构造方法public Student(){System.out.println(Student());}private Student(String name,int age) {this.name name;this.age age;System.out.println(Student(String,name));}private void eat(){System.out.println(make hamburger!);}public void sleep(){System.out.println(go to bed!);}private void function(String str) {System.out.println(str);}Overridepublic String toString() {return Student{ name name \ , age age };}
} 此处介绍三种方式来获取 Student 的 Class 对象 public class Demo1 {public static void main(String[] args) {
// 有三种方式可以获取 Class 对象Student student1 new Student();
// 1、通过对象的 getClass() 方法Class? c1 student1.getClass();
// 2、通过类名 .class 获取Class? c2 Student.class;
// 3、通过调用 Class.forName() 方法获取了 Student 类的 Class 对象
// Class.forName() 方法需要一个类的全限定名(包括 包名和类名) 作为参数
// 此处的 ? 是一个通配符用于表示未知类型
// 当我们声明一个泛型变量时如果我们不确定或不关心实际的类型参数我们可以使用 ? 来表示Class? c3 null;try {c3 Class.forName(Student);} catch (ClassNotFoundException e) {throw new RuntimeException(e);}
// 此处证明通过上述三种方式所获取的 Class 对象 都是同一个System.out.println((c1.equals(c2) c1.equals(c3) c2.equals(c3)) ? true : false);}
} 此处我们通过反射机制创建一个对象 import java.lang.reflect.InvocationTargetException;public class ReflectClassDemo {// 通过反射创建一个对象public static void reflectNewInstance() throws InstantiationException, IllegalAccessException, ClassNotFoundException {Class? c3 Class.forName(Student);
// 通过调用 Class 类的 newInstance() 方法来创建一个 c3 对应类的新实例
// newInstance() 方法调用的是这个类的无参构造函数
// 如果这个类没有无参构造函数或者无参构造函数是私有的那么 newInstance 会抛出一个异常
// 因为 newInstance() 方法返回的类型为 Object 类 所以需要类型转换此处转换为 Student 类Student student (Student) c3.newInstance();System.out.println(student);}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException {reflectNewInstance();}
} 运行结果 此处我们通过反射机制获取私有的构造方法 import java.lang.reflect.Constructor;public class ReflectClassDemo {// 通过反射获取私有的构造方法public static void reflectPrivateConstructor() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {Class? c3 Class.forName(Student);Constructor? constructor c3.getDeclaredConstructor(String.class,int.class);
// 注意只要是涉及到 private 都要使用 setAccessible(true) 来打开权限此处的构造方法为私有的constructor.setAccessible(true);
// 此处利用构造方法 修改年龄和性别Student student (Student)constructor.newInstance(xiaolin,20);System.out.println(student);}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException {reflectPrivateConstructor();}
}运行结果 此处我们通过反射机制获取私有属性 import java.lang.reflect.Field;public class ReflectClassDemo {// 通过反射获取私有属性public static void reflectPrivateField() throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {Class? c3 Class.forName(Student);Field field c3.getDeclaredField(name);
// 注意只要是涉及到 private 都要使用 setAccessible(true) 来打开权限此处的 name 属性是私有的field.setAccessible(true);Student student (Student) c3.newInstance();
// 此处修改私有属性field.set(student,haoran);System.out.println(student);}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException {reflectPrivateField();}
}运行结果 此处我们通过反射机制获取私有方法 import java.lang.reflect.Method;public class ReflectClassDemo {// 通过反射获取私有方法public static void reflectPrivateMethod() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {Class? c3 Class.forName(Student);Method method1 c3.getDeclaredMethod(function, String.class);Method method2 c3.getDeclaredMethod(sleep);
// 注意只要是涉及到 private 都要使用 setAccessible(true) 来打开权限此处的 function 方法是私有的method1.setAccessible(true);Student student (Student) c3.newInstance();
// 此处给 function 方法传参method1.invoke(student,此处利用反射机制给 function 方法传个字符串参数);
// 此处调用 sleep 方法该方法为 public 无需额外打开权限直接调用即可method2.invoke(student);}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException {reflectPrivateMethod();}
}运行结果 反射优缺点 优点 对于任意一个类都能够知道这个类的所有属性和方法对于任意一个类都能调用它的任意一个方法增加程序的灵活性和扩展性降低耦合性提高自适应性反射已经运用在很多流行框架典型代表为 Spring 缺点 使用反射会有效率问题会导致程序效率降低反射技术绕过了源代码的技术因而会带来维护问题反射代码比相应的直接代码更复杂 总结 虽然反射非常强大但也需要谨慎使用我们需要在反射带来的灵活性和可扩展性与其带来的性能开销、维护问题和代码复杂性之间找到一个平衡某些情况下比如开发通用的框架使用反射式非常有价值的但在其他情况下我们可能更倾向于使用更简单、更直接的代码