黑马程序员_反射

------------------ Android培训 java培训 、期待与您交流! ------------------

概念:

        java反射机制就是在运行状态中,对于任意一个类,都能够指定这个类的所有属性和方法。对于任意一个类,都能够调用它的任意一个方法和属性。这种动态获取信息以及动态调用对象的方法的功能称为java语言的反射机制。动态获取类中信息,就是java反射(可以理解为对类的解剖)。按毕老师说的,反射大大加强了程序的扩展性。


动态获取类中的信息。在动态时,我们并不能够new一个对象,那怎样才能获取类的信息呢?

 所有的java对象都有class属性的Class类,java提供了三种获取class的办法:

        1、通过一个对象获取;

                Person p = new Person();

                Class clazz = p.getClass();

                这种方式需要明确具体的类,并且创建对象,没有扩展性。

        2、任何数据类型都具备一个静态的属性 .class 来获取其对应的Class对象;

              Class clazz = Person.class;

              这种方式要用到类中的静态成员,不够扩展。

        3、通过类名获取(Class的forName()方法);

                String className = "IODemo.Person";(这是我创建的一个地址,需要在同一个project下)

                Class clazz = Class.forName(className);

               这种 只要通过给定的类的字符串名称就可以获取该类,更为扩展。

        因而在反射时,第三种方式更多使用。


反射机制创建对象(以我创建的有age(int)和name(String)属性的Person类为例):

 找寻该名称类文件,并加载进内存,产生Class对象:

                String className = "IODemo.Person";(需要注意这里,名字需要完整的包名或者绝对路径,路径找不到下面的代码会发生ClassNotFoundException异常)

                Class clazz = Class.forName(className);

创建无参构造函数:

                Object obj = clazz.newInstance();

通过指定构造函数创建对象:getConstructor(参数类型...)

                Constructor constructor = clazz.getConstructor(String.class,int.class);

                Object obj = constructor.newInstance("ad",34);

获取类中的字段,也就是通常我们所说的属性:

        getField(String):Field; 此方法只能获取公有的(public修饰的);

        getFields():Field[];获取字段数组;

获取私有字段:

        getDeclaredField(String):Field;

        getDeclaredFields():Field[];

但当我们想要访问私有变量或是私有函数时,由于权限,并不能简单的访问到,于是反射也给我们提供了方法:

        setAccessible(boolean); 当boolean值设置为true时,则可以调用的字段对象进行权限的取消,暴力访问。


获取函数:

        getMethod(传入函数名和参数列表,空参数传null(String.class,int.class)):获取公有函数

        getMethods():Method[];

        getDeclaredMethod():Method;获取本类中的方法

        getDeclaredMethods():Method[];获取本类中所有方法,不包括父类

        invoke(Object,函数的参数(空就为null));       函数运行(如果invoke(null,参数),则是静态方法)


        当我们在进行一个程序的功能扩展时,如果频繁地去修改源程序,不但容易出现些错误,扩展性也极差。因而,若源程序提供了一个借口,我们只需要能够实现这个接口,便能将新功能添加进去,而不必要去修改程序,这样就显得简便安全。但我们的功能需要去让源程序知道,因此,新的功能和源程序的连接,就由配置文件来搭建。例,


我创建了一个USB接口,添加的新功能能够实现此接口以便扩展原功能:

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


并创建源代码Computer类去运行USB功能:

public class Computer {
	
	Computer(){
		System.out.println("computer......................run");
	}
	
	public void UseUSB(USB u){
		u.open();
		u.close();
	}
}



并再创建了一个配置文件“USB.properties”,里面的信息如“pro1 = Reflect.USB1”,以便Properties集合能够加载文件中的内容:


public class ReflectTest {
	public static void main(String[] args) throws Exception{
		//创建Computer类
		Computer com = new Computer();
		
		//创建流对象,读取文件内容
		File file = new File("USB.properties");
		Properties pro = new Properties();
		FileInputStream fis = new FileInputStream(file);
		
		//加载文件中的内容
		pro.load(fis);
		
		//将文件中添加的新类加载并运行
		for (int i = 0; i < pro.size(); i++) {
			String className = pro.getProperty("pro" +(i+1));
			Class clazz = Class.forName(className);
			
			USB usb = (USB)clazz.newInstance();
			com.UseUSB(usb);
		}
		fis.close();
	}
}

        只要实现USB接口的子类复写了其中的open和close方法,并将子类的名字写进配置文件,在运行Computer时,流会读取文件并加载其中的内容,动态地获取到了添加的类中的信息,而无需我们去修改代码,或是new一个对象。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值