概述

通过Java语言中的反射机制可以操作字节码文件,优点是类似于黑客,可以读和修改字节码文件。。Java反射相关的类在java.lang.reflect.*包下,具体来讲,包括:
①java.lang.Class;代表字节码文件
②java.lang.reflect.Method;方法字节码
③java.lang.reflect.Constructor;构造器字节码
④java.lang.reflect.Field属性字节码

  1. package reflect;
  2. /**
  3. * 字节码文件中的xxx字节码
  4. */
  5. //Class文件代表整个字节码文件
  6. public class User {
  7. //Field字节码,即属性字节码
  8. int no;
  9. //Constructor字节码,即构造器字节码
  10. public User() {
  11. }
  12. //Method字节码,即方法字节码
  13. public int getNo() {
  14. return no;
  15. }
  16. public void setNo(int no) {
  17. this.no = no;
  18. }
  19. }

想要获得字节码文件中的属性、方法或者构造器,首先要获得字节码文件。

3种方式获得字节码文件

①Class.forName(“类名”);
Class c1 = Class.forName(“java.util.String”); //c1代表的是String.class
②对象.getClass();
③包括基本数据类型中在内的任何一种类型,都有.class属性:
Class c = String.class,c代表String类型

  1. package reflect;
  2. /**
  3. * 想要操作一个类的字节码,首先要获得这个类的字节码,有三种方式获得这个类的字节码文件(java.lang.Class)
  4. */
  5. public class RefectTest01 {
  6. public static void main(String[] args) throws ClassNotFoundException {
  7. //方式一:c1,c2,c3是对应类的整个.class文件
  8. Class c1 = Class.forName("java.lang.String");
  9. Class c2 = Class.forName("java.util.Date");
  10. Class c3 = Class.forName("java.lang.System");
  11. //方式二:java中任何一个对象都有getClass()方法,旨在获取该对象所在的类
  12. String s = "abc";
  13. Class x = s.getClass(); //x代表的是String.class字节码文件,x代表的是String类型
  14. System.out.println(c1 == x); //true
  15. //方式三:java语言中,任何一种类型,包括基本数据类型,都有.class属性
  16. Class str = String.class; //str代表String类型
  17. System.out.println(c1 == str); //true
  18. }
  19. }

反射 - 图1

获得Class,能做什么?

获取对象

  1. package reflect.bean;
  2. public class User {
  3. public User(){
  4. System.out.print("无参构造方法执行了!"+"\t");
  5. }
  6. //若没有无参构造方法,对象.newInstance()会出现实例化异常
  7. }
  8. package reflect;
  9. /**
  10. * 获取到Class之后,能做什么?
  11. * 通过Class的newInstance方法来实例化对象。
  12. * 注意:newInstance方法内部实际上调用了无参构造器,所以必须保证无参构造器存在才行
  13. * 那么问题来了:这种方式创建对象和常规方法相比,优势在哪?
  14. */
  15. public class ReflectTest02 {
  16. //通过反射机制获取Class,通过Class来实例化对象
  17. public static void main(String[] args) {
  18. //使用反射机制创建对象
  19. try {
  20. Class c1 = Class.forName("reflect.bean.User");
  21. //这个方法会调用User这个类的无参构造方法,完成对象的创建
  22. Object obj = c1.newInstance();
  23. System.out.println(obj); //无参构造方法执行了! reflect.bean.User@1b6d3586
  24. } catch (ClassNotFoundException e) {
  25. e.printStackTrace();
  26. } catch (IllegalAccessException e) {
  27. e.printStackTrace();
  28. } catch (InstantiationException e) {
  29. e.printStackTrace();
  30. }
  31. //不使用反射机制创建对象
  32. User user = new User();
  33. System.out.println(user); //reflect.User@4554617c
  34. }
  35. }

如何体现发射机制的优越性?

