建议在阅读本文之前,先理解Java反射机制的原理,再结合案例进行理解。
反射代码案例
【案例1】通过一个对象获得完整的包名和类名
package 反射Reflect;
class Demo{
//other codes...
}
class Hello{
public static void main(String[] args) {
Demo demo=new Demo();
System.out.println(demo.getClass().getName()); //通过一个对象获得完整的类名(包含包名)
}
}
【运行结果】:反射Reflect.Demo
【案例2】实例化Class类对象的方法
package 反射Reflect;
class Demo {
// other codes...
}
class Hello {
public static void main(String[] args) {
Class<?> demo1 = null; //此时对象是哪个类尚不清楚
Class<?> demo2 = null;
Class<?> demo3 = null;
//demo1=Class.forName(demo1.getClass().getName()); //报错,类尚未实例化
try {
//实例化方法1,一般尽量采用这种形式
demo1=Class.forName("反射Reflect.Demo"); //需要异常捕获
} catch (ClassNotFoundException e) {//或Exception e
e.printStackTrace();
}
//实例化方法2、3
demo2=new Demo().getClass();
demo3=Demo.class;
System.out.println("类名称 :"+demo1.getName());
System.out.println("类名称 :"+demo2.getName());
System.out.println("类名称 :"+demo3.getName());
}
}
【运行结果】:
类名称 :反射Reflect.Demo
类名称 :反射Reflect.Demo
类名称 :反射Reflect.Demo
【案例3】通过Class类实例化其他类的对象
package 反射Reflect;
class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "[" + this.name + " " + this.age + "]";
}
public Person(String name, int age) { //当只有一个有参构造函数,会报错java.lang.InstantiationException
this.age = age;
this.name = name;
}
public Person(){ } //自己定义一个无参的构造函数,很重要
}
// 通过Class类实例化任意类的对象
class Hello {
public static void main(String[] args) {
// Class<?> demo = Person.class;//获得Class类实例
Class<?> demo = null;
try {
demo = Class.forName("反射Reflect.Person");
} catch (Exception e) {
e.printStackTrace();
}
Person per = null;
try {
per = (Person) demo.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
per.setName("Rollen");
per.setAge(20);
System.out.println(per);
}
}
【运行结果】:
[Rollen 20]
如果了解Java虚拟机,应该知道,一个对象在new之前,堆里是不会分配内存的。因此这个UserInfo的实例是通过Class的实例得到的。
注意:如注释中所言,如果把无参构造函数取消,只有一个有参构造函数,代码运行会报异常,所以,显式声明空的构造函数有时候也是一种很好的习惯。当你要使用反射时,一定不要忘记无参构造。
【案例4】通过Class调用其他类中的构造函数 (也可以通过这种方式通过Class创建其他类的对象)
package 反射Reflect;
import java.lang.reflect.Constructor;
class Person{
private String name;
private int age;
public Person() {
}
public Person(String name){
this.name=name;
}
public Person(int age){
this.age=age;
}
public Person(String name, int age) {
this.age=age;
this.name=name;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String toString(){
return "["+this.name+" "+this.age+"]";
}
}
class Hello{
public static void main(String[] args) {
Class<?> demo=null;
try{
demo=Class.forName("反射Reflect.Person");
}catch (Exception e) {
e.printStackTrace();
}
Person per0=null;
Person per1=null;
Person per2=null;
Person per3=null;
//取得全部的构造函数
// Constructor<?> cons[]=demo.getConstructors();//每次得到的构造方法数组的顺序是随机的,无法得知构造方法的顺序,应具体去得到相应的构造方法
// for(int i=0;i<cons.length;i++){
// //System.out.println(cons[i].getClass().getMethods());
System.out.println(cons[i]);//输出构造方法
// }
try{
//取得无参数的构造函数
Constructor<?> cons0=demo.getDeclaredConstructor();
//取得有参数的构造函数
Constructor<?> cons1=demo.getDeclaredConstructor(String.class);
Constructor<?> cons2=demo.getDeclaredConstructor(int.class);
Constructor<?> cons3=demo.getDeclaredConstructor(String.class,int.class);
per0=(Person)cons0.newInstance();
per1=(Person)cons1.newInstance("Rollen");
per2=(Person)cons2.newInstance(20);
per3=(Person)cons3.newInstance("Rollen",20);
}catch(Exception e){
e.printStackTrace();
}
System.out.println(per0);
System.out.println(per1);
System.out.println(per2);
System.out.println(per3);
}
}
【运行结果】:
[null 0]
[Rollen 0]
[null 20]
[Rollen 20]
【案例5】 返回一个类实现的接口:
package 反射Reflect;
import java.lang.reflect.Constructor;
interface China{
public static final String name="Rollen";
public static int age=20;
public void sayChina();
public void sayHello(String name, int age);
}
class Person implements China{
private String name;
private int age;
public Person() {
}
public Person(String name){
this.name=name;
}
public Person(int age){
this.age=age;
}
public Person(String name, int age) {
this.age=age;
this.name=name;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String toString(){
return "["+this.name+" "+this.age+"]";
}
public void sayChina() {
System.out.println("hello ,china");
}
public void sayHello(String name, int age) {
System.out.println(name+" "+age);
}
}
class Hello{
public static void main(String[] args) {
Class<?> demo=null;
try{
demo=Class.forName("反射Reflect.Person");
}catch (Exception e) {
e.printStackTrace();
}
//保存所有的接口
Class<?> intes[]=demo.getInterfaces();
for (int i = 0; i < intes.length; i++) {
System.out.println("实现的接口 :"+intes[i].getName());
}
}
}
【运行结果】:
实现的接口 :反射Reflect.China
【案例6】:取得其他类中的父类
以下几个例子中用得到之前的Person类,但只改动Hello中的方法,故此都省略Person代码。
class Hello{
public static void main(String[] args) {
Class<?> demo=null;
try{
demo=Class.forName("反射Reflect.Person");
}catch (Exception e) {
e.printStackTrace();
}
//取得父类
Class<?> temp=demo.getSuperclass();
System.out.println("继承的父类为: "+temp.getName());
}
}
【运行结果】:
继承的父类为: java.lang.Object
之前案例4中获取的构造方法,输出是不包含修饰符的,下面我们来获取修饰符:
【案例7】:取得包含修饰符的构造方法
package 反射Reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
【运行结果】:
构造方法: public 反射Reflect.Person(java.lang.String arg0,int arg0){}
构造方法: public 反射Reflect.Person(int arg1){}
构造方法: public 反射Reflect.Person(java.lang.String arg2){}
构造方法: public 反射Reflect.Person(){}
【案例8】:取得包含修饰符的类及父类的所有public方法
class Hello{
public static void main(String[] args) {
Class<?> demo=null;
try{
demo=Class.forName("反射Reflect.Person");
System.out.println("类名:"+demo);
}catch (Exception e) {
e.printStackTrace();
}
Method method[]=demo.getMethods();//取得当前类和父类中public类型的所有方法
for(int i=0;i<method.length;++i){
Class<?> returnType=method[i].getReturnType(); //获得方法 返回值类型
Class<?> para[]=method[i].getParameterTypes(); //获得方法 参数类型 如果底层构造函数没有参数,则返回长度为0的数组。
int temp=method[i].getModifiers(); //权限修饰符 作为整数
System.out.print(Modifier.toString(temp)+" "); //Modifier类解码这个修饰符
System.out.print(returnType.getName()+" ");
System.out.print(method[i].getName()+" "); //方法名
System.out.print("(");
for(int j=0;j<para.length;++j){
System.out.print(para[j].getName()+" "+"arg"+j);
if(j<para.length-1){
System.out.print(",");
}
}
Class<?> exce[]=method[i].getExceptionTypes(); //得到 由该对象所表示的方法抛出的异常类型,如果方法在抛出子句中声明没有异常,那么返回一个长度为0的数组。
if(exce.length>0){
System.out.print(") throws ");
for(int k=0;k<exce.length;++k){
System.out.print(exce[k].getName()+" ");
if(k<exce.length-1){//多个参数用,分隔
System.out.print(",");
}
}
}else{
System.out.print("){}");
}
System.out.println();
}
}
}
【运行结果】:
类名:class 反射Reflect.Person
public java.lang.String toString (){}
public java.lang.String getName (){}
public int getAge (){}
public final native void wait (long arg0) throws java.lang.InterruptedException
public final void wait (long arg0,int arg1) throws java.lang.InterruptedException
public final void wait () throws java.lang.InterruptedException
public native int hashCode (){}
public final native java.lang.Class getClass (){}
public boolean equals (java.lang.Object arg0){}
public final native void notify (){}
public final native void notifyAll (){}
【案例9】调用其他类的set和get方法
package 反射Reflect;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
class Person {
private String name;
private int age;
private String sex;
public Person() {
}
public Person(String name) {
this.name = name;
}
public Person(int age) {
this.age = age;
}
public Person(String name, int age) {
this.age = age;
this.name = name;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getSex() {
return sex;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String toString() {
return "[" + this.name + " " + this.age + "]";
}
}
class Hello { //调用其他类的set和get方法
/**
* @param obj 操作的对象
* @param att 操作的属性
* */
public static void getter(Object obj, String att) {
try {
Method method = obj.getClass().getMethod("get" + att); //这里method是得到obj类的getSex方法
System.out.println(method.invoke(obj));//调用包装在当前Method对象中的方法 ,接收参数和返回类型都必须是对象
// System.out.println(obj);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @param obj 操作的对象
* @param att 操作的属性
* @param value 设置的值
* @param type 参数的属性
* */
public static void setter(Object obj, String att, Object value,
Class<?> type) {
try {
Method method = obj.getClass().getMethod("set" + att, type);//这里method是得到obj类的setSex方法 ,后为参数类型
method.invoke(obj, value);//调用包装在当前Method对象中的方法 ,接收参数和返回类型都必须是对象
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Class<?> demo = null;
Object obj = null;
try {
demo = Class.forName("反射Reflect.Person");
} catch (Exception e) {
e.printStackTrace();
}
try {
obj = demo.newInstance(); //obj实例化为demo所获得的类的对象
} catch (Exception e) {
e.printStackTrace();
}
setter(obj, "Sex", "男", String.class);
getter(obj, "Sex");
}
}// end class
【运行结果】:
男
反射中的其他用法类似,最主要先获取类Class对象,具体方法具体讨论即可。
案例转自:(以上代码本人都是实测过的,这篇文章中代码有一些问题)
http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html#!comments