黑马程序员——反射其他

——- android培训java培训、期待与您交流! ———-

Field类
代表某个类中的一个成员变量

问! 将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的”b“改成”a“



changeSringValue(pt1);//定义一个单独的方法
            System.out.println(pt1);



private static void changeSringValue(Object obj) throws Exception {
        // TODO Auto-generated method stub
        Field[] fields = obj.getClass().getFields();
        for(Field field : fields){
            //if(field.getType().equals(String.class))
            if(field.getType()==String.class){
                String oldValue =(String)field.get(obj);
                String newValue =oldValue.replace('b','a');
                field.set(obj, newValue);
/*
Method类
    代表某个类中的一个成员方法

得到类中的某一个方法;
    例子:  Method charAt =
    Class.forName("java.lang.String").getMethod(”charAt“,int.class);

调用方法:
    通常方式;System.out.println(str.chatAt(1));
    反射方式:System.out.println(charAt.invoke(str.1));
        如果传递给Method对象invoke()方法的一个参数为null,还有这什么样的意义?
            说明该Method对象对应的是一个【静态】的方法!
*/

Method methodCharAt = String.class.getMethod("charAt",int.class);
            System.out.println(methodCharAt.invoke(str1,1));
/*
反射方式执行某个类中的main方法

目标:
    写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法

问题:
    启动Java程序的main方法的参数是一个字符串数组,即public static void main(String[] args),
通过反射来调用这个mian 方法时,如何为invoke方法传递参数?

    按jdk1.5的语法:
        整个数组是一个参数,
    按jdk1.4的语法:
        数组中的每一个元素对应的一个参数,

当把一个字符串数组作为参数传递给invoke方法时,javac会到底按照哪种语法进行处理呢?
jdk1.5肯定要兼容jdk1.4的语法,会按照,jdk1.4的方法处理,即把数组打散为若干个单独的参数,
所以,在给main参数是,不能使用代码
    mainMethod.invoke(null,String[] {"xxx"});

    javac只把它当作jdk1.4的语法进行理解,而不是把他当作jdk1.5的语法解释,
        因此会出现参数类型不对的问题

解决办法:
    mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});//jkd会拆包,拆完会变成多个单独参数,那给外面在加个包,拆完还是一个数组

    mainMethod,invoke(null,(Object)new String[]{"xxx"});//强转成 object 跟编译器说明只有一个对象
    编译器会做特殊处理,编译时不把参数当作数组看待,也就不会数组打散若干个参数
*/

TestArguments.main(new String[]{"111","222","333"});
      //程序中使用静态代码直接调用main方法


class TestArguments{
    public static void main(String[] args){
        for(String arg : args){
            System.out.println(arg);
//先敲sysout,然后组合快捷键:alt+/,就可以不全代码为:System.out.println();

        }
    }
}





//为什么?  使用反射的方式调用          
//  编写代码时候,不知道 【具体】的类名

String startingClassName = args[0];
Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class);

mainMethod.invoke(null, new Object[]{new String[]{"111","222","333"}});//要拆包,那就外面再包一次
//mainMethod.invoke(null, (Object)new String[]{"111","222","333"});//法2 跟编译器说我给的是一个数组不需要拆包


class TestArguments{
    public static void main(String[] args){
        for(String arg : args){
            System.out.println(arg);
//先敲sysout,然后组合快捷键:alt+/,就可以不全代码为:System.out.println();

        }
    }
}
/*
数组的反射

具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
    数组字节码的名字:有[和数组对应类型的缩写,如int[]数组的名称为:[I

代表数组的Class实例对象的个体SuperClass()方法返回的父类为Object类对应的Class。

基本类型的一维数组可以被当作Objcet类型使用,不能当作Object[]类型使用;
非基本类型的一维数组,既可以到做Object类型使用,又可以当作Object[]类型使用

Object[]与String[]没有父子关系,Object与String有父子关系,
所以new Object[]{“aaa”,”bb”}不能强制转换成new String[]{“aaa”,”bb”}; 
    Object x =“abc”能强制转换成String x =“abc”。



Arrays.asList();方法处理int[]和String[]时的差异。

Array 工具类 用于 完成对数组的反射操作
    Array.getLength(Object obj);//获取数组的长度
        Array.get(Object obj,int x);//获取数组中的元素

如何得到某个数组中的某个元素的类型,

        例:
              int a = new int[3];Object[] obj=new Object[]{”ABC”,1};
        无法得到某个数组的具体类型,只能得到其中某个元素的类型,
        如:
               Obj[0].getClass().getName()得到的是java.lang.String。


思考题:怎么得到数组中的元素类型?
  【占时没有方法,只能得到数组中元素所属的类型,数组的类型是不确定的】
*/

Object obj = null ;
printObject(obj);

}

private static void printObject(Object obj){
    Class clazz = obj.geetClass();
    if(clazz.isArray()){
        int len = Array.getLength(obj);
        for (int i = 0;i<len ;i++ )
        {
            System.out.println(Array.get(obj,i));
        }
    }
}
   /*
    HashCode    ArrayList  分析

   提示
        1.通常来说,一个类的2个实例对象用 equals()方法比较的结果相等时,他们的哈希码必须相等
但反之则不成立,即equals()方法比较结果不相等的对象可以有相同的哈希码,或许说哈希姆相同的2个
对象equals()比较方法可以不等,
    例如:字符串"BB"和"Aa",的equals()的方法比较结果肯定不相等,但他们hasCode返回的值却相等。

        2.当一个对象被存储进HashSet集合中,就不能修改这个对象中的那些【参与计算】哈希值的字段了,
否则,对象修改后的哈希值与最初的存储进HashSet集合中时的哈希值就不同了,这种情况下,即使在
contains方法使用该对象当前引用作为参数去HashSet集合中检索对象,也将返回找不到对象的额结果,
这也会导致无法从HashSet集合中单独删除当前对象,从而造成内存泄漏。


补充
    【内存泄露】:某些对象不再使用了,占用着内存空间,并未被释放,就会导致内存泄露;
也就是说当程序不断增加对象,修改对象,删除对象,日积月累,内存就会用光了,就导致【内存溢出】。


    */


package com.itheima;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;

public class ReflectTest2 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //Collection collections = new ArrayList();//【未生成 方法之前】数组长度是4 自然数组 有一个放一个

        Collection collections = new HashSet();//——————————————————————框架需要修改的地方
        //【未生成 方法之前】数组长度是3 有相同的第二个开始就不放了
        //【生成之后】数组长都为2,相同的就不再放了

        ReflectPoint pt1 = new ReflectPoint(3,3);
        ReflectPoint pt2 = new ReflectPoint(5,5);
        ReflectPoint pt3 = new ReflectPoint(3,3);

        collections.add(pt1);
        //collections.add(new ReflectPoint(3,3));
        collections.add(pt2);
        collections.add(pt3);
        collections.add(pt1);

        System.out.println(collections.size());


    }

}


