您的位置:首页 > 职场人生

黑马程序员 反射

2015-07-15 16:15 471 查看
------- <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

 
4000
   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());

    }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: