最近在做项目用到spring 框架,好多功能只会用,却不知道其中的原理。如果让我写一个框架,我只会for循环、接口、类等一些教科书上前几章节的知识点。
毕竟从接触Java,做java项目到现在已经有一年,用的都是C#和Java通用的部分(以前读书的时候用C#写过毕业设计而已,都是皮毛,至少我是这样觉得的。)
为了能更好理解框架的实现原理,了解到Java有种机制叫“反射”,动态加载类、泛类型等都用到反射这个吊炸天的机制。
一,反射的初步认识
类的反射, 先看一段代码:
public static void main(String[] args) {
Foo foo = new Foo(); ///<
Class c1 = Foo.class; ///<获取Foo类的类类型
Class c2 = foo.getClass(); ///<获取foo对象的类类型
Class c3 =null;
try {
c3 = Class.forName("util.reflect.Foo");///<需要写完整的包名和类名
Foo foo2 = c3.newInstance(); ///< 创建Foo的对象
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(c1 == c2);
System.out.println(c2 == c3);
}
class Foo{
void print(){
System.out.println("我是Foo类的方法");
}
}
输出是:
true
true
为什么,明明c1和c2是不同对象(我一开始也是搞不明白)。
原来,在Java中,万事万物皆对象,除了我们new出来的对象,还有我们定义的类(其实它是Class的对象,类的类类型)。
所以c1, c2, c3 全部都是同一个类类型Foo,它们是Class的一个“唯一对象”(这么称呼是不对的,只是好理解)。 官方给出的解释:“c1和c2表示Foo类的类类型”
以上,就是对类的放射的初步认识。它们怎么用呢?
二,动态加载类和静态加载类
先来看看,一年前我写的代码(不忍直视啊。。。),有三个文件:Office.java, Excel.java, Word.java
Office.java
class Office{
public static void main(String[] args){
if("Word".equals(args[0])){
Word w = new Word();
w.start();
}
if("Excel".equals(args[0])){
Excel e = new Excel();
e.start();
}
}
}
Word.java
class Word{
public void start(){
System.out.println("word start...");
}
}
Excel.java
class Excel{
public void start(){
System.out.println("excel start...");
}
}
从编译到运行,没什么问题。仔细一想,就有好多潜在的问题:
1) 对于Office.java 而已,如果我只用Word类,是必须要把Word类和Excel类都定义出来,不然编译都不通过;
2)后续拓展,如果我要加一个PPT类,除了手动添加一个PPT类,我还得改原来得Office代码,而且是复制粘贴一小段代码;
3)静态加载的坏处等等。。
经过K书,看视频,查别人写得博客,我把代码改进了一下,有四个文件:OfficeBetter.java, Excel.java, Word.java, OfficeAble.java,
OfficeBetter.java
class OfficeBetter{
public static void main(String[] args){
try{
Class c = Class.forName(args[0]); ///<获取第一参数的类类型
//System.out.println(args[0]);
OfficeAble oa = (OfficeAble) c.newInstance(); ///<新建一个对象
oa.start();
}catch(Exception e){
e.printStackTrace();
}
}
}
OfficeAble.java
interface OfficeAble{
///< 指定一套标准
public void start();
}
Word.java
class Word implements OfficeAble{
public void start(){
System.out.println("word start...");
}
}
Excel.java
class Excel implements OfficeAble{
public void start(){
System.out.println("excel start...");
}
}
这样子写了之后,有几点好处:
1) 就算没有word类和Excel类,OfficeBetter类依旧可以编译通过;
2) 如果添加一个PPT类,只需增加一个PPT类并实现OfficeAble这个接口即可,不用修改OfficeBetter类;
3)动态加载的好处等等。。