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());
}
}

}
取得父类,只需将class1.getInterfaces()改成class1.getSuperClass()、class.getConstructors()、class1.getConstructors()[0].getModifiers()


posted on 2011-02-28 10:33  弱弱的风  阅读(1270)  评论(0编辑  收藏  举报

导航