话不多说,先上代码。
先来一个接口
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 + ")";
}
}