zoukankan      html  css  js  c++  java
  • Java反射机制详解

    一、内容提要:

      1、反射机制是什么

      2、反射机制能做什么

      3、反射机制相关的API

      4、通过一个对象获得完整的包名和类名

      5、实例化Class类对象

      6、获取一个对象的父类与实现的接口

      7、获取某个类的全部构造函数

      8、通过反射机制实例化一个类的对象

      9、获取某个类的全部属性

      10、获取某个类的全部方法

      11、通过反射机制调用某个类的方法

      12、通过反射机制操作某个类的属性

      13、反射机制的动态代理

      14、反射机制的应用实例

      15、在范型为Integer的ArrayList中存放一个String类型的对象

      16、通过反射取得并修改数组的信息

      17、通过反射机制修改数组的大小

      18、将反射机制应用于工厂模式

    1、反射机制是什么?

      反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象的方法的功能称为java语言的反射机制。

    2、反射机制能做什么?

      反射机制主要提供了以下功能:

      1、在运行时判断任意一个对象所属的类

      2、在运行时构造任意一个类的对象

      3、在运行时判断任意一个类所具有的成员变量和方法

      4、在运行时调用任意一个对象的方法

      5、生成动态代理

    3、反射机制相关的API

      通过一个对象获得完整的包名和类名

    package com.wangjun.ThinkingInJava.java_14.third.java_10;
    
    public class TestReflect {
    
        public static void main(String[] args) {
            TestReflect testReflect=new TestReflect();
            System.out.println(testReflect.getClass().getName());
    
        }
    
    }

      输出结果:

    1 com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect

      实例化Class类对象

     1 package com.wangjun.ThinkingInJava.java_14.third.java_10;
     2 
     3 public class TestReflect {
     4 
     5     public static void main(String[] args) throws ClassNotFoundException {
     6         Class<?> class1=null;
     7         Class<?> class2=null;
     8         Class<?> class3=null;
     9         
    10         //一般采用这种形式
    11         class1=Class.forName("com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect");
    12         class2=new TestReflect().getClass();
    13         class3=TestReflect.class;
    14         System.out.println("类名称: "+class1.getName());
    15         System.out.println("类名称: "+class2.getName());
    16         System.out.println("类名称: "+class3.getName());
    17 
    18     }
    19 
    20 }

      输出结果:

    1 类名称: com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect
    2 类名称: com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect
    3 类名称: com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect

      获取一个对象的父类与实现的接口:

     1 package com.wangjun.ThinkingInJava.java_14.third.java_10;
     2 
     3 import java.io.Serializable;
     4 
     5 public class TestReflect1 implements Serializable {
     6 
     7     public static void main(String[] args) throws ClassNotFoundException {
     8         Class<?> clazz=Class.forName("com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect1");
     9         //取得父类
    10         Class<?> parentClass=clazz.getSuperclass();
    11         System.out.println("clazz的父类为: "+parentClass.getName());
    12         //clazz的父类为:java.lang.Object
    13         //获取所有的接口
    14         Class<?> intes[]=clazz.getInterfaces();
    15         System.out.println("clazz实现的接口有:");
    16         for(int i=0;i<intes.length;i++){
    17             System.out.println((i+1)+":"+intes[i].getName());
    18         }
    19     }
    20 
    21 }

      输出结果:

    1 clazz的父类为: java.lang.Object
    2 clazz实现的接口有:
    3 1:java.io.Serializable

      通过反射机制实例化一个类的对象

     1 public class TestReflect2 {
     2 
     3     public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
     4         Class<?> class1=null;
     5         class1=Class.forName("com.wangjun.ThinkingInJava.java_14.third.java_10.User");
     6         //第一种方法,实例化默认构造方法,调用set赋值
     7         User user=(User) class1.newInstance();
     8         user.setAge(20);
     9         user.setName("Rollen");
    10         System.out.println(user);
    11         
    12         //第二种方法 取得全部的构造函数 使用构造函数赋值
    13         Constructor<?> cons[]=class1.getConstructors();
    14         //查看每个构造方法需要的参数
    15         for(int i=0;i<cons.length;i++){
    16             Class<?>clazzs[]=cons[i].getParameterTypes();
    17             System.out.print("cons["+i+"](");
    18             for(int j=0;j<clazzs.length;j++){
    19                 if(j==clazzs.length-1){
    20                     System.out.print(clazzs[j].getName());
    21                 }else {
    22                     System.out.print(clazzs[j].getName()+",");
    23                 }
    24             }
    25             System.out.println(")");
    26         }
    27         
    28         user=(User) cons[1].newInstance("Rollen");
    29         System.out.println(user);
    30         user = (User) cons[0].newInstance(20, "Rollen");
    31         System.out.println(user);
    32     }
    33 
    34 }
     1 package com.wangjun.ThinkingInJava.java_14.third.java_10;
     2 
     3 public class User {
     4     private int age;
     5     private String name;
     6     public User(){}
     7     public User(String name){
     8         super();
     9         this.name=name;
    10     }
    11     public User(int age,String name){
    12         super();
    13         this.age=age;
    14         this.name=name;
    15     }
    16     public int getAge() {
    17         return age;
    18     }
    19     public void setAge(int age) {
    20         this.age = age;
    21     }
    22     public String getName() {
    23         return name;
    24     }
    25     public void setName(String name) {
    26         this.name = name;
    27     }
    28     
    29     
    30     public String toString(){
    31         return "User [age=]"+age+",name="+name+"]";
    32     }
    33 
    34 }

      输出结果:

    1 User [age=]20,name=Rollen]
    2 cons[0](int,java.lang.String)
    3 cons[1](java.lang.String)
    4 cons[2]()
    5 User [age=]0,name=Rollen]
    6 User [age=]20,name=Rollen]

       获取某个类的全部属性:

     1 import java.io.Serializable;
     2 import java.lang.reflect.Field;
     3 import java.lang.reflect.Modifier;
     4 
     5 public class TestReflect3 implements Serializable{
     6     private String name="main";
     7     public static void main(String[] args) throws ClassNotFoundException{
     8         Class<?> clazz=Class.forName("com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect3");
     9         System.out.println("======本类属性========");
    10         Field[] fields=clazz.getDeclaredFields();
    11         for(int i=0;i<fields.length;i++){
    12             //权限修饰符
    13             int mo=fields[i].getModifiers();
    14             String priv=Modifier.toString(mo);
    15             //属性类型
    16             Class<?> type=fields[i].getType();
    17             System.out.println(priv+" "+type.getName()+" "+fields[i].getName()+";");
    18         }
    19         System.out.println("==========实现的接口或者 父类的属性==============");
    20         //取得实现的接口或者父类的属性
    21         Field[] filed1=clazz.getFields();
    22         for(int j=0;j<filed1.length;j++){
    23             //    权限修饰
    24             int mo=filed1[j].getModifiers();
    25             String priv=Modifier.toString(mo);
    26             
    27             //属性类型
    28             Class<?> type=filed1[j].getType();
    29             System.out.println(priv + " " + type.getName() + " " + filed1[j].getName() + ";");
    30             
    31         } 
    32         
    33     }
    34 
    35 }

      输出结果:

    1 ======本类属性========
    2 private java.lang.String name;
    3 ==========实现的接口或者 父类的属性==============

      获取某个类的全部方法

     1 package com.wangjun.ThinkingInJava.java_14.third.java_10;
     2 
     3 import java.io.Serializable;
     4 import java.lang.reflect.Method;
     5 import java.lang.reflect.Modifier;
     6 
     7 public class TestReflect4 implements Serializable {
     8 
     9     public static void main(String[] args) throws Exception{
    10         Class<?> clazz=Class.forName("com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect4");
    11         Method method[]=clazz.getMethods();
    12         for (int i = 0; i < method.length; ++i) {
    13             Class<?> returnType = method[i].getReturnType();
    14             Class<?> para[] = method[i].getParameterTypes();
    15             int temp = method[i].getModifiers();
    16             System.out.print(Modifier.toString(temp) + " ");
    17             System.out.print(returnType.getName() + "  ");
    18             System.out.print(method[i].getName() + " ");
    19             System.out.print("(");
    20             for (int j = 0; j < para.length; ++j) {
    21                 System.out.print(para[j].getName() + " " + "arg" + j);
    22                 if (j < para.length - 1) {
    23                     System.out.print(",");
    24                 }
    25             }
    26             Class<?> exce[] = method[i].getExceptionTypes();
    27             if (exce.length > 0) {
    28                 System.out.print(") throws ");
    29                 for (int k = 0; k < exce.length; ++k) {
    30                     System.out.print(exce[k].getName() + " ");
    31                     if (k < exce.length - 1) {
    32                         System.out.print(",");
    33                     }
    34                 }
    35             } else {
    36                 System.out.print(")");
    37             }
    38             System.out.println();
    39         }
    40 
    41     }
    42 
    43 }

      输出结果:

    1 public boolean  equals (java.lang.Object arg0)
    2 public java.lang.String  toString ()
    3 public native int  hashCode ()
    4 public final native java.lang.Class  getClass ()
    5 public final native void  notify ()
    6 public final native void  notifyAll ()

      通过反射机制调用某个类的方法

     1 public class TestReflect5 {
     2 
     3     public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
     4         Class<?> clazz=Class.forName("com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect5");
     5         //调用TestReflect类中的reflect1方法
     6         Method method=clazz.getMethod("reflect1");
     7         method.invoke(clazz.newInstance());
     8         //Java 反射机制-调用某个类的方法1.
     9         //调用TestReflect的reflect2方法
    10         method=clazz.getMethod("reflect2", int.class,String.class);
    11         method.invoke(clazz.newInstance(), 20,"张三");
    12 
    13     }
    14     
    15     public void reflect1(){
    16         System.out.println("Java 反射机制 - 调用某个类的方法1.");        
    17     }
    18     public void reflect2(int age, String name) {
    19         System.out.println("Java 反射机制 - 调用某个类的方法2.");
    20         System.out.println("age -> " + age + ". name -> " + name);
    21     }
    22 
    23 }

      运行结果:

    1 Java 反射机制 - 调用某个类的方法1.
    2 Java 反射机制 - 调用某个类的方法2.
    3 age -> 20. name -> 张三

      通过反射机制调用某个类的方法

     1 package net.xsoftlab.baike;
     2 import java.lang.reflect.Method;
     3 public class TestReflect {
     4     public static void main(String[] args) throws Exception {
     5         Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
     6         // 调用TestReflect类中的reflect1方法
     7         Method method = clazz.getMethod("reflect1");
     8         method.invoke(clazz.newInstance());
     9         // Java 反射机制 - 调用某个类的方法1.
    10         // 调用TestReflect的reflect2方法
    11         method = clazz.getMethod("reflect2", int.class, String.class);
    12         method.invoke(clazz.newInstance(), 20, "张三");
    13         // Java 反射机制 - 调用某个类的方法2.
    14         // age -> 20. name -> 张三
    15     }
    16     public void reflect1() {
    17         System.out.println("Java 反射机制 - 调用某个类的方法1.");
    18     }
    19     public void reflect2(int age, String name) {
    20         System.out.println("Java 反射机制 - 调用某个类的方法2.");
    21         System.out.println("age -> " + age + ". name -> " + name);
    22     }
    23 }

      通过反射机制调用某个类的属性

     1 package net.xsoftlab.baike;
     2 import java.lang.reflect.Field;
     3 public class TestReflect {
     4     private String proprety = null;
     5     public static void main(String[] args) throws Exception {
     6         Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
     7         Object obj = clazz.newInstance();
     8         // 可以直接对 private 的属性赋值
     9         Field field = clazz.getDeclaredField("proprety");
    10         field.setAccessible(true);
    11         field.set(obj, "Java反射机制");
    12         System.out.println(field.get(obj));
    13     }
    14 }

      反射机制的动态代理

     1 // 获取类加载器的方法
     2 TestReflect testReflect = new TestReflect();
     3         System.out.println("类加载器  " + testReflect.getClass().getClassLoader().getClass().getName());
     4 package net.xsoftlab.baike;
     5 import java.lang.reflect.InvocationHandler;
     6 import java.lang.reflect.Method;
     7 import java.lang.reflect.Proxy;
     8 //定义项目接口
     9 interface Subject {
    10     public String say(String name, int age);
    11 }
    12 // 定义真实项目
    13 class RealSubject implements Subject {
    14     public String say(String name, int age) {
    15         return name + "  " + age;
    16     }
    17 }
    18 class MyInvocationHandler implements InvocationHandler {
    19     private Object obj = null;
    20     public Object bind(Object obj) {
    21         this.obj = obj;
    22         return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
    23     }
    24     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    25         Object temp = method.invoke(this.obj, args);
    26         return temp;
    27     }
    28 }
    29 /**
    30  * 在java中有三种类类加载器。
    31  * 
    32  * 1)Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。
    33  * 
    34  * 2)Extension ClassLoader 用来进行扩展类的加载,一般对应的是jrelibext目录中的类
    35  * 
    36  * 3)AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。
    37  * 
    38  * 如果想要完成动态代理,首先需要定义一个InvocationHandler接口的子类,已完成代理的具体操作。
    39  * 
    40  * @author xsoftlab.net
    41  * 
    42  */
    43 public class TestReflect {
    44     public static void main(String[] args) throws Exception {
    45         MyInvocationHandler demo = new MyInvocationHandler();
    46         Subject sub = (Subject) demo.bind(new RealSubject());
    47         String info = sub.say("Rollen", 20);
    48         System.out.println(info);
    49     }
    50 }

    二、反射机制的应用实例

      在泛型为Integer的ArrayList中存放一个String类型的对象

     1 package net.xsoftlab.baike;
     2 import java.lang.reflect.Method;
     3 import java.util.ArrayList;
     4 public class TestReflect {
     5     public static void main(String[] args) throws Exception {
     6         ArrayList<Integer> list = new ArrayList<Integer>();
     7         Method method = list.getClass().getMethod("add", Object.class);
     8         method.invoke(list, "Java反射机制实例。");
     9         System.out.println(list.get(0));
    10     }
    11 }

      通过反射取得并修改数组的信息

     1 package net.xsoftlab.baike;
     2 import java.lang.reflect.Array;
     3 public class TestReflect {
     4     public static void main(String[] args) throws Exception {
     5         int[] temp = { 1, 2, 3, 4, 5 };
     6         Class<?> demo = temp.getClass().getComponentType();
     7         System.out.println("数组类型: " + demo.getName());
     8         System.out.println("数组长度  " + Array.getLength(temp));
     9         System.out.println("数组的第一个元素: " + Array.get(temp, 0));
    10         Array.set(temp, 0, 100);
    11         System.out.println("修改之后数组第一个元素为: " + Array.get(temp, 0));
    12     }
    13 }

      通过反射机制修改数组的大小

     1 package net.xsoftlab.baike;
     2 import java.lang.reflect.Array;
     3 public class TestReflect {
     4     public static void main(String[] args) throws Exception {
     5         int[] temp = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
     6         int[] newTemp = (int[]) arrayInc(temp, 15);
     7         print(newTemp);
     8         String[] atr = { "a", "b", "c" };
     9         String[] str1 = (String[]) arrayInc(atr, 8);
    10         print(str1);
    11     }
    12     // 修改数组大小
    13     public static Object arrayInc(Object obj, int len) {
    14         Class<?> arr = obj.getClass().getComponentType();
    15         Object newArr = Array.newInstance(arr, len);
    16         int co = Array.getLength(obj);
    17         System.arraycopy(obj, 0, newArr, 0, co);
    18         return newArr;
    19     }
    20     // 打印
    21     public static void print(Object obj) {
    22         Class<?> c = obj.getClass();
    23         if (!c.isArray()) {
    24             return;
    25         }
    26         System.out.println("数组长度为: " + Array.getLength(obj));
    27         for (int i = 0; i < Array.getLength(obj); i++) {
    28             System.out.print(Array.get(obj, i) + " ");
    29         }
    30         System.out.println();
    31     }
    32 }

      将反射应用于工厂模式

     1 package net.xsoftlab.baike;
     2 interface fruit {
     3     public abstract void eat();
     4 }
     5 class Apple implements fruit {
     6     public void eat() {
     7         System.out.println("Apple");
     8     }
     9 }
    10 class Orange implements fruit {
    11     public void eat() {
    12         System.out.println("Orange");
    13     }
    14 }
    15 class Factory {
    16     public static fruit getInstance(String ClassName) {
    17         fruit f = null;
    18         try {
    19             f = (fruit) Class.forName(ClassName).newInstance();
    20         } catch (Exception e) {
    21             e.printStackTrace();
    22         }
    23         return f;
    24     }
    25 }
    26 /**
    27  * 对于普通的工厂模式当我们在添加一个子类的时候,就需要对应的修改工厂类。 当我们添加很多的子类的时候,会很麻烦。
    28  * Java 工厂模式可以参考
    29  * http://baike.xsoftlab.net/view/java-factory-pattern
    30  * 
    31  * 现在我们利用反射机制实现工厂模式,可以在不修改工厂类的情况下添加任意多个子类。
    32  * 
    33  * 但是有一点仍然很麻烦,就是需要知道完整的包名和类名,这里可以使用properties配置文件来完成。
    34  * 
    35  * java 读取 properties 配置文件 的方法可以参考
    36  * http://baike.xsoftlab.net/view/java-read-the-properties-configuration-file
    37  * 
    38  * @author xsoftlab.net
    39  */
    40 public class TestReflect {
    41     public static void main(String[] args) throws Exception {
    42         fruit f = Factory.getInstance("net.xsoftlab.baike.Apple");
    43         if (f != null) {
    44             f.eat();
    45         }
    46     }
    47 }
  • 相关阅读:
    《转》MFC六大关键技术之(五)(六)——消息映射与命令传递
    《转》MFC六大关键技术之(四)——永久保存(串行化)
    《转》MFC六大关键技术之(三)——动态创建
    《转》MFC六大关键技术之(二)——运行时类信息(RTTI)
    《转》MFC六大关键技术之(一)—— 初始化过程
    C++ 语言的 15 个晦涩特性
    QT的项目管理文件pro的编写
    使用C++编写的一个Find(查找)对话框例子
    如何让Fedora能够打开RAR文件
    Undefined symbols for architecture i386:和"_OBJC_CLASS_$_xx", referenced from:问题解决方法
  • 原文地址:https://www.cnblogs.com/xuanlin666/p/10862595.html
Copyright © 2011-2022 走看看