这里并不对Class类对象中的方法进行过多描述,直接以案例来讲一下反射的作用,如果想了解反射可以先看这篇https://blog.csdn.net/weixin_43400205/article/details/99759760
顺带给观众老爷们附上反射API一份:http://tool.oschina.net/apidocs/apidoc?api=jdk-zh
例:
比如说我们现在有一个项目是举办一个晚会:晚会的流程是开始—节目表演----结束
我们先创建一个Party类
public class Party {
public static void main(String[] args) {
System.out.println("晚会开始");
System.out.println("cxk唱歌:鸡你太美");
System.out.println("Hjx跳舞:Popping");
System.out.println("晚会结束");
}
}
既然我们用的是java,肯定不能这样写,要用面向对象的思维去写代码,代码都放到主业务类里面肯定是不行的,这种紧耦合会造成代码的拓展性和维护性很差,那么我们把节目封装成对象,通过new对象的形式来达到效果
public class Cxk{
// Cxk类,有sing的方法
public void sing() {
System.out.println("cxk唱歌:鸡你太美");
}
}
public class Hjx {
//Hjx类,有跳舞的方法
public void dance() {
System.out.println("Hjx跳舞:Popping");
}
}
那么现在我们主业务类的代码应该是
public class Party {
public static void main(String[] args){
System.out.println("晚会开始");
Cxk cxk = new Cxk();
cxk.sing();
Hjx hjx = new Hjx();
hjx.dance();
System.out.println("晚会结束");
}
}
按理说我们应该这样写,但是问题来了,客户要修改需求,不要Cxk来了,换成电鳗来,那么我们要创建一个电鳗类,new他的对象,调用他的方法
public class Wyf{
public void sing() {
System.out.println("Wyf电音:大碗面宽");
}
}
此时的主业务类变成了
public class Party {
public static void main(String[] args){
System.out.println("晚会开始");
//Cxk cxk = new Cxk();
//cxk.sing();
Wyf wyf = new Wyf();
wyf.sing();
Hjx hjx = new Hjx();
hjx.dance();
System.out.println("晚会结束");
}
}
需求是解决了,但是问题又来了,如果需求再次更改,那么我还要再写那么多,用什么可以减少代码修改量呢,这时候我们发现,cxk和电鳗都是歌手,有共同的方法唱歌,我们可以把他们共有的方法抽出来,我们使用多态的方式来减少代码修改量,创建一个接口Singer定义一个方法sing
public interface Singer {
public void sing();
}
Cxk和Wyf分别实现这个接口,重写sing方法
public class Cxk implements Singer{
@Override
public void sing() {
System.out.println("cxk唱歌:鸡你太美");
}
}
public class Wyf implements Singer {
@Override
public void sing() {
System.out.println("Wyf电音:打完面宽");
}
}
这是我们的主业务类就是
public class Party {
public static void main(String[] args){
System.out.println("晚会开始");
//如果我们需要变更选手,只需要把Cxk变成Wyf就行
Singer singer = new Cxk();
singer.sing();
Hjx hjx = new Hjx();
hjx.dance();
System.out.println("晚会结束");
}
}
通过使用多态,我们变更需求需要修改两行代码,现在只需要修改一下new的实现类,但是改多改少终归是改了主业务类,我们能否在不修改主业务类的情况下实现需求变更?这时我们可以使用工厂模式,创建一个晚会工厂
public class PartFactory {
//因为不需要实例化,我们将getSinger定义成静态的
//通过getSinger方法返回一个歌手对象
//当然我们还可以写dancer对象,都是一样的,就不写了
public static Singer getSinger(){
Singer singer = new Cxk();
return singer;
}
}
主业务类的代码现在就是
public static void main(String[] args){
System.out.println("晚会开始");
Singer singer = PartFactory.getSinger();
singer.sing();
Hjx hjx = new Hjx();
hjx.dance();
System.out.println("晚会结束");
}
}
如果我们要更换选手,只需要将工厂中的new Cxk()换成new Wyf(),主业务类中代码不用更改,但是现在还有个问题,更改代码,就意味着要重新编译,重新编译就要重新启动,就意味着要停服更新,相信每一个玩家都体会过停服更新的痛苦,那么我们如何做到不用重启服务器就实现需求的变更呢?现在引入主角:反射,我们将工厂类的代码改一改
public class PartFactory {
public static Singer getSinger() throws Exception {
//通过Class.forName(完全限定名)的方式来获取该类的Class对象
Class<?> clazz = Class.forName("com.xy.party.Cxk");
//使用类对象中的newInstance方法创建该类的实例对象
//强转一下,抛出异常
Singer singer = (Singer) clazz.newInstance();
return singer;
}
}
现在我们修改的话,只需要修改字符串就行了,虽然还没有达到效果,但是从修改代码变成了修改字符串,字符串我们可以放到文件中,我们把字符串放到一个properties文件中,读取文件就行了,代码需要编译,文件不需要编译,不需要编译就意味着不用重启服务器,就不用管停机更新,可以不停机更新
首先创建一个properties文件,写上键和值
singer=com.xy.party.Wyf
同时工厂中的代码变成了
public class PartFactory {
public static Singer getSinger() throws Exception {
InputStream in = PartFactory.class.getResourceAsStream("/party.properties");
Properties pro = new Properties();
pro.load(in);
String className = pro.getProperty("singer");
Class<?> clazz = Class.forName(className);
Singer singer = (Singer) clazz.newInstance();
return singer;
}
}
主业务类中的代码还是
public class Party {
public static void main(String[] args) throws Exception {
System.out.println("晚会开始");
Singer singer = PartFactory.getSinger();
singer.sing();
Hjx hjx = new Hjx();
hjx.dance();
System.out.println("晚会结束");
}
}
这时候我们修改需求,只需要修改properties配置文件中的内容就可以,不需要修改代码,不需要重新编译,就像写web项目,无论我们修改静态代码还是动态代码,都需要重新部署一下,但是如果我们修改的是数据库里面的数据,那么只要刷新一下页面就行了