在IDEA中创建以上文件,布局如右图:image.png

  1. package reflect;
  2. import java.io.FileReader;
  3. import java.io.IOException;
  4. import java.util.Properties;
  5. /**
  6. * 验证反射机制的灵活性:
  7. * Java代码写一遍,在不改变代码的基础上,可以做到不同对象的实例化,这就体现了反射的灵活性
  8. * 符合OCP原则:对扩展开放,对修改关闭
  9. * 高级框架例如:SSM、SSH的底层都使用了反射机制
  10. */
  11. public class ReflectTest03 {
  12. public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
  13. //用IO流读取classinfo.properties文件
  14. FileReader fr = new FileReader("D:\\DataValue\\project\\MyData\\Data1\\src\\reflect\\classinfo.properties");
  15. //创建属性类对象
  16. Properties pro = new Properties();
  17. //加载
  18. pro.load(fr);
  19. //关闭流
  20. fr.close();
  21. //通过key获取value
  22. String className = pro.getProperty("className");
  23. System.out.println(className); //reflect.User
  24. //通过反射机制实例化对象
  25. Class c2 = Class.forName(className);
  26. Object obj = c2.newInstance();
  27. System.out.println(obj); //reflect.User@1b6d3586
  28. //以上代码不改,改配置文件的className,改为:java.util.Date
  29. //输出为:
  30. // java.util.Date
  31. // Thu Oct 14 08:00:56 CST 2021
  32. }
  33. }

Class.forName()的作用

  1. package reflect;
  2. /*
  3. 研究一下,Class.forName()发生了什么?
  4. Class.forName()这个方法的执行会导致类加载,类加载时静态代码块会执行!
  5. */
  6. public class ReflectTest04 {
  7. public static void main(String[] args) throws ClassNotFoundException {
  8. Class.forName("reflect.MyClass"); //静态代码块执行了!
  9. }
  10. }
  11. class MyClass{
  12. //静态代码块在类加载时执行,且只执行一次
  13. static {
  14. System.out.println("静态代码块执行了!");
  15. }
  16. }

获取类路径下文件的绝对路径

  1. package reflect;
  2. /*
  3. 研究一下文件路径的问题
  4. 相对路径的缺点:可移植性差,换个编译工具,可能就找不到该文件了
  5. */
  6. public class AboutPathTest {
  7. public static void main(String[] args) {
  8. //方式一
  9. //使用以下方式的前提是,这个文件必须在类路径(src,src是类的根路径)下--Tcggg
  10. //当前线程对象的类加载器的根路径下加载资源获取绝对路径
  11. //这种方式获取绝对路径是通用的,不管是在哪个盘,什么系统
  12. String path = Thread.currentThread().getContextClassLoader().getResource("reflect/classinfo.properties").getPath();
  13. // /D:/DataValue/project/MyData/Data1/out/production/Data1/reflect/classinfo.properties
  14. //起点类的根路径
  15. System.out.println(path);
  16. //方式二:以流的形式返回
  17. /* String path1 = Thread.currentThread().getContextClassLoader().getResource("").getPath();
  18. FileReader fileReader = new FileReader(path1);*/
  19. //以上2行可以合并为以下这行,直接以流形式返回
  20. InputStream reader = Thread.currentThread().getContextClassLoader().getResourceAsStream("reflect/classinfo.properties");
  21. Properties pro = new Properties();
  22. pro.load(reader);
  23. reader.close();
  24. String className = pro.getProperty("className");
  25. System.out.println(className); //java.util.Date
  26. }
  27. }

获取属性配置文件的内容

类及其他文件布局如下图:
image.png

  1. package reflect.bean;
  2. public class User {
  3. String name;
  4. public User(String name) {
  5. this.name = name;
  6. }
  7. }
  1. package reflect;
  2. import java.util.ResourceBundle;
  3. /*
  4. java.util包下提供了一个资源绑定器,便于获取属性配置文件中的内容
  5. 使用以下这种方式的时候,属性配置文件xxx.properties必须放到类路径下
  6. */
  7. public class ResourceBundleTest {
  8. public static void main(String[] args) {
  9. //资源绑定器,只能绑定xxx.properties文件。并且这个文件必须在类路径下,文件扩展名也必须是properties
  10. //并且在写路径的时候,路径后面的扩展名不能写
  11. //总之三个要求:①src目录下 ②文件是属性配置文件 ③后缀名不能写
  12. ResourceBundle bundle = ResourceBundle.getBundle("classinfo");
  13. String className = bundle.getString("className");
  14. System.out.println(className); //reflect.bean.User
  15. }
  16. }

