• Java反射实战


    一、背景

      最近的项目中需要使用到Java 反射的知识,以前不怎么了解,也基本没怎么用过,抽出一片时间,来具体学习和实战下Java的反射!拿来和大家分享以及记录方便以后学习!

    二、反射相关概念解析

    1.Class类

      Class类:Java程序中的各个Java类属于同一类事物,描述这类事物的Java类名就是Class

      如何得到各个类的字节码即Class类呢?

        [1].类名.class:直接通过类.class获得。

        [2].对象.getClass():通过对象调用其getClass方法获得。  

        [3].Class.forName("类全路径"):通过类加载器加载获得

      注:Java中的原始基本类型:booleanbytecharshortintlongfloat,double和关键词 void同样都有Class类,通过.class可获得它们的类字节码。

    2.反射的概念

      反射就是把Java类中的各种成分映射成相应的Java类,例如一个Java类中用一个Class类的对象表示一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,例如人是一个类,那么人的大脑、双手等也是一个个类。表示Java的Class类显然要提供一系列的方法,来获得其中的变量、方法、构造方法,修饰符、包等信息,这些信息就是用相应的类的实例对象来表示,他们是Field、Method、Contructor、Package等等。

      一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示。

    三、反射实战

    测试Bean:Person.java

     1 package com.hafiz.zhang.Bean;
     2 
     3 public class Person {
     4     public Integer id;
     5     private String name;
     6     
     7     public Person() {
     8     }
     9     public Person(Integer id, String name) {
    10         super();
    11         this.id = id;
    12         this.name = name;
    13     }
    14     public Integer getId() {
    15         return id;
    16     }
    17     public void setId(Integer id) {
    18         this.id = id;
    19     }
    20     public String getName() {
    21         return name;
    22     }
    23     public void setName(String name) {
    24         this.name = name;
    25     }
    26     @Override
    27     public String toString() {
    28         return "Person [id=" + id + ", name=" + name + "]";
    29     }
    30     
    31     public void sayHello() throws Exception{
    32         System.out.println("Hello Reflect!");
    33     }
    34 }

    1.使用反射获取对象所属类的全路径(包括报名和类名)

     1 package com.hafiz.zhang.test;
     2 
     3 import com.hafiz.zhang.Bean.Person;
     4 
     5 /**
     6  * @author hafiz.Zhang
     7  * @Date 2016年5月18日 下午4:28:35
     8  * @Description 测试通过一个对象获取该对象所属于的类的全路径(包括完整包名和类名)
     9  */
    10 public class ReflectTest1 {
    11     public static void main(String[] args) {
    12         Person person = new Person();
    13         System.out.println("ClassName = " + person.getClass().getName());
    14     }
    15 }

    测试结果:

    ClassName = com.hafiz.zhang.Bean.Person

    2.测试使用反射实例化Class类对象

     1 package com.hafiz.zhang.test;
     2 
     3 import com.hafiz.zhang.Bean.Person;
     4 
     5 /**
     6  * @author hafiz.Zhang
     7  * @Date 2016年5月18日 下午4:31:36
     8  * @Description 测试获取Class类的三种方式
     9  */
    10 public class ReflectTest2 {
    11     public static void main(String[] args) {
    12         Class<?> obj1 = null;
    13         Class<?> obj2 = null;
    14         Class<?> obj3 = null;
    15         try {
    16             //一般尽量要采用这种方式进行实例化Class类对象
    17             obj1 = (Class<?>) Class.forName("com.hafiz.zhang.Bean.Person");
    18         } catch (ClassNotFoundException e) {
    19             e.printStackTrace();
    20         }
    21         obj2 = new Person().getClass();
    22         obj3 = Person.class;
    23         
    24         System.out.println("ClassName:" + obj1.getName());
    25         System.out.println("ClassName:" + obj2.getName());
    26         System.out.println("ClassName:" + obj3.getName());
    27     }
    28 }

    测试结果:

    ClassName:com.hafiz.zhang.Bean.Person
    ClassName:com.hafiz.zhang.Bean.Person
    ClassName:com.hafiz.zhang.Bean.Person

    3.测试通过Class类对象实例化其他类

     1 package com.hafiz.zhang.test;
     2 
     3 import com.hafiz.zhang.Bean.Person;
     4 
     5 /**
     6  * @author hafiz.Zhang
     7  * @Date 2016年5月18日 下午4:38:15
     8  * @Description 测试通过Class类对象实例化其他类
     9  */
    10 public class ReflectTest3 {
    11     public static void main(String[] args) {
    12         Class<?> clazz = null;
    13         try {
    14             clazz = Class.forName("com.hafiz.zhang.Bean.Person");
    15         } catch (ClassNotFoundException e) {
    16             e.printStackTrace();
    17         }
    18         Person person = null;
    19         try {
    20             person = (Person) clazz.newInstance();
    21         } catch (InstantiationException e) {
    22             e.printStackTrace();
    23         } catch (IllegalAccessException e) {
    24             e.printStackTrace();
    25         }
    26         if(null != person) {
    27             person.setId(1);
    28             person.setName("Hafiz.Zhang");
    29             System.out.println("person=" + person);
    30         }else{
    31             System.out.println("实例化对象失败");
    32         }
    33     }
    34 }

    测试结果:

    person=Person [id=1, name=Hafiz.Zhang]

    4.测试通过Class调用其他类中的构造函数 (也可以通过这种方式通过Class创建其他类的对象)

     1 package com.hafiz.zhang.test;
     2 
     3 import java.lang.reflect.Constructor;
     4 import java.lang.reflect.InvocationTargetException;
     5 
     6 import com.hafiz.zhang.Bean.Person;
     7 
     8 /**
     9  * @author hafiz.Zhang
    10  * @Date 2016年5月18日 下午4:42:08
    11  * @Description 测试通过Class调用其他类中的构造函数 (也可以通过这种方式通过Class创建其他类的对象)
    12  */
    13 public class ReflectTest4 {
    14     public static void main(String[] args) {
    15         Class<?> clazz = null;
    16         try {
    17             clazz = Class.forName("com.hafiz.zhang.Bean.Person");
    18         } catch (ClassNotFoundException e) {
    19             e.printStackTrace();
    20         }
    21         Person p1 = null;
    22         Person p2 = null;
    23         Constructor<?>[] cs = clazz.getConstructors();
    24         try {
    25             p1 = (Person) cs[0].newInstance();//通过无参构造获得对象
    26             p2 = (Person) cs[1].newInstance(1, "Hafiz.Zhang");//通过有参构造获得对象
    27         } catch (InstantiationException e) {
    28             e.printStackTrace();
    29         } catch (IllegalAccessException e) {
    30             e.printStackTrace();
    31         } catch (IllegalArgumentException e) {
    32             e.printStackTrace();
    33         } catch (InvocationTargetException e) {
    34             e.printStackTrace();
    35         }
    36         System.out.println("Person1=" + p1);
    37         System.out.println("Person2=" + p2);
    38     }
    39 }

    测试结果:

    Person1=Person [id=null, name=null]
    Person2=Person [id=1, name=Hafiz.Zhang]

    5.测试使用反射获取一个类实现的接口

    接口Animal.java

     1 package com.hafiz.zhang.Bean;
     2 
     3 /**
     4  * @author hafiz.Zhang
     5  * @Date 2016年5月19日 下午6:13:37
     6  * @Description 动物接口
     7  */
     8 public interface Animal {
     9     public abstract void eat();
    10     public abstract void sleep();
    11 }

    接口Skill.java

     1 package com.hafiz.zhang.Bean;
     2 
     3 /**
     4  * @author hafiz.Zhang
     5  * @Date 2016年5月19日 下午6:14:06
     6  * @Description 技能接口
     7  */
     8 public interface Skill {
     9     public abstract void sayMiao();
    10 }

    实现类:Cat.java

     1 package com.hafiz.zhang.Bean;
     2 
     3 public class Cat implements Animal, Skill  {
     4     private Integer num;
     5     private String desc;
     6     public Integer getNum() {
     7         return num;
     8     }
     9 
    10     public void setNum(Integer num) {
    11         this.num = num;
    12     }
    13 
    14     public String getDesc() {
    15         return desc;
    16     }
    17 
    18     public void setDesc(String desc) {
    19         this.desc = desc;
    20     }
    21 
    22     @Override
    23     public void eat() {
    24         System.out.println("cat eat fish");
    25     }
    26 
    27     @Override
    28     public void sleep() {
    29         System.out.println("cat sleep in the day");
    30     }
    31 
    32     @Override
    33     public void sayMiao() {
    34         System.out.println("cat say miao");
    35     }
    36     
    37     public void sayHello(String name){
    38         System.out.println("Hello " + name);
    39     }
    40 }

    测试类

     1 package com.hafiz.zhang.test;
     2 
     3 /**
     4  * @author hafiz.Zhang
     5  * @Date 2016年5月18日 下午4:51:29
     6  * @Description 测试使用反射获取一个类实现的接口
     7  */
     8 public class ReflectTest5 {
     9     public static void main(String[] args) {
    10         Class<?> clazz = null;
    11         try {
    12             clazz = Class.forName("com.hafiz.zhang.Bean.Cat");
    13         } catch (ClassNotFoundException e) {
    14             e.printStackTrace();
    15         }
    16         Class<?>[] interfaces = clazz.getInterfaces();
    17         System.out.println("Cat实现的接口有");
    18         for(Class<?> cl : interfaces) {
    19             System.out.println(cl.getName());
    20         }
    21     }
    22 }

    测试结果:

    Cat实现的接口有
    com.hafiz.zhang.Bean.Animal
    com.hafiz.zhang.Bean.Skill

    6.测试通过反射取得指定类的父类

     1 package com.hafiz.zhang.test;
     2 
     3 /**
     4  * @author hafiz.Zhang
     5  * @Date 2016年5月18日 下午5:03:25
     6  * @Description 测试通过反射取得指定类的父类
     7  */
     8 public class ReflectTest6 {
     9     public static void main(String[] args) {
    10         Class<?> clazz = null;
    11         try {
    12             clazz = Class.forName("com.hafiz.zhang.Bean.Cat");
    13         } catch (ClassNotFoundException e) {
    14             e.printStackTrace();
    15         }
    16         Class<?> superClass = clazz.getSuperclass();
    17         System.out.println("SuperClass=" + superClass);
    18     }
    19 }

    测试结果:SuperClass=class com.hafiz.zhang.Bean.Person

    7.测试通过反射获得其他类中的全部构造函数

     1 package com.hafiz.zhang.test;
     2 
     3 import java.lang.reflect.Constructor;
     4 import java.lang.reflect.Modifier;
     5 
     6 /**
     7  * @author hafiz.Zhang
     8  * @Date 2016年5月18日 下午5:06:02
     9  * @Description 测试通过反射获得其他类中的全部构造函数
    10  */
    11 public class ReflectTest7 {
    12     public static void main(String[] args) {
    13         Class<?> clazz = null;
    14         try {
    15             clazz = Class.forName("com.hafiz.zhang.Bean.Person");
    16         } catch (ClassNotFoundException e) {
    17             e.printStackTrace();
    18         }
    19         Constructor<?>[] cs = clazz.getConstructors();
    20         //实现方式1
    21         /*for(Constructor<?> item : cs) {
    22             System.out.println("构造方法:" + item.getName());
    23         }*/
    24         //实现方式2
    25         for(Constructor<?> item : cs) {
    26             System.out.print("构造方法:");
    27             System.out.print(Modifier.toString(item.getModifiers()) + " ");
    28             System.out.print(item.getName() + "(");
    29             Class<?>[] paramterTypes = item.getParameterTypes();
    30             for(int i = 0; i < paramterTypes.length; i++) {
    31                 System.out.print(paramterTypes[i].getName() + " arg" + i);
    32                 if(i < paramterTypes.length-1) {
    33                     System.out.print(",");
    34                 }
    35             }
    36             System.out.println(")");
    37         }
    38     }
    39 }

    测试结果:

    构造方法:public com.hafiz.zhang.Bean.Person()
    构造方法:public com.hafiz.zhang.Bean.Person(java.lang.Integer arg0,java.lang.String arg1)

    8. 测试通过反射获取类中的所有方法(包括方法包含的异常)

     1 package com.hafiz.zhang.test;
     2 
     3 import java.lang.reflect.Method;
     4 import java.lang.reflect.Modifier;
     5 
     6 /**
     7  * @author hafiz.Zhang
     8  * @Date 2016年5月18日 下午5:22:51
     9  * @Description 测试通过反射获取类中的所有方法
    10  */
    11 public class ReflectTest8 {
    12     public static void main(String[] args) {
    13         Class<?> clazz = null;
    14         try {
    15             clazz = Class.forName("com.hafiz.zhang.Bean.Person");
    16         } catch (ClassNotFoundException e) {
    17             e.printStackTrace();
    18         }
    19         Method[] methods = clazz.getDeclaredMethods();
    20         for(Method method : methods) {
    21             Class<?> returnType = method.getReturnType();
    22             System.out.print(Modifier.toString(method.getModifiers()) + " ");
    23             System.out.print(returnType.getName() + " " + method.getName() + "(");
    24             Class<?>[] paras = method.getParameterTypes();
    25             for(int i = 0 ; i < paras.length ; i++) {
    26                 System.out.print(paras[i].getName() + " arg" + i);
    27                 if(i < paras.length - 1) {
    28                     System.out.print(",");
    29                 }
    30             }
    31             Class<?>[] exces = method.getExceptionTypes();
    32             if(exces.length > 0) {
    33                 System.out.print(") throws ");
    34                 for(int j = 0; j < exces.length; j++) {
    35                     System.out.print(exces[j].getName());
    36                     if(j < exces.length - 1) {
    37                         System.out.print(", ");
    38                     }
    39                 }
    40             }else{
    41                 System.out.print(")");
    42             }
    43             System.out.println();
    44         }
    45     }
    46 }

    测试结果:

    public java.lang.String toString()
    public java.lang.String getName()
    public void setName(java.lang.String arg0)
    public java.lang.Integer getId()
    public void sayHello() throws java.lang.Exception
    public void setId(java.lang.Integer arg0)

    9.测试通过反射获取类中所有的属性

     1 package com.hafiz.zhang.test;
     2 
     3 import java.lang.reflect.Field;
     4 import java.lang.reflect.Modifier;
     5 
     6 /**
     7  * @author hafiz.Zhang
     8  * @Date 2016年5月18日 下午5:38:09
     9  * @Description 测试通过反射获取类中所有的属性
    10  */
    11 public class ReflectTest9 {
    12     public static void main(String[] args) {
    13         Class<?> clazz = null;
    14         try {
    15             clazz = Class.forName("com.hafiz.zhang.Bean.Cat");
    16         } catch (ClassNotFoundException e) {
    17             e.printStackTrace();
    18         }
    19         Field[] fields = clazz.getDeclaredFields();
    20         System.out.println("=========通过反射获取指定类中所有的属性=========");
    21         for(Field field : fields) {
    22             System.out.println(Modifier.toString(field.getModifiers()) + " " + field.getType().getName() + " " + field.getName());
    23         }
    24         System.out.println("=========通过反射获取指定类实现的接口或者父类中所有的属性=========");
    25         Field[] fields2 = clazz.getSuperclass().getDeclaredFields();
    26         for(Field item : fields2) {
    27             System.out.println(Modifier.toString(item.getModifiers()) + " " + item.getType() + " " + item.getName());
    28         }
    29     }
    30 }

    测试结果:

    =========通过反射获取指定类中所有的属性=========
    private java.lang.Integer num
    private java.lang.String desc
    =========通过反射获取指定类实现的接口或者父类中所有的属性=========
    public class java.lang.Integer id
    private class java.lang.String name

    10.测试使用反射调用指定类的方法

     1 package com.hafiz.zhang.test;
     2 
     3 import java.lang.reflect.InvocationTargetException;
     4 import java.lang.reflect.Method;
     5 
     6 /**
     7  * @author hafiz.Zhang
     8  * @Date 2016年5月19日 下午3:22:33
     9  * @Description 测试使用反射调用指定类的方法
    10  */
    11 public class ReflectTest10 {
    12     public static void main(String[] args) {
    13         Class<?> clazz = null;
    14         try {
    15             clazz = Class.forName("com.hafiz.zhang.Bean.Cat");
    16         } catch (ClassNotFoundException e) {
    17             e.printStackTrace();
    18         }
    19         try {
    20             //调用Cat类中的eat无参方法
    21             Method method = clazz.getMethod("eat");
    22             method.invoke(clazz.newInstance());
    23             //调用Cat类中的sayHello有参方法
    24             Method method2 = clazz.getDeclaredMethod("sayHello", String.class);
    25             method2.invoke(clazz.newInstance(), "Hafiz.Zhang");
    26         } catch (NoSuchMethodException e) {
    27             e.printStackTrace();
    28         } catch (SecurityException e) {
    29             e.printStackTrace();
    30         } catch (IllegalAccessException e) {
    31             e.printStackTrace();
    32         } catch (IllegalArgumentException e) {
    33             e.printStackTrace();
    34         } catch (InvocationTargetException e) {
    35             e.printStackTrace();
    36         } catch (InstantiationException e) {
    37             e.printStackTrace();
    38         }
    39     }
    40 }

    测试结果:

    cat eat fish
    Hello Hafiz.Zhang

    11.测试通过反射调用其他类中的setter和getter方法

     1 package com.hafiz.zhang.test;
     2 
     3 import java.lang.reflect.InvocationTargetException;
     4 import java.lang.reflect.Method;
     5 
     6 /**
     7  * @author hafiz.Zhang
     8  * @Date 2016年5月19日 下午3:29:34
     9  * @Description 测试通过反射调用其他类中的setter和getter方法
    10  */
    11 public class ReflectTest11 {
    12     public static void main(String[] args) {
    13         Class<?> clazz = null;
    14         Object obj = null;
    15         try {
    16             clazz = Class.forName("com.hafiz.zhang.Bean.Cat");
    17             obj = clazz.newInstance();
    18         } catch (ClassNotFoundException e) {
    19             e.printStackTrace();
    20         } catch (InstantiationException e) {
    21             e.printStackTrace();
    22         } catch (IllegalAccessException e) {
    23             e.printStackTrace();
    24         }
    25         getter(obj,"Desc");
    26         setter(obj,"Desc","测试调用set方法",String.class);
    27         getter(obj,"Desc");
    28     }
    29 
    30     private static void getter(Object obj, String name) {
    31         try {
    32             Method method = obj.getClass().getMethod("get"+name);
    33             System.out.println(name + ":" + method.invoke(obj));
    34         } catch (NoSuchMethodException e) {
    35             e.printStackTrace();
    36         } catch (SecurityException e) {
    37             e.printStackTrace();
    38         } catch (IllegalAccessException e) {
    39             e.printStackTrace();
    40         } catch (IllegalArgumentException e) {
    41             e.printStackTrace();
    42         } catch (InvocationTargetException e) {
    43             e.printStackTrace();
    44         }
    45     }
    46 
    47     private static void setter(Object obj, String name, String desc, Class<?> type) {
    48         try {
    49             Method method = obj.getClass().getMethod("set" + name, type);
    50             method.invoke(obj, desc);
    51         } catch (NoSuchMethodException e) {
    52             e.printStackTrace();
    53         } catch (SecurityException e) {
    54             e.printStackTrace();
    55         } catch (IllegalAccessException e) {
    56             e.printStackTrace();
    57         } catch (IllegalArgumentException e) {
    58             e.printStackTrace();
    59         } catch (InvocationTargetException e) {
    60             e.printStackTrace();
    61         }
    62     }
    63 }

    测试结果:

    Desc:null
    Desc:测试调用set方法

    12.测试通过反射操作属性

     1 package com.hafiz.zhang.test;
     2 
     3 import java.lang.reflect.Field;
     4 
     5 /**
     6  * @author hafiz.Zhang
     7  * @Date 2016年5月19日 下午3:41:59
     8  * @Description 测试通过反射操作属性
     9  */
    10 public class ReflectTest12 {
    11     public static void main(String[] args) {
    12         Class<?> clazz = null;
    13         Object obj = null;
    14         try {
    15             clazz = Class.forName("com.hafiz.zhang.Bean.Cat");
    16             obj = clazz.newInstance();
    17             Field field = clazz.getDeclaredField("desc");
    18             //若要设置private属性,需要设置
    19             field.setAccessible(true);//设置成员变量可访问,包括private成员变量(暴力反射),private成员通过这步操作才能被访问
    20             field.set(obj, "this is test demo");
    21             System.out.println("Desc=" + field.get(obj));
    22         } catch (ClassNotFoundException e) {
    23             e.printStackTrace();
    24         } catch (InstantiationException e) {
    25             e.printStackTrace();
    26         } catch (IllegalAccessException e) {
    27             e.printStackTrace();
    28         } catch (NoSuchFieldException e) {
    29             e.printStackTrace();
    30         } catch (SecurityException e) {
    31             e.printStackTrace();
    32         }
    33         
    34     }
    35 }

    测试结果:Desc=this is test demo

    13.测试通过反射进行数组操作

     1 package com.hafiz.zhang.test;
     2 
     3 import java.lang.reflect.Array;
     4 
     5 /**
     6  * @author hafiz.Zhang
     7  * @Date 2016年5月19日 下午4:52:21
     8  * @Description 测试通过反射进行数组操作
     9  * 
    10  */
    11 public class ReflectTest13 {
    12     public static void main(String[] args) {
    13         Integer[] array = {1,2,3,4,5,6};
    14         Class<?> clazz = array.getClass().getComponentType();
    15         System.out.println("数组类型:" + clazz.getName());
    16         System.out.println("数组长度:" + Array.getLength(array));
    17         System.out.println("数组第一个元素:" + Array.get(array, 0));
    18         Array.set(array, 0, 8);
    19         System.out.println("修改之后数组第一个元素:" + Array.get(array, 0));
    20         System.out.println("=============反射修改数组长度=================");
    21         Integer[] arr2 = (Integer[])changeLength(array, 10);
    22         print(arr2);
    23     }
    24     private static void print(Object obj) {
    25         Class<?> clazz = obj.getClass();
    26         if(!clazz.isArray()) {
    27             return;
    28         }
    29         System.out.println("数组长度为:" + Array.getLength(obj));
    30         for(int i = 0; i < Array.getLength(obj); i++){
    31             System.out.print(Array.get(obj, i) + " ");
    32         }
    33     }
    34     public static Object changeLength(Object obj, Integer length){
    35         Class<?> clazz = obj.getClass().getComponentType();
    36         Object newArr = Array.newInstance(clazz, length);
    37         Integer len = Array.getLength(obj);
    38         System.arraycopy(obj, 0, newArr, 0, len);
    39         return newArr;
    40     }
    41 }

    测试结果:

    数组类型:java.lang.Integer
    数组长度:6
    数组第一个元素:1
    修改之后数组第一个元素:8
    =============反射修改数组长度=================
    数组长度为:10
    8 2 3 4 5 6 null null null null

  • 相关阅读:
    未能创建可接受的游标。
    怎样修改查看Oracle字符集
    2005年国内各大公司的薪酬一览 同学发给我的,留在这里刺激一下自己,不过他说到了中国工程物理研究院(四川绵阳) 对此不表同意,具体情况我可最清楚呀,哈哈
    破解低价笔记本惊人的秘密
    Struts 的安装、配置与运行zt
    有用的数据:30款市场主流车型真实油耗一览
    JDBC连接Oracle数据库常见问题及解决方法
    查锁的方法
    用Oracle闪回功能恢复偶然丢失的数据数据被误删除了,多亏了万能的oracle,....后怕
    powerdesigner中去掉生成sql中的引号
  • 原文地址:https://www.cnblogs.com/hafiz/p/5509726.html
Copyright © 2020-2023  润新知