ppt素材免费网站,下载类网站 前置备案,企业网站免费推广软件,仙游县住房和城乡建设局网站1.1 反射的概述#xff1a;专业的解释#xff08;了解一下#xff09;#xff1a;是在运行状态中#xff0c;对于任意一个类#xff0c;都能够知道这个类的所有属性和方法#xff1b;对于任意一个对象#xff0c;都能够调用它的任意属性和方法#xff1b;这种动态获取…1.1 反射的概述专业的解释了解一下是在运行状态中对于任意一个类都能够知道这个类的所有属性和方法对于任意一个对象都能够调用它的任意属性和方法这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。通俗的理解掌握利用反射创建的对象可以无视修饰符调用类里面的内容可以跟配置文件结合起来使用把要创建的对象信息和方法写在配置文件中。读取到什么类就创建什么类的对象读取到什么方法就调用什么方法此时当需求变更的时候不需要修改代码只要修改配置文件即可。1.2 学习反射到底学什么反射都是从class字节码文件中获取的内容。如何获取class字节码文件的对象利用反射如何获取构造方法创建对象利用反射如何获取成员变量赋值获取值利用反射如何获取成员方法运行1.3 获取字节码文件对象的三种方式Class这个类里面的静态方法forName“全类名”最常用通过class属性获取通过对象获取字节码文件对象代码示例
//1.Class这个类里面的静态方法forName//Class.forName(类的全类名) 全类名 包名 类名Class clazz1 Class.forName(com.itheima.reflectdemo.Student);//源代码阶段获取 --- 先把Student加载到内存中再获取字节码文件的对象//clazz 就表示Student这个类的字节码文件对象。//就是当Student.class这个文件加载到内存之后产生的字节码文件对象//2.通过class属性获取//类名.classClass clazz2 Student.class;//因为class文件在硬盘中是唯一的所以当这个文件加载到内存之后产生的对象也是唯一的System.out.println(clazz1 clazz2);//true//3.通过Student对象获取字节码文件对象Student s new Student();Class clazz3 s.getClass();System.out.println(clazz1 clazz2);//trueSystem.out.println(clazz2 clazz3);//true1.4 字节码文件和字节码文件对象java文件就是我们自己编写的java代码。字节码文件就是通过java文件编译之后的class文件是在硬盘上真实存在的用眼睛能看到的字节码文件对象当class文件加载到内存之后虚拟机自动创建出来的对象。这个对象里面至少包含了构造方法成员变量成员方法。而我们的反射获取的是什么字节码文件对象这个对象在内存中是唯一的。1.5 获取构造方法规则get表示获取Declared表示私有最后的s表示所有复数形式如果当前获取到的是私有的必须要临时修改访问权限否则无法使用方法名说明Constructor?[] getConstructors()获得所有的构造只能public修饰Constructor?[] getDeclaredConstructors()获得所有的构造包含private修饰ConstructorT getConstructor(Class?... parameterTypes)获取指定构造只能public修饰ConstructorT getDeclaredConstructor(Class?... parameterTypes)获取指定构造包含private修饰代码示例
public class ReflectDemo2 {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {//1.获得整体class字节码文件对象Class clazz Class.forName(com.itheima.reflectdemo.Student);//2.获取构造方法对象//获取所有构造方法publicConstructor[] constructors1 clazz.getConstructors();for (Constructor constructor : constructors1) {System.out.println(constructor);}System.out.println();//获取所有构造带私有的Constructor[] constructors2 clazz.getDeclaredConstructors();for (Constructor constructor : constructors2) {System.out.println(constructor);}System.out.println();//获取指定的空参构造Constructor con1 clazz.getConstructor();System.out.println(con1);Constructor con2 clazz.getConstructor(String.class,int.class);System.out.println(con2);System.out.println();//获取指定的构造(所有构造都可以获取到包括public包括private)Constructor con3 clazz.getDeclaredConstructor();System.out.println(con3);//了解 System.out.println(con3 con1);//每一次获取构造方法对象的时候都会新new一个。Constructor con4 clazz.getDeclaredConstructor(String.class);System.out.println(con4);}}1.6 获取构造方法并创建对象涉及到的方法newInstance代码示例
//首先要有一个javabean类public class Student {private String name;private int age;public Student() {}public Student(String name) {this.name name;}private Student(String name, int age) {this.name name;this.age age;}/*** 获取* return name*/public String getName() {return name;}/*** 设置* param name*/public void setName(String name) {this.name name;}/*** 获取* return age*/public int getAge() {return age;}/*** 设置* param age*/public void setAge(int age) {this.age age;}public String toString() {return Student{name name , age age };}}//测试类中的代码//需求1//获取空参并创建对象//1.获取整体的字节码文件对象Class clazz Class.forName(com.itheima.a02reflectdemo1.Student);//2.获取空参的构造方法Constructor con clazz.getConstructor();//3.利用空参构造方法创建对象Student stu (Student) con.newInstance();System.out.println(stu);System.out.println();//测试类中的代码//需求2//获取带参构造并创建对象//1.获取整体的字节码文件对象Class clazz Class.forName(com.itheima.a02reflectdemo1.Student);//2.获取有参构造方法Constructor con clazz.getDeclaredConstructor(String.class, int.class);//3.临时修改构造方法的访问权限暴力反射con.setAccessible(true);//4.直接创建对象Student stu (Student) con.newInstance(zhangsan, 23);System.out.println(stu);1.7 获取成员变量规则get表示获取Declared表示私有最后的s表示所有复数形式如果当前获取到的是私有的必须要临时修改访问权限否则无法使用方法名方法名说明Field[] getFields()返回所有成员变量对象的数组只能拿public的Field[] getDeclaredFields()返回所有成员变量对象的数组存在就能拿到Field getField(String name)返回单个成员变量对象只能拿public的Field getDeclaredField(String name)返回单个成员变量对象存在就能拿到代码示例
public class ReflectDemo4 {public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {//获取成员变量对象//1.获取class对象Class clazz Class.forName(com.itheima.reflectdemo.Student);//2.获取成员变量的对象Field对象)只能获取public修饰的Field[] fields1 clazz.getFields();for (Field field : fields1) {System.out.println(field);}System.out.println();//获取成员变量的对象public privateField[] fields2 clazz.getDeclaredFields();for (Field field : fields2) {System.out.println(field);}System.out.println();//获得单个成员变量对象//如果获取的属性是不存在的那么会报异常//Field field3 clazz.getField(aaa);//System.out.println(field3);//NoSuchFieldExceptionField field4 clazz.getField(gender);System.out.println(field4);System.out.println();//获取单个成员变量私有Field field5 clazz.getDeclaredField(name);System.out.println(field5);}}public class Student {private String name;private int age;public String gender;public String address;public Student() {}public Student(String name, int age, String address) {this.name name;this.age age;this.address address;}public Student(String name, int age, String gender, String address) {this.name name;this.age age;this.gender gender;this.address address;}/*** 获取* return name*/public String getName() {return name;}/*** 设置* param name*/public void setName(String name) {this.name name;}/*** 获取* return age*/public int getAge() {return age;}/*** 设置* param age*/public void setAge(int age) {this.age age;}/*** 获取* return gender*/public String getGender() {return gender;}/*** 设置* param gender*/public void setGender(String gender) {this.gender gender;}/*** 获取* return address*/public String getAddress() {return address;}/*** 设置* param address*/public void setAddress(String address) {this.address address;}public String toString() {return Student{name name , age age , gender gender , address address };}}1.8 获取成员变量并获取值和修改值方法说明void set(Object obj, Object value赋值Object get(Object obj)获取值代码示例
public class ReflectDemo5 {public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {Student s new Student(zhangsan,23,广州);Student ss new Student(lisi,24,北京);//需求//利用反射获取成员变量并获取值和修改值//1.获取class对象Class clazz Class.forName(com.itheima.reflectdemo.Student);//2.获取name成员变量//field就表示name这个属性的对象Field field clazz.getDeclaredField(name);//临时修饰他的访问权限field.setAccessible(true);//3.设置(修改)name的值//参数一表示要修改哪个对象的name//参数二表示要修改为多少field.set(s,wangwu);//3.获取name的值//表示我要获取这个对象的name的值String result (String)field.get(s);//4.打印结果System.out.println(result);System.out.println(s);System.out.println(ss);}}public class Student {private String name;private int age;public String gender;public String address;public Student() {}public Student(String name, int age, String address) {this.name name;this.age age;this.address address;}public Student(String name, int age, String gender, String address) {this.name name;this.age age;this.gender gender;this.address address;}/*** 获取* return name*/public String getName() {return name;}/*** 设置* param name*/public void setName(String name) {this.name name;}/*** 获取* return age*/public int getAge() {return age;}/*** 设置* param age*/public void setAge(int age) {this.age age;}/*** 获取* return gender*/public String getGender() {return gender;}/*** 设置* param gender*/public void setGender(String gender) {this.gender gender;}/*** 获取* return address*/public String getAddress() {return address;}/*** 设置* param address*/public void setAddress(String address) {this.address address;}public String toString() {return Student{name name , age age , gender gender , address address };}}1.9 获取成员方法规则get表示获取Declared表示私有最后的s表示所有复数形式如果当前获取到的是私有的必须要临时修改访问权限否则无法使用方法名说明Method[] getMethods()返回所有成员方法对象的数组只能拿public的Method[] getDeclaredMethods()返回所有成员方法对象的数组存在就能拿到Method getMethod(String name, Class?... parameterTypes)返回单个成员方法对象只能拿public的Method getDeclaredMethod(String name, Class?... parameterTypes)返回单个成员方法对象存在就能拿到代码示例
public class ReflectDemo6 {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {//1.获取class对象Class? clazz Class.forName(com.itheima.reflectdemo.Student);//2.获取方法//getMethods可以获取父类中public修饰的方法Method[] methods1 clazz.getMethods();for (Method method : methods1) {System.out.println(method);}System.out.println();//获取所有的方法包含私有//但是只能获取自己类中的方法Method[] methods2 clazz.getDeclaredMethods();for (Method method : methods2) {System.out.println(method);}System.out.println();//获取指定的方法空参Method method3 clazz.getMethod(sleep);System.out.println(method3);Method method4 clazz.getMethod(eat,String.class);System.out.println(method4);//获取指定的私有方法Method method5 clazz.getDeclaredMethod(playGame);System.out.println(method5);}}1.10 获取成员方法并运行方法Object invoke(Object obj, Object... args) 运行方法参数一用obj对象调用该方法参数二调用方法的传递的参数如果没有就不写返回值方法的返回值如果没有就不写代码示例
package com.itheima.a02reflectdemo1;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public class ReflectDemo6 {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {//1.获取字节码文件对象Class clazz Class.forName(com.itheima.a02reflectdemo1.Student);//2.获取一个对象//需要用这个对象去调用方法Student s new Student();//3.获取一个指定的方法//参数一方法名//参数二参数列表如果没有可以不写Method eatMethod clazz.getMethod(eat,String.class);//运行//参数一表示方法的调用对象//参数二方法在运行时需要的实际参数//注意点如果方法有返回值那么需要接收invoke的结果//如果方法没有返回值则不需要接收String result (String) eatMethod.invoke(s, 重庆小面);System.out.println(result);}}public class Student {private String name;private int age;public String gender;public String address;public Student() {}public Student(String name) {this.name name;}private Student(String name, int age) {this.name name;this.age age;}/*** 获取* return name*/public String getName() {return name;}/*** 设置* param name*/public void setName(String name) {this.name name;}/*** 获取* return age*/public int getAge() {return age;}/*** 设置* param age*/public void setAge(int age) {this.age age;}public String toString() {return Student{name name , age age };}private void study(){System.out.println(学生在学习);}private void sleep(){System.out.println(学生在睡觉);}public String eat(String something){System.out.println(学生在吃 something);return 学生已经吃完了非常happy;}}面试题你觉得反射好不好好有两个方向第一个方向无视修饰符访问类中的内容。但是这种操作在开发中一般不用都是框架底层来用的。第二个方向反射可以跟配置文件结合起来使用动态的创建对象动态的调用方法。1.11 练习泛型擦除掌握概念了解代码理解掌握集合中的泛型只在java文件中存在当编译成class文件之后就没有泛型了。代码示例了解
package com.itheima.reflectdemo;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.ArrayList;public class ReflectDemo8 {public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {//1.创建集合对象ArrayListInteger list new ArrayList();list.add(123);// list.add(aaa);//2.利用反射运行add方法去添加字符串//因为反射使用的是class字节码文件//获取class对象Class clazz list.getClass();//获取add方法对象Method method clazz.getMethod(add, Object.class);//运行方法method.invoke(list,aaa);//打印集合System.out.println(list);}}1.12 练习修改字符串的内容掌握概念了解代码在这个练习中我需要你掌握的是字符串不能修改的真正原因。字符串在底层是一个byte类型的字节数组名字叫做valueprivate final byte[] value;真正不能被修改的原因final和privatefinal修饰value表示value记录的地址值不能修改。private修饰value而且没有对外提供getvalue和setvalue的方法。所以在外界不能获取或修改value记录的地址值。如果要强行修改可以用反射代码示例了解
String s abc;String ss abc;// private final byte[] value {97,98,99};// 没有对外提供getvalue和setvalue的方法不能修改value记录的地址值// 如果我们利用反射获取了value的地址值。// 也是可以修改的final修饰的value// 真正不可变的value数组的地址值里面的内容利用反射还是可以修改的比较危险//1.获取class对象Class clazz s.getClass();//2.获取value成员变量privateField field clazz.getDeclaredField(value);//但是这种操作非常危险//JDK高版本已经屏蔽了这种操作低版本还是可以的//临时修改权限field.setAccessible(true);//3.获取value记录的地址值byte[] bytes (byte[]) field.get(s);bytes[0] 100;System.out.println(s);//dbcSystem.out.println(ss);//dbc1.13 练习反射和配置文件结合动态获取的练习重点需求: 利用反射根据文件中的不同类名和方法名创建不同的对象并调用方法。分析:①通过Properties加载配置文件②得到类名和方法名③通过类名反射得到Class对象④通过Class对象创建一个对象⑤通过Class对象得到方法⑥调用方法代码示例
public class ReflectDemo9 {public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {//1.读取配置文件的信息Properties prop new Properties();FileInputStream fis new FileInputStream(day14-code\\prop.properties);prop.load(fis);fis.close();System.out.println(prop);String classname prop.get(classname) ;String methodname prop.get(methodname) ;//2.获取字节码文件对象Class clazz Class.forName(classname);//3.要先创建这个类的对象Constructor con clazz.getDeclaredConstructor();con.setAccessible(true);Object o con.newInstance();System.out.println(o);//4.获取方法的对象Method method clazz.getDeclaredMethod(methodname);method.setAccessible(true);//5.运行方法method.invoke(o);}}配置文件中的信息classnamecom.itheima.a02reflectdemo1.Studentmethodnamesleep1.14 利用发射保存对象中的信息重点
public class MyReflectDemo {public static void main(String[] args) throws IllegalAccessException, IOException {/*对于任意一个对象都可以把对象所有的字段名和值保存到文件中去*/Student s new Student(小A,23,女,167.5,睡觉);Teacher t new Teacher(播妞,10000);saveObject(s);}//把对象里面所有的成员变量名和值保存到本地文件中public static void saveObject(Object obj) throws IllegalAccessException, IOException {//1.获取字节码文件的对象Class clazz obj.getClass();//2. 创建IO流BufferedWriter bw new BufferedWriter(new FileWriter(myreflect\\a.txt));//3. 获取所有的成员变量Field[] fields clazz.getDeclaredFields();for (Field field : fields) {field.setAccessible(true);//获取成员变量的名字String name field.getName();//获取成员变量的值Object value field.get(obj);//写出数据bw.write(name value);bw.newLine();}bw.close();}}
public class Student {private String name;private int age;private char gender;private double height;private String hobby;public Student() {}public Student(String name, int age, char gender, double height, String hobby) {this.name name;this.age age;this.gender gender;this.height height;this.hobby hobby;}/*** 获取* return name*/public String getName() {return name;}/*** 设置* param name*/public void setName(String name) {this.name name;}/*** 获取* return age*/public int getAge() {return age;}/*** 设置* param age*/public void setAge(int age) {this.age age;}/*** 获取* return gender*/public char getGender() {return gender;}/*** 设置* param gender*/public void setGender(char gender) {this.gender gender;}/*** 获取* return height*/public double getHeight() {return height;}/*** 设置* param height*/public void setHeight(double height) {this.height height;}/*** 获取* return hobby*/public String getHobby() {return hobby;}/*** 设置* param hobby*/public void setHobby(String hobby) {this.hobby hobby;}public String toString() {return Student{name name , age age , gender gender , height height , hobby hobby };}}
public class Teacher {private String name;private double salary;public Teacher() {}public Teacher(String name, double salary) {this.name name;this.salary salary;}/*** 获取* return name*/public String getName() {return name;}/*** 设置* param name*/public void setName(String name) {this.name name;}/*** 获取* return salary*/public double getSalary() {return salary;}/*** 设置* param salary*/public void setSalary(double salary) {this.salary salary;}public String toString() {return Teacher{name name , salary salary };}}