电商网站建设建站方案,制作网页需要哪些技术,设计师常用的图库网站,wordpress升级php版本崩溃运行java代码要经历的三个阶段 反射#xff0c;程序框架设计的灵魂#xff0c;将类的各个组成部分封装成其他对象#xff0c;这就是反射机制。 框架#xff1a;半成品的软件#xff0c;在框架的基础上进行开发#xff0c;可以简化编码 反射的好处#xff1a; 可以在… 运行java代码要经历的三个阶段 反射程序框架设计的灵魂将类的各个组成部分封装成其他对象这就是反射机制。 框架半成品的软件在框架的基础上进行开发可以简化编码 反射的好处 可以在程序运行的过程中操作这些对象可以解耦提高程序的可拓展性 在运行状态中 对于任意一个类都能够知道这个类的所有属性和方法对于任意一个对象都能够调用它的任意属性和方法 与反射机制相关的类 Java.lang.class :代表整个类编译得到的class文件字节码Java.lang.reflect.Method 代表字节码中的方法字节码Java.lang.reflect.Constructor 代表字节码中的构造器字节码Java.lang.reflect.Field 代表字节码中的属性字节码 要操作一个字节码首先要得到这个类的字节码下面是三种得到字节码的方式 static Class.forName(String className) 这里的className需要时类的全路径这是一个静态方法 public class reflect1 {public static void main(String[] args) throws ClassNotFoundException {//第一种方式Class c1Class.forName(java.lang.String);System.out.println(c1);}
} java中的任意一个对象.getClass() 这个方法继承自Object public class reflect1 {public static void main(String[] args) throws ClassNotFoundException {//第一种方式Class c1Class.forName(java.lang.String);System.out.println(c1);//第二种方式String shello;Class c2s.getClass();System.out.println(c2);}
} java语言中的任意一种类型包括基本数据类型都有.class属性。 public class reflect1 {public static void main(String[] args) throws ClassNotFoundException {//第一种方式Class c1Class.forName(java.lang.String);System.out.println(c1);//第二种方式String shello;Class c2s.getClass();System.out.println(c2);//第三种方式Class c3String.class;System.out.println(c3);}
} JVM在加载一个类的时候会把这个类的.class字节码文件放在方法区中栈中放入main方法进行压栈堆中new出对象c但是无论使用什么方法获取字节码一样的class字节码文件只会放一份在方法区中得到的c变量都是指向方法区中的同一份.class文件。 使用反射机制来实例化对象 通过Class的newInstance() 方法可以实例化对象 但是newInstance()方法内部实际上调用了无参构造方法必须要保证无参构造的存在才可以 private static void test2() throws InstantiationException, IllegalAccessException {Object oStudent.class.newInstance();System.out.println(o);}反射机制的灵活性在不修改源码的情况下可以做到不同对象的实例化符合OCP开闭原则对拓展开放对修改关闭. 下面的代码中首先利用FileReader读取配置文件配置文件里面保存了键和值值是类名之后new了一个Properties对象Properties对象的键和值都是String类型是一种Map数据类型之后将文件流对象传入Properties对象再根据键得到值然后利用反射机制传入类名新建一个对象实现了对象的灵活创建。 private static void test3() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {FileReader frnew FileReader(Student.properties);Properties pronew Properties();pro.load(fr);fr.close();String forNamepro.getProperty(Student);Class CClass.forName(forName);Object oC.newInstance();System.out.println(o);}如果只想要让类里面的某些代码被执行那么可以使用静态代码和Class.forName,像下面的代码那样每次类加载器加载一个类的时候就会先执行静态代码块使用Class.forName而不用创建类的实例化变量 public class reflect1 {static {System.out.println(静态代码执行);}
}private static void test4() {try {Class.forName(reflect1);} catch (ClassNotFoundException e) {throw new RuntimeException(e);}}获取文件的类路径可以通过类加载器获取具体如下 private static void test4() {String pathThread.currentThread().getContextClassLoader().getResource(a.txt).getPath();System.out.println(path);}资源绑定器 用来获取属性配置文件中的内容 属性配置文件必须要放在类路径下(src下面) 必须是properties后缀 绑定某个属性配置文件的时候只需要填写配置文件的名字不需要写后缀也不能写后缀 private static void test4() {ResourceBundle bundleResourceBundle.getBundle(Student);String pathbundle.getString(Student);System.out.println(path);}获取并操作属性字节码 首先获取整个字节码 利用字节码的getFields可以获取到public修饰的所有属性 利用字节码的getDeclaredFields可以获取到所有属性无论什么修饰符都可以获取到 遍历属性列表 通过属性.getName()可以获取到属性的名字 通过属性.getType()可以获取到属性的完整类型getSimpleName是获取简化的类名 通过属性.getModifiers()可以获取到属性的修饰符id通过Modifier.toString(id)就可以拿到完整的修饰符 import java.io.Serializable;public class Student implements Serializable {
// 属性设置为privateprivate String name;private int age;private static String room;//无参数构造public Student() {}//有参数构造public Student(String name, int age, String room) {this.name name;this.age age;this.roomroom;}//getter方法public String getName() {return name;}public int getAge() {return age;}public static String getRoom() {return room;}//setter方法public void setName(String name) {this.name name;}public void setAge(int age) {this.age age;}public static void setRoom(String room) {Student.room room;}//重写equals方法public boolean equals(Object obj){if(obj instanceof Student) {//首先将得到的Object转为Student否则使用不了Student特有的方法多态的弊端Student t (Student) obj;return t.getAge() this.getAge() t.getName() this.getName() t.getRoom() this.getRoom();}return false;}Overridepublic String toString() {return Student{ name name \ , age age };}
} private static void test5() throws ClassNotFoundException {//获取整个类Class studentClassStudent.class;//获取public修饰的属性,一个Filed包括private static String room;Field[] filedsstudentClass.getFields();for (Field filed : fileds) {System.out.println(filed);}//获取所有的属性,一个Filed包括private static String room;filedsstudentClass.getDeclaredFields();for (Field filed : fileds) {//获取属性的名字System.out.println(属性的名字:);System.out.println(filed.getName());//获取属性的类型Class filedTypeClassfiled.getType();//getName是获取完整类型getSimpleName是获取简化的类名String filedTypefiledTypeClass.getSimpleName();System.out.println(属性的类型);System.out.println(filedType);//获取属性的修饰符int modifyfiled.getModifiers();String modifyName Modifier.toString(modify);System.out.println(属性的修饰符);System.out.println(modifyName);System.out.println();}}利用反射机制访问一个对象的属性 要使用反射当然要先获取一个类的字节码文件 利用获取到的字节码文件再用newInstance方法创建一个对象使用反射的类必须有无参构造 利用字节码文件获取这个类的某个属性 利用这个属性给创建的对象的对应的属性赋值 在设置对象的属性值之前需要在使用 set 方法之前调用 setAccessible(true) 方法来取消对字段的访问权限检查。否则 会报IllegalAccessException 异常。这是因为 name 字段被声明为 private无法直接访问。但是使用反射机制绕过访问权限限制可能会导致安全问题。 private static void test6() throws NoSuchFieldException, InstantiationException, IllegalAccessException {//获取整个类Class studentClassStudent.class;Field filedstudentClass.getDeclaredField(name);Object objstudentClass.newInstance();filed.setAccessible(true); // 取消对字段的访问权限检查filed.set(obj,zs);System.out.println(obj);}利用反射机制获取Method 获取整个类的字节码文件 通过字节码文件得到方法的字节码并且遍历它 通过.getName()获取方法名字 通过.getReturnType().getSimpleName()获取返回值类型 通过.getModifiers()获取修饰符id然后通过Modifier.toString(id)得到修饰符 通过.getParameterTypes()得到修饰符列表遍历这个列表通过.getSimpleName()得到参数名称 private static void test7() {Class studentClassStudent.class;Method[] methodsstudentClass.getDeclaredMethods();for (Method method : methods) {//获取方法名System.out.println(方法名);System.out.println(method.getName());//获取方法的返回值类型System.out.println(方法的返回值类型);System.out.println(method.getReturnType().getSimpleName());//获取修饰符列表System.out.println(方法的修饰符列表);System.out.println(Modifier.toString(method.getModifiers()));//方法的参数列表System.out.println(方法的参数列表);Class[] parametorType method.getParameterTypes();for (Class aClass : parametorType) {System.out.println(aClass.getSimpleName());}System.out.println();}}通过反射机制操纵Method 首先获取字节码 利用得到的字节码新建一个对象 利用得到的字节码获取一个指定的方法在java里面由于存在方法的重载所以区分一个方法是由方法名方法参数类型而不仅仅是方法名所以使用getDeclaredMethod方法需要一个方法名和若干参数的class 最后使用这个方法的invoke方法传入要操纵的对象和实参 private static void test8() throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {Class studentClassStudent.class;Object objstudentClass.newInstance();Method setNamestudentClass.getDeclaredMethod(setName,String.class);Object returnVasetName.invoke(obj,zs);System.out.println(obj);}通过反射机制获取构造方法 获取整个类的字节码文件 通过字节码文件得到构造方法的字节码并且遍历它 通过.getName()获取方法名字 通过.getModifiers()获取修饰符id然后通过Modifier.toString(id)得到修饰符 通过.getParameterTypes()得到修饰符列表遍历这个列表通过.getSimpleName()得到参数名称 private static void test9() {Class studentClassStudent.class;Constructor[] constructorsstudentClass.getDeclaredConstructors();for (Constructor constructor : constructors) {//获取构造方法名System.out.println(构造方法名);System.out.println(constructor.getName());//获取修饰符列表System.out.println(构造方法的修饰符列表);System.out.println(Modifier.toString(constructor.getModifiers()));//方法的参数列表System.out.println(构造方法的参数列表);Class[] parametorType constructor.getParameterTypes();for (Class aClass : parametorType) {System.out.println(aClass.getSimpleName());}System.out.println();}}使用反射机制的构造方法创建对象 直接利用字节码创建已过时 首先获取无参构造函数然后调用无参构造函数 首先获取有参构造函数然后调用有参构造函数 private static void test10() throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {//使用反射创建对象//1. 直接利用字节码创建Class studentClassStudent.class;Object t1studentClass.newInstance();//2. 先利用字节码获取构造函数然后再利用构造函数创建对象//首先是无参构造Constructor con1studentClass.getDeclaredConstructor();Object t2con1.newInstance();//最后是有参构造方法Constructor con2studentClass.getDeclaredConstructor(String.class,int.class,String.class);Object t3con2.newInstance(zs,18,h111);System.out.println(t1);System.out.println(t2);System.out.println(t3);}使用反射获取一个类的父类以及接口 private static void test11() {Class stringClassString.class;//获取String的父类Class superClassstringClass.getSuperclass();System.out.println(父类是);System.out.println(superClass.getSimpleName());//获取接口Class[] interface1stringClass.getInterfaces();System.out.println(接口是);for (Class aClass : interface1) {System.out.println(aClass.getSimpleName());}}