首页 > 代码库 > java的反射

java的反射

2017年 3月11号 周六 晴

 前言:理解java的反射能更好的理解spring的运行机制。

   因为spring的两大核心技术是Ioc(Inversion of Control,控制反转,有时也称为依赖注入,即DI,Dependcy Injection)和AOP(Aspect Oriented Programming,面向切面编程,即纵向的编程)。Ioc实现原理是java反射机制,Aop实现原理是java的动态代理。

    java的反射机制概念:

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

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

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

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

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

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

    5 生成动态代理

    在jdk中,主要由以下类来实现java的反射机制,这些类都位于java.lang.reflect包中。

      Class:表示正在运行的java应用程序中的类和接口。Class类是java反射中最重要的一个功能类,所有获取对象信息(包括方法,构造方法,访问权限)都由它来实现

      Field:提供有关类或接口的属性信息,以及对它的动态访问权限

      Constructor:提供关于类的单个构造方法的信息以及对它的访问权限

      Method:提供关于类或接口中某个方法信息

      Array类:提供动态创建数组,以及访问数组元素的静态方法

    在java.lang.Object类中定义了getClass()方法,因此对于任意一个java对象,都可以通过此方法获取对象类型。

    Class类是Reflection API中的核心类,它有一下方法:

    1 获取对象类型

      a   getName():获取类的完整名字

      b   getFields():获得类的public类型的属性

      c   getDeclareFields():获得类的所有属性

      d   getMethods():获得类的public类型的方法

      e   getDeclaredMethods():获取类的所有方法

      f   getMethod(String name,Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes参数的构造方法。

      g  getConstrutors():获得类的public类型的构造方法

      h newInstance():通过类的不带参数的构造方法创建这个类的一个对象

    2 通过默认构造方法创建一个新的对象

      Object objectCopy=classType.getConstructor(new Class[]{}).newInstance(new Object[]{});

      此代码先调用Class类的getConstructor()方法获得一个Constructor对象,它代表默认的构造方法,然后调用Constructor对象的newInstance()方法构造一个实例

    3 获得对象的所有属性

      Filed fileds[]=classType.getDeclareFields();

      Class类的getDeclaredFields()方法返回类的所有属性,包括public,protected,default(默认)和private访问级别的属性

    4 获得每个属性响应的getXXX()和setXXX()方法,然后执行这些方法,把原来对象的属性复制到新对象中。典型代码如下:

      for(int i=0;i Field field=fields[i];

       String filedName=field.getName();
         String firstLetter=fieldName.substring(0,1).toUpperCase();

       String getMethodName="get"+firstLetter+fieldName.substring(1);//获得和属性对应的getXXX()方法名字

       String setMethodName="set"+firstLetter+fieldName.substring(1);//获得和属性对应的setxxx()方法的名字

       Method getMethod=classType.getMethod(getMethodName, new Class[]{});//获得和属性对应的getxxx()方法

       Method setMethod=classType.getMethod(setMethodName, new Class[]{field.getType()});//获得和属性对应的setxxx()方法

       Object value=http://www.mamicode.com/getMethod.invoke(object,new Object[]{});//调用原对象的getXXX()方法

       System.out.println(fieldName+":"+value);

       setMethod.invoke(objectCopy,new Object[]{value});}

    Method类的invoke(Object obj,new Object args[])方法接收的参数必须为对象,如果参数的基本类型数据,必须转换成相应包装类型的对象。

    Invoke()方法的返回值总是对象,如果实际被调用的方法的返回值类型是基本类型数据,那么invoke()方法会把它转换为相应的包转类的对象,再将其返回

    java.lang.Array类提供了动态创建和访问数组元素的各种静态方法。如下所示代码的ArrayTester1类的main()方法创建一个长度为10的字符串数组,接着把索引位置为5的元素设为hello,然后在读取索引位置为5的元素的值。

技术分享
import java.lang.reflect.Array;
public class ArrayTest1 {
    public static void main(String[] args) throws Exception {
        Class classType = Class.forName("java.lang.String");
        //创建一个长度为10的字符串数组
        Object array = Array.newInstance(classType, 10);
        //把索引位置为5的元素设置为hello
        Array.set(array, 5, "hello");
        //读取索引位置为5的元素的值
        String s = (String) Array.get(array, 5);
        System.out.println(s);
    }

}
View Code

    

    关于java反射机制中的应用简单例子

    例子1:通过对象获取完整的包名和类名

技术分享
package qianyu.com;

class Hello{
    public void say(){
        System.out.println("hello,Everyone");
    }
}

public class Demo1 {
    public static void main(String[] args) {
         Demo1 demo = new Demo1();
         System.out.println("demo:"+demo.getClass());
         System.out.println("demo:"+demo.getClass().getName());
         
         Hello hello = new Hello();
         System.out.println("hello:"+hello.getClass());
         System.out.println("hello:"+hello.getClass().getName());
         
    }
}
case1

    运行结果如下:

      demo:class qianyu.com.Demo1
      demo:qianyu.com.Demo1
      hello:class qianyu.com.Hello
      hello:qianyu.com.Hello

    如上所示:通过java的反射机制,可以在运行过程中获取对象完整的路径,实际上,在java中所有类的对象其实都是Class的实例

     例子2:实例化Class类对象

   

技术分享
package qianyu.com;
class Hello1{
    public void say(){
        System.out.println("hello,Everyone");
    }
}

public class Demo2 {
    public static void main(String[] args) {
        Class<?> demo1=null;
        Class<?> demo2=null;
        Class<?> demo3=null;
        Class<?> demo4=null;
        try {
             demo1 = Class.forName("qianyu.com.Demo2");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
         demo2 = new Demo2().getClass();
        demo3=Hello.class;
        demo4=Hello1.class;
        System.out.println("本代码中Demo2类名称"+demo1.getName());
        System.out.println("本代码中Demo2类名称"+demo2.getName());
        System.out.println("同一个包中hello类名称"+demo3.getName());
        System.out.println("本代码中hello1类名称"+demo4.getName());
    }
}
case2

    运行结果如下:

    本代码中Demo2类名称qianyu.com.Demo2
    本代码中Demo2类名称qianyu.com.Demo2
    同一个包中hello类名称qianyu.com.Hello
    本代码中hello1类名称qianyu.com.Hello1

  

    

 

java的反射