Java当中的反射

1:反射的概念

  反射是指一类应用,它们能够自描述和自控制。也就是说,这类应用通过采用某种机制来实现对自己行为的描述(self-representation)和监测(examination),并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。

2:反射的作用

  可以说,实现了反射机制的系统都具有开放性,但具有开放性的系统并不一定采用了反射机制,开放性是反射系统的必要条件。一般来说,反射系统除了满足开放性条件外还必须满足原因连接(Causally-connected)。所谓原因连接是指对反射系统自描述的改变能够立即反映到系统底层的实际状态和行为上的情况,反之亦然。开放性和原因连接是反射系统的两大基本要素.

  举个例子:在做项目的过程中,可能会遇到数据库变化,当然是一次使用一个数据库的时候,而可能要在两个数据库之间切换,就可以在config文件中根据关键属性的设置即可,根据反射实例不同的对象,而其他操作数据库的代码不需要改变,当然前提是你已经为两个数据库写好不同的操作的代码,这样就可以实现系统的开放性,一个实例如此,可能有人会说,那我根据字符串判断生成不同的对象就可以了呀,当然可以,但是如果需要根据配置文件同时实例多个不同的对象的话,而配置文件是可以动态变化的,这样就可以实现更好的开放性

3:反射机制中的类:

java.lang.Class;                

java.lang.reflect.Constructor; 

java.lang.reflect.Field;        

java.lang.reflect.Method;

java.lang.reflect.Modifier;

4:获取字节码文件对象(Person.class)的三种方式

package reflect;

public class Demo1
{
    /* 1:使用Object类提供的Class getClass()方法,获取字节码文件对象
    *   需要先创建对象
    *   
    * 2:每个数据类型都有一个静态的属性class, 这个属性返回的是该数据类型所属的字节码文件对象
    *   需要这个类事先存在
    *   String.class  int.class
    *   
    * 3:使用 Class类中的Class forName(String str)方法
    *   只需要提供一个字符串,字符串中指明包名和类名
    *   
    */
    public static void main(String[] args) throws ClassNotFoundException
    {
        getClass3();
    }

    // 使用 Class类中的Class forName(String str)方法
    public static void getClass3() throws ClassNotFoundException
    {
        Class<?> cla = Class.forName("reflect.Person");
        Class<?> cla2 = Class.forName("reflect.Person");
        System.out.println(cla == cla2);
    }

    // 静态的属性class
    public static void getClass2()
    {
        Class<Person> cla = Person.class;
        Class<Person> cla2 = Person.class;
        System.out.println(cla == cla2);
    }

    // 使用Object类提供的Class getClass()方法
    public static void getClass1()
    {
        Person person = new Person();
        Class<? extends Person> cla = person.getClass();
        Person person2 = new Person();
        Class<? extends Person> cla2 = person.getClass();
        System.out.println(cla == cla2);
    }
}

5:字节码文件对象Class对象的使用(重点)

  • java.lang.reflect.Constructor ==》 动态获取类并创建对象

    • 我们知道创建对象必须要用到构造函数,无法使用Person类来new一个对象,我们如何通过字节码文件对象创建一个Person类的对象?
    • 那就要就要用用newInstance方法了,如果是无参的,就用Class对象的newInstance方法,如果是有参的,就用Class对象创建的构造函数的对象的newInstance方法..
package reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Demo2
{
    public static void main(String[] args) throws ClassNotFoundException,
            InstantiationException, IllegalAccessException, IllegalArgumentException, SecurityException, InvocationTargetException, NoSuchMethodException
    {
        createObj2();
    }
    //使用带参数的构造方法创建对象
    public static void createObj2() throws ClassNotFoundException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException
    {
        //获取字节码文件对象---Person.class
        Class<?> claz = Class.forName("reflect.Person");
        //获取带参数的构造方法所属的Constructor类型的对象
        Constructor<?> con = claz.getConstructor(String.class, int.class,
                String.class);
         //使用Constructor类提供的创建对象的方法
        Person person = (Person) con.newInstance("李鹏", 21, "男");
        
        System.out.println(person);
    }

    // 使用空参的构造方法创建对象
    // newInstance()使用的是空参数的构造方法创建对象,所以但空参的构造方法不存在时会发生InstantiationException
    // 当空参的构造方法的权限比较低的时候,会发生 IllegalAccessException
    public static void createObj1() throws ClassNotFoundException,
            InstantiationException, IllegalAccessException
    {
        Class claz = Class.forName("reflect.Person");
        Person p = (Person) claz.newInstance();//默认使用的是空参数的构造方法创建的对象
        System.out.println(p);
    }
}
  • java.lang.reflect.Field==》动态创建对象并给对象的属性赋值;

 

