黑马程序员技术交流社区

标题: 可不可以通过反射获得内部类的字节码? [打印本页]

作者: mulua    时间: 2013-6-22 16:13
标题: 可不可以通过反射获得内部类的字节码?
本帖最后由 孙百鑫 于 2013-6-27 07:00 编辑

可不可以通过反射获得内部类的字节码?
作者: 007诸葛亮    时间: 2013-6-22 16:28
代表字节码对象的Class
java中所有的类都有自己特有的一份字节码,当程序调用该类时,JVM便会将这份字节码装载到内存中来。在java中主要有三种方法来得到相应的字节码对象。
1.通过类的实例的getClass()方法获取,如 Class clazz=new Date().getClass()得到了Date类的字节码对象。
2.通过类的class属性获取。如Class clazz=String.class或者Class clazz=System.class.值得注意的是,java中八个主类型(byte,char,short,int,long,float,double,boolean)和一个返回类型void都有class属性,并且都返回自己的字节码对象。如int.class,boolean.class,float.class等。其中他们的包装类的TYPE属性也分别返回它们主类型的那份字节码,如int.class==Integer.TYPE为true,void.class==Void.TYPE为true;
3.通过Class类的forName()方法获取,如Class clazz=Class.forName("java.lang.Math");
java中可以通过Class类的isPrimitive()方法判断当前的字节码是否为主类型,isEnum()判断字节码是否为枚举类。isArray()判断字节码是否为数组类型。某个类和它所组成的数组分别持有的字节码也不相同,例如int.class==int[].class这种写法在编译期就会被编译器阻止,因为编译器发现两边参与比较的对象不在一个继承树分支上。只有相同类型和相同维度的数组才会共用一个字节码对象.
如int a1[]=new int[1], a2[]=new int[5];int a3[][]=new int[2][5];a1.getClass()==a2.getClass()为true,a2.getClass()==a3.getClass()为false;
对内部类的反射
Class类本身还提供对于获取内部类字节码的方法,分别为getClasses和getDeclaredClasses(),其中getClasses()只能得到访问级别为public的内部类,而getDeclaredClasses()则能得到所有声明了的内部类。
由于内部类可以分为实例内部类,静态内部类,匿名内部类,前面提到的getClasses()和getDeclaredClasses()目前还都只能得到实例内部类和静态内部类,对于后面两种情况却无能为力,为此还需要采取一些特殊的手段才能针对匿名内部类进行反射操作。
[java] view plaincopy
01.package net.csdn.blog;  
02.  
03.public class ReflectInnerClass {  
04.  
05.  
06.      
07.    public Runnable ta=new Runnable(){  
08.        public void run(){  
09.            System.out.println("匿名内部类中的方法被执行了");  
10.        }  
11.    };  
12.  
13.      
14.    private class Inner2{  
15.        public Inner2(){  
16.            System.out.println("Inner2类被实例化了");  
17.        }  
18.    }  
19.      
20.    class Inner3{  
21.        public Inner3(){  
22.            System.out.println("Inner2类被实例化了");  
23.        }  
24.    }     
25.    public class Inner1{  
26.        public Inner1(){  
27.            System.out.println("Inner1类被实例化了");  
28.        }  
29.    }  
30.}  

下面对内部类进行反射

[java] view plaincopy
01.package net.csdn.blog;  
02.  
03.import java.lang.reflect.InvocationTargetException;  
04.import java.lang.reflect.Modifier;  
05.  
06.public class ReflectInnerClassTest {  
07.  
08.    public static void main(String args[]){  
09.        ReflectInnerClass ric=new ReflectInnerClass();  
10.        try {  
11.            reflectInnerClass(ric);  
12.        } catch (Exception e) {  
13.            e.printStackTrace();  
14.        }   
15.    }  
16.  
17.    private static void reflectInnerClass(ReflectInnerClass ric) throws InstantiationException, IllegalAccessException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException, NoSuchFieldException {  
18.        Class clazz=ric.getClass();  
19.        Class classes[]=clazz.getDeclaredClasses();  
20.        for(Class c:classes){//对成员内部类进行反射  
21.            int i=c.getModifiers();  
22.            String s=Modifier.toString(i);  
23.            if(s.contains("static"))//静态内部类的处理  
24.                 c.getConstructor().newInstance();  
25.            else//实例内部类的处理  
26.                 c.getConstructor(ric.getClass()).newInstance(ric);  
27.        }  
28.        //由于匿名内部类没有构建器,因此无法创建实例,也无法直接访问其中的方法,但可以通过下面的方式巧秒的执行其中的方法或成员变量。  
29.        Runnable r=(Runnable)(clazz.getField("ta").get(ric));  
30.        r.run();  
31.         
32.    }  
33.}  






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2