类加载器概述

类加载器是负责专门加载类的命令或是工具,jdk自带的有3种类加载器:

  1. - 启动类加载器(父)
  2. - 扩展类加载器(母)
  3. - 应用类加载器

父和母被称为双亲委派机制。先父后母,即如果你写了String类,Sun公司自己也有String类,按这个机制来,优先加载Sun公司写的String类。这是为了类加载的安全而设置的双亲委派机制。
假设有这样一段代码:String s = “abc”;
在代码开始执行之前,会将所需的类全部加载到JVM中。那么是怎么进行加载的呢?首先是启动类加载器去加载,加载的对象是jdk目录下jdk/jre/lib/rt.jar。(注:rt.jar中的都是JDK最核心的类库。)
如果通过启动类加载器加载不到,会通过扩展类加载器去加载。注意:扩展类加载器专门加载jre/lib/ext.jar。
如果扩展类加载器也没加载到,就会通过应用类加载器加载,这里加载的是classpath中的类(class文件).

获取属性对象

  1. package reflect;
  2. import java.lang.reflect.Field;
  3. import java.lang.reflect.Modifier;
  4. /*
  5. 反射Student类中所有的Field
  6. */
  7. public class ReflectTest05 {
  8. public static void main(String[] args) throws ClassNotFoundException {
  9. //获取整个类
  10. Class studentClass = Class.forName("reflect.bean.Student");
  11. String className = studentClass.getName();
  12. System.out.println(className); //reflect.bean.Student
  13. String simpleName = studentClass.getSimpleName();
  14. System.out.println(simpleName); //Student
  15. //获取类中所有public 修饰的Field
  16. Field[] fields = studentClass.getFields();
  17. System.out.println(fields.length); //1
  18. //取出这个Field
  19. Field f = fields[0];
  20. //取出这个Field的名字
  21. String fieldName = f.getName();
  22. System.out.println(fieldName); //no
  23. //获取类中所有Field
  24. Field[] fs = studentClass.getDeclaredFields();
  25. System.out.println("------------------------------------");
  26. System.out.println(fs.length);
  27. for (Field field : fs) {
  28. //获取属性的修饰符列表
  29. //返回的修饰符是一个数字,每个数字是修饰符的代号
  30. int i = field.getModifiers();
  31. // System.out.println(i);
  32. //可以将这个代号数字转换为“字符串”吗?
  33. String modifierStr = Modifier.toString(i);
  34. System.out.print(modifierStr+" ");
  35. //获取属性的类型
  36. Class fieldType = field.getType();
  37. // String fieldTypeName = fieldType.getName();
  38. // System.out.println(fieldTypeName);
  39. String fieldTypeSimpleName = fieldType.getSimpleName();
  40. System.out.print(fieldTypeSimpleName+" ");
  41. //获取属性的名字
  42. System.out.println(field.getName());
  43. }
  44. }
  45. }
  46. /*
  47. 整体内容输出如下:
  48. ------------------------------------
  49. 5
  50. private String name
  51. protected int age
  52. boolean gender
  53. public int no
  54. public static final double MATH_PI
  55. */

反编译之Student类

  1. package reflect;
  2. import java.lang.reflect.Field;
  3. import java.lang.reflect.Modifier;
  4. /*
  5. 反编译Student这个Bean类
  6. 只需要提供全类名
  7. */
  8. public class ReflectTest06 {
  9. public static void main(String[] args) throws Exception{
  10. Class studentClass = Class.forName("reflect.bean.Student");
  11. StringBuilder s = new StringBuilder();
  12. s.append(Modifier.toString(studentClass.getModifiers()) + " class " + studentClass.getSimpleName() + "{\n");
  13. Field[] fields = studentClass.getDeclaredFields();
  14. for (Field field : fields) {
  15. s.append("\t");
  16. s.append(Modifier.toString(field.getModifiers())+" "+field.getType().getSimpleName()+" "+field.getName()+";\n");
  17. }
  18. s.append("}");
  19. System.out.println(s);
  20. }
  21. }
  22. /*
  23. 反编译Students类的输出结果:
  24. public class Student{
  25. private String name;
  26. protected int age;
  27. boolean gender;
  28. public int no;
  29. public static final double MATH_PI;
  30. }
  31. */

