网站开发官网源码,石家庄怎样做网站,免费美食网站源码,安徽省交通运输厅秦勤大家好我是苏麟 , 今天聊聊反射 .
反射
专业的解释#xff1a; 反射允许对封装类的字段#xff0c;方法和构造函数的信息进行编程访问 是在运行状态中#xff0c;对于任意一个类#xff0c;都能够知道这个类的所有属性和方法
对于任意一个对象#xff0c;都能够调…大家好我是苏麟 , 今天聊聊反射 .
反射
专业的解释 反射允许对封装类的字段方法和构造函数的信息进行编程访问 是在运行状态中对于任意一个类都能够知道这个类的所有属性和方法
对于任意一个对象都能够调用它的任意属性和方法
这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制
通俗的理解 利用反射创建的对象可以无视修饰符调用类里面的内容 可以跟配置文件结合起来使用把要创建的对象信息和方法写在配置文件中。 读取到什么类就创建什么类的对象 读取到什么方法就调用什么方法 此时当需求变更的时候不需要修改代码只要修改配置文件即可。
反射涉及到四个核心类
java.lang.Class.java类对象java.lang.reflect.Constructor.java类的构造器对象java.lang.reflect.Method.java类的方法对象java.lang.reflect.Field.java类的属性对象 学什么
反射都是从class字节码文件中获取的内容。
如何获取class字节码文件的对象利用反射如何获取构造方法创建对象利用反射如何获取成员变量赋值获取值利用反射如何获取成员方法运行
获取字节码文件对象的三种方式 //1.Class这个类里面的静态方法forName//Class.forName(类的全类名) 全类名 包名 类名Class user Class.forName(org.example.User);//源代码阶段获取 --- 先把User加载到内存中再获取字节码文件的对象//clazz 就表示User这个类的字节码文件对象。//就是当User.class这个文件加载到内存之后产生的字节码文件对象 //2.通过class属性获取//类名.classClass userClass User.class;//因为class文件在硬盘中是唯一的所以当这个文件加载到内存之后产生的对象也是唯一的System.out.println(user userClass);//true //3.通过Student对象获取字节码文件对象User u new User();Class us u.getClass();System.out.println(user userClass);//trueSystem.out.println(userClass us);//true
哪些类型可以获取class
public static void main(String[] args) {String s new String(1);//继承Class aClass s.getClass();//.classClass stringClass String.class;ClassInteger integerClass int.class;Classint[] aClass1 int[].class;ClassVoid voidClass void.class;ClassRunnable runnableClass Runnable.class;
} 字节码文件和字节码文件对象
java文件就是我们自己编写的java代码。
字节码文件就是通过java文件编译之后的class文件是在硬盘上真实存在的用眼睛能看到的
字节码文件对象当class文件加载到内存之后虚拟机自动创建出来的对象。
这个对象里面至少包含了构造方法成员变量成员方法。
而我们的反射获取的是什么字节码文件对象这个对象在内存中是唯一的。
创建对象
一般情况下我们通过反射创建类对象主要有两种方式
通过 Class 对象的 newInstance() 方法通过 Constructor 对象的 newInstance() 方法
// 通过 Class 对象的 newInstance() 方法。
Class user Class.forName(org.example.User);
User newUser (User) user.newInstance();
//通过 Constructor 对象的 newInstance() 方法
Class user Class.forName(org.example.User);
User newUser (User) user.getConstructor().newInstance();
通过 Constructor 对象创建类对象可以选择特定构造方法而通过 Class 对象则只能使用默认的无参数构造方法
API 可以看到 Class 有很多方法 getName()获得类的完整名字。getFields()获得类的public类型的属性。getDeclaredFields()获得类的所有属性。包括private 声明的和继承类getMethods()获得类的public类型的方法。getDeclaredMethods()获得类的所有方法。包括private 声明的和继承类getMethod(String name, Class[] parameterTypes)获得类的特定方法name参数指定方法的名字parameterTypes 参数指定方法的参数类型。getDeclaredConstructors()返回类中所有的构造方法。getConstructors()获得类的public类型的构造方法。getConstructor(Class[] parameterTypes)获得类的特定构造方法parameterTypes 参数指定构造方法的参数类型。newInstance()通过类的不带参数的构造方法创建这个类的一个对象。getModifiers()获取属性的修饰符列表,返回的修饰符是一个数字每个数字是修饰符的代号【一般配合Modifier类的toString(int x)方法使用】getSuperclass()返回调用类的父类。getInterfaces()返回调用类实现的接口集合。 入门案例
反编译一个类
package org.example;/*** className: User* author: SL 苏麟**/
public class User {private String name;public User() {}public User(String name) {this.name name;}/*** 获取* return name*/public String getName() {return name;}/*** 设置* param name*/public void setName(String name) {this.name name;}public String toString() {return User{name name };}
}Testpublic void testUser() throws Exception {StringBuffer stringBuffer new StringBuffer();Class? userClass Class.forName(org.example.User);stringBuffer.append(Modifier.toString(userClass.getModifiers()) class userClass.getSimpleName() {);Constructor?[] constructors userClass.getDeclaredConstructors();for (Constructor? constructor : constructors) {stringBuffer.append(\n\t Modifier.toString(constructor.getModifiers()) ();Class?[] parameterTypes constructor.getParameterTypes();int flag 0;for (Class? parameterType : parameterTypes) {StringBuffer buffer flag 0 ? stringBuffer.append(parameterType.getSimpleName()) : stringBuffer.append( , parameterType.getSimpleName());flag;}stringBuffer.append() \n);}Field[] fields userClass.getDeclaredFields();for (Field field : fields) {stringBuffer.append(\n\t Modifier.toString(field.getModifiers()) field.getType().getSimpleName() field.getName() ;\n);}Method[] methods userClass.getDeclaredMethods();for (Method method : methods) {stringBuffer.append(\n\t Modifier.toString(method.getModifiers()) method.getReturnType().getSimpleName() method.getName() {}\n);}stringBuffer.append(});System.out.println(stringBuffer);}
打破封装
Field类的方法
public void setAccessible(boolean flag) 默认false设置为true为打破封装 Testpublic void testUserPrivate() throws Exception {Class user Class.forName(org.example.User);Field nameField user.getDeclaredField(name);//破坏封装nameField.setAccessible(true);User newUser (User) user.getConstructor().newInstance();nameField.set(newUser, sl);System.out.println(newUser);} 这期就到这里 , 下期见!