黑马程序员技术交流社区

标题: java基础加强总结3(纯手打)反射 [打印本页]

作者: 等风来_________    时间: 2014-3-16 20:52
标题: java基础加强总结3(纯手打)反射
反射
        概述:把java类中的各种成分映射成相应的java类

反射的基础:Class类               
        Class类:在java中表示众多的java类。       
                        描述了,类的名字,类的访问属性,类所属的包名,字段名称的列表,方法名称的列表等。
        如何得到各个字节码对应的实例对象(Class类型)
                类名.class,例如:System.class;
                对象.getClass(),例如,new Date().getClass();
                Class.forName("类名"),例如,Class.forName("java.util.Date");
        九个预定义的Class实例对象
                表示八个基本类型和 void。
                这些类对象由 Java 虚拟机创建,与其表示的基本类型同名,即 boolean、byte、char、short、int、long、float 和 double。
        基本类型对象.TYPE
                基本类型对象.TYPE:获取基本类型对象的类型。
        Class.isPrimitive()
                判断是否是基本数据类型
        Class.isArray()
                数组类型的Class实例对象
        例子:
                String str1="abc";
                Class cls1=str1.getClass();               
                Class cls2=String.class;
                Class cls3=Class.forName("java.lang.String");
                System.out.println(cls1==cls2);
                System.out.println(cls2==cls3);
                System.out.println(cls1.isPrimitive()); //验证是否是基本类型
                System.out.println(int.class);
                System.out.println("int.class==Integer.class"+(int.class==Integer.class));
                System.out.println("int.class==Integer.TYPE:"+(int.class==Integer.TYPE));
                System.out.println("判断数组是否是基本类型"+int[].class.isPrimitive());
                System.out.println("判断是否是数组类型:"+int[].class.isArray());       
        总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如:int[],void
       
反射-Constructor类
        代表某个类中的一个构造方法
        得到某个类中的所有的构造方法
                Constructor[] constructor=Class.forName("java.lang.String").getConstructors();
        得到某一个构造方法
                Constructor constructor=Class.forName("java.lang.String").getConstructor(StringBuffer.class);
        创建实例方法
                通常方式:
                        String str=new String(new StringBuffer("abc"));
                反射方式:
                        String str=(String)constructor.newInstance(new StringBuffer("abc"));
                Class.newInstance()方法
                        例子:String obj=(String)Class.forName("java.lang.String").newInstance();
                        该方法内部先得到默认的构造方法,然后该构造方法创建实例对象。
                        该方法内部的具体代码是怎样写的呢?用到了缓存机制来保存默认构造方法的实例对象。
        例子:
                //new String(new StringBuffer("abc"));
                Constructor constructor=String.class.getConstructor(StringBuffer.class);//传递数据类型
                String str=(String) constructor.newInstance(new StringBuffer("abc"));
                //传递相同类型的对象 System.out.println(str);
        总结,Constructor大量的消耗资源

反射-Field类
        代表某个类中的成员变量
        获取Field类变量的值例子:
                public class ReflectPoint {       
                        private int x;
                        public int y;
                       
                        public ReflectPoint(int x, int y) {
                                super();
                                this.x = x;
                                this.y = y;
                        }                       
                }
       
                ReflectPoint rp=new ReflectPoint(3, 5);
                try {
                        Field field=rp.getClass().getField("y");
                        //field不是对象的变量,而是类上,要用它去取某个对象上对应的值
                        System.out.println(field.get(rp));
                       
                        Field fieldx=rp.getClass().getDeclaredField("x");
                        //暴力反射
                        fieldx.setAccessible(true);
                        System.out.println(fieldx.get(rp));
                       
                } catch (Exception e) {
                        e.printStackTrace();
                }
               
        利用Field类进行反射修改变量的值例子:
                public String str1="ball";
                public String str2="basketball";
                public String str3="itcast";
               
                public String toString(){
                        return str1+":"+str2+":"+str3;
                }       
       
                private static void changeStringValue(Object obj) throws Exception {
                Field[] fields = obj.getClass().getFields();

                for (Field field : fields) {

                        // field.getType().equals(String.class);

                        // 同一个字节码,使用双等号进行判断
                        if (field.getType() == String.class) {
                                String strValue = (String) field.get(obj);
                                String newValue = strValue.replace('b', 'a');
                                // 设置对象的新值
                                field.set(obj, newValue);
                        }
                }
        }
       
