码迷,mamicode.com
首页 > 编程语言 > 详细

Java基础笔记-反射及应用

时间:2015-08-25 19:34:48      阅读:235      评论:0      收藏:0      [点我收藏+]

标签:java   反射   

反射:
动态获取字节码文件对象(Person.class),并对其成员进行运行。
动态获取字节码文件对象的方式:
1:任何一个对象都是由字节码文件对象创建的,所以任何一个对象都可以得到自己的字节码文件对象
那么这个功能应该定义在Object中,所以使用 getClass()
需要先new对象

  2:每种数据类型都有一个 静态的class 属性,通过该属性可以得到字节码文件对象
    不需要new对象,但是需要Person类存在

  3:Class类提供了一个静态的forName(String str)方法 
    只需要提供字符串形式的包名+类名
1.
Person person1 = new Person();//先加载Person.class到方法区
Class<? extends Person> claz1 = person1.getClass();//得到了Person.class
Person person2 = new Person();
Class<? extends Person> claz2 = person2.getClass();//得到了 Person.class
System.out.println(claz1==claz2);//true 
---->字节码文件只加载一次到方法区,所以两次得到的是同一个

2.
Class<Person> claz1 = Person.class;
3.
Class<?> claz1 = Class.forName("com.reflect.Person");

动态获取字节码文件对象,并创建对象:
1)调用无参构造方法创建对象

//当无参的构造方法不存在时,会发生InstantiationException
    //当构造方法的权限过低时,会发生IllegalAccessException
    public static void createObj1() throws ClassNotFoundException, InstantiationException, IllegalAccessException
    {
        //Person person = new Person();
        //获取字节码文件对象---Person.class
        Class<?> claz = Class.forName("com.reflect.Person");            
        //使用Class提供的newInstance()方法创建Person类型的对象
        Object obj = claz.newInstance();//使用无参的构造方法创建对象
        Person person = (Person)obj;
        System.out.println(person);
}

2)使用有参数的构造方法创建对象

public static void createObj2() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
    {   //Person person = new Person("小红",20);
        //获取字节码文件对象---Person.class
        Class<?> claz = Class.forName("com.reflect.Person");        
        //得到构造方法所属的Constructor类型的对象
        Constructor<?> constructor = claz.getConstructor(String.class,int.class);       
        //使用构造方法创建对象--使用Constructor提供的创建对象的功能
        Person person =(Person)constructor.newInstance("小红",20);
        System.out.println(person);
}

3)动态创建对象并给属性赋值

Class<?> claz = Class.forName("com.reflect.Person");         
//得到属性name所属的 Field类型的对象
//Field field = claz.getField("name");//只能获取权限是public 的属性
//System.out.println(field);//NoSuchFieldException
Field field = claz.getDeclaredField("name");
//因为name是非静态属性,所以必须通过对象访问,所以先创建对象
Object obj = claz.newInstance();
//设置name属性为可访问的
field.setAccessible(true);// 该方法是从父类中继承的
//使用Field类提供的赋值功能,给属性赋值
field.set(obj, "小红");
System.out.println(obj);

4)调用静态方法

public static void method3() throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
    {
        //获取字节码文件对象---Person.class
         Class<?> claz = Class.forName("com.reflect.Person");

         ///获取被调用的方法所属的 Method类型的对象
         Method method = claz.getMethod("function", null);
         //执行方法
         method.invoke(null, null);
}

5)通过对象调用无参方法

public static void method1() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
    {
        // Person person = new Person();person.show();
        //获取字节码文件对象---Person.class
         Class<?> claz = Class.forName("com.reflect.Person");
         //获取被调用的方法所属的 Method类型的对象
         Method method = claz.getMethod("show", null);
         //show()属于非静态方式,需要对象去调用
         Object obj = claz.newInstance();
         //执行方法
         method.invoke(obj, null);
}

6)通过对象调用有参方法

//调用带参的方法
public static void method2() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
{
        //获取字节码文件对象---Person.class
         Class<?> claz = Class.forName("com.reflect.Person");        
       //获取被调用的方法所属的 Method类型的对象
         Method method = claz.getMethod("fun", String.class);        
         //fun()属于非静态方式,需要对象去调用
         Object obj = claz.newInstance();
         //执行方法
         method.invoke(obj, "hello");
}

反射应用:
这里有一台笔记本,刚开始只有外设鼠标。后来增加键盘、摄像头等等。
笔记本有running方法和use方法.外设都有open和close方法

public class NoteBook { 
    public void runing(){
        System.out.println("电脑运行");
    }   
    public void useKeyBoard(KeyBoard kb){
        if(kb!=null){
            kb.open();
            kb.close();
        }
    }
}
调用:
NoteBook noteBook = new NoteBook();
noteBook.runing();
KeyBoard keyBoard = new KeyBoard ();
noteBook.use(keyBoard );

如果添加外设鼠标呢?
NoteBook又得添加一个useMouse(Mouse mouse){..}方法,如果再添加外设的话,还得添加相应的方法。
当然,这里很容易解决,定义一个借口Usb.

interface Usb { 
    public void open();
    public void close();
}

然后让外设去实现这个接口,
在NoteBook里面只用定义一个

useUsb(Usb usb){
    usb.open();
    usb.close();
}
在主程里调用:
Usb keyBoard = new KeyBoard ();
noteBook.useUsb(keyBoard );
Usb mouse = new Mouse();
noteBook.useUsb(mouse);

如果还要添加外设,只用添加相应的类并实现Usb接口即可,那么问题来了,主程序里面又得new新的对象,调用相同的语句。

解决方法就可以用反射了:

1.把所有的外设添加到一个配置文件中
usb1=com.reflect.test.KeyBoard
usb2=com.reflect.test.Mouse
2.主程序里调用

Properties properties = new Properties();
FileInputStream fileInputStream = new FileInputStream("config\\config.properties");
properties.load(fileInputStream);            
for(int i=1;i<=properties.size();i++)
{
       String value properties.getProperty("usb"+i);
       Class<?> claz = Class.forName(value);
       Object obj = claz.newInstance();
       Usb usb = (Usb)obj;
       noteBook.useUsb(usb);
}

–>添加外设只用在配置文件中添加,主程序调用不用修改

版权声明:本文为博主原创文章,未经博主允许不得转载。

Java基础笔记-反射及应用

标签:java   反射   

原文地址:http://blog.csdn.net/u011102153/article/details/47981533

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!