黑马程序员_java之反射

反射

透彻分析反射的基础_Class类

JAVA类用于描述一类事物的共性,JAVA程序中的各个JAVA类属于同一类事物,类名就是Class.

Class类描述类的名字、访问属性、所属包名、字段、方法名称的列表等

一个类被类加载器加载到内存中,占用一个存储空间,不同类的字节码是不同的,但类型相同

得到字节码对应的实例对象?

类名.class; 对象.getClass(); Class.forName(“类名”)

作用:返回字节码

方式:字节码直接返回,加载后返回

九个预定义Class实例对象(八个基本类型+void

System.out.println(int.class.isPrimitive());//true 是否为原始类型

System.out.println(int.class = =Integer.class);//fasle

System.out.println(int.class = =Integer.TYPE);//true

System.out.println(int[].class.isPrimitive());//false 是否为原始类型

System.out.println(int[].class.isArray());//数组类型的Class实例对象用的是Class.isArray()

反射的概念

反射就是把JAVA类中的各种成分映射成相应的java类

一个类中的每个成员都可以用相应的反射API类的一个实例对象表示

构造方法的反射应用

Constructor类代表某个类的一个构造方法

得到所有的构造方法

Constructor<?>[] getConstructors()

得到某一个的构造方法

Constructor<T> getConstructor(Class<?>... parameterTypes)

创建实例对象

//new String(new StringBuffer("abc"));

//程序开发分为编译时和运行时 得到方法要类型,调用得到的方法要同样类型的对象

Constructor constructor1=String.class.getConstructor(StringBuffer.class);//得到构造方法

//反射方法创建实例

// 编译器不知道返回的是String的构造方法

String str2=(String)constructor1.newInstance(new StringBuffer("abc"));

System.out.println(str2.charAt(2));

Class. newInstance():

//得到默认的构造方法, 用该构造方法创建实例(用到了缓存机制来保存默认构造方法的实例对象)

String obj=(String) String.class.newInstance();

class-->constructor-->new object变成class -->new object

反射导致性能下降

成员变量的反射

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

//成员变量的反射

       ReflectPoint pt1=new ReflectPoint(3,5);

       Field fieldy=pt1.getClass().getField("y");

       //fieldy不是对象身上的变量,而是类上的变量

       System.out.println(fieldy.get(pt1));

       //x为私有,不可见

       //Field fieldx=pt1.getClass().getField("x");

       Field fieldx=pt1.getClass().getDeclaredField("x");

       fieldx.setAccessible(true);//暴力反射

       System.out.println(fieldx.get(pt1));

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

private static void changeStringValue(Object obj) throws Exception{

       Field [] fields=obj.getClass().getFields();

       for(Field field: fields){

           //字节码只有一份,用==好比较

           if(field.getType()==String.class){

              String oldValue=(String)field.get(obj);

              String newValue=oldValue.replace('b', 'a');

              field.set(obj, newValue);

           }

       }

    }

成员方法的反射

Method类代表某个类中的一个成员方法

得到类中的某一个方法

Method methodCharAt=String.class.getMethod("charAt", int.class);

调用方法

//通常方式str1.chaAt(1);

//反射方式

System.out.println(methodCharAt.invoke(str1, 1));// JDK1.5

System.out.println(methodCharAt.invoke(str1, new Object []{2}));//JDK1.4

//静态方法

//System.out.println(methodCharAt.invoke(null, 1));

对接受数组参数的成员方法进行反射

JDK1.5整个数组就是一个参数,JDK1.4数组中每一个元素对应一个参数

对接受数组参数的成员方法进行反射时会用JDK1.4

例:根据用户提供的类名,去执行该类的main方法

普通方法:

//TestArguments.main(new String[]{"11","22"});

反射方法:

//为什么要用反射?不知道类名,根据参数获得启动类名

String startingClassName=args[0];

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

//mainMethod.invoke(null,new String[]{"11","22"});

方法掉用一:mainMethod.invoke(null,new Object[]{ new String[]{"11","22"}});

方法掉用二:mainMethod.invoke(null, (Object)new String[]{"11","22"});

数组与Object的关系及其反射类型

数组反射的Class跟数组的维数和类型有关

具有相同维数和元素类型的数组属于同一个类型;

代表数组的Class实例对象的getSuperclass()返回的父类为Object类对应的Class

基本类型的一维数组可被当做Object类型使用,不可当做Object[]类型使用

非基本类型的一维数组可被当做Object类型使用,可当做Object[]类型使用

int [] a1=new int[]{1,2,3};

int [] a2=new int[4];

int [][] a3=new int[2][3];

String [] a4=new String []{"a","b","c"};

System.out.println(a1.getClass()==a2.getClass());//true

System.out.println(a1.getClass()==a4.getClass());//false

System.out.println(a1.getClass()==a3.getClass());//false

System.out.println(a1.getClass().getSuperclass().getName());

//java.lang.Object

System.out.println(a4.getClass().getSuperclass().getName());

Object aobj1=a1;

Object aobj2=a4;

//Object [] aobj3=a1;基本类型不是object

Object [] aobj4=a3;

Object [] aobj5=a4;

System.out.println(a1);

System.out.println(a4);

数组的反射应用

Array工具类用于完成对数组的反射操作

private static void printObject(Object obj) {

       Class clazz=obj.getClass();

       if(clazz.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);

       }

    }

只能得到某一个元素的具体类型,不能得到整个数组的类型

Object[] a=new Object[]{"a",1};

System.out.println(a[0].getClass().getName());

posted on 2013-01-28 16:00  念满  阅读(213)  评论(0编辑  收藏  举报