【JavaSE】反射机制(工具思想)

话不多说,先上代码。
先来一个接口

public interface IDoSomething {
	//简单定义一个方法
	void doSomething(String message);
}

然后,实现两个有关于这个接口的实现类:

public class Teddy implements IDoSomething {
	//实现该接口,必然要实现该接口所定义的方法;
	public Teddy() {
	}
	
	@Override
	public void doSomething(String message) {
	//这里我们仅仅简单实现一下
		System.out.println("我是渣男,我怕谁!" + message);
	}

}

public class Rascal implements IDoSomething {
	//实现该接口,必然要实现该接口所定义的方法;
	public Rascal() {
	}

	@Override
	public void doSomething(String message) {
	//这里我们仅仅简单实现一下
		System.out.println("不接受!!不拒绝!!!" + message);
	}
	
}

最后,再写一个SomeRakishClass 类,

public class SomeRakishClass {
	//定义一个接口类型的成员,
	private IDoSomething doSomething;
	
	static {
		//这里的 PropertiesParser是我自己曾经做过的一个properties文件解析工具,
		//现在直接使用该工具,代码写起来很爽。 
		//properties文件解析工具 请看博文连接:
		//    https://blog.youkuaiyun.com/weixin_44836233/article/details/103111697

		PropertiesParser pp = new PropertiesParser();
		//需要注意的是文件的路径, 一个“/”是把src当做根目录。
		pp.loadProperties("/class.properties");
	}
	
	public SomeRakishClass() {
	}
	
