Java反射机制
反射机制的基础:
在Java中Object类是一切类的父类,因此所有类的对象实际上也就都是java.lang.Class类的实例,所有对象都可以转变为java.lang.Class类型表示。
Class表示一个类的本身,通过Class可以完整地得到一个类中的完整结构,包括此类中的方法定义、属性定义等,常用操作如下:
public static Class<?> forName(String className) throws ClassNotFoundException 传入完整的“包.类”名称实例化Class对象
public Constructor[] getConstructors() throws SecurityException 得到一个类中的全部构造方法
public Field[] getDeclaredFields[] throws SecurityException 得到本类中单独定义的全部属性
public Field[] getFields() throws SecurityException 取得本类继承而来的全部属性
public Method[] getMethods() throws SecurityException 得到一个类中的全部方法
public Method getMethod(String name,Class...parameter Types) throws NoSuchMethodException, SecurityException 返回一个Method对象,并设置一个方法中的所有参数类型
public Class[] getInterfaces() 得到一个类中所实现的全部接口
public String getName() 得到一个类完整的“包.类”名称
public Package getPackage() 得到一个类的包
pubilc Class getSuperclass() 得到一个类的父类
public Object newInstance() 根据Class定义的类实例人对象
public Class<?> getComponentType() 返回表示数组类型的Class
public boolean isArray() 判断此Class是否是一个数组
实例化Class类对象的三种方法
package com.yuchao.reflect;
class X
{
}
public class Reflection {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Class<?> class1=null;
Class<?> class2=null;
Class<?> class3=null;
try {
class1=Class.forName("com.yuchao.reflect.X");
} catch (ClassNotFoundException e) {
// TODO: handle exception
e.printStackTrace();
}
class2=new X().getClass();
class3=X.class;
System.out.println("类名称:"+class1.getName());
System.out.println("类名称:"+class2.getName());
System.out.println("类名称:"+class3.getName());
}
}
从程序的运行中可以发现,3种实例化Class对象的方法是一样的,但是使用forName()的静态方法实例化Class对象是较为常用的一种方式。
Class类的使用
Class类在开发中最常见的用法就是实例化对象的操作,即可以通过一个给定的字符串来实例化一个类的对象。
通过无参构造实例化对象
package com.yuchao.reflect;
class Person
{
private String name;
private int age;
public String getName()
{
return this.name;
}
public void setName(String name)
{
this.name=name;
}
public int getAge()
{
return this.age;
}
public void setAge(int age)
{
this.age=age;
}
public String toString()
{
return "姓名:"+this.name+";"+"年龄:"+this.age;
}
}
public class ClassInstance {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stubC
Class<?> class1=null;
try {
class1=Class.forName("com.yuchao.reflect.Person");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
Person person=null;
try {
person=(Person)class1.newInstance();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
person.setName("yuchao");
person.setAge(25);
System.out.println(person);
}
}
程序运行结果:
姓名:yuchao;年龄:25
Class.forName()方法实例化Class对象之后,直接调用newInstance()方法就可以进行对象的实例化操作。但要注意的是,被实例化对象的类中必须存在无参构造方法,如果不存在则肯定是无法实例化的。在实际的Java程序开发中,反射是最为重要的操作原理,在现在的开发设计中大量地应用了反射处理机制,如Struts、Spring框架等;在大部分的操作中基本上都是操作无参构造方法,所以使用反射开发时类中尽量保留无参的构造方法。
调用有参构造实例化的对象
如果没有无参构造方法,就一定不能进行实例化对象操作吗?答案是否定的,只要在操作时明确地调用类中的构造方法,将参数传递进去同样可以进行实例化操作。操作步骤如下:
1.通过Class类中的getConstructors()取得本类中的全部构造方法;
2.向构造方法中传递一个对象数组进行,里面包含了构造方法中所需的各个参数;
3.之后通过Constructor实例化对象
package com.yuchao.reflect;
import java.lang.reflect.Constructor;
class Person
{
private String name;
private int age;
public Person(String name,int age)
{
this.name=name;
this.age=age;
}
public String getName()
{
return this.name;
}
public void setName(String name)
{
this.name=name;
}
public int getAge()
{
return this.age;
}
public void setAge(int age)
{
this.age=age;
}
public String toString()
{
return "姓名:"+this.name+";"+"年龄:"+this.age;
}
}
public class ClassInstance {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stubC
Class<?> class1=null;
try {
class1=Class.forName("com.yuchao.reflect.Person");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
Person person=null;
Constructor<?> constructons[]=null;
constructons=class1.getConstructors();
try {
//person=(Person)class1.newInstance();
person=(Person)constructons[0].newInstance("yuchao",25);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
System.out.println(person);
}
}
程序运行结果:
姓名:yuchao;年龄:25
以上代码虽然已经完成了对象的实例化过程,但是代码比较复杂,因此在实际开发中尽量保留无参的构造函数。
反射的应用-取得类的结构
java.lang.reflect包中有以下几个类:Constructor、Field、Method
通过以下几个类和Class类就可以共同完成类的反射操作。
取得所实现的全部接口
package com.yuchao.reflect;
interface China
{
public static final String NATIONAL_STRING="China";
public static final String AUTHOR_STRING="yuchao";
public void sayChina();
public String sayHello(String name,int age);
}
class Person implements China
{
private String name;
private int age;
public Person()
{
}
public Person(String name,int age)
{
this.name=name;
this.age=age;
}
public String getName()
{
return this.name;
}
public void setName(String name)
{
this.name=name;
}
public int getAge()
{
return this.age;
}
public void setAge(int age)
{
this.age=age;
}
public String toString()
{
return "姓名:"+this.name+";"+"年龄:"+this.age;
}
@Override
public void sayChina() {
// TODO Auto-generated method stub
System.out.println("作者:"+AUTHOR_STRING+",国籍:"+NATIONAL_STRING);
}
@Override
public String sayHello(String name, int age) {
// TODO Auto-generated method stub
return name+",你好!我今年"+age+"岁了!";
}
}
public class ClassInstance {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stubC
Class<?> class1=null;
try {
class1=Class.forName("com.yuchao.reflect.Person");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
Class<?> class2[]=class1.getInterfaces();
for(int i=0;i<class2.length;i++)
{
System.out.println("实现的接口名称:"+class2[i].getName());
}
}
}