//——————————————————————————————————————————————————


package com.itheima;                                                                                             

public class ReflectPoint {                                                                                      
    private int x;                                                                                               
    public int y;                                                                                                
    public String str1 = "ball";                                                                                 
    public String str2 ="basketball";                                                                            
    public String str3 ="itcast";                                                                                

    public ReflectPoint(int x, int y) {//快捷键alt+shift+s   ……Fields……                                             
        super();                                                                                                 
        this.x = x;                                                                                              
        this.y = y;                                                                                              
    }                                                                                                            

    //右击 source 产生 HasCode代码                                                                                     

    @Override                                                                                                    
    public int hashCode() {//【hashCode方法生成】                                                                      
        final int prime = 31;                                                                                    
        int result = 1;                                                                                          
        result = prime * result + x;                                                                             
        result = prime * result + y;                                                                             
        return result;                                                                                           
    }                                                                                                            


    @Override                                                                                                    
    public boolean equals(Object obj) {// 【equals 方法生成】                                                          
        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;                                                                                             
    }                                                                                                            


    @Override                                                                                                    
    public String toString(){                                                                                    
        return str1 +":"+str2+":"+str3;                                                                          

    }                                                                                                            


    }                                                                                                            





/*
反射的左右——>实现框架功能

框架 与 框架要解决的核心问题

    我要做房子卖给住户,有用户自己安装 门窗, 我做的房子就是【框架】,
用户需要使用我的框架,然后把门窗插入到我提供的框架中。
    框架与工具类有区别,工具类被【用户的类】调用,而框架则是调用用户提供的类。


框架要解决的核心问题
    我在写框架的时候,用户可能不存在,那编写的框架如何调用 后来存在的类呢???

    因为编写时候,无法知道要被调用的类名,所以,在程序中无法直接的new某个类的实例对象,
    故要使用,反射方法。



*/

Collection collections = new HashSet();//——————————————————————框架需要修改的地方
//HashSet()这里不出现具体的类名,从配置文件中读取

//右击最上javapa 包——New ——File —— config.properties —— className=java.until.ArrayList



config.properties

Source

className=java.until.ArrayList

Collection collections = new HashSet();//——————————————————————框架需要修改的地方
//HashSet()这里不出现具体的类名,从配置文件中读取

//右击最上javapa 包——New ——File —— config.properties —— className=java.until.ArrayList

config.properties

Source

className=java.until.ArrayList

package com.itheima;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Properties;

public class ReflectTest2 {

    public static void main(String[] args)throws Exception {
        // TODO Auto-generated method stub
        //Collection collections = new ArrayList();//【未生成 方法之前】数组长度是4 自然数组 有一个放一个

        InputStream ips =new FileInputStream("config.properties"); //加载properties文件
        Properties props = new Properties();
        props.load(ips);
        ips.close();//关门
        String className = props.getProperty("className");
        Collection collections = (Collection)Class.forName(className).newInstance();


        //Collection collections = new HashSet();
        //【未生成 方法之前】数组长度是3 有相同的第二个开始就不放了
        //【生成之后】数组长都为2,相同的就不再放了

        ReflectPoint pt1 = new ReflectPoint(3,3);
        ReflectPoint pt2 = new ReflectPoint(5,5);
        ReflectPoint pt3 = new ReflectPoint(3,3);

        collections.add(pt1);
        //collections.add(new ReflectPoint(3,3));
        collections.add(pt2);
        collections.add(pt3);
        collections.add(pt1);

        System.out.println(collections.size());


    }

}

——- android培训java培训、期待与您交流! ———-

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值