反编译之Date类

  1. package reflect;
  2. import java.lang.reflect.Field;
  3. import java.lang.reflect.Modifier;
  4. public class ReflectTest06 {
  5. public static void main(String[] args) throws Exception{
  6. Class studentClass = Class.forName("java.util.Date");
  7. StringBuilder s = new StringBuilder();
  8. s.append(Modifier.toString(studentClass.getModifiers()) + " class " + studentClass.getSimpleName() + "{\n");
  9. Field[] fields = studentClass.getDeclaredFields();
  10. for (Field field : fields) {
  11. s.append("\t");
  12. s.append(Modifier.toString(field.getModifiers())+" "+field.getType().getSimpleName()+" "+field.getName()+";\n");
  13. }
  14. s.append("}");
  15. System.out.println(s);
  16. }
  17. }
  18. /*
  19. 反编译Students类的输出结果:
  20. public class Date{
  21. private static final BaseCalendar gcal;
  22. private static BaseCalendar jcal;
  23. private transient long fastTime;
  24. private transient Date cdate;
  25. private static int defaultCenturyStart;
  26. private static final long serialVersionUID;
  27. private static final String[] wtb;
  28. private static final int[] ttb;
  29. }
  30. */

反编译之String类

  1. package reflect;
  2. import java.lang.reflect.Field;
  3. import java.lang.reflect.Modifier;
  4. public class ReflectTest06 {
  5. public static void main(String[] args) throws Exception{
  6. Class studentClass = Class.forName("java.lang.String");
  7. StringBuilder s = new StringBuilder();
  8. s.append(Modifier.toString(studentClass.getModifiers()) + " class " + studentClass.getSimpleName() + "{\n");
  9. Field[] fields = studentClass.getDeclaredFields();
  10. for (Field field : fields) {
  11. s.append("\t");
  12. s.append(Modifier.toString(field.getModifiers())+" "+field.getType().getSimpleName()+" "+field.getName()+";\n");
  13. }
  14. s.append("}");
  15. System.out.println(s);
  16. }
  17. }
  18. /*
  19. 反编译Students类的输出结果:
  20. public final class String{
  21. private final char[] value;
  22. private int hash;
  23. private static final long serialVersionUID;
  24. private static final ObjectStreamField[] serialPersistentFields;
  25. public static final Comparator CASE_INSENSITIVE_ORDER;
  26. }
  27. */

外部修改属性值

  1. package reflect.bean;
  2. import java.lang.reflect.Field;
  3. /*
  4. 通过反射机制去访问对象属性,包括对对象属性值的获取和修改
  5. 这种方法的好处是能写到配置文件中,能发挥反射机制的灵活性
  6. */
  7. public class ReflectTest07 {
  8. public static void main(String[] args) throws Exception{
  9. Class studentClass = Class.forName("reflect.bean.Student");
  10. //注意:这个obj就是Student对象。效果等同 Student student = new Student();中的student
  11. Object obj = studentClass.newInstance();
  12. //获取no属性,属性之间是按照属性名来区分的
  13. Field noField = studentClass.getDeclaredField("no");
  14. //给obj对象的no属性赋值
  15. /*
  16. 虽然使用了反射机制,但是三要素还是缺一不可的:
  17. 要素1:obj对象
  18. 要素2:no属性
  19. 要素3:属性值2222
  20. */
  21. noField.set(obj,2222);
  22. //读取属性的值:2个要素:①对象 ②属性
  23. System.out.println(noField.get(obj)); //2222
  24. //可以从外部修改私有的属性吗
  25. Field nameField = studentClass.getDeclaredField("name");
  26. //打破封装!!!可能会给不法分子留下机会
  27. nameField.setAccessible(true);
  28. nameField.set(obj,"jackson");
  29. System.out.println(nameField.get(obj));
  30. }
  31. }

