一、反射的概念
反射是java语言提供的一项非常吸引人的特性,利用反射可以在运行时对程序进行动态的控制。开发使用反射特性的程序需要使用一套专门的工具类,这些类大部分都位于java.lang.reflect包中。
二、Class类
Class类属于java.lang包,不需要使用import语句引入特殊的包就可以使用,其对象代表一个类,携带类的相应信息,主要包括构造器、方法、成员变量等。其实,java程序运行过程中,每个类被加载都在内存中产生一个对应的Class类对象,在普通应用程序中这些对象是由系统自动维护的,开发人员不需要关心。
1、对类和对象的理解
(1)在面向对象的世界里,万事万物皆对象
(2)java语言中静态的成员、普通数据类型类不是对象。
(3)类是对象,类是java.lang.Class类的实例对象。(任何一个类都是Class的实例对象)
2、任何类都是Class的实例对象,这个实例对象有三种表示方式(可以通过三种方式获取Class类对象)
类类型不可以使用Class类的构造器来创建Class类对象,只能使用其提供的静态工厂方法来获取对象。
(1)实际上,在告诉我们任何类都有一个隐含的静态成员变量Class,所以可以通过下面方式获取Class类对象
Class c1=FOO.class; // FOO是一个类
(2)已知一个类的实例对象,通过getClass方法获取Class类对象
1 FOO foo=new FOO();
2 Class c1=foo.getClass();
注:c1,c2都代表了FOO类的Class类对象,但是一个类只可能是Class类的一个实例对象。
1 package Reflect; 2 3 public class Test { 4 5 public static void main(String[] args) { 6 FOO foo=new FOO(); 7 Class c=foo.getClass(); 8 Class c1=FOO.class; 9 System.out.println(c1==c); 10 } 11 }
运行结果:
true
(3)通过Class.forName(String className),className指出类的全称名。,如果找不到,就会抛出ClassNotFoundException异常
1 try { 2 Class c3=Class.forName("Reflect.FOO"); 3 } catch (ClassNotFoundException e) { 4 // TODO Auto-generated catch block 5 e.printStackTrace(); 6 } 7 }
3、Class类的常用方法
Class类没有构造方法,所以很自然创建Class类对象,不能通过构造器来创建,而只能通过其提供的静态工厂方法来获取对象。Filed、Method、Constructor为java.lang.reflect包的类,它们分别代表了成员变量、方法、构造器,分别携带对应成员变量、方法、构造器信息。package类在java.lang包中,其对象代表一个包,携带相应包的信息。
Class类的常用方法表
方法关键字 |
含义 |
public Method[] getDeclaredMethods() |
获取声明的所有的方法 |
public Method getDeclaredMethod("方法名",参数类型.class,……) |
获得特定的方法 |
public Constructor[] getDeclaredConstructors() |
获取所有声明的构造方法 |
public Constructor[] getConstructors() |
获取所有的构造方法 |
public Constructor getDeclaredConstructor(参数类型.class,……) |
获取特定的构造方法 |
public Field[] getFields() |
获取所有成员变量 |
public Field[] getDeclaredFields() |
获取所有声明的成员变量 |
public Field getField(String name) |
获取指定的成员变量 |
public Package getPackage() |
返回Class对象所对应类所在的包 |
public String getName() |
返回Class对象对应类的名称 |
public static Class forName(String className) |
通过此方法获取指定名称的类对应的Class对象,className指出类的全名称 |
Public Object newInstance() |
调用默认的无参构造器新建Class对象对应类的一个对象。 |
注:标红的两个方法是Class类实现动态加载类的核心方法。
通过newInstance()方法创建的对象与普通方式创建的对象在使用上完全相同(区别:用于动态加载类后的实例化)。
代码示例:
1 package Reflect; 2 3 public interface OfficeAble { 4 5 public void start(); 6 } 7 8 9 package Reflect; 10 11 public class Word implements OfficeAble { 12 13 private String name; 14 private String gender; 15 public Word() { 16 System.out.println("word的构造方法1~~"); 17 } 18 19 public Word(String name,String gender) { 20 this.name=name; 21 this.gender=gender; 22 System.out.println("word的构造方法1~~"+name+" "+gender); 23 } 24 25 @Override 26 public void start() { 27 System.out.println("word..start......."); 28 } 29 30 public void start1() { 31 System.out.println("word..start1......."); 32 } 33 34 } 35 36 package Reflect; 37 38 import java.lang.reflect.Constructor; 39 import java.lang.reflect.Field; 40 import java.lang.reflect.Method; 41 42 public class OfficeBetter { 43 44 public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { 45 //动态加载类,在运行时刻加载 46 Class c=Class.forName("Reflect.Word"); 47 //通过类类型,创建该类对象 48 OfficeAble oa=(OfficeAble) c.newInstance(); 49 oa.start(); 50 51 //获取Word类中所有构造函数对象,所有成员变量对象,所有方法对象 52 Constructor []cs=c.getConstructors(); 53 Field []fd=c.getFields(); 54 Method []md=c.getMethods(); 55 56 //遍历构造函数对象,成员变量对象,方法对象,打印他们的信息 57 for (Method method : md) { 58 System.out.println(method.getName()+" "+method.getParameterCount()); 59 } 60 61 for (Field field : fd) { 62 System.out.print(field.getName()+" "); 63 } 64 System.out.println(); 65 66 for (Constructor constructor : cs) { 67 System.out.println(constructor.getName()+" "+constructor.getParameterCount()); 68 } 69 } 70 71 }
运行结果:
1 word的构造方法1~~ 2 word..start....... 3 start 0 4 start1 0 5 wait 0 6 wait 2 7 wait 1 8 equals 1 9 toString 0 10 hashCode 0 11 getClass 0 12 notify 0 13 notifyAll 0 14 15 Reflect.Word 0 16 Reflect.Word 2