黑马程序员 反射

来源:互联网 发布:阿里云客服考试好考吗 编辑:程序博客网 时间:2024/06/17 02:24

------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------

反射

1、反射的基石:class

    字节码:是class的实例对象。
    得到字节码方式
    1)class.forName
    2)类名.class 如Person.class
    3)对象.getClass()

    isPrimitive()是否是基本类型的字节码
    int.class==Integer.TYPE
    数组类型的class 实例对象
    class.isArray()
    总之,只要是在源程序中出现的类型,都有各自的class实例对象。
    例如:int[],void

2、反射:就是把java类中的各种成分映射成相应的java类。
    
3、 Constructor   构造方法

        //选择哪个构造方法
        Constructor cr1=String.class.getConstructor(StringBuffer.class);//参数可

以多个,如int.class等
        //用这个方法时,传一个对象进去
        String str2=(String)cr1.newInstance(new StringBuffer("abc"));
        //获得方法时要要到类型

        有class得到Constructor,再new object


4、Field类:代表某个类中的成员变量

需求:从Demo2.java中获取x,y到Demo1.java
Demo2    
    private int x;
    public int y;
    //alt+shift+s
    public ReflectPointDemo(int x, int y) {
        super();
        this.x = x;
        this.y = y;
    }
    
Demo1        ReflectPointDemo rpd=new ReflectPointDemo(3, 5);
        Field fdy=rpd.getClass().getField("y");
        //fdy的值是多少?    5,wrong
        //fdy不是对象身上的变量,而是类上的,要用它去取某个对象上对应的值
        System.out.println("y="+fdy.get(rpd));
        //Field fdx=rpd.getClass().getField("x");//无法获取私有
        Field fdx=rpd.getClass().getDeclaredField("x");//获取私有
        
        fdx.setAccessible(true);//强行获取
        System.out.println("x="+fdx.get(rpd));

---------
需求:对Demo2.java中s1,s2,s3数据修改,在Demo1.java实现
Demo2.java
    public String s1="wang";
    public String s2="wei";
    public String s3="song";
    
    @Override //请编译器查询
    public String toString() {
        return s1+":"+s2+":"+s3;
    }
Demo1.java
        changeStringValue(rpd);//rpd属于上述中的rpd
        System.out.println(rpd);
    }
    public static void changeStringValue(Object obj)throws Exception
    {
        Field[] fs=obj.getClass().getFields();
        for(Field f:fs)
        {
            //字节码用等号比==,因为这里是同一份字节码
            if(f.getType()==String.class){
                String oldValue=(String)f.get(obj);
                String newValue=oldValue.replace("w", "t");
                f.set(obj, newValue);
                
            }
        }


5、Method类代表某个类中的一个成员方法
    通常方式:System.out.Println(str.charAt(1))
    反射方式: System.out.Println(charAt.invoke(str,1))
    若传递给Method对象的invoke()方法的第一个参数为null,
    那么该Method对象对应的一个静态方法

Demo1.java    //调用str2.charAt(1),str2="abc";
        
        Method mdCharAt=String.class.getMethod("charAt", int.class);
        System.out.println("str2.charAt(1)="+mdCharAt.invoke(str2, 1));
        //jdk1.4的方式
        System.out.println("str2.charAt(1)="+mdCharAt.invoke(str2,new Object[]

{2}));
        
6、 外部函数调用Demo2.java的main函数
    用发射的目的:
        当不知道执行哪个class时,用这个更适应
    通常: Demo2.main(new string{}{"1","2","3"});

        //ReflectPointDemo.main(new String[]{"1","2","3"});
        String startClassName=args[0];
        Method mainMethod=Class.forName(startClassName).getMethod("main",

String[].class);
        //mainMethod.invoke(null, new String[]{"1","2","3"});//此时会出现数组下

标越界,会对 new String[]{"1","2","3"}进行拆分
        mainMethod.invoke(null,new Object[]{ new String[]{"1","2","3"}});

7、数组的反射:

        int[] a1=new int[]{1,2,3};
        int[] a2=new int[4];
        int[][] a3=new int[2][3];
        String[] s4=new String[]{"a","1",","};
        System.out.println(a1.getClass()==a2.getClass());//字节码相同
        //System.out.println(a1.getClass()==a3.getClass());
        System.out.println(a1.getClass().getSuperclass().getName());
        
        System.out.println(s4.getClass().getSuperclass().getName());
        //都是java.lang.Object
        //所以能实现
        Object obj1=a1;//...
        //但是一维int数组无法赋值给Object数组
        Object[] ob=a3;
        Object[] obs=s4;
        System.out.println(a1);//[I@1fb8ee3  哈希口?@1fb8ee3
        //于是采用Arrays工具类
        System.out.println(Arrays.asList(a1));//[[I@1fb8ee3]
        System.out.println(Arrays.asList(s4));//[a, 1, ,]


        //数组的反射
        printObject(a1);
        printObject(s4);
        
    }
    public static void printObject(Object obj) {
        Class clzz=obj.getClass();
        if(clzz.isArray())
        {
            int len=Array.getLength(obj);
            for(int i=0;i<len;i++)
                System.out.print(Array.get(obj, i));
            System.out.println();
        }
    }
    
8、  ArrayList_HashSet的比较及Hashcode分析

    hashcode方法与hashSet类

    分区域、通过算哈希值找区域,再找目标。提高了效率
    hashSet类:去重复的引用
    hashcode方法:通过计算哈希值,去等值对象。

    
练习        public static void main(String[] args) {
        // TODO Auto-generated method stub
        //Collection cn=new ArrayList();//size=4
        Collection cn=new HashSet();    //size=3
        ReflectPointDemo rpd =new ReflectPointDemo(3,3);
        ReflectPointDemo rpd2=new ReflectPointDemo(4,4);
        ReflectPointDemo rpd3=new ReflectPointDemo(3,3);
        
        cn.add(rpd);//将引用添加进去
        cn.add(rpd2);
        cn.add(rpd3);
        cn.add(rpd);//与第一个引用相同
        //hashcat若引用相同则无法加入
        //若在ReflectPointDemo添加hashCode(),用于去同点  size=2
        
        rpd.y=7;//将rpd存放在其他地方,不被发现 ,使cn.remove(rpd);操作失败,

size=2
        cn.remove(rpd);//删除rpd
        
        
        System.out.println(cn.size());//4
    }

    
ReflectPointDemo 中
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + x;
        result = prime * result + y;
        return result;
    }


9、实现框架功能
    解决的核心问题:适应性强,时用长(如虚类)

项目->file 取名config.properties
    className=java.util.ArrayList    //size=4
    className=java.util.HashSet    //size=2
    
Demo.java
    public static void main(String[] args)throws Exception
    {
        // TODO Auto-generated method stub
        InputStream ips=new FileInputStream("config.properties");
        Properties pop=new Properties();
        pop.load(ips);
        ips.close();//释放资源。
        
        String className=pop.getProperty("className");//前后className不必一样,

但..
        Collection cn=(Collection)Class.forName(className).newInstance();
        
        ReflectPointDemo rpd =new ReflectPointDemo(3,3);
        ReflectPointDemo rpd2=new ReflectPointDemo(4,4);
        ReflectPointDemo rpd3=new ReflectPointDemo(3,3);
        
        cn.add(rpd);//将引用添加进去
        cn.add(rpd2);
        cn.add(rpd3);
        cn.add(rpd);//与第一个引用相同
        
        System.out.println(cn.size());
    }


0 0