java反射视频_Java反 射

java中java语言的反射机制:

java反射机制在运行状态中,对于任意一个类(class文件),都能知道这个类的所有属性和方法;

对于任意一个对象,能够调用它的任意一个方法和属性:

这种动态获取的信息以及动态调用对象的方法的动能称为java语言的反射机制。

动态获取类中信息,就是java反射,可以理解对类的解剖。有些应用程序是不能new对象的,但是可以动态加载类获取类信息。

1c4b168987b5262761b7ea43eef5d4d2.png

如图所示,就像类是对象的描述一样,Class类可以对字节码文件(.class文件)对象进行描述。

7c0fb75d0b02ae1d9f714f1492e1dacb.png

//早期:new时候,先根据被new的类的名称找寻该类的字节码文件,并加载进内存,

//并创建该字节码文件对象,并接着创建该字节码文件的对应的Person对象。

com.xidian.Person p=new com.xidian.Person();

//现在

String name="com.xidian.Person";

//找寻该文件类文件,并加载进内存,并产生Class对象。

Class clazz=Class.forName(name);

//如何产生该类的对象呢?

Object obj=clazz.newInstance();

用反射类加载的方式,从表面上看形式较为复杂但是可扩展性却更强。原来需要自己在程序文件手动中创建一个对象,

现在只用在配置文件中写入字符串,就可以创建对应的对象。

问题:使用clazz.newInstance()只能使用空参构造函数,要使用参数列表的构造函数怎么办?

/*

* 获取指定名称对应类中的所体现的对象时,

* 而该对象初始化不使用空参构造函数该怎么办?

*

* 既然是通过指定的构造函数进行对象的初始化,

* 所以应该先获得到该构造函数。通过字节码文件即可完成。

* 该方法是:getConstructor(parameterTypes)

*

* 在反射中构造器、字段、方法都是对象。

*/

String name="com.xidian.Person";

Class clazz=Class.forName(name);

//获取到指定的构造函数对象

Constructor constructor=clazz.getConstructor(String.class,int.class); //所有数据类型都可以用字节码文件.class来描述

//通过该构造器对象的newInstance方法进行对象的初始化。

Object obj=constructor.newInstance("xiaoming",12);

获取指定字段的值:

//对私有字段的访问全校权限检查。暴力访问。

field_1.setAccessible(true);

Object obj=clazz.newInstance();

field_1.set(obj,88);

Object o=field_1.get(obj);

System.out.println(o);

获取函数:

Method method=clazz.getMethod("show",null); //获取无参的方法

Object obj=clazz.newInstance();

method.invoke(obj, null);

Method method2=clazz.getMethod("paramMethod",String.class,int.class); //获取有参的方法,方法名、参数列表

Object obj2=clazz.newInstance();

method2.invoke(obj2, "小强",89); //invoke:对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。

反射的应用:

定义一个接口:package com.xidian;

public interface PCI {

public void open();

public void close();

}

定义一个接口实现类:package com.xidian;

public class SoundCard implements PCI{

public void open(){

System.out.println("sound open");

}

public void close(){

System.out.println("sound close");

}

}

定义一个主板:package com.xidian;

public class Mainboard {

public void run(){

System.out.println("main run...");

}

public void usePCI(PCI p){

if(p!=null){

p.open();

p.close();

}

}

}

测试:package com.xidian;

public class Test {

public static void main(String[] args){

Mainboard mb=new Mainboard();

mb.run();

mb.usePCI(new SoundCard()); //如果主板需要使用其他设备,必须重新修改代码,传递一个新创建的对象,可扩展性不好。

}

}

虽然使用接口的方式已经降低了程序的耦合度,但是代码的可扩展性不好。

如果想增加主板的设备但是不想修改代码,改用反射的方式:

不用new来完成,而是只获取其class文件,在其内部是实现创建对象的动作。

用反射做配置是应该使用.xml,更加准确。而在此我们使用properties对象实现。

修改主函数代码:public class Test {

public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException{

Mainboard mb=new Mainboard();

mb.run();

//mb.usePCI(new SoundCard()); //如果主板需要使用其他设备,必须重新修改代码,可扩展性不好。

File configFile=new File("pci.properties");

Properties prop=new Properties(); //注意是将配置文件放在项目的一级目录下。

FileInputStream fis=new FileInputStream(configFile);

prop.load(fis);

for(int x=0;x配置文件pci.properties:pci1=com.xidian.SoundCard

当扩展设备的时候,只需要将设备程序写好,写好配置文件,而不需要改动主程序代码就可使用。

本文原创发布php中文网,转载请注明出处,感谢您的尊重!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值