首页 > 代码库 > Java反射机制

Java反射机制

 

 

Class类

1)在面向对象的世界里,万事万物皆对象。Java语言中,静态的成员、普通数据类型不是对象,其他的都是对象。而普通数据类型采用了包装类进行了弥补。我们写的每一个类,类实例化后可以得到一个对象。那么,类是不是对象呢?类是谁的对象呢?类是哪个类的对象呢?我们说,万事万物皆对象,我们写的每一个类,我们所提供的每一个类,也是对象,类是java.lang.Class类的实例对象。比如,写一个A类,它是Class类的实例对象。我写一个Student类,它也是Class类的实例对象。表述这个有一句话叫做“There is a class named Class”。现在有一个类,名字就叫做类。现在有一个类,它的名字就是Class。那么它的实例是什么呢?我们的每一个对象所属的类,就是它的实例。

2)这个对象到底如何表示呢?我们现在要写一个案例,就是要表示Class类的实例,

class Foo{}

这个Foo类就是一个对象。万事万物皆对象。谁的对象?java.lang.Class的实例对象。

那么,Foo的实例对象如何表示?

Foo foo1 = new Foo();

那么,我们知道Foo这个类也是一个对象,Class类的实例对象,如何表示呢?

我们可以看到,Class类的构造:

/*Constructor. Only the Java Virtual Machine creates Class objects.  */

private Class(){}

是私有的构造函数,在类的外部是不能访问的。我们没有办法来直接创建这个对象。

任何一个类都是Class的实例,这个实例对象有三种表示方式。

第一种方式:  实际也在告诉我们,任何一个类都有一个隐含的静态成员变量class

Class c1 = Foo.class;

第二种表达方式: 已经知道该类的对象通过getClass方法

Class c2 = foo1.getClass();

注意,这点很容易混淆。foo1代表的是Foo的实例对象,c1,c2代表的是Class的实例对象,但这个对象本身说明Foo这个类是一个实例对象。官网上的说明为c1,c2表示了Foo类的类类型(class type)。Foo类的类类型指的就是,Foo这个类本身它就是一个对象,哪个类的对象?Class类的对象。我们说类类型指的是本身自己就是一个Class类的实例。但是Foo这个类本身也有实例对象,那就是Foo这个类的实例对象。这就和Foo类的类类型进行分开了。类类型指的是万事万物皆对象,类也是一个对象。这个对象,我们把它称之为类类型。

c1 == c2 //true

不管c1  or  c2都代表了Foo类的类类型,一个类只可能是Class类的一个实例对象。

如果知道类名的话,可以采用.class,如果知道对象的话可以采用getClass()

第三种表达方式: 

Class c3 = null;

try{

   c3 = Class.forName("com.reflext.Foo");  //这里是类的全称,包含了package在内

} catch (ClassNotFoundException e) {

   e.printStackTrace();

}

c2 == c3 // true

以上把Class的概念弄清楚了。

我们完全可以通过类的类型创建该类的对象实例。也就是通过c1 or c2 or c3创建Foo的实例

这个c1如果是A类的类类型,那么创建出来的就是A类的实例对象,如果是B类的类类型,那么创建出来的就是B类的实例对象。现在它是Foo类的类类型,那么创建出来的就是Foo类的实例对象。

所以这个地方需要做强制类型转换。

Foo foo = (Foo)c1.newInstance();  //需要有无参数的构造方法

 

动态加载类

Class.forName("类的全称")

不仅表示了类的类型,还代表了动态加载类

一定要区分编译,运行

编译时刻加载类是静态加载类,运行时刻加载类是动态加载类

class Office {
    public sataic void main(String[] args) {
    if("Word".equals(arg[0])){
      Word w = new Word();
      w.strat();
    }
    if("Excel".equals(arg[0])){
      Excel e = new Excel();
      e.strat();
    }
  }
}

  如果编译这个程序,会发现报错,提示两个类和两个方法找不到。如果再写一个Word类并编译,那么回头编译Office,仍然会提示2个错误,Excel类和run方法找不到。这是因为:new创建对象 是静态加载类,在编译时刻就需要加载所有的可能使用到的类。即便不适用Excel,即便Word已经存在,仍然无法使用Office程序。那么在实际应用中,我们当然希望Word存在,Word就能够使用,而现在Word虽然存在,却因为Excel不存在,造成了Word无法使用。如果将来有100个功能,只要有一个功能有问题,那么就会造成另外的99个功能不能使用,显然,这种情形不是我们所希望看到的。我们所希望看到的功能是,你用哪个,就加载哪个。不用不加载。所以我们希望在运行时进行加载。通过动态加载类,可以解决该问题。

 

Java反射机制