最近学习的内容,怎么都是离不开反射,可一直对反射的理解一知半解的,不够系统。今天认真地学习了一下反射,下面做个总结。
反射是用来做什么的
java程序中的许多对象在运行时都会出现两种类型:编译是类型和运行时类型,例如代码:Person p = new Student();这行代码将会生成一个p变量,该变量的编译时类型为Person,运行时类型为Student;除此之外,还有更极端的情形,程序在运行时接收到外部传入的一个对象,该对象的编译时类型为Object,但程序又需要调用该对象运行时类型的方法。那么,这些问题怎么解决呢?
编译时无法预知该对象和类可能属于哪些类,但程序可以依靠运行时的信息来发现该对象和类的真实信息,然后使用反射来解决。
反射的核心
先来理解一下Class对象。我们都知道,类是某一类对象的抽象,类是概念层次的东西。但不知道有没有想过,类也是一种对象。就像我们说概念主要用于定义、描述其他事物,但概念本身也是一种事物,那么概念本身也需要被描述——这有点像一个哲学命题。但是事实就是这样,每个类是一批具有相同特征的对象的抽象,而系统中所有的类实际上也是实例,他们都是java.lang.Class的实例。
当类被加载后,系统就会为给类生成一个对应的Class对象。通过该Class对象就可以访问到JVM中的这个类。在java程序中获得Class对象通常有三种方式。使用Class类的forName(String clazzName)静态方法。该方法需要传入字符串参数,该字符串参数的值是某个类的全限定类名。
调用某个类的class属性来获取该类对应的Class对象。
调用某个对象的getClass()方法。该方法是java.lang.Object类中的一个方法,所以所有的java对象都可以调用该方法,该方法返回该对象所属类对应的Class对象。
我们获得了Class对象,调用该对象的一系列方法就可以获得运行时需要的信息,从而解决问题。
反射的优缺点
优点:可以实现动态创建对象和编译,体现出很大的灵活性。
缺点:对性能有影响。尽管反射非常强大,但也不能滥用。
反射的基本使用
首先是基础代码,我们定义一个接口及其实现,作为我们反射操作的目标:
interface HelloWorldService
{
void sayHello(String name);
}
class MyHelloWorld implements HelloWorldService
{
public String name;
public void sayHello(String name)
{
System.out.println("Hello " + name + ".");
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
实例化对象:
private static void createInstanceTest() throws ClassNotFoundException, InstantiationException, IllegalAccessException
{
Class classType = Class.forName("sample.reflection.MyHelloWorld");
MyHelloWorld hello = (MyHelloWorld)classType.newInstance();
hello.sayHello("Zhang San");
}
获取方法及字段信息:
private static void printClassTypeInfo(String type) throws ClassNotFoundException
{
Class classType = Class.forName(type);
Method[] methods = classType.getDeclaredMethods();
System.out.println("Methods info as below:");
for(Method method : methods)
{
System.out.println(method.toGenericString());
}
Field[] fields = classType.getFields();
System.out.println("Fields info as below:");
for (Field field : fields)
{
System.out.println(field.toGenericString());
}
}
调用对象的方法:
private static void invokeMethodTest() throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException
{
Class classType = Class.forName("sample.reflection.MyHelloWorld");
MyHelloWorld hello = (MyHelloWorld)classType.newInstance();
Method method = classType.getMethod("sayHello", new Class[]{String.class});
method.invoke(hello, new Object[]{"Zhang San"});
}