• Java笔记(27):反射


    1、获取class文件对象的三种方式

     1 package cn.itcast_01;
     2 
     3 public class Person {
     4     private String name;
     5     int age;
     6     public String address;
     7 
     8     public Person() {
     9     }
    10 
    11     private Person(String name) {
    12         this.name = name;
    13     }
    14 
    15     Person(String name, int age) {
    16         this.name = name;
    17         this.age = age;
    18     }
    19 
    20     public Person(String name, int age, String address) {
    21         this.name = name;
    22         this.age = age;
    23         this.address = address;
    24     }
    25 
    26     public void show() {
    27         System.out.println("show");
    28     }
    29 
    30     public void method(String s) {
    31         System.out.println("method " + s);
    32     }
    33 
    34     public String getString(String s, int i) {
    35         return s + "---" + i;
    36     }
    37 
    38     private void function() {
    39         System.out.println("function");
    40     }
    41 
    42     @Override
    43     public String toString() {
    44         return "Person [name=" + name + ", age=" + age + ", address=" + address
    45                 + "]";
    46     }
    47 
    48 }
    Person
     1 package cn.itcast_01;
     2 
     3 /*
     4  * 反射:就是通过class文件对象,去使用该文件中的成员变量,构造方法,成员方法。
     5  * 
     6  * Person p = new Person();
     7  * p.使用
     8  * 
     9  * 要想这样使用,首先你必须得到class文件对象,其实也就是得到Class类的对象。
    10  * Class类:
    11  *         成员变量    Field
    12  *         构造方法    Constructor
    13  *         成员方法    Method
    14  * 
    15  * 获取class文件对象的方式:
    16  * A:Object类的getClass()方法
    17  * B:数据类型的静态属性class
    18  * C:Class类中的静态方法
    19  *         public static Class forName(String className)
    20  * 
    21  * 一般我们到底使用谁呢?
    22  *         A:自己玩    任选一种,第二种比较方便
    23  *         B:开发    第三种
    24  *             为什么呢?因为第三种是一个字符串,而不是一个具体的类名。这样我们就可以把这样的字符串配置到配置文件中。
    25  */
    26 public class ReflectDemo {
    27     public static void main(String[] args) throws ClassNotFoundException {
    28         // 方式1
    29         Person p = new Person();
    30         Class c = p.getClass();
    31 
    32         Person p2 = new Person();
    33         Class c2 = p2.getClass();
    34 
    35         System.out.println(p == p2);// false
    36         System.out.println(c == c2);// true
    37 
    38         // 方式2
    39         Class c3 = Person.class;
    40         // int.class;
    41         // String.class;
    42         System.out.println(c == c3);
    43 
    44         // 方式3
    45         // ClassNotFoundException
    46         Class c4 = Class.forName("cn.itcast_01.Person");
    47         System.out.println(c == c4);
    48     }
    49 }

    2、通过反射获取无参构造方法并使用

     1 package cn.itcast_02;
     2 
     3 import java.lang.reflect.Constructor;
     4 
     5 import cn.itcast_01.Person;
     6 
     7 /*
     8  * 通过反射获取构造方法并使用。
     9  */
    10 public class ReflectDemo {
    11     public static void main(String[] args) throws Exception {
    12         // 获取字节码文件对象
    13         Class c = Class.forName("cn.itcast_01.Person");
    14 
    15         // 获取构造方法
    16         // public Constructor[] getConstructors():所有公共构造方法
    17         // public Constructor[] getDeclaredConstructors():所有构造方法
    18         // Constructor[] cons = c.getDeclaredConstructors();
    19         // for (Constructor con : cons) {
    20         // System.out.println(con);
    21         // }
    22 
    23         // 获取单个构造方法
    24         // public Constructor<T> getConstructor(Class<?>... parameterTypes)
    25         // 参数表示的是:你要获取的构造方法的构造参数个数及数据类型的class字节码文件对象
    26         Constructor con = c.getConstructor();// 返回的是构造方法对象
    27 
    28         // Person p = new Person();
    29         // System.out.println(p);
    30         // public T newInstance(Object... initargs)
    31         // 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
    32         Object obj = con.newInstance();
    33         System.out.println(obj);
    34         
    35         // Person p = (Person)obj;
    36         // p.show();
    37     }
    38 }

    3、通过反射获取带参构造方法并使用

     1 package cn.itcast_02;
     2 
     3 import java.lang.reflect.Constructor;
     4 
     5 /*
     6  * 需求:通过反射去获取该构造方法并使用:
     7  * public Person(String name, int age, String address)
     8  * 
     9  * Person p = new Person("林青霞",27,"北京");
    10  * System.out.println(p);
    11  */
    12 public class ReflectDemo2 {
    13     public static void main(String[] args) throws Exception {
    14         // 获取字节码文件对象
    15         Class c = Class.forName("cn.itcast_01.Person");
    16 
    17         // 获取带参构造方法对象
    18         // public Constructor<T> getConstructor(Class<?>... parameterTypes)
    19         Constructor con = c.getConstructor(String.class, int.class,
    20                 String.class);
    21 
    22         // 通过带参构造方法对象创建对象
    23         // public T newInstance(Object... initargs)
    24         Object obj = con.newInstance("林青霞", 27, "北京");
    25         
    26         System.out.println(obj);
    27     }
    28 }

    4、通过反射获取私有构造方法并使用

     1 package cn.itcast_02;
     2 
     3 import java.lang.reflect.Constructor;
     4 
     5 /*
     6  * 需求:通过反射获取私有构造方法并使用
     7  * private Person(String name){}
     8  * 
     9  * Person p = new Person("风清扬");
    10  * System.out.println(p);
    11  */
    12 public class ReflectDemo3 {
    13     public static void main(String[] args) throws Exception {
    14         // 获取字节码文件对象
    15         Class c = Class.forName("cn.itcast_01.Person");
    16 
    17         // 获取私有构造方法对象
    18         // NoSuchMethodException:每个这个方法异常
    19         // 原因是一开始我们使用的方法只能获取公共的,下面这种方式就可以了。
    20         Constructor con = c.getDeclaredConstructor(String.class);
    21 
    22         // 用该私有构造方法创建对象
    23         // IllegalAccessException:非法的访问异常。
    24         // 暴力访问
    25         con.setAccessible(true);// 值为true则指示反射的对象在使用时应该取消Java语言访问检查。
    26         Object obj = con.newInstance("风清扬");
    27 
    28         System.out.println(obj);
    29     }
    30 }

    5、通过反射获取成员变量并使用

     1 package cn.itcast_03;
     2 
     3 import java.lang.reflect.Constructor;
     4 import java.lang.reflect.Field;
     5 
     6 /*
     7  * 通过发生获取成员变量并使用
     8  */
     9 public class ReflectDemo {
    10     public static void main(String[] args) throws Exception {
    11         // 获取字节码文件对象
    12         Class c = Class.forName("cn.itcast_01.Person");
    13 
    14         // 获取所有的成员变量
    15         // Field[] fields = c.getFields();
    16         // Field[] fields = c.getDeclaredFields();
    17         // for (Field field : fields) {
    18         // System.out.println(field);
    19         // }
    20 
    21         /*
    22          * Person p = new Person(); p.address = "北京"; System.out.println(p);
    23          */
    24 
    25         // 通过无参构造方法创建对象
    26         Constructor con = c.getConstructor();
    27         Object obj = con.newInstance();
    28         System.out.println(obj);
    29 
    30         // 获取单个的成员变量
    31         // 获取address并对其赋值
    32         Field addressField = c.getField("address");
    33         // public void set(Object obj,Object value)
    34         // 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
    35         addressField.set(obj, "北京"); // 给obj对象的addressField字段设置值为"北京"
    36         System.out.println(obj);
    37 
    38         // 获取name并对其赋值
    39         // NoSuchFieldException
    40         Field nameField = c.getDeclaredField("name");
    41         // IllegalAccessException
    42         nameField.setAccessible(true);
    43         nameField.set(obj, "林青霞");
    44         System.out.println(obj);
    45 
    46         // 获取age并对其赋值
    47         Field ageField = c.getDeclaredField("age");
    48         ageField.setAccessible(true);
    49         ageField.set(obj, 27);
    50         System.out.println(obj);
    51     }
    52 }

    6、通过反射获取成员方法并使用

     1 package cn.itcast_04;
     2 
     3 import java.lang.reflect.Constructor;
     4 import java.lang.reflect.Method;
     5 
     6 public class ReflectDemo {
     7     public static void main(String[] args) throws Exception {
     8         // 获取字节码文件对象
     9         Class c = Class.forName("cn.itcast_01.Person");
    10 
    11         // 获取所有的方法
    12         // Method[] methods = c.getMethods(); // 获取自己的包括父亲的公共方法
    13         // Method[] methods = c.getDeclaredMethods(); // 获取自己的所有的方法
    14         // for (Method method : methods) {
    15         // System.out.println(method);
    16         // }
    17 
    18         Constructor con = c.getConstructor();
    19         Object obj = con.newInstance();
    20 
    21         /*
    22          * Person p = new Person(); p.show();
    23          */
    24 
    25         // 获取单个方法并使用
    26         // public void show()
    27         // public Method getMethod(String name,Class<?>... parameterTypes)
    28         // 第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型
    29         Method m1 = c.getMethod("show");
    30         // obj.m1(); // 错误
    31         // public Object invoke(Object obj,Object... args)
    32         // 返回值是Object接收,第一个参数表示对象是谁,第二参数表示调用该方法的实际参数
    33         m1.invoke(obj); // 调用obj对象的m1方法
    34 
    35         System.out.println("----------");
    36         // public void method(String s)
    37         Method m2 = c.getMethod("method", String.class);
    38         m2.invoke(obj, "hello");
    39         System.out.println("----------");
    40 
    41         // public String getString(String s, int i)
    42         Method m3 = c.getMethod("getString", String.class, int.class);
    43         Object objString = m3.invoke(obj, "hello", 100);
    44         System.out.println(objString);
    45         // String s = (String)m3.invoke(obj, "hello",100);
    46         // System.out.println(s);
    47         System.out.println("----------");
    48 
    49         // private void function()
    50         Method m4 = c.getDeclaredMethod("function");
    51         m4.setAccessible(true);
    52         m4.invoke(obj);
    53     }
    54 }

    7、通过反射运行配置文件内容

    配置文件class.txt的内容:

    className=cn.itcast.test.Student
    methodName=love

    1 package cn.itcast.test;
    2 
    3 public class Student {
    4     public void love() {
    5         System.out.println("爱生活,爱烨儿");
    6     }
    7 }
    1 package cn.itcast.test;
    2 
    3 public class Teacher {
    4     public void love() {
    5         System.out.println("爱生活,爱青霞");
    6     }
    7 }
    1 package cn.itcast.test;
    2 
    3 public class Worker {
    4     public void love() {
    5         System.out.println("爱生活,爱娘子");
    6     }
    7 }
     1 package cn.itcast.test;
     2 
     3 import java.io.FileReader;
     4 import java.lang.reflect.Constructor;
     5 import java.lang.reflect.Method;
     6 import java.util.Properties;
     7 
     8 /*
     9  * 通过配置文件运行类中的方法
    10  * 
    11  * 反射:
    12  *         需要有配置文件配合使用。
    13  *         用class.txt代替。
    14  *         并且你知道有两个键。
    15  *             className
    16  *             methodName
    17  */
    18 public class Test {
    19     public static void main(String[] args) throws Exception {
    20         // 反射前的做法
    21         // Student s = new Student();
    22         // s.love();
    23         // Teacher t = new Teacher();
    24         // t.love();
    25         // Worker w = new Worker();
    26         // w.love();
    27         // 反射后的做法
    28 
    29         // 加载键值对数据
    30         Properties prop = new Properties();
    31         FileReader fr = new FileReader("class.txt");
    32         prop.load(fr);
    33         fr.close();
    34 
    35         // 获取数据
    36         String className = prop.getProperty("className");
    37         String methodName = prop.getProperty("methodName");
    38 
    39         // 反射
    40         Class c = Class.forName(className);
    41 
    42         Constructor con = c.getConstructor();
    43         Object obj = con.newInstance();
    44 
    45         // 调用方法
    46         Method m = c.getMethod(methodName);
    47         m.invoke(obj);
    48     }
    49 }

    8、通过反射越过泛型检查

     1 package cn.itcast.test;
     2 
     3 import java.lang.reflect.InvocationTargetException;
     4 import java.lang.reflect.Method;
     5 import java.util.ArrayList;
     6 
     7 /*
     8  * 我给你ArrayList<Integer>的一个对象,我想在这个集合中添加一个字符串数据,如何实现呢?
     9  */
    10 public class ArrayListDemo {
    11     public static void main(String[] args) throws NoSuchMethodException,
    12             SecurityException, IllegalAccessException,
    13             IllegalArgumentException, InvocationTargetException {
    14         // 创建集合对象
    15         ArrayList<Integer> array = new ArrayList<Integer>();
    16 
    17         // array.add("hello");
    18         // array.add(10);
    19 
    20         Class c = array.getClass(); // 集合ArrayList的class文件对象
    21         Method m = c.getMethod("add", Object.class);
    22 
    23         m.invoke(array, "hello"); // 调用array的add方法,传入的值是hello
    24         m.invoke(array, "world");
    25         m.invoke(array, "java");
    26 
    27         System.out.println(array);
    28     }
    29 }

    9、通过反射写一个通用的设置某个对象的某个属性为指定的值

     1 package cn.itcast.test;
     2 
     3 public class ToolDemo {
     4     public static void main(String[] args) throws NoSuchFieldException,
     5             SecurityException, IllegalArgumentException, IllegalAccessException {
     6         Person p = new Person();
     7         Tool t = new Tool();
     8         t.setProperty(p, "name", "林青霞");
     9         t.setProperty(p, "age", 27);
    10         System.out.println(p);
    11         System.out.println("-----------");
    12 
    13         Dog d = new Dog();
    14 
    15         t.setProperty(d, "sex", '男');
    16         t.setProperty(d, "price", 12.34f);
    17 
    18         System.out.println(d);
    19     }
    20 }
    21 
    22 class Dog {
    23     char sex;
    24     float price;
    25 
    26     @Override
    27     public String toString() {
    28         return sex + "---" + price;
    29     }
    30 }
    31 
    32 class Person {
    33     private String name;
    34     public int age;
    35 
    36     @Override
    37     public String toString() {
    38         return name + "---" + age;
    39     }
    40 }

    10、动态代理的概述和实现

     1 package cn.itcast_06;
     2 
     3 import java.lang.reflect.InvocationHandler;
     4 import java.lang.reflect.Method;
     5 
     6 public class MyInvocationHandler implements InvocationHandler {
     7     private Object target; // 目标对象
     8 
     9     public MyInvocationHandler(Object target) {
    10         this.target = target;
    11     }
    12 
    13     @Override
    14     public Object invoke(Object proxy, Method method, Object[] args)
    15             throws Throwable {
    16         System.out.println("权限校验");
    17         Object result = method.invoke(target, args);
    18         System.out.println("日志记录");
    19         return result; // 返回的是代理对象
    20     }
    21 }
     1 package cn.itcast_06;
     2 
     3 /*
     4  * 用户操作接口
     5  */
     6 public interface UserDao {
     7     public abstract void add();
     8 
     9     public abstract void delete();
    10 
    11     public abstract void update();
    12 
    13     public abstract void find();
    14 }
     1 package cn.itcast_06;
     2 
     3 public class UserDaoImpl implements UserDao {
     4 
     5     @Override
     6     public void add() {
     7         System.out.println("添加功能");
     8     }
     9 
    10     @Override
    11     public void delete() {
    12         System.out.println("删除功能");
    13     }
    14 
    15     @Override
    16     public void update() {
    17         System.out.println("修改功能");
    18     }
    19 
    20     @Override
    21     public void find() {
    22         System.out.println("查找功能");
    23     }
    24 
    25 }
     1 package cn.itcast_06;
     2 
     3 import java.lang.reflect.Proxy;
     4 
     5 public class Test {
     6     public static void main(String[] args) {
     7         UserDao ud = new UserDaoImpl();
     8         ud.add();
     9         ud.delete();
    10         ud.update();
    11         ud.find();
    12         System.out.println("-----------");
    13         // 我们要创建一个动态代理对象
    14         // Proxy类中有一个方法可以创建动态代理对象
    15         // public static Object newProxyInstance(ClassLoader loader,Class<?>[]
    16         // interfaces,InvocationHandler h)
    17         // 我准备对ud对象做一个代理对象
    18         MyInvocationHandler handler = new MyInvocationHandler(ud);
    19         UserDao proxy = (UserDao) Proxy.newProxyInstance(ud.getClass()
    20                 .getClassLoader(), ud.getClass().getInterfaces(), handler);
    21         proxy.add();
    22         proxy.delete();
    23         proxy.update();
    24         proxy.find();
    25         // System.out.println("-----------");
    26         //
    27         // StudentDao sd = new StudentDaoImpl();
    28         // MyInvocationHandler handler2 = new MyInvocationHandler(sd);
    29         // StudentDao proxy2 = (StudentDao) Proxy.newProxyInstance(sd.getClass()
    30         // .getClassLoader(), sd.getClass().getInterfaces(), handler2);
    31         // proxy2.login();
    32         // proxy2.regist();
    33     }
    34 }
    如欢如殇 授以青春鲜活肢体奔忙 如思如忘 驱以老朽深沉灵魂冥想 始自情热激荡 从未敢终于世事炎凉 无能执手相望 无法去尝试结发同床 无力至心死身僵 一息坚强 ------ 我一直没有放弃,如果你也能看到 修身 修禅
  • 相关阅读:
    大数据技术学习之Spark技术总结
    PS教程之利用像素化来制作一个乐高积木的创意海报
    Java教程之SpringMVC的请求和响应
    GCC中 -I、-L、-l 选项的作用
    给阿里云主机添加swap分区,解决问题:c++: internal compiler error: Killed (program cc1plus)
    使用 C++11 编写可复用多线程任务池
    Go语言学习-函数
    Goland安装与配置
    Go语言学习-基础知识
    VSCode配置Go插件和第三方拓展包
  • 原文地址:https://www.cnblogs.com/lz2lhy/p/7044597.html
Copyright © 2020-2023  润新知