对反射的理解

1、反射的概念和作用

反射是Java的一个重要特征。反射是指在运行时动态加载类(获取Class对象)、获取类信息(如获取字段,方法,构造器等信息)、生成对象、操作对象的属性或方法。
Java中反射需要用到 java.lang.Class 和 java.lang.reflect包下面的类。

2、类加载的方式

类加载相当于Class对象的加载,类在第一次运行时才加载到JVM
反射可以提供运行时的类信息,并且这个类可以在运行时才加载进来,甚至在编译时该类的.class文件不存在也可以加载进来

类加载有以下几种方式
(1)Class.forName(类的权限定名即“包名.类名”)
(2)类名.Class
(3)对象名.getClass()

3、获取类信息

Class类的方法:
public String getName() 返回类的名称:“包名.类名”
public Field getField(String name) 获取所有public字段信息
public Field[] getDeclaredFields() 获取所有字段信息
public Method[] getMethods() 获取所有public的Method对象
public Method[] getDeclaredMethod() 获取所有定义的Method对象
public Constructor[] getConstructors() 获取所有public的Constructor对象
public Constructor[] getDeclaredConstructors() 获取所有已定义的Constructor对象

4、利用反射创建对象的方式

(1)获取Class对象clazz,调用clazz对象的newInstance()方法创建对象; 该方法要求相应的类中必须有无参数的构造方法
(2)获取Class对象clazz,调用clazz对象的getConstructors()方法获取所有的构造器数组。选择数组中特定的构造器对象,调用构造器对象的newInstance(xx,xxx)方法,传入构造器所需的参数创建对象

5、获取对象属性,调用对象方法

public class Student {

	public String height;
	private double weight;
	
	public Student(){}

	public Student(String height, double weight) {
		super();
		this.height = height;
		this.weight = weight;
	}
	
	public void print(){
		System.out.println("调用print方法...");
	}
	
	public char getSex(int num){
		return num==1?'m':'f';
	}
}
public class Test {
	
	public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
		Class clazz = Student.class;
		Student obj = (Student) clazz.newInstance();
		
		//获取public属性
		Field f1 = clazz.getField("height");
		f1.set(obj, "173");
		System.out.println(f1.get(obj));;
		//获取private属性
		Field f2 = clazz.getDeclaredField("weight");
		f2.setAccessible(true);
		f2.set(obj, 56);
		System.out.println(f2.get(obj));
		
		//获取方法
		Method m1 = clazz.getMethod("print");
		m1.invoke(obj);
		//获取带参数方法
		Method m2 = clazz.getMethod("getSex", int.class);
		char a = (char) m2.invoke(obj, 1);
		System.out.println("性别:"+a);
	}

}

6、反射的应用

(1)反射的一个简单应用-- 简单工厂设计模式中
简单工厂设计模式是工厂方法模式的缩小版,先介绍工厂方法模式

(i)工厂方法模式:工厂方法模式是一个创建型设计模式,他的定义是“定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法时一个类的实例化延迟到其子类。”
简单地说,是可以动态的实例化某个接口下的任何实现类。工厂方法模式应用了反射的设计思想。

(a)组成: AbstractFactory,ConcreateFactory, Product, ConcreateProduct1,ConcreateProduct2…
(b)代码:

//抽象工厂
public abstract class AbstractFactory {
	public abstract <T extends Product>T createProduct(Class<T> clazz);
}

//具体工厂
public class ConcreateFactory extends AbstractFactory {

	@Override
	public <T extends Product> T createProduct(Class<T> clazz) {
		Product product = null;
		try {
			product = (Product) Class.forName(clazz.getName()).newInstance();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return (T)product;
	}

}

//待生产的产品抽象类
public abstract class Product {

	public void method1(){
		//具体方法
	}
	
	//抽象方法
	public abstract void method2();
	
}

//被生产的具体产品1
public class ConcreateProduct1 extends Product {

	@Override
	public void method2() {
		System.out.println("我是concreteProduct1...");
	}

}
//被生产的具体产品2
public class ConcreateProduct2 extends Product {

	@Override
	public void method2() {
		System.out.println("我是concreteProduct2...");
	}

}

//场景类
public class Client {
	
	public static void main(String[] args) {
		
		AbstractFactory factory = new ConcreateFactory();
		
		ConcreateProduct1 product1 = factory.createProduct(ConcreateProduct1.class);
		product1.method2();
		
		ConcreateProduct2 product2 = factory.createProduct(ConcreateProduct2.class);
		product2.method2();
		
	}

}

(c)优点及应用
优点:
(1)具有良好的封装性、代码结构清晰;
(2)对象创建是有条件约束的(需要传入class对象,或类的权限定名称字符串)
(3)解耦合:降低了调用方和被调用方的耦合
应用
(1)根据不同的数据库,JDBC可以加载不同的驱动
(2)spring中的IOC

(ii)简单工厂设计模式是工厂方法设计模式的缩小版,主要区别是无需抽象工厂,直接提供一个具体地工厂,且提供静态的创建产品的方法
代码如下:

//具体地工厂,提供一个静态的用于创建产品的方法
public class ConcreateFactory {
	
	public static <T extends Product>T createProduct(Class<T> clazz){
		Product product = null;
		try {
			product = (Product) Class.forName(clazz.getName()).newInstance();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return (T)product;
	}

}

//场景类
public class Client {
	
	public static void main(String[] args) {
		
		ConcreateProduct1 product1 = ConcreateFactory.createProduct(ConcreateProduct1.class);
		product1.method2();
		
		ConcreateProduct2 product2 = ConcreateFactory.createProduct(ConcreateProduct2.class);
		product2.method2();
		
	}

}

(2)spring框架中的依赖注入和控制反转
spring框架中,用了工厂方法来完成控制反转的功能,而工厂方法应用了反射,故spring中也应用了反射机制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值