package reflect;

import java.lang.reflect.Field;

public class Demo3
{
    public static void main(String[] args) throws ClassNotFoundException,
            SecurityException, NoSuchFieldException, InstantiationException,
            IllegalAccessException
    {
        Class claz = Class.forName("reflect.Person");

        // 获取属性所属的Field类型的对象
        // Field field = claz.getField("name");//只能获取public权限的属性
        Field field = claz.getDeclaredField("name");// 可以获取任何权限的属性

        Person person = (Person) claz.newInstance();

        // 设置name为可访问的,如果属性原来的是私有的,这句话必不可少
        field.setAccessible(true);

        field.set(person, "李鹏");// 给name属性赋值

        System.out.println(person);
    }
}
  •  java.lang.reflect.Method==》动态创建对象,并调用其方法;

 

package reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Demo4
{
    public static void main(String[] args) throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException
    {
         method3();
    }
    //调用静态方法
    public static void method3() throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, NoSuchMethodException
    {
        Class claz = Class.forName("reflect.Person");
        
        //Person p = (Person) claz.newInstance();
        
        Method method = claz.getMethod("fun", null);
        
        method.invoke(null, null);//这里的第一个参数可以使null,可以是对象.. 
}

//调用带参数的方法
   
public static void method2() throws ClassNotFoundException, InstantiationException, IllegalAccessException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException { Class claz = Class.forName("reflect.Person"); Person p = (Person) claz.newInstance(); Method method = claz.getMethod("say", String.class,int.class); method.invoke(p,"哈哈",3); } //调用无参的方法 public static void method1() throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException, ClassNotFoundException { Class claz = Class.forName("reflect.Person"); Constructor con = claz.getConstructor(String.class,int.class,String.class); Person person = (Person) con.newInstance("李鹏",21,"男"); //使用Person的Class对象得到被调用的方法所属的Method类型的对象 Method m = claz.getMethod("show", null); //使用 Method对象的invoke()方法执行 m.invoke(person, null); } }

 

6:反射的应用==》实现根据配置文件实现自定义不同接口的启动

package reflect;

interface USB
{
    public abstract void open();
    public abstract void close();
}
USB接口
package reflect;

public class MouseUsb implements USB
{

    @Override
    public void close()
    {
        System.out.println("mouse close");
    }

    @Override
    public void open()
    {
        System.out.println("mouse open");
    }

}
MouseUsb
package reflect;

public class KeyUsb implements USB
{

    @Override
    public void close()
    {
        System.out.println("Key Close");

    }

    @Override
    public void open()
    {
        System.out.println("Key open");

    }

}
KeyUsb
package reflect;

public class NoteBook
{
    public void run()
    {
        System.out.println("笔记本运行了!");
    }

    public void usbRun(USB usb)
    {
        if (usb != null)
            usb.open();
    }
}
NoteBook
package reflect;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

public class Test
{

    public static void main(String[] args) throws IOException,
            ClassNotFoundException, InstantiationException,
            IllegalAccessException
    {
        NoteBook nb = new NoteBook();
        nb.run();
        Properties pro = new Properties();
        FileInputStream fis = new FileInputStream("config.properties");

        pro.load(fis);

        for (int i = 1; i <= pro.size(); i++)
        {
            String value = pro.getProperty("usb" + i);
            if (value != null)
            {
                Class<?> claz = Class.forName(value);

                USB usb = (USB) claz.newInstance();
                
                nb.usbRun(usb);
            }
        }

    }
}
Client

 

 

 

 

posted @ 2015-08-12 23:59  李_鹏  阅读(173)  评论(0编辑  收藏  举报