文章目录:
Demo2:如何通过反射机制访问一个Java对象的属性?(Field)
Demo3:如何通过反射机制调用一个对象的方法?(Method)
Demo4:如何通过反射机制创建一个对象?(Constructor)
Demo5:给你一个类,如何获取这个类的父类、已实现的接口?
写在前面
- 反射机制有什么用?
通过java语言中的反射机制可以操作字节码文件。
优点类似于黑客。(可以读和修改字节码文件。)
通过反射机制可以操作代码片段。(class文件。)
- 反射机制的相关类在哪个包下?
java.lang.reflect.*;
- 反射机制相关的重要的类有哪些?
java.lang.Class:代表整个字节码,代表一个类型,代表整个类。
java.lang.reflect.Method:代表字节码中的方法字节码。代表类中的方法。
java.lang.reflect.Constructor:代表字节码中的构造方法字节码。代表类中的构造方法
java.lang.reflect.Field:代表字节码中的属性字节码。代表类中的成员变量(静态变量+实例变量)。
//java.lang.Class: public class User{ // Field int no; // Constructor public User(){ } public User(int no){ this.no = no; } // Method public void setNo(int no){ this.no = no; } public int getNo(){ return no; } }
关于JDK中自带的类加载器
- 什么是类加载器?
专门负责加载类的命令/工具。
ClassLoader
- JDK中自带了3个类加载器
启动类加载器: rt.jar
扩展类加载器: ext/*.jar
应用类加载器: classpath
- 首先通过 “启动类加载器” 加载。如果通过 “启动类加载器” 加载不到的时候,会通过 "扩展类加载器" 加载。如果 “扩展类加载器” 没有加载到,那么会通过 “应用类加载器” 加载。
- java中为了保证类加载的安全,使用了双亲委派机制。
优先从启动类加载器中加载,这个称为“父”;“父”无法加载到,再从扩展类加载器中加载,这个称为“母”。双亲委派。如果都加载不到,才会考虑从应用类加载器中加载。直到加载到为止。
Demo1:获取Class的三种方式
package com.szh.reflect; import java.util.Date; /** * 要操作一个类的字节码,需要先获取这个类的字节码 * 怎么获取 java.lang.Class 实例? * Class.forName() * 1.静态方法 * 2.方法的参数是一个字符串 * 3.字符串必须是一个完整类名的全限定名称 */ public class ReflectTest01 { public static void main(String[] args) { /* Class.forName() 1.静态方法 2.方法的参数是一个字符串 3.字符串必须是一个完整类名的全限定名称 */ try { //c1代表String.class文件,或者说c1代表String类型,下面c2、c3、c4同理 Class c1=Class.forName("java.lang.String"); Class c2=Class.forName("java.util.Date"); Class c3=Class.forName("java.lang.Integer"); Class c4=Class.forName("java.lang.System"); System.out.println(c4.getName()); } catch (ClassNotFoundException e) { e.printStackTrace(); } //Java中任何一个对象都有一个方法:getClass() String s="abc"; //x代表String.class文件,或者说x代表String类型 Class x=s.getClass(); System.out.println(x.getName()); //Java中任何一种类型(包括基本数据类型),都有一个 class 属性 Class z=String.class; Class i= Date.class; Class j=int.class; Class k=Double.class; System.out.println(i.getName()); } }
Demo2:如何通过反射机制访问一个Java对象的属性?(Field)
package com.szh.bean; /** * */ public class Student { public int id; private String name; protected int age; boolean sex; }
package com.szh.reflect; import java.lang.reflect.Field; /** * 必须掌握:如何通过反射机制访问一个Java对象的属性? * 给属性赋值 set * 获取属性的值 get */ public class ReflectTest07 { public static void main(String[] args) throws Exception { //通过反射机制获取Class,通过Class实例化对象 Class studentClass=Class.forName("com.szh.bean.Student"); //newInstance() 这个方法会调用Student类中的无参构造方法,完成对象的创建 //obj此时是一个Student对象 Object obj=studentClass.newInstance(); //获取公共属性:id Field idField=studentClass.getDeclaredField("id"); //给obj对象的id属性赋值 idField.set(obj,1001); //获取obj对象的id属性值 System.out.println(idField.get(obj)); //获取私有属性:name Field nameField=studentClass.getDeclaredField("name"); //打破封装 nameField.setAccessible(true); //给obj对象的name属性赋值 nameField.set(obj,"张起灵"); //获取obj对象的name属性值 System.out.println(nameField.get(obj)); } }
Demo3:如何通过反射机制调用一个对象的方法?(Method)
package com.szh.bean; /** * */ public class UserService { public boolean login(String username,String password) { if ("root".equals(username) && "12345678".equals(password)) { return true; } return false; } public void logout() { System.out.println("成功退出!"); } }
package com.szh.reflect; import java.lang.reflect.Method; /** * 必须掌握:通过反射机制调用一个对象的方法 */ public class ReflectTest08 { public static void main(String[] args) throws Exception { //获取类 Class userServiceClass=Class.forName("com.szh.bean.UserService"); //创建对象 Object obj=userServiceClass.newInstance(); //获取类中的Method Method loginMethod=userServiceClass.getDeclaredMethod("login", String.class, String.class); //调用方法 /* loginMethod 是方法 obj 是对象 "root","12345678" 是实参 retValue 是返回值 合起来:调用UserService类中的userService对象调用login方法,传入"root","12345678"实参,获取retValue返回值 */ Object retValue=loginMethod.invoke(obj,"root","12345678"); System.out.println(retValue); } }
Demo4:如何通过反射机制创建一个对象?(Constructor)
package com.szh.bean; /** * */ public class Vip { public int no; public String name; public String birth; public boolean sex; public Vip() { } public Vip(int no) { this.no = no; } public Vip(int no, String name) { this.no = no; this.name = name; } public Vip(int no, String name, String birth) { this.no = no; this.name = name; this.birth = birth; } public Vip(int no, String name, String birth, boolean sex) { this.no = no; this.name = name; this.birth = birth; this.sex = sex; } @Override public String toString() { return "Vip{" + "no=" + no + ", name='" + name + '\'' + ", birth='" + birth + '\'' + ", sex=" + sex + '}'; } }
package com.szh.reflect; import java.lang.reflect.Constructor; /** * 必须掌握:通过反射机制创建一个对象 */ public class ReflectTest09 { public static void main(String[] args) throws Exception { Class vipClass=Class.forName("com.szh.bean.Vip"); //调用无参构造方法 Constructor c=vipClass.getConstructor(); Object obj=c.newInstance(); System.out.println(obj); //调用有参构造方法 //第一步:先获取这个对象的有参构造方法 Constructor constructor=vipClass.getDeclaredConstructor(int.class,String.class,String.class,boolean.class); //第二步:调用有参构造方法new对象 Object newObj=constructor.newInstance(1001,"张起灵","2000-05-01",true); System.out.println(newObj); } }
Demo5:给你一个类,如何获取这个类的父类、已实现的接口?
package com.szh.reflect; /** * 给你一个类,如何获取这个类的父类、已实现的接口 */ public class ReflectTest10 { public static void main(String[] args) throws Exception { //String Class stringClass=Class.forName("java.lang.String"); //获取String的父类 Class superClass=stringClass.getSuperclass(); System.out.println(superClass.getName()); //获取String类实现的所有接口 Class[] strings=stringClass.getInterfaces(); for (Class c : strings) { System.out.println(c.getName()); } } }