反射-Method类
        代表某个类中的一个成员方法
        得到类中的某一个方法
                例子:Method charAt=Class.forName("java.lang.String").getMethod("charAt",int.class);
        调用方法:
                通常方法:
                        System.out.println(str.charAt(1));
                反射方法:
                        System.out.println(charAt.invoke(str,1));
                        如果传递给Method对象的invoke()方法的一个参数为null,这有着什么意义呢?说明该Method对象对应的是一个静态方法。
        JDK1.4和JDK1.5的invoke方法的区别:
                JDK1.5:public Object invoke(Object obj,Object...args)
                JDK1.4: public Object invoke(Object obj,Object[] args)
                        即按JDK1.4的语法,需要将一个数组作为参数传递给invoke方法时,数组中的每个元素分别对应被调用方法中的一个参数。
                        所以,调用charAt方法的代码也可以用JDK1.4改写为        charAt.invoke("str",new Object[]{1})形式。
        例子:
                String str1="abc";
                Method methodCharAt=String.class.getMethod("charAt", int.class);
                System.out.println(methodCharAt.invoke(str1, 1)); //JDK1.5
                System.out.println(methodCharAt.invoke(str1, new Object[]{1})); //JDK1.4
               
        main方法的反射例子:
                class TestArguments{
                        public static void main(String[] args) {
                                for (String string : args) {
                                        System.out.println(string);
                                }
                        }
                }
               
                String startingClassName=args[0];
                Method main=Class.forName(startingClassName).getMethod("main", String[].class);
                main.invoke(null, new Object[]{new String[]{"111","222","333"}}); //把传入的数组看成一个整体
                main.invoke(null, (Object)new String[]{"111","222","333"});//把传入的数组看成一个整体
               
数组的反射:
        具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
       
        代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class。
       
        基本类型的一维数组可以被当做Object类型使用,不能当做Object[]类型使用。
        非基本类型的一维数组,既可以当做Object类型使用,也可以当做Object[]类型使用。
       
        Arrays.asList()方法处理int[]和String[]时的差异:
                处理int[]时,把他当做一个Object类型看待,打印结果是带有hashCode的值。
                处理String[]时,当做Object[]类型看待,打印结果是具体的数组元素值。
                例子:
                        int[] a1=new int[]{1,2,3};
                        int[] a2=new int[4];
                        int[][] a3=new int[2][3];
                        String[] a4=new String[]{"aa","bb","cc"};
                        System.out.println(a1.getClass()==a2.getClass());
        //                System.out.println(a1.getClass()==a3.getClass());
        //                System.out.println(a1.getClass()==a4.getClass());
                        System.out.println(a1.getClass().getSuperclass().getName());
                        System.out.println(a4.getClass().getSuperclass().getName());
                       
                        Object aObj1=a1;
                        Object aObj2=a4;
        //                Object[] aObj3=a1;
                        Object[] aObj4=a3;
                        Object[] aObj5=a4;
                       
                        System.out.println(Arrays.asList(a1));
                        System.out.println(Arrays.asList(a4));       
       
        Array工具类完成对数组的反射例子:
                private static void printObject(Object obj) {
                Class arr=obj.getClass();
                if(arr.isArray()){
                        int len=Array.getLength(obj);
                        for (int i = 0; i < len; i++) {
                                System.out.println(Array.get(obj, i));
                        }
                }else{
                        System.out.println(obj);
                }
        }
       
ArrayList和HashSet的比较和hashCode的分析
        例子:
                Collection collections=new HashSet();
               
                ReflectPoint rp1=new ReflectPoint(3,3);
                ReflectPoint rp2=new ReflectPoint(5,5);
                ReflectPoint rp3=new ReflectPoint(3,3);
               
                collections.add(rp1);
                collections.add(rp2);
                collections.add(rp3);
                collections.add(rp1);
               
                System.out.println(collections.size());
               
                @Override
                public int hashCode()
                {
                        final int prime = 31;
                        int result = 1;
                        result = prime * result + x;
                        result = prime * result + y;
                        return result;
                }
       
                @Override
                public boolean equals(Object obj)
                {
                        if (this == obj)
                                return true;
                        if (obj == null)
                                return false;
                        if (getClass() != obj.getClass())
                                return false;
                        ReflectPoint other = (ReflectPoint) obj;
                        if (x != other.x)
                                return false;
                        if (y != other.y)
                                return false;
                        return true;
                }






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