黑马程序员——高新技术(反射)

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

反射的基石Class类

字节码:硬盘上类的代码编译成二进制代码。

获得类的字节码的方法:

Perso p = new Person();

1. Class cls1 = Person.class;

2.Class cls2 = p1.getClass();

3.Class cls3 = Class.forName("java.lang.String");//Class类中的静态方法 jvm中还没有这个类的字节码,就用类加载器去把类的字节码加载进内存来,然后缓存起来返回该字节码。

String str1 = "abc";
  Class cls1 = str1.getClass();
  Class cls2 = String.class;
  Class cls3 = Class.forName("java.lang.String");
  System.out.println(cls1 == cls2);//true
  System.out.println(cls1 == cls3);//true
  System.out.println(cls2 ==cls3);//true

System.out.println(cls1.isPrimitive());//false 判断该类型是否是原始类型。

System.out.println(int.class == Integer.TYPE);//.TYPE包装类型所包装的基本类型的字节码。

System.out.println(int[].class.isPrimitive());//数组也是一种类型,数组不是原始类型。

System.out.println(int[].class.isArray());//isArray()判断该类型是否是数组。

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

****反射:就是把Java类中的各种成分映射成相应的Java类。

1.构造方法的反射应用Constructor类。

Constructor [] constructors = Class.forName("java.lang.String").getConstructors();//得到所有构造方法返回一个数组

Constructor constructor1 = String.class.getConstructor(StringBuffer.class);//得到StringBuffer参数类型的构造方法。因为1.5新特性可变参数,可以写若干个参数,

2.成员类的反射应用Field类。

ReflectPoint pt1 = new ReflectPoint(3,5);

Field fieldY = pt1.getClass().getField("y");//filedY的值是多少?是5.错!filldy不是对象身上的变量,而是类上,要用它去取某个对象上对应的值

fieldY.get(pt1);//取出y这个变量在pt1这个对象中Y这个成员的值。

Filed fieldX = pt1.getClass().getDeclaredField("x");//只要是声明的变量都可以获得不管修饰符。

fieldX.setAccessible(true);//取消访问权限。

fieldX.get(pt1); //这种取出私有成员变量的值的方法叫做暴力反射。

 

把一个对象中所有String类型变量的b换成a

private static void changeStringValue(Object obj) throws Exception{
  Field[]fields = obj.getClass().getFields();
  for(Field field : fields){
   //field.getType().equals(String.class);
   if(field.getType() == String.class){//同一份字节码用==不用equals
    String oldValue = (String)field.get(obj);
    String newValue = oldValue.replace('b','a');
    field.set(obj,newValue);
   }
  }
  
 }

3.成员方法的反射应用Method类。

得到方法:

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

methodCharAt.invoke(str1,1);//在str1对象上调用charAt方法,方法参数为1//如果第一个参数为null,则为静态方法。

用反射方式执行某个类中的main方法。

为什么要用反射的方式去调?

String startingClassName = args[0];

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

mainMethod.invoke(null,new String[]{"111","222","333"});//不对 因为1.5可变参数把String[]当做一个Object数组给打开,吧每一个元素分别作为一个参数。

mainMethod.invoke(null,new Object[]{new String[]{"111","222","333"}});把String数组再打包当做Object数组中的第一个元素。

mainMethod.invoke(null,(Object)new String[]{"111","222","333"});//这样也可以

4.数组的反射

 有相同的元素相同的维度的数组是同一个类型。

 int []a1 = new int[3];

int [] a2 = new int[4];

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

String[]a4 = new String[3];

Object aObj1 = a1;

Object aObj2 = a4;

Object[] aObj3 = a1;//错。a1是一个Object。不能把他当做Object数组

Object[] aObj4 = a3;//一维数组是一个Object。二维数组可以看做Object数组中的元素是一维数组

Object[] aObj5 = a4;//String是一个Object,String数组可以看做Object中的元素是String

Arrays.asList(a1);//把al当做一个Object作为参数

Arrays.asList(a4);//把String数组当做一个Object数组,数组的元素作为参数,存入集合

数组的反射应用

private static void printObject(Object obj) {
  Class clazz = obj.getClass();//获得要打印对象的类型
  if(clazz.isArray()){//判断是否是数组
   int len = Array.getLength(obj);//获得obj这个数组长度。
   for(int i=0;i<len;i++){
    System.out.println(Array.get(obj,i));//获得obj这个数组第i个元素。
   }
  }else{
   System.out.println(obj);
  }
  
 }

反射的作用-->实现框架功能

InputStream ips = new FileInputStream("config.properties");

Properties props = new Properties();

props.load(ips);

ips.close();

String className = props.getProperty("className");

 

 Collection collections = (Collection)Class.forName(className).newInstance();

用类加载器的方式管理资源和配置文件。

Myeclipse把所有的.java文件编译成.class文件存到ClassPath指定目录下。把其他文件原封不动存到ClassPath指定目录下。

Strus框架的配置文件都是放在ClassPath指定的目录下,原因就是用类加载器加载的配置文件。

 InputStream ips = ReflectTest2.class.getClassLoader().getResourceAsStream("cn/itcast/day1/config.properties");//用类加载器的getResourceAsStream去加载

ReflectTest2.class.getResourceAsStream("resource/config.properties");//相对于ReflectTest2这个类所在包下的Resource目录下的config.properties。只需要写上配置文件的名字,不需要写上目录名,没用/打头表示相对路径,表示配置文件在我这个类所在的包

------- android培训java培训、期待与您交流! ----------详细请查看:http://edu.csdn.net

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值