	public void doSome() {
 //因为我的工具中的Map是static,是单例的,所以不论我怎么new,都是对同一个Map进行操作的
		String className = new PropertiesParser().getValue("class");
		try {
		//以下则是反射机制:
		
			Class<?> klass = Class.forName(className);
			Object obj = klass.newInstance();
			if (!(obj instanceof IDoSomething)) {
				return;
			}
			doSomething = (IDoSomething) obj;
			
			//因为定义了一个接口类型的成员,那么我们一定可以调用该接口所定义的方法
			doSomething.doSomething("我是一个乖宝宝!");
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
	
}

因为SomeRakishClass 类用到了properties文件,所以我们要建立一个properties文件:
在这里插入图片描述

用Test类测试一下:

public class Test {

	public static void main(String[] args) {
		new SomeRakishClass().doSome();
	}

}

上述代码的执行结果很简单:
在这里插入图片描述
然而,若果我们只修改properties文件,而不修改源代码,再看执行结果:
在这里插入图片描述
在这里插入图片描述
显而易见,这里的结果发生了更改。
由此我们可以想象,假如把SomeRakishClass 类和接口,打包,以后让别人用,那么,只要我们以后实现了该接口,把properties文件配置好,那么我们根本不用去更改源代码,这在c语言里,是想都不敢想的啊。这就是反射机制。
上述其实只用到了反射机制的一个Class.forName();其实,我们还可以更改成员的值,执行类里面的方法……
来看下面的代码:

public static void main(String[] args) {
	//这里同样用到了PropertiesParser工具:
	//配置文件,进行了修改,改成了一个复数相加的类,具体代码见最后。
		PropertiesParser property = new PropertiesParser();
		property.loadProperties("/class.properties");
		String className = property.getValue("class");
		System.out.println(className);
		try {
			Class<?> klass = Class.forName(className);
			Object obj = klass.newInstance();
			System.out.println("obj :" + obj.getClass());
			
			Constructor<?> constructor = klass
									.getConstructor(double.class,double.class);
			Object object = constructor.newInstance(3.14,5.36);
			System.out.println(object + "  obj :" + obj.getClass());
			
			Method method = klass.getMethod("add", klass);
			//这里getMethod()方法是指找到该方法,并用method指向它
			//其中的两个参数分别是:
			//前面是指klass类中的方法名称,后面是指这个类的这个方法的参数类型
			Object ob = method.invoke(obj, object);
			//invoke()方法是指执行method所指向的方法
			//其中的两个参数分别是:
			//前面是指要执行的对象,后面是指符合该方法的参数类型的值。
			System.out.println(ob + "  obj : " + obj.getClass());
			
			Field field = klass.getDeclaredField("vir");
			field.setAccessible(true);
			field.set(object, 123);
			System.out.println(object);
			
			Field virField = klass.getDeclaredField("vir");
			String fileName = virField.getName();
			String name = "set" + fileName.substring(0, 1)
						.toUpperCase() + fileName.substring(1);
			Method m = klass.getDeclaredMethod(name,virField.getType());
			m.invoke(object, 1.0);
			System.out.println(object);
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		}

结果如下:
在这里插入图片描述
由此可见,反射机制的强大!!!

这里是复数类的相关代码:

public class Complex {
	private double real;
	private double vir;
	
	public Complex() {
	}

	public Complex(double real) {
		this.real = real;
	}

	public Complex(double real, double vir) {
		this.real = real;
		this.vir = vir;
	}
	
	public Complex(Complex complex) {
		this.real = complex.real;
		this.vir = complex.vir;
	}

	public double getReal() {
		return real;
	}

	public void setReal(double real) {
		this.real = real;
	}

	public double getVir() {
		return vir;
	}

	public void setVir(double vir) {
		this.vir = vir;
	}

	// 四则运算的实现
	// 先实现加法;根据需求分析可知:加法需要实现两种:
	// c = a + b和
	// a += b
	// 先实现a += b
	public Complex add(Complex other) {
		this.real += other.real;
		this.vir += other.vir;
		
		return this;
	}
	
	// 再实现c = a + b
	public static Complex add(Complex one, Complex other) {
		return new Complex(one).add(other);
	}

	/*
		Complex result = new Complex();
		
		result.real = one.real + other.real;
		result.vir = one.vir + other.vir;
		
		return result;
		
		c = -b;
		b的值在执行完上述语句后,当然不能更改!
	 */
	
	private static Complex opposite(Complex one) {
		return new Complex(-one.real, -one.vir);
	}
	
	public Complex sub(Complex other) {
		return add(opposite(other));
	}
	
	public static Complex sub(Complex one, Complex other) {
		return new Complex(one).sub(other);
	}

	// 1/(a+bi)
	// (a-bi)/((a+bi)(a-bi))
	// (a-bi)/(a*a + b*b)
	// 实部:a/(a*a + b*b);虚部:-b/(a*a + b*b)
	private static Complex reciprocal(Complex c) {
		double mod = c.real*c.real + c.vir*c.vir;
		
		return Math.abs(mod) <= 1e-6 ? null : new Complex(c.real / mod, -c.vir / mod);
	}
	
	// a *= b
	// (a1+b1i) * (a2+b2i) = (a1*a2 - b1*b2) + (a1*b2 + a2*b1)i
	public Complex mul(Complex other) {
		double real = this.real;
		this.real = real * other.real - this.vir *other.vir;
		this.vir = real * other.vir + vir * other.real;
		
		return this;
	}
	
	// c = a*b
	public static Complex mul(Complex one, Complex other) {
		return new Complex(one).mul(other);
	}
	
	// a /= b
	public Complex div(Complex other) {
		Complex reciprocal = Complex.reciprocal(other);
		return reciprocal == null ? null : this.mul(reciprocal);
	}
	
	// c = a / b
	public static Complex div(Complex one, Complex other) {
		return new Complex(one).div(other);
	}
	
	@Override
	public boolean equals(Object obj) {
		if (obj == null) {
			return false;
		}
		if (this == obj) {
			return true;
		}
		if (obj.getClass() != this.getClass()) {
			return false;
		}
		
		Complex c = (Complex) obj;
		
		return Math.abs(c.real - this.real) < 1e-6 && Math.abs(c.vir - this.vir) < 1e-6;
	}

	@Override
	public String toString() {
		return "(" + real + ", " + vir + ")";
	}
	
}

$(function(){ $.fn.extend({ SimpleTree:function(options){ //初始化参数 var option = $.extend({ click:function(a){ } },options); option.tree=this; /* 在参数对象中添加对当前菜单树的引用,以便在对象中使用该菜单树 */ option._init=function(){ /* * 初始化菜单展开状态,以及分叉节点的样式 */ this.tree.find("ul ul").hide(); /* 隐藏所有子级菜单 */ this.tree.find("ul ul").prev("li").removeClass("open"); /* 移除所有子级菜单父节点的 open 样式 */ this.tree.find("ul ul[show='true']").show(); /* 显示 show 属性为 true 的子级菜单 */ this.tree.find("ul ul[show='true']").prev("li").addClass("open"); /* 添加 show 属性为 true 的子级菜单父节点的 open 样式 */ }/* option._init() End */ /* 设置所有超链接不响应单击事件 */ this.find("a").click(function(){ $(this).parent("li").click(); return false; }); /* 菜单项 接受单击 */ this.find("li").click(function(){ /* * 当单击菜单项 * 1.触发用户自定义的单击事件,将该 标签中的第一个超链接做为参数传递过去 * 2.修改当前菜单项所属的子菜单的显示状态(如果等于 true 将其设置为 false,否则将其设置为 true) * 3.重新初始化菜单 */ option.click($(this).find("a")[0]); /* 触发单击 */ /* * 如果当前节点下面包含子菜单,并且其 show 属性的值为 true,则修改其 show 属性为 false * 否则修改其 show 属性为 true */ /* if($(this).next("ul").attr("show")=="true"){ $(this).next("ul").attr("show","false"); }else{ $(this).next("ul").attr("show","true"); }*/ /* 初始化菜单 */ option._init(); }); /* 设置所有父节点样式 */ this.find("ul").prev("li").addClass("folder"); /* 设置节点“是否包含子节点”属性 */ this.find("li").find("a").attr("hasChild",false); this.find("ul").prev("li").find("a").attr("hasChild",true); /* 初始化菜单 */ option._init(); }/* SimpleTree Function End */ }); });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值