浅谈反射使用

  • 反射的实现主要通过以下四个类:

Class:类的对象,Constructor:类的构造方法,Field:类中的属性对象,Method:类中的方法对象

  • 获取Class对象的三种方法:

Class.forName(类名全称即包含了包名),类名.class实例.getClass()

注意类的加载信息只会在永久代里留存一份,所以同一个对象不管是通过forName还是class或者getClass方法获得的Class对象,都是同一个

  • 几种情况下的使用:

有参构造方法获取实例

Class c = Class.forName(类名全称);
Constructor con = c.getConstructor(String.class, int.class,String.class);//此处对应构造函数参数为(String a, int b,String c)
Object obj = con.newInstance("xxx", x, "xxx");//取得有参构造方法对象的实例

无参构造方法获取实例

Object obj=Class.forName(类名全称).newInstance();//通过反射获取无参构造方法对象的实例

修改字段内容

JDK1.8中String类:

        String str="abc";
		Field field=str.getClass().getDeclaredField("value");//String类中的value字段(char数组)
		field.setAccessible(true);//将该字段设置为可以访问
		char[] ch=(char[])field.get(str);//从str中取得这个对象(char数组)
		ch[1]='d';//将char数组中下标为1的位置上设置为d
        //此时打印str显示为 adc

调用其他方法

JDK1.8中Method类中invoke方法源码,可知,第一个参数是要对其进行操作的实例(或者说,要调用的方法的名字所隶属的对象实体必须有,如果参数为基本类型数据,必须转换为相应的包装类型的对象,invoke()方法的返回值总是对象;第二个不定参数为调用的方法的那些参数,也许有也许没有,总之,都不能是基本数据类型

String str = "hello";
Method m = str.getClass().getMethod("toUpperCase");
m.invoke(str);  // 此处返回HELLO
  • 常用情景

框架设计中,不管是SSH还是SSM,或者JUnit等都有较多使用,而且一般需要结合xml或者properties来使用

例如:

工厂模式+单例+反射+properties

前提:properties中两个实现类都继承了同一个接口BankDaoInterface,只是实现方式不同

注意:除了工厂类,这两个dao也采用了单例模式

properties文件:

工厂类:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
/**
 * 工厂模式
 * @author LuoPiao
 *
 */
public class BankDaoFactory {
	 //安全的单例模式
	private static volatile BankDaoFactory baf = null;
	
	private BankDaoFactory() {//防止乱实例化,构造方法私有化
	}
	
	public static BankDaoFactory getInstance() {
       if (baf == null) {//双层检查
    	   synchronized(BankDaoFactory.class){//同步
    		   if(baf == null){
    			   baf=new BankDaoFactory();
    		   }
    	   }
       }
       return baf;

	}
	
	//获取操作对象
	public  Object choose(String shortName){
    
	Object obj=null;
    //对文件进行操作,获取类名全称
		Properties p=new Properties();
		try {
			p.load(new FileInputStream("src/classInfo.properties"));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		String fullName=p.getProperty(shortName);//拿到完整名称
		try {
			Method method=Class.forName(fullName).getMethod("getInstance");//拿到需要调用的单例对象的方法
			obj=method.invoke(Class.forName(fullName));//调用方法,拿到返回值,此处的参数是要调用的方法隶属的对象实体,在这里它和getInstance返回值类型一致
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return obj;
	}
}

 

其中一个dao例如:

public class SqlDaoImpl implements BankDaoInterface {
	
	 //单例模式
	private static volatile SqlDaoImpl bai = null;
	
	private SqlDaoImpl() {	
	}
	
	public static SqlDaoImpl getInstance() {
       if (bai == null) {
    	   synchronized(SqlDaoImpl.class){
    		   if(bai == null){
    			   bai=new SqlDaoImpl();
    		   }
    	   }
       }
       return bai;

	}

//实现接口定义的方法
......

}

调用:

//在需要调用的类中,声明成员变量
public static BankDaoInterface dao=null;


//在初始化方法或者构造方法中对以上变量进行赋值
BankDaoFactory bdf=BankDaoFactory.getInstance();
//dao=(BankDaoImpl) bdf.choose("BankDaoImpl");
dao=(SqlDaoImpl) bdf.choose("SqlDaoImpl");//dao层修改为使用数据库操作

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值