浅析Class类(反射机制原理)

来源:互联网 发布:mac登录不了app store 编辑:程序博客网 时间:2024/05/29 19:33

浅析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 错误: 找不到符号  符号:   类 WordOffice.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();        }

这样做还有一个好处就是我们以后对这个类不用做任何修改,只需要去修改实现类就行了,比如软件升级,程序员只需运行新添加的功能,不用去修改以前的代码,更不用重新编译.

所有功能性的类一般都使用动态加载而不是静态加载.