获取对象方法

先定义一个类,然后通过反射去拿取这个类的所有方法(签名)

  1. package reflect.service;
  2. /*
  3. 用户业务类
  4. */
  5. public class UserService {
  6. public boolean login(String name,String password){
  7. if ("admin".equals(name)&&"123".equals(password)){
  8. return true;
  9. }
  10. return false;
  11. }
  12. public void logout(){
  13. System.out.println("系统已经安全退出");
  14. }
  15. }
  1. package reflect;
  2. import java.lang.reflect.Method;
  3. import java.lang.reflect.Modifier;
  4. /*
  5. 反射获取对象的方法
  6. */
  7. public class ReflectTest08 {
  8. public static void main(String[] args) throws Exception{
  9. Class userServiceClass = Class.forName("reflect.service.UserService");
  10. //获取对象的所有方法
  11. Method[] declaredMethods = userServiceClass.getDeclaredMethods();
  12. //下面对方法进行遍历:
  13. for (Method declaredMethod : declaredMethods) {
  14. //获取方法的修饰符列表
  15. System.out.println(Modifier.toString(declaredMethod.getModifiers()));
  16. //获取方法的返回值类型
  17. System.out.println(declaredMethod.getReturnType());
  18. //获取方法名
  19. System.out.println(declaredMethod.getName());
  20. //获取方法的参数列表
  21. Class[] parameterTypes = declaredMethod.getParameterTypes();
  22. for (Class parameterType : parameterTypes) {
  23. System.out.println(parameterType.getSimpleName());
  24. }
  25. }
  26. }
  27. }
  28. /*
  29. 结果输出:
  30. public
  31. void
  32. logout
  33. public
  34. boolean
  35. login
  36. String
  37. String
  38. */

可变长参数

  1. package reflect;
  2. /*
  3. 可变长度参数
  4. int... args
  5. 语法格式:类型...(注意,是3个点)
  6. 1.可变长参数的参数个数是0-n个
  7. 2.可变长参数必须在参数列表中的最后一个,且只能有一个可边长参数
  8. 3.可变长参数
  9. */
  10. public class ArgsTest {
  11. public static void main(String[] args) {
  12. m(); //m方法执行了...
  13. m(10); //m方法执行了...
  14. m(10,20,30,40); //m方法执行了...
  15. m3("ab","cd","ef"); //ab cd ef
  16. //可以传一个数组
  17. String[] strs = {"a","b","c"};
  18. m3(strs); //a b c
  19. m3(new String[]{"我","是","中","国","人"});//我 是 中 国 人
  20. }
  21. public static void m(int... args){
  22. System.out.println("m方法执行了...");
  23. }
  24. public static void m3(String... args){
  25. //args有length属性,说明args是一个数组
  26. //
  27. for (int i = 0; i < args.length; i++) {
  28. System.out.print(args[i]+"\t");
  29. }
  30. }
  31. }

反编译对象的方法

  1. package reflect.service;
  2. /*
  3. 用户业务类
  4. */
  5. public class UserService {
  6. public boolean login(String name,String password){
  7. if ("admin".equals(name)&&"123".equals(password)){
  8. return true;
  9. }
  10. return false;
  11. }
  12. public void logout(){
  13. System.out.println("系统已经安全退出");
  14. }
  15. }
  1. package reflect;
  2. import java.lang.reflect.Method;
  3. import java.lang.reflect.Modifier;
  4. /*
  5. 反编译方法签名
  6. public class UserService {
  7. public boolean login(String name,String password){}
  8. }
  9. */
  10. public class ReflectTest09 {
  11. public static void main(String[] args) throws Exception{
  12. StringBuilder s = new StringBuilder();
  13. Class userServiceClass = Class.forName("reflect.service.UserService");
  14. s.append(Modifier.toString(userServiceClass.getModifiers()));
  15. s.append(" class ");
  16. s.append(userServiceClass.getSimpleName()+"{\n");
  17. Method[] declaredMethods = userServiceClass.getDeclaredMethods();
  18. //public boolean login(String name,String password){}
  19. for (Method declaredMethod : declaredMethods) {
  20. s.append(" "+Modifier.toString(declaredMethod.getModifiers()));
  21. s.append(" "+declaredMethod.getReturnType()+" ");
  22. s.append(declaredMethod.getName());
  23. s.append("(");
  24. Class[] parameterTypes = declaredMethod.getParameterTypes();
  25. for (Class parameterType : parameterTypes) {
  26. s.append(parameterType.getSimpleName());
  27. s.append(",");
  28. }
  29. s.deleteCharAt(s.length()-1);
  30. s.append("){}\n");
  31. }
  32. s.append("}");
  33. System.out.println(s);
  34. }
  35. }
  36. /*
  37. 输出如下:
  38. public class UserService{
  39. public void logout){}
  40. public boolean login(String,String){}
  41. }
  42. */

