浅析Class类(反射机制原理)
本文总结自网上视频(讲的很详细)
视频链接地址:http://www.imooc.com/learn/199
原文地址:http://blog.csdn.net/zxpmojoker
一.万事万物皆对象
1.静态成员不是对象
静态成员属于类,不属于对象
2.普通数据类型也不属于对象
3.类本身也是对象,是属于java.lang.Class类的实例对象
二.Class对象如何表示
现在有一个类
class Person{
public void print(){
System.out.println("Person");
}
}
Person的实例对象如何表示
Person person = new Person();//person代表Person的实例,可以new出来
Person 这个类也是一个实例对象,是 java.lang.Class 的实例对象,如何表示?
Class类的构造方法是私有的,只有JVM能创建类对象
所以任何一个类都是Class的实例对象,这个实例对象一共有3种表示方式
1.第一种(知道类名): 可以知道任何一个类都有一个隐含的静态成员变量class
Class clazz1 = Person.class;
2.第二种(知道对象名):已经知道该类的对象,通过getClass方法
Class clazz2 = person.getClass();
clazz1 和 clazz2 表示了 person类的类类型(class type)
话句话就是:类也是对象,是Class的实例对象,这个对象我们称为该类的类类型,一个类只能是Class类的一个实例对象.
3.第三种表达方式
Class clazz3 = null;
clazz3 = Class.forName("com.class.reflect.Person");//写类名全称
这样我们就可以通过类的类类型创建该类的对象实例--->通过clazz1 或 clazz2 或 clazz3 创建Person的实例
Person person = (Person)clazz3.newInstance();//需要有无参构造方法
三.动态加载类
Class.forName("类名全称")
先来体会下静态加载类
注:这里是在文件里边编写代码
首先创建一个Office.java文件
public class Office {
public static void main(String[] args) {
if ("World".equals(args[0])){
Word w = new Word();
w.start();
}
if ("Excel".equals(args[0])){
Excle e = new Excel();
e.start();
}
}
}
编译Office.java文件
Office.java:7 错误: 找不到符号
符号: 类 Word
Office.java:12 错误: 找不到符号
符号: 类 Excle
会告诉我们Word和Excel都找不到(这是理所当然的,因为我没写Word类和Excel类),但是我们可以想一下,Word和Excel我们一定用的到吗?
再创建出Word类
public class Word {
public void start(){
System.out.println("Word");
}
}
再编译Office.java文件
Office.java:12 错误: 找不到符号
符号: 类 Excle
依然会有提示找不到Excel类
但是Word存在了,我们想用Word,但是用不了,原因是现在类是静态加载的.
new创建的对象是静态加载类,在编译时刻就需要加载所有可能使用到的类,也就是说如果我们这个程序如果有很多个功能,只要有一个功能有问题,其他的功能全都用不了,而这不是我们期望看到的.这就是静态加载.
而通过动态加载类,我们就可以解决该问题
进行动态加载类
创建OfficeBetter.java文件
public class OfficeBetter {
public static void main(String[] args) {
try {
//动态加载类,在运行时刻
Class c = Class.forName(args[0]);
} catch (Exception e) {
e.printStackTrace();
}
}
}
编译OfficeBetter.java文件,不会报错
接下来通过类类型, 创建该类对象:
try {
//动态加载类,在运行时刻
Class c = Class.forName(args[0]);
//通过类类型, 创建该类对象
(强制类型转换)c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
强制类型转换这又有一个新的问题,如果强转的是Word,而加载的是Excel怎么办,反之,如果强转的是Excel,加载的是Word又怎么办?
为了能让Word和Excel都能用,就要统一标准,比如都叫OfficeAble:
public interface OfficeAble {
void start();
}
然后让Word和Excel都实现OfficeAble这个接口就OK了
try {
//动态加载类,在运行时刻
Class c = Class.forName(args[0]);
//通过类类型, 创建该类对象
OfficeAble officeAble = (OfficeAble) c.newInstance();
officeAble.start();
} catch (Exception e) {
e.printStackTrace();
}
这样做还有一个好处就是我们以后对这个类不用做任何修改,只需要去修改实现类就行了,比如软件升级,程序员只需运行新添加的功能,不用去修改以前的代码,更不用重新编译.
所有功能性的类一般都使用动态加载而不是静态加载.