java中提供了一种叫做反射的方式,这个东西能够帮助我们架构更加的优美。
之前在项目中,遇到一个问题:对外提供接口,需要根据前端请求的url来进入不同的逻辑执行方法中。如果简单粗暴的通过添加多个if来控制进入不同的方法,就显得不专业了。 新增功能需要添加if判断,完全远离了设计本质。
这篇文章并不是深入其原理,仅在使用层面上花费口舌。(哎,能力有限啊,后续慢慢深入学习)
java为我们提供了一个Class的类(称为类类型),这个类的话可以理解为 管理 开发者所写的所有类。通过Class我们可以通过相应提供的API到 每个开发者所写类(包含jdk的类)的相应Filed属性信息, Method方法信息, Constructor构造函数信息。
相对于开发者所写的类, 都可以找到对应的类类型。如果有类A, A a = new A(); A这个类的类类型可以通过下面三种方式获得
1. a.getClass();
2. A.class;
3. Class.forName(“A的路径”);
再通过Class的相关API即可进行相应操作
为什么需要反射(例子)?
生活中,大家都会唱歌,有明星唱歌好听的,有孩子唱歌纯真。。。现在我需要根据某个标识来判断 让明星唱歌,还是让孩子唱歌。简单粗暴的方法如下。
简单举一个Child的类,其他类类似
package com.yangs.reflect;
/**
* Created by Ytadpole on 2018/2/18.
*/
public class Child{
public void sing() {
System.out.println("小孩子的唱歌方式");
}
}
主逻辑代码
package com.yangs.reflect;
/**
* Created by Ytadpole on 2018/2/18.
*/
public class DynamicAndStaticTest {
public static void main(String[] args){
if("child".equals(args[0])){
Child child = new Child();
child.sing();
}else if("start_man".equals(args[0])){
StarMan starMan = new StarMan();
starMan.sing();
}
}
非反射弊端简单描述
首先这个程序,需要提前将 StarMan和Child这两个类都建立好,需要加载进入JVM中才能正常执行程序,否则程序编译上就不通过,这个也是传统的通过new方式来创建对象并执行相应的方法。倘若这个时候我需要添加一个MusicTeacher,那有需要在这个逻辑上添加新的if条件。
再说一点,如果 这个主判断 和 新类MusicTeacher是两个人开发,开发主判断的人 需要等待 开发MusicTeacher这个类完成。在MusicTeacher这个功能完成之前, 主逻辑都不能添加与其相关的代码。
那怎么解决?接下来就到 反射 和接口了。
反射
首先看主逻辑
package com.yangs.reflect;
/**
* Created by Ytadpole on 2018/2/18.
*/
public class DynamicAndStaticTest {
public static void main(String[] args){
try {
Class clazz = Class.forName("com.yangs.reflect.Child");
Child child = (Child) clazz.newInstance();
child .sing();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
先获取到对应的类类型Class,通过Class的API newInstance()得到对应的实例。这里返回处 有可能实例是Child的实例,也有可能是StarMan的实例,以及后续我们会新增更多的实例。还是要根据不同的情况,强制转化为不同的类实例,那这样就有问题。
这个时候我们就通过让我这些StarMan,Child实现于同一个**接口**SingAble,这就体现到接口的作用了。
接口配合反射
package com.yangs.reflect;
/**
* Created by Ytadpole on 2018/2/18.
*/
public interface SingAble {
void sing();
}
对应其他的Child类实现SingAble接口
package com.yangs.reflect;
/**
* Created by Ytadpole on 2018/2/18.
*/
public class Child implements SingAble{
@Override
public void sing() {
System.out.println("小孩子的唱歌方式");
}
}
这时主逻辑对应修改
package com.yangs.reflect;
/**
* Created by Ytadpole on 2018/2/18.
*/
public class DynamicAndStaticTest {
public static void main(String[] args){
try {
Class clazz = Class.forName("com.yangs.reflect.Child");
SingAble singAble = (SingAble) clazz.newInstance();
singAble.sing();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
再次简单描述
这样,通过反射,我们只需要用到哪个类就去加载哪个类,后续有新的MusicTeacher,也无需修改主逻辑代码,体现出设计的艺术。
同时,新增的MysicTeacher这些功能实现SingAble接口,也体现到接口的作用。各部分开发互补影响。
Class对应API还有其他许多功能自行查阅摸索。
8393

被折叠的 条评论
为什么被折叠?



