什么是反射机制?
正常情况下如果有一个类,则肯定可以通过类创建对象;那么如果现在要求通过一个对象
找到一个类的名称,此时就需要用到反射机制。如果要完成反射机制,则首先应该认识的
就是Class类。
在学习过程中的核心概念:“一切的操作都将使用Object完成,类、数组的引用都可以
使用Object进行接收”,只有把握这个概念才能更清楚地掌握反制机制的作用。
一、认识Class类
在正常情况下,需要先有一个类的完整路径引入之后才可以按照固定的格式产生实例化对象
,但是在Java中允许通过一个实例化对象找到一个类的完整信息,那就是Class类的功能。
提示:在用Eclipse时,的src文件夹下,建立包org.lxh.demo15.getclassdemo
例:通过一个对象得到完整的“包.类”名称
package org.lxh.demo15.getclassdemo ;
class X{
};
public class GetClassDemo01{
public static void main(String args[]){
X x = new X() ; // 实例化X类的对象
System.out.println(x.getClass().getName()) ; // 得到对象所在的类
}
};
输出:
org.lxh.demo15.getclassdemo.X
从程序中可以发现,通过一个对象得到了对象所在的完整的“包.类”名称,那么有些读者
会觉得奇怪,getClass()方法是哪里定义的呢?从之前学习到的知识读者知道,任何一个
类如果没有明确地声明继承自哪个父类的,则默认继承Object类,所以getClass()方法是
Object类中的,此方法如下:
public final Class getClass()
以上方法返回值的类型是一个Class类,实际上此类是Java反射的源头。所谓反射从程序的
运行结果来看也很好理解,即可以通过反射求出类的名称,如:
正常方式: 引入需要的“包.类”名称 --> 通过new实例化 --> 取得实例化对象
反射方式: 实例化对象 --> getClass()方法 --> 得到完整的“包.类”名称
图:反射过程
提示:所有类的对象实际上都是Class类的实例。
在Java中Object类是一切类的父类,那么所有类的对象实际上也就是java.lang.Class类
的实例,所以所有的对象都可以转变为lang.lang.Class类型表示。
在定义Class类时也使用泛型声明,所以为了让程序不出现警告信息,可以指定好其操作的
泛型类型,下面介绍Class类的作用。
Class本身表示一个类的本身,通过Class可以完整地得到一个类中的完整结构,包括此类
中的方法定义、属性定义等。
Class类的常用方法
(。。。)
在Class类中本身没有定义任何的构造方法,所以如果要使用则首先必须通过forName()方法
实例化对象。除此之外,也可以使用“类.class”或“对象.getClass()”方法实例化。
例:实例化Class类对象
package org.lxh.demo15.getclassdemo ;
class X{
};
public class GetClassDemo{
public static void main(String args[]){
Class> c1 = null ; //指定泛型
Class> c2 = null ;
Class> c3 = null ;
try{
c1 = Class.forName(
"org.lxh.demo15.getclassdemo.X") ;//最常用形式
}catch(ClassNotFoundException e){
e.printStackTrace() ;
}
c2 = new X().getClass() ; //通过Object类中的方法实例
c3 = X.class ; //通过类.class实例化
System.out.println("类名称:" + c1.getName());//得到类名称
System.out.println("类名称:" + c2.getName());//得到类名称
System.out.println("类名称:" + c3.getName());//得到类名称
}
};
输出:
类名称:org.lxh.demo15.getclassdemo.X
类名称:org.lxh.demo15.getclassdemo.X
类名称:org.lxh.demo15.getclassdemo.X
从程序的运行结果中可以发现,3种实例化Class对象的方式是一样的,但是使用forName()
的静态方法实例化Class对象的方式是较为常用的,应该重点掌握。
提示:使用forName()方法更加具备灵活性。
从以上程序的3种使用方式上可发现,除forName()方法外,其他的两种:“对象.getClass”
、“类.class”都需要导入一个明确的类,如果一个类操作不明确时,使用起来可能会受到
一些限制。但是forName()传入时只需要以字符串的方式传入即可,这样就让程序具备了更
大的灵活性,所以此种方式是最常用的。