访问或者修改对象的方法

  1. package reflect.service;
  2. /*
  3. 用户业务类
  4. */
  5. public class UserService {
  6. public boolean login(String name,String password){
  7. if ("admin".equals(name)&&"123".equals(password)){
  8. return true;
  9. }
  10. return false;
  11. }
  12. public void logout(){
  13. System.out.println("系统已经安全退出");
  14. }
  15. }
  1. package reflect;
  2. import reflect.service.UserService;
  3. import java.lang.reflect.Method;
  4. /*
  5. ★★★★★重点:通过反射机制怎么去调用一个对象的方法?★★★★★
  6. 反射机制让代码具有通用性,把需要改变的东西写到配置文件里,灵活
  7. */
  8. public class ReflectTest10 {
  9. public static void main(String[] args) throws Exception{
  10. //不使用反射机制,如何调用方法?
  11. UserService userService = new UserService();
  12. boolean loginSuccess = userService.login("admin", "123");
  13. System.out.println(loginSuccess); //true
  14. //通过反射机制如何调用对象的方法?
  15. Class uService = Class.forName("reflect.service.UserService");
  16. //创建对象
  17. Object obj = uService.newInstance();
  18. //获取Method(方法名和形参列表)
  19. Method loginMethod = uService.getDeclaredMethod("login", String.class, String.class);
  20. //反射方法四要素:对象、方法名、实参、返回值
  21. Object retValue = loginMethod.invoke(obj, "admin", "123");
  22. System.out.println(retValue); //true
  23. }
  24. }

获取构造器信息

反编译构造器(烂尾工程)

  1. package reflect.bean;
  2. public class Vip {
  3. int no;
  4. String name;
  5. String birth;
  6. boolean gender;
  7. public Vip(int no, String name, String birth, boolean gender) {
  8. this.no = no;
  9. this.name = name;
  10. this.birth = birth;
  11. this.gender = gender;
  12. }
  13. public Vip(int no, String name, String birth) {
  14. this.no = no;
  15. this.name = name;
  16. this.birth = birth;
  17. }
  18. public Vip(int no, String name) {
  19. this.no = no;
  20. this.name = name;
  21. }
  22. public Vip(int no) {
  23. this.no = no;
  24. }
  25. public Vip() {
  26. }
  27. }
  1. package reflect;
  2. import java.lang.reflect.Constructor;
  3. import java.lang.reflect.Modifier;
  4. /*
  5. 反编译一个类的Constructor构造方法
  6. */
  7. public class ReflectTest11 {
  8. public static void main(String[] args) throws Exception{
  9. //public class Vip{}
  10. StringBuilder s = new StringBuilder();
  11. Class vipClass = Class.forName("reflect.bean.Vip");
  12. s.append(Modifier.toString(vipClass.getModifiers())+" class ");
  13. s.append(vipClass.getSimpleName()+"(");
  14. // Constructor[] declaredConstructors = vipClass.getDeclaredConstructors();
  15. // for (Constructor declaredConstructor : declaredConstructors) {
  16. // s.append("{\n\t"+Modifier.toString(declaredConstructor.getModifiers())+" class ");
  17. // s.append(vipClass.getSimpleName()+"(");
  18. //
  19. // s.append(")\n");
  20. // }
  21. s.append("){");
  22. s.append("}");
  23. s.append("\n}");
  24. System.out.println(s);
  25. }
  26. }

