JAVA反射机制案例解析

建议在阅读本文之前,先理解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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值