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

黑马程序员-框架技术实现的手段-反射基础

2015-06-01 14:55 549 查看
------------android培训        java培训    期待与您的交流!--------------

/*
* 反射的基础------->Class类:描述各个Java类的一个类
* 字节码 一个类的标识,使用时,从硬盘上加载进来
*/

//得到字节码对应的实例对象的三种方式
  Date date=new Date();
  Class c1=Date.class     //--> 通过类名:c1指向内存中已加载的类的字节码
  date.getClass();        //--> 通过类创建的实例对象:调用getClass方法返回自己所属于的字节码
  Class.forName("java.lang.String");  //--> 通过Class类的静态方法  比较常用 可以由String临时送进来
                                      //如果已经加载,则直接返回类的字节码,没有加载过,则调用类加载器去加载到缓存区,再返回

//八个基本类型 boolean byte char short int long float double和一个void都有Class objects
 

 //反射实例代码1 Class基本分析
 public class ReflecTest1
 {
     public static void main(String [] args ) throws Exception
     {
            
     }
     public static void test1() throws Exception
     {
        String str1="hello";
        Class c1=str1.getClass();
        Class c2=String.class;
        Class c3=Class.forName("java.lang.String");

        //验证他们在内存中是否是同一个字节码
        System.out.println(c1==c2);    //true
        System.out.println(c1==c3); //true
        

        System.out.println(c1.isPrimitive());   //是否是基本类型 否
        System.out.println(int.class==Integer.class); //false
        System.out.println(int.class==Integer.TYPE);    //常量标示被包装的基本类型
        System.out.println(int [].class.isPrimitive());  //数组不是基本类型  数组类型的Class实例对象用Class.isArray()

//总之,只要是在源程序中出现的类型,都有各自的Class实例对象
     }
 }

 //反射实例代码2   反射知识
/*
*反射就是把Java类中的各种成分  映射成相应的所属的Java类

*Class表示Java类

*以下类都是对不同java类的不同成分的统一管理
*Method类         代表某个类的一个成员方法
*Constructor类   代表某个类中的构造方法
*Field类         代表某个类的一个成员变量

*/

//Constructor类分析
    //通过参数来区别所要获取的构造方法 jdk.1.5之后的可变参数
    Constructor const1=String.class.getCostructor(StringBuffer.class); //const1反射String类的一个构造方法
    
    //实现const1反射的构造方法  要用到相同的参数类型,否则会报错
    String str2=(String)const1.newInstance(new StringBuffer("hello"));

    //Class.newInstance()------>对应无参数的构造方法
    String str21=(String)Class.forName("java.lang.String").newInstance();

//Field类分析与案例
public class ReflectPoint
{
    private int x;
    public int y;
    public ReflectPoint(int x,int y)
    {
        super();
        this.x=x;
        this.y=y;
    }
}
import java.lang.reflect.Field;
public class ReflectPointTest
{
    public static void main(String [] args ) throws Exception
    {
        ReflectPoint pt1=new ReflectPoint(5,20);
        Field fY=pt1.getClass().getField("y");//将类的y字段转为Field对象
        //--->fY不代表一个某个对象的具体值,只代表类上一个变量
        System.out.println(fY.get(pt1));    //取出对象pt1的y变量的值

        Field fX=pt1.getClass().getDeclaredField("x");//只要定义了就能让你反射到。(不管这个变量是否私有)
        //暴力反射
        fX.setAccessible(true); //私有变量可以通过get获取到
        System.out.println(fX.get(pt1));
    
    }
}

//关于Field的一个反射小案例:将任意的一个对象中的所有String类型的成员变量所对应的字符串内容的'b'改写成'a'
import java.lang.reflect.Field;
class ReflectPoint1
{
    public String str1="abcde";
    public String str2="borball";
    public String str3="niubi";
    
    @Override
    public String toString()
    {
        return str1+"\t"+str2+"\t"+str3;
    }
}
class ReflectPoint1Test
{
    public static void main(String [] args)throws Exception
    {
        ReflectPoint1 rp1=new ReflectPoint1();
        changeStringValue(rp1);
        System.out.println(rp1);
    }
    public static void changeStringValue(Object obj) throws Exception   //将案例单独做成一个函数
    {
        Field [] fields=obj.getClass().getFields();
        for (Field field:fields)                        //加强版的for循环
        {
            if(field.getType()==String.class)            //字段都有类型,两个字节码的比较用==,而不用equals,字节码就一份
            {
                String oldValue=(String)field.get(obj); //取得字段的值
                String newValue=oldValue.replace('b','a'); //替换字符
                field.set(obj,newValue);                //新的字段写入对象
            }
        }
    }
}

//Method类分析与案例
import java.lang.reflect.Method;
//Method的用法
class MethodTest
{
    public static void main(String [] args) throws Exception{
        Method funCharAt=String.class.getMethod("charAt",int.class);        //funCharAt就是String的成员方法CharAt();这里也一样通过参数区分重载问题
        String str1="abcde";
        //如果第一个参数是null;说明是静态方法 下面等价于str1.CharAt(1);
        System.out.println(funCharAt.invoke(str1,1));   //调用Method的invoke来实现被其反射到的方法
    }
}

//小案例要求: 写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法
class MethodTest1
{
    public static void main(String []args ) throws Exception
    {
        MethodTest.main(new String [] {});//普通方式调用
        //反射方式,在不知道类名,类名由args[0]传入
        String className=args[0];
        Method funMain=Class.forName(className).getMethod("main",String [].class); //反射到你传入的那个类的main方法

        funMain.invoke(null,new Object[]{new String[]{"dawd","daw"}});               //必须将数组在封装成一个对象,数组才不会拆包
                    //(null,(Object)new String[]{"dawd",dwad}) 这两种方式在调用这个数组时都不会将数组拆包                        
    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 反射 Class Method