zoukankan      html  css  js  c++  java
  • 【JAVA反射机制】

    一、Class类

    Java.lang.Object

             |-java.lang.Class<T>

    构造方法:无。

    常用方法:

    static Class<?>

    forName(String className)
              返回与带有给定字符串名的类或接口相关联的 Class 对象。

    Constructor<T>

    getConstructor(Class<?>... parameterTypes)
              
    返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。

    Constructor<?>[]

    getConstructors()
              
    返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。

     Constructor<T>

    getDeclaredConstructor(Class<?>... parameterTypes)
              
    返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。

     Constructor<?>[]

    getDeclaredConstructors()
              
    返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。

     Field

    getDeclaredField(String name)
              
    返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。

     Field[]

    getDeclaredFields()
              
    返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。

     Method

    getDeclaredMethod(String name, Class<?>... parameterTypes)
              
    返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。

     Method[]

    getDeclaredMethods()
              
    返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。

     Field

    getField(String name)
              
    返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。

     Field[]

    getFields()
              
    返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。

     Method

    getMethod(String name, Class<?>... parameterTypes)
              
    返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。

     Method[]

    getMethods()
              
    返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。

     T

    newInstance()
              
    创建此 Class 对象所表示的类的一个新实例。

    二、Constructor

    Java.lang.Object

             |-java.lang.reflect.AccessibleObject

                       |-java.lang.reflect.Constructor<T>

    1. 构造方法:无。
    2. 常用方法:

     T

    newInstance(Object... initargs)
              使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。

     String

    toString()
              
    返回描述此 Constructor 的字符串。

    三、Field

    Java.lang.Object

             |-java.lang.reflect.AccessibleObject

                       |-java.lang.reflect.Field

    1. 构造方法:无
    2. 常用方法:

     Object

    get(Object obj)
              返回指定对象上此 Field 表示的字段的值。

     String

    getName()
              
    返回此 Field 对象表示的字段的名称。

     void

    set(Object obj, Object value)
              
    将指定对象变量上此 Field 对象表示的字段设置为指定的新值。

    还有诸如getInt与setInt等操作基本数据类型的方法。

    四、Method

    Java.lang.Object

             |-java.lang.reflect.AccessibleObject

                       |-java.lang.reflect.Method

    1.构造方法:无

    2.常用方法:

     String

    getName()
              以 String 形式返回此 Method 对象表示的方法名称。

     Class<?>

    getReturnType()
              
    返回一个 Class 对象,该对象描述了此 Method 对象所表示的方法的正式返回类型。

     Object

    invoke(Object obj, Object... args)
              
    对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。

     String

    toString()
              
    返回描述此 Method 的字符串。

    五、暴力访问

    使用方法:Constructor、Field、Method三个类均为AccessibleObject类的子类,AccessibleObject类中有一个方法用于暴力访问类中私有的、受保护的构造方法、成员变量、普通方法。

    static void

    setAccessible(AccessibleObject[] array, boolean flag)
              使用单一安全性检查(为了提高效率)为一组对象设置 accessible 标志的便捷方法。

     void

    setAccessible(boolean flag)
              
    将此对象的 accessible 标志设置为指示的布尔值。

    前者为静态方法,用于为一组对象设置可访问标记的方法,后者为非静态方法,用于为特定的对象设置可访问标记的方法。

    六、示例:    

     1 package p09.ReflectDemo.p01.Demo01;
     2 
     3 /**
     4  * @author kuangdaoyizhimei
     5  *
     6  */
     7 public class Person {
     8     //两个字段
     9     private int age;
    10     private String name;
    11     public String id;
    12     //带参数构造方法
    13     public Person(int age, String name) {
    14         super();
    15         this.age = age;
    16         this.name = name;
    17         System.out.println("Person(int age,String name)run");
    18     }
    19     //无参构造方法
    20     public Person() {
    21         super();
    22         System.out.println("Person()run");
    23     }
    24     //公有无参数show方法
    25     public void show()
    26     {
    27         System.out.println(name+"-----is show runnig---"+age);
    28     }
    29     //私有无参数method方法
    30     private void method()
    31     {
    32         System.out.println("method is running");
    33     }
    34     //私有带参数set方法
    35     private void set(int age,String name)
    36     {
    37         this.age=age;
    38         this.name=name;
    39         System.out.println("set function is run,name is "+name+" ,age is "+age);
    40     }
    41     //公有静态无参数go方法。
    42     public static void go()
    43     {
    44         System.out.println("static go function is running!");
    45     }
    46 }
    Person.java

    该类封装了一些成员变量和方法。

     1 package p09.ReflectDemo.p01.Demo01;
     2 
     3 import java.lang.reflect.Constructor;
     4 import java.lang.reflect.InvocationTargetException;
     5 
     6 /**
     7  * 该类为测试拿到字节码文件中的构造方法。
     8  * @author kuangdaoyizhimei
     9  *
    10  */
    11 public class GetConstructorDemo {
    12 
    13     public static void main(String[] args) throws Exception {
    14         getAllConstructors();
    15         getNoneParameterConstructor();
    16         getParameterConstructor();
    17     }
    18 
    19     /**
    20      * 使用带参数构造方法创建本类实例
    21      * @throws InstantiationException
    22      * @throws IllegalAccessException
    23      * @throws IllegalArgumentException
    24      * @throws InvocationTargetException
    25      * @throws NoSuchMethodException
    26      * @throws SecurityException
    27      * @throws ClassNotFoundException
    28      */
    29     private static void getParameterConstructor() throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException {
    30         Class<?> clazz=Class.forName("p09.ReflectDemo.p01.Demo01.Person");
    31         Constructor<?> con=clazz.getConstructor(int.class,String.class);
    32         Object obj=con.newInstance(24,"张三");
    33     }
    34  
    35     /**
    36      * 使用无参构造方法创建本类的实例。
    37      * @throws NoSuchMethodException
    38      * @throws SecurityException
    39      * @throws ClassNotFoundException
    40      * @throws InstantiationException
    41      * @throws IllegalAccessException
    42      * @throws IllegalArgumentException
    43      * @throws InvocationTargetException
    44      */
    45     private static void getNoneParameterConstructor() throws NoSuchMethodException, SecurityException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
    46         Class clazz=Class.forName("p09.ReflectDemo.p01.Demo01.Person");
    47         Constructor con=clazz.getConstructor();
    48         Object obj=con.newInstance();
    49     }
    50 
    51     /**
    52      * 得到字节码文件中定义的所有构造方法
    53      * @throws ClassNotFoundException
    54      * @throws NoSuchMethodException
    55      * @throws SecurityException
    56      * @throws InstantiationException
    57      * @throws IllegalAccessException
    58      * @throws IllegalArgumentException
    59      * @throws InvocationTargetException
    60      */
    61     private static void getAllConstructors() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    62         Class clazz=Class.forName("p09.ReflectDemo.p01.Demo01.Person");
    63         Constructor arr[]=clazz.getConstructors();
    64         for(Constructor con:arr)
    65         {
    66             System.out.println(con);
    67         }
    68     }
    69 
    70 }
    GetConstructorDemo.java

    该类用于演示怎样使用反射机制获取Person.java中的构造方法,并使用获取到的构造方法创建对象(但参数构造方法与不带参数构造方法)。

     1 package p09.ReflectDemo.p01.Demo01;
     2 
     3 import java.lang.reflect.Field;
     4 import java.lang.reflect.Method;
     5 
     6 /**
     7  * 该类用于拿到字节码文件中的字段。
     8  * @author kuangdaoyizhimei
     9  *
    10  */
    11 public class GetFieldsDemo {
    12     public static void main(String args[]) throws Exception
    13     {
    14 //        getPublicFields();
    15 //        getPublicSpecialField();
    16 //        getPrivateSpecialField();
    17     }
    18     private static void getPrivateSpecialField() throws ClassNotFoundException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, InstantiationException {
    19         Class clazz=Class.forName("p09.ReflectDemo.p01.Demo01.Person");
    20 //        Field name=clazz.getField("name");
    21         Field name=clazz.getDeclaredField("name");
    22         name.setAccessible(true);//暴力访问
    23         Object obj=clazz.newInstance();
    24         name.set(obj, "张三");
    25         System.out.println(name.get(obj));
    26     }
    27 
    28     private static void getPublicSpecialField() throws ClassNotFoundException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, InstantiationException {
    29         Class clazz=Class.forName("p09.ReflectDemo.p01.Demo01.Person");
    30         Field field=clazz.getField("id");
    31 //        System.out.println(field);
    32         Object obj=clazz.newInstance();
    33         field.set(obj, "12345");
    34         System.out.println(field.get(obj));
    35     }
    36 
    37     private static void getPublicFields() throws ClassNotFoundException {
    38         Class clazz=Class.forName("p09.ReflectDemo.p01.Demo01.Person");
    39         Field f[]=clazz.getDeclaredFields();//得到所有的字段
    40 //        Field f[]=clazz.getFields();//得到公有的字段
    41         for(Field field :f)
    42         {
    43             System.out.println(field);
    44         }
    45     }
    46 }
    GetFieldsDemo.java

    该类用于演示怎样使用反射机制获取Person.java中的字段,并对字段赋值与获取。

     1 package p09.ReflectDemo.p01.Demo01;
     2 
     3 import java.lang.reflect.InvocationTargetException;
     4 import java.lang.reflect.Method;
     5 
     6 /**
     7  * 该类用于测试拿到字节码文件对象中的普通方法
     8  * @author kuangdaoyizhimei
     9  *
    10  */
    11 public class GetMethodsDemo {
    12 
    13     public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    14 //        showAllMethods();
    15 //        getSpecialMethod();
    16 //        getSpecialPrivateParameterMethod();
    17         getPublicStaticMethod();
    18     }
    19 
    20     private static void getPublicStaticMethod() throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
    21         Class clazz=Class.forName("p09.ReflectDemo.p01.Demo01.Person");
    22         Method method=clazz.getMethod("go", null);
    23         Object obj=clazz.newInstance();
    24         method.invoke(obj, null);
    25     }
    26     private static void getSpecialPrivateParameterMethod() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    27         Class clazz=Class.forName("p09.ReflectDemo.p01.Demo01.Person");
    28         Method method=clazz.getDeclaredMethod("set", int.class,String.class);
    29         method.setAccessible(true);//暴力访问,如果不是私有方法,这里可以不使用该语句
    30         Object obj=clazz.newInstance();
    31         method.invoke(obj, 23,"张三");
    32     }
    33 
    34     private static void getSpecialMethod() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    35         Class clazz=Class.forName("p09.ReflectDemo.p01.Demo01.Person");
    36         Method method=clazz.getMethod("show",null);
    37         Object obj=clazz.newInstance();
    38         method.invoke(obj, null);
    39     }
    40 
    41     private static void showAllMethods() throws ClassNotFoundException {
    42         Class clazz=Class.forName("p09.ReflectDemo.p01.Demo01.Person");
    43 //        Method methods[]=clazz.getMethods();//得到所有的公有方法,包括父类的
    44         Method methods[]=clazz.getDeclaredMethods();//得到所有本类中的方法
    45         for(Method method:methods)
    46         {
    47             System.out.println(method);
    48         }
    49     }
    50 
    51 }
    GetMethodsDemo

    该类用于演示怎样使用反射机制获取Person.java中的普通方法,并调用特定的方法(带参数方法与不带参数方法)。

    七、实例:模拟电脑运行过程

     1 package p10.ReflectDemo.p02.Demo01;
     2 
     3 /**
     4  * 模拟主板
     5  * 
     6  * @author kuangdaoyizhimei
     7  * 
     8  */
     9 public class MainBoard {
    10     public void run() {
    11         System.out.println("主板已经通电,即将运行!");
    12     }
    13 
    14     public void usePCI(PCI pci) {
    15         if (pci != null) {
    16             pci.open();
    17             pci.close();
    18         }
    19     }
    20 }
    MainBoard.java

    该类用于模拟主板对象。

     1 package p10.ReflectDemo.p02.Demo01;
     2 
     3 /**
     4  * 模拟接口PCI
     5  * @author kuangdaoyizhimei
     6  *
     7  */
     8 public interface PCI {
     9     public void open();
    10     public void close();
    11 }
    PCI.java

    该接口模拟PCI接口。

     1 package p10.ReflectDemo.p02.Demo01;
     2 
     3 import java.io.File;
     4 import java.io.FileInputStream;
     5 import java.util.Properties;
     6 
     7 /**
     8  * 模拟电脑运行
     9  * @author kuangdaoyizhimei
    10  *
    11  */
    12 public class Entry {
    13 
    14     public static void main(String[] args) throws Exception {
    15         MainBoard mb=new MainBoard();
    16         mb.run();
    17         
    18         //这种扩展方法烂透了,应当使用反射技术来完成,可以大大提高扩展性
    19 //        mb.usePCI(new SoundCard());
    20         
    21         File file=new File("pci.conf");
    22         FileInputStream fis=new FileInputStream(file);
    23         Properties pro=new Properties();
    24         pro.load(fis);
    25         if(pro.size()>=4)
    26         for(int i=0;i<4;i++)
    27         {
    28             String pciname=pro.getProperty("pci"+(i+1));
    29             if(pciname.equals(""))
    30             continue;
    31             Class<?> clazz=Class.forName(pciname);
    32             PCI pci=(PCI)clazz.newInstance();
    33             mb.usePCI(pci);
    34         }
    35         fis.close();
    36     }
    37 }
    Entry.java

    该类模拟电脑运行过程。

    1 pci1=p10.ReflectDemo.p02.Demo01.SoundCard
    2 pci2=
    3 pci3=
    4 pci4=
    pci.conf

    该配置文件用于模拟给主板插上扩展硬件,如声卡、显卡等,默认有声卡

    运行结果为:

    如果想要添加一个显卡,则只需要改变配置文件为:

    1 pci1=p10.ReflectDemo.p02.Demo01.SoundCard
    2 pci2=p10.ReflectDemo.p02.Demo01.DisplayCard
    3 pci3=
    4 pci4=
    pci.conf

    同时需要在p10.ReflectDemo.p02.Demo01包下创建DisplayCard.java文件,该类实现了PCI接口。

     1 package p10.ReflectDemo.p02.Demo01;
     2 
     3 public class DisplayCard implements PCI {
     4 
     5     @Override
     6     public void open() {
     7         System.out.println("显卡已经打开!");
     8     }
     9 
    10     @Override
    11     public void close() {
    12         System.out.println("显卡已经关闭!");
    13     }
    14 
    15 }
    DisplayCard.java

    这样,就可以将该显卡安装到了主板上,电脑运行时就可以正常使用该显卡了。

    运行结果是:

    八、总结。

    接口+配置文件是软件开发中非常有用的开发方式,使用这种开发范式可以极大扩展软件功能而不需要修改源代码。

  • 相关阅读:
    eclipse中svn的各种状态图标详解
    Invalid configuation file. File "**********" was created by a VMware product with more feature than this version of VMware Workstation and cannot be
    linux下tomcat无法访问问题(换一种说法:无法访问8080端口)
    安装MySQL start Service(无法启动服务)
    eclipse下SVN subclipse插件
    tomcat启动窗口中的时间与系统时间不一致
    关于如果从SQLSERVER中获取 数据库信息 或者 表信息
    有关google的appengine部署服务器的简单教程
    部署到Google App Engine时中途退出后引起的问题
    重温WCF之数据契约中使用枚举(转载)(十一)
  • 原文地址:https://www.cnblogs.com/kuangdaoyizhimei/p/4241422.html
Copyright © 2011-2022 走看看