zoukankan      html  css  js  c++  java
  • java学习笔记09--反射机制

     

    什么是反射:

    反射是java语言的一个特性,它允许程序在运行时来进行自我检查并且对内部的成员进行操作。例如它允许一个java的类获取他所有的成员变量和方法并且显示出来。
    java的反射机制的实现要借助4个类:Class,Constructor,Field,Method 其中Class代表的是类对象,Constructor  类的构造器对象,Field  类的属性对象,Method 

    类的方法对象。通过这四个对象我们可以粗略的看到一个类的各个组成部分。

     

    在正常情况下,必须知道一个类的完整路径之后才可以实例化对象,但是在java中也允许通过一个对象来找到其所在的类的信息,那么这实际上就是Class类的功能。

    1. package com.itmyhome;  
    2.   
    3. class A{  
    4.       
    5. }  
    6. public class T {  
    7.   
    8.     public static void main(String[] args) {  
    9.         // TODO Auto-generated method stub  
    10.         A a = new A();  
    11.         System.out.println(a.getClass().getName());  //com.itmyhome.A  
    12.     }  
    13.   
    14. }  


    Object类的支持

    在Object类中定义了以下的方法,此方法将被所有子类继承:

    public  final  Class getClass()

    以上的方法返回值的类型是一个"Class"类,实际上此类是java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。

    Class类

    Class本身表示一个类的本身,通过Class可以完整的得到一个类中的完整结构,包括此类中的方法定义,属性定义等。

    实例化Class类对象

    有三种方法实例化Class对象:

    第一种:通过forName()方法

    第二种:类.class

    第三种:对象.getClass()

    1. package com.itmyhome;  
    2.   
    3. class A{  
    4.       
    5. }  
    6. public class T {  
    7.   
    8.     public static void main(String[] args) throws ClassNotFoundException {  
    9.         // TODO Auto-generated method stub  
    10.         Class<?> c1 = Class.forName("com.itmyhome.A");  
    11.         Class<?> c2 = A.class;  
    12.         Class<?> c3 = new A().getClass();  
    13.         System.out.println(c1.getName());  
    14.         System.out.println(c2.getName());  
    15.         System.out.println(c3.getName());  
    16.     }  
    17.   
    18. }  

    Class主要是反射的源头,不光可以取得对象所在类的信息,也可以直接通过Class类的方法进行对象的实例化操作正常情况下,使用关键字new为对象实例化,如果现在已经实例化好了Class对象,则就可以通过Class类中提供的

    实例化对象

    1. package com.itmyhome;  
    2.   
    3. class Person {  
    4.     private String name;  
    5.     private int age;  
    6.       
    7.     public String getName() {  
    8.         return name;  
    9.     }  
    10.     public void setName(String name) {  
    11.         this.name = name;  
    12.     }  
    13.     public int getAge() {  
    14.         return age;  
    15.     }  
    16.     public void setAge(int age) {  
    17.         this.age = age;  
    18.     }  
    19.     public String toString() {  
    20.         // TODO Auto-generated method stub  
    21.         return "name: " + name + ",age: " + age;  
    22.     }  
    23. }  
    24.   
    25. public class T {  
    26.   
    27.     public static void main(String[] args) throws ClassNotFoundException {  
    28.         Class<?> c = Class.forName("com.itmyhome.Person");  
    29.         Person person = null;  
    30.         try {  
    31.             person = (Person) c.newInstance();  //实例化对象  
    32.         } catch (InstantiationException e) {  
    33.             e.printStackTrace();  
    34.         } catch (IllegalAccessException e) {  
    35.             e.printStackTrace();  
    36.         }  
    37.         person.setName("itmyhome");  
    38.         person.setAge(23);  
    39.         System.out.println(person);  
    40.     }  
    41.   
    42. }  


    通过以上的代码,可以发现,即使不使用关键字new对象也可以进行实例化操作,反射的作用。

    但是,在使用以上操作的时候有一点必须注意,在操作中类中必须存在无参构造方法,否则无法实例化

    报以下异常

    1. java.lang.InstantiationException: com.itmyhome.Person  
    2.     at java.lang.Class.newInstance0(Class.java:340)  
    3.     at java.lang.Class.newInstance(Class.java:308)  
    4.     at com.itmyhome.T.main(T.java:35)  
    5. Exception in thread "main" java.lang.NullPointerException  
    6.     at com.itmyhome.T.main(T.java:41)  


    对于以上的程序也并非没有解决的方法,也是可以通过其他的方式进行实例化操作的,只是在操作的时候需要明确的调用类中的构造方法,并将参数传递进去之后才可以进行实例化操作,操作步骤如下:

    1、通过Class类中的getConstructors()取得本类中的全部构造方法。

    2、向构造方法中传递一个对象数组进去,里面包含了构造方法中所需的各个参数。

    3、之后通过Constructor实例化对象。

    1. package com.itmyhome;  
    2.   
    3. import java.lang.reflect.Constructor;  
    4.   
    5. class Person {  
    6.     private String name;  
    7.     private int age;  
    8.       
    9.     public Person(String name,int age){  
    10.         this.name = name;  
    11.         this.age = age;  
    12.     }  
    13.     public String getName() {  
    14.         return name;  
    15.     }  
    16.     public void setName(String name) {  
    17.         this.name = name;  
    18.     }  
    19.     public int getAge() {  
    20.         return age;  
    21.     }  
    22.     public void setAge(int age) {  
    23.         this.age = age;  
    24.     }  
    25.     public String toString() {  
    26.         // TODO Auto-generated method stub  
    27.         return "name: " + name + ",age: " + age;  
    28.     }  
    29. }  
    30.   
    31. public class T {  
    32.   
    33.     public static void main(String[] args) throws ClassNotFoundException{  
    34.         Class<?> c = Class.forName("com.itmyhome.Person");  
    35.         Constructor<?> cons[] = c.getConstructors();  
    36.         Person person = null;  
    37.         try {  
    38.             person = (Person) cons[0].newInstance("itmyhome",23);  //实例化对象  
    39.         } catch (Exception e) {  
    40.             e.printStackTrace();  
    41.         }   
    42.         person.setName("itmyhome");  
    43.         person.setAge(23);  
    44.         System.out.println(person);  
    45.     }  
    46.   
    47. }  


    反射机制的深入----取得类的结构

    在实际开发中,以上的程序就是反射应用最多的地方,当然,反射机制所提供的功能远不止如此,还可以通过反射得到一个类的完整结构,那么这就要使用到java.lang.reflect包中的以下几个类:

    Constructor:表示类中的构造方法

    Field:表示类中的属性

    Method:表示类中的方法

    这三个类都是AccessibleObject类中的子类

    1. package com.itmyhome;  
    2.   
    3. interface IPerson{  
    4.     public static final String NAME = "itmyhome";  
    5.     public String toSay();  
    6.     public String toEat(String name,int age);  
    7. }  
    8. class Person implements IPerson{  
    9.     private String name;  
    10.     private int age;  
    11.     public Person(){    //无参构造  
    12.           
    13.     }  
    14.     public Person(String name,int age){  
    15.         this.name = name;  
    16.         this.age = age;  
    17.     }  
    18.     @Override  
    19.     public String toSay() {  
    20.         return "hello!";  
    21.     }  
    22.       
    23.     @Override  
    24.     public String toEat(String name, int age) {  
    25.         return "name: "+name+",age: "+age;  
    26.     }  
    27.     public String getName() {  
    28.         return name;  
    29.     }  
    30.     public void setName(String name) {  
    31.         this.name = name;  
    32.     }  
    33.     public int getAge() {  
    34.         return age;  
    35.     }  
    36.     public void setAge(int age) {  
    37.         this.age = age;  
    38.     }  
    39. }  


    取得类所实现的全部接口

    要想取得一个类所实现的全部接口,则必须使用Class类中的getInterfaces()方法,此方法定义如下:

    1. public Class[] getInterfaces()  


    此方法返回一个Class类的对象数组,之后就可以直接利用Class类中的getName()方法输出即可。

    因为一个类可以同时实现多个接口,所以在此处就以一个数组的形式返回实现的全部接口。

    1. public class T {  
    2.     public static void main(String[] args) throws Exception{  
    3.         Class<?> cl = Class.forName("com.itmyhome.Person");  //实例化对象  
    4.         Class<?> c[] = cl.getInterfaces();   //以数组形式返回实现的全部接口  
    5.         for (int i = 0; i < c.length; i++) {  
    6.             System.out.println(c[i].getName());   //输出接口名称  
    7.         }  
    8.     }  
    9. }  


    取得类所继承的父类

    一个类可以实现多个接口,但是只能继承一个父类,所以如果要想取得一个类的父类,可以直接使用Class类中的getSuperClass()方法。此方法定义如下:

    1. public Class<? super T> getSuperClass()  


    此方法返回的是Class实例,和之前的得到接口一样,可以通过getName()方法取得名次。

    一个类只继承一个父类,如果一个类中没有明确的指明继承哪个类,则肯定继承的是Object类。

    1. public class T {  
    2.     public static void main(String[] args) throws Exception{  
    3.         Class<?> cl = Class.forName("com.itmyhome.Person");  //实例化对象  
    4.         Class<?> c = cl.getSuperclass();   //取得继承父类  
    5.         System.out.println(c.getName());  
    6.     }  
    7. }  


    取得类中的全部构造方法

    1. public class T {  
    2.     public static void main(String[] args) throws Exception{  
    3.         Class<?> cl = Class.forName("com.itmyhome.Person");  //实例化对象  
    4.         Constructor<?> c[] = cl.getConstructors();  
    5.         for (int i = 0; i < c.length; i++) {  
    6.             System.out.println(c[i]);  
    7.         }  
    8.     }  
    9. }  


    取得类中的方法

    要想取得一个类中的全部方法,可以使用Class类中的getDeclaredMethods()方法,此方法返回一个Method类的对象数组,而如果要想进一步取得方法的具体信息,例如:方法的参数,抛出的异常等等,则就必须依靠Method类

    public  Method[]  getDeclaredMethods()      输出本类中的全部方法

    public  Method[]  getMethods()  输出全部的方法

    1. public class T {  
    2.     public static void main(String[] args) throws Exception{  
    3.         Class<?> cl = Class.forName("com.itmyhome.Person");  //实例化对象  
    4.         Method m1[] = cl.getMethods();  
    5.         for (int i = 0; i < m1.length; i++) {  
    6.             System.out.println(m1[i]);  
    7.         }  
    8.         System.out.println("*************");  
    9.         Method m2[] = cl.getDeclaredMethods();  
    10.         for (int i = 0; i < m2.length; i++) {  
    11.             System.out.println(m2[i]);  
    12.         }  
    13.     }  
    14. }  


    取得类中的属性

    public  Field[]  getFields()    得到实现的接口和父类中的公共属性

    public  Field[]  getDeclaredFields()  得到本类中的全部属性

    以上方法返回的都是Field的数组,每一个Field对象就表示类中的一个属性

    1. public class T {  
    2.     public static void main(String[] args) throws Exception{  
    3.         Class<?> cl = Class.forName("com.itmyhome.Person");  //实例化对象  
    4.         Field f1[] = cl.getFields();  
    5.         for (int i = 0; i < f1.length; i++) {  
    6.             System.out.println(f1[i]);  
    7.         }  
    8.         System.out.println("*********");  
    9.         Field f2[] = cl.getDeclaredFields();   //本类中的属性  
    10.         for (int i = 0; i < f2.length; i++) {  
    11.             System.out.println(f2[i]);  
    12.         }  
    13.     }  
    14. }  


     

  • 相关阅读:
    纯CSS打造圆角Table效果
    [RabbitMQ+Python入门经典] 兔子和兔子窝[转]
    salesforce 调用webservice
    maven+spring+cxf编写web service
    Appfuse 教程
    eclipse的maven project,如何添加.m2里的那些jar包?
    java fullstack 框架
    Maven Jetty Plugin运行配置jetty:run
    Appfuse下载及安装步骤
    fullstack设计
  • 原文地址:https://www.cnblogs.com/timssd/p/4790458.html
Copyright © 2011-2022 走看看