JAVA学习之反射以及Class类的常用方法

Class类

Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。

Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。

取得某一个类的Class类实例方法一般情况下可以用以下三种方法;

class test
{
public static void main(String[] args) throws Exception{
Class a=Class.forName("MyClass");
Class b=MyClass.class;
Class c=new MyClass().getClass();
System.out.println(a==b);//输出true
System.out.println(c==b);//输出true
}
}
class MyClass{
public void print(String value){
System.out.println(value);
}
}

如上代码所示,

第一种,使用Class.forName()方法,该方法返回与带有给定字符串名的类或接口相关联的 Class 对象。

第二种,直接使用对应类的class属性,

第三种,使用某个类的实例化对象的getClass()方法,这个方法是在java.lang.Object的上帝类中定义的,功能是返回此 Object 的运行时类

这三种方法取得的Class对象是同一个引用,也就是说,这三种方法取得的Class对象都是一样的.

或许还有其他方法,不过这三个方法就够用了吧,

关于Class对象的常用方法有很多,下面对应着对Class对象的用法,一边使用一边介绍.

1.根据Class对象取得这个类的方法,包括自己定义的方法和继承过来的方法

getMethods() ,返回类型 Method[]

返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。

getDeclaredMethods() ,返回类型 Method[]

返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。

getMethod(String name, Class<?>... parameterTypes)

返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。

getDeclaredMethod(String name, Class<?>... parameterTypes)

返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。

……

取得Method对象后,就可以使用Method的API方法了,

比如Invoke()调用方法,getName()取得这个方法的名字,getParameterTypes() 取得这个方法的签名类型,getReturnType() 取得这个方法的返回类型......

//使用方法之1
import java.lang.*;
import java.lang.reflect.*;
class FanShen//反射
{
public void print(String value){
System.out.println(value);
}
}
class Test
{
public static void main(String[] args)throws Exception{
Class c=Class.forName("FanShen");//取得类FanShen的一个类对象
Method m=c.getMethod("print",String.class);//根据方法的名字和方法签名(参数类型),取得一个方法
m.invoke(c.newInstance(),"打印情况");//调用新实例的这个方法

}
}

2.根据类对象,取得这个类的字段,并且可以更改字段的值

getField(String name)

返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。

getFields()

返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。

getDeclaredField(String name)

返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。

getDeclaredFields()

返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。

//使用方法之二
import java.lang.*;
import java.lang.reflect.*;
class FanShen//反射
{
private int f1;//新添加的三个字段
private int f2;//新添加的三个字段
public int f3; //新添加的三个字段
public void print(String value){
System.out.println(value);
}
}
class Test
{
public static void main(String[] args)throws Exception{
Class c=Class.forName("FanShen");//取得类FanShen的一个类对象
Method m=c.getMethod("print",String.class);//根据方法的名字和方法签名(参数类型),取得一个方法
m.invoke(c.newInstance(),"打印情况");//调用新实例的这个方法
Field[] f=c.getDeclaredFields();
for(int i=0;i<f.length;i++)
{
//输出字段的类型的字段的名称
System.out.println(""+f[i].getType()+" "+f[i].getName());
}
Field f3=c.getField("f3");//取得一个f3字段的对象
FanShen fs=new FanShen();//实例化一个对象,并给字段赋值
fs.f3=8;
f3.set(fs,88888);//用这个字段,并对fs对象修改
System.out.println(fs.f3);//已经修改为88888 
 }
}

3.取得方法后,可以用Method的invoke()方法来调用这个类的指定方法,Method类是在包java.lang.reflect.Method中的,在使用时要记得导入包.

这个类的方法也是有不少,常用的有getName(),

getDeclaringClass()

返回表示声明由此 Method 对象表示的方法的类或接口的 Class 对象。

getModifiers()

以整数形式返回此 Method 对象所表示方法的 Java 语言修饰符。

getReturnType()

返回一个 Class 对象,该对象描述了此 Method 对象所表示的方法的正式返回类型。

getParameterTypes()

按照声明顺序返回 Class 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型。

invoke(Object obj, Object... args)

对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。

......等其它方法,下面的代码示例写的是用反射的方法来调用一个类的方法,并取得返回值打印输出.

//第三
import java.lang.*;
import java.lang.reflect.*;
class FanShen//反射
{
public void print(String value)
{
System.out.println(value);
}
//新添加一个方法,连接两个字符串
public String addString(String arg1, String arg2) {
String r=arg1 + arg2;
return r;
}
}
class Test
{
public static void main(String[] args)throws Exception
{
Class c=Class.forName("FanShen");//取得类FanShen的一个类对象
Method m=c.getMethod("print",String.class);//根据方法的名字和方法签名(参数类型),取得一个方法
Class[] sign=new Class[2];//方法签名数组
sign[0]=String.class;
sign[1]=String.class;
Method addString=c.getMethod("addString",sign);
System.out.println(addString.getName());
//调用方法,并接收方法返回的值
String result=(String)addString.invoke(c.newInstance(),new Object[]{"第一个参数 ","第二个参数"});
System.out.println(result);
}
}

反射的用法当然远远不止这一些,想法有多远,就能走多远,Class类的方法还有其它好多好多,还有其它取得抛出异常的方法,取得方法修饰符的方法,等,这里就不全部写出来了

工厂方法模式里面就有用到反射来生成子类的用法,具体的在其他的学习日记里有了.这里就不重复了.

  一边写一边复习,写了大半天,不容易啊.