用反射初始化对象

  1. package reflect.bean;
  2. public class Vip {
  3. int no;
  4. String name;
  5. String birth;
  6. boolean gender;
  7. public Vip(int no, String name, String birth, boolean gender) {
  8. this.no = no;
  9. this.name = name;
  10. this.birth = birth;
  11. this.gender = gender;
  12. }
  13. public Vip(int no, String name, String birth) {
  14. this.no = no;
  15. this.name = name;
  16. this.birth = birth;
  17. }
  18. public Vip(int no, String name) {
  19. this.no = no;
  20. this.name = name;
  21. }
  22. public Vip(int no) {
  23. this.no = no;
  24. }
  25. public Vip() {
  26. }
  27. @Override
  28. public String toString() {
  29. return "Vip{" +
  30. "no=" + no +
  31. ", name='" + name + '\'' +
  32. ", birth='" + birth + '\'' +
  33. ", gender=" + gender +
  34. '}';
  35. }
  36. }
  1. package reflect;
  2. import reflect.bean.Vip;
  3. import java.lang.reflect.Constructor;
  4. /*
  5. 使用反射机制创建对象
  6. */
  7. public class ReflectTest12 {
  8. public static void main(String[] args) throws Exception{
  9. //不使用反射机制怎么创建对象?
  10. Vip v1 = new Vip();
  11. Vip v2 = new Vip(110, "zhangsan", "2001-10-1", true);
  12. //使用反射机制怎么创建对象
  13. //无参
  14. Class vipClass = Class.forName("reflect.bean.Vip");
  15. Object obj1 = vipClass.newInstance();
  16. //有参
  17. //第一步,先获取到这个有参数的构造方法
  18. Constructor constructor = vipClass.getDeclaredConstructor(int.class, String.class, String.class, boolean.class);
  19. //第二步,调用构造方法new对象
  20. Object obj2 = constructor.newInstance(110, "lisi", "1996-7-10", false);
  21. System.out.println("obj1:" + obj1 + "\nobj2:" + obj2);
  22. }
  23. }
  24. //输出:
  25. //obj1:Vip{no=0, name='null', birth='null', gender=false}
  26. //obj2:Vip{no=110, name='lisi', birth='1996-7-10', gender=false}

获取一个类的父类及其实现的所有接口

  1. package reflect;
  2. /*
  3. 给你一个类,如何获取这个类的父类,以及实现了哪些接口?
  4. */
  5. public class ReflectTest13 {
  6. public static void main(String[] args) throws Exception{
  7. //以String举例
  8. Class stringClass = Class.forName("java.lang.String");
  9. //获取String类的父类
  10. Class superclass = stringClass.getSuperclass();
  11. System.out.println(superclass.getName());//java.lang.Object
  12. //获取String类所实现的所有接口(一个类可以实现多个接口)
  13. Class[] interfaces = stringClass.getInterfaces();
  14. for (Class anInterface : interfaces) {
  15. System.out.println(anInterface.getName());
  16. }
  17. //java.io.Serializable
  18. //java.lang.Comparable
  19. //java.lang.CharSequence
  20. }
  21. }

重点笔记

  1. Class studentClass = Class.forName("reflect.bean.Student");
  2. Field nameField = studentClass.getDeclaredField("name");
  3. //打破封装!!!可能会给不法分子留下机会
  4. nameField.setAccessible(true);
  5. nameField.set(obj,"jackson");
  6. Class uService = Class.forName("reflect.service.UserService");
  7. Method loginMethod = uService.getDeclaredMethod("login", String.class, String.class);
  8. Object obj = uService.newInstance();
  9. //反射方法四要素:对象、方法名、实参、返回值
  10. Object retValue = loginMethod.invoke(obj, "admin", "123");
  11. Class vipClass = Class.forName("reflect.bean.Vip");
  12. Constructor constructor = vipClass.getDeclaredConstructor(int.class, String.class, String.class, boolean.class);
  13. //第二步,调用构造方法new对象
  14. Object obj2 = constructor.newInstance(110, "lisi", "1996-7-10", false);