- 浏览: 24030 次
- 性别:
- 来自: 长春
最新评论
黑马程序员——反射
- 博客分类:
- 黑马程序员
----------------- android培训、java培训、期待与您交流! -----------------
反射 1. Class类 平常的java类是通过一些固定的支架(方法,成员变量等)搭建来的,搭建完成后它就具备了描述一类事物的特性。 而这些支架也属于事物,它也能够被类描述。所以java中就提供了Class类进行描述。 Class类所描述的事物是:java类在编译完成后,会生成class文件存在硬盘上。也就是 字节码。把字节码(保存了该类的基本信息)加载到内存中来。返回的类型是Class,当然 Class就具备了描述该类固定支架(方法,成员变量等)的特性。得到字节码的方法3种: 类名.class 例如,System.class 对象.getClass() 例如,new Date().getClass(); Class.forName(),例如,Class.forName("java.util.Date"); 1,如果字节码已经在内存中,直接拿过来就哦了。 2,如果字节码不在内存中,需要从硬盘上把字节码加载到内存中去。 2. 分析Class类。 package reflect; public class ReflectTest { public static void main(String[] args) throws ClassNotFoundException { String abc = "afd"; Class cls1 = abc.getClass(); Class cls2 = String.class; Class cls3 = Class.forName("java.lang.String"); // 虚拟机上做出该类一份字节码,其他要用就直接拿了。所以打印结果都为true System.out.println(cls1 == cls2); System.out.println(cls1 == cls3); // 判断是否是基本数据类型的字节码isPrimitive()。false System.out.println(cls1.isPrimitive()); // 基本类型的字节码和对应的封装类的字节码是不相同的。false、 System.out.println(int.class == Integer.class); // TYPE常量代表包装类型所包装的基本类型的字节码。true System.out.println(int.class == Integer.TYPE); // 数组的字节码类型,不是原始类型false。 System.out.println(int[].class.isPrimitive()); // 数组的字节码类型,判断一个Class类型是否为数组用isArray()。true System.out.println(int[].class.isArray()); // Class类型,判断基本数据类型:isPrimitive();判断数组类型:isArray(); // 总之:只要是在源程序中出的类型,都有各自的Class } } 3. 反射的概念。 反射就是把Java类中的各种成分映射成相应的java类。 4. Constructor类 Constructor类代表某个类中的一个构造方法。 //得到构造方法: 通过构造函数参数列表的类型,来确定获取的具体构造类。 Constructor<String> strCon = String.class.getConstructor(StringBuffer.class); // new String(new StringBuffer("abc")); //创建实例对象: // 1,在对strCon进行实例化对象的时候,需要指定参数对象。 String str2 = strCon.newInstance(new StringBuffer("abc")); System.out.println(str2.charAt(2)); // 2,Class类提供了一个便利,有newInstance方法。直接可以创建对象。省去了获取Constructor再去创建对象。 // 反射的缺点:反射比较消耗性能占用时间,进行反射以后把得出的结果存在缓存起来。为后面尽可能的减少反射的使用量。 String s = String.class.newInstance(); } 5. Field类 package reflect; import java.lang.reflect.Field; public class FieldDemo { public static void main(String[] args) throws SecurityException, NoSuchFieldException, InstantiationException, IllegalAccessException { ReflectPoint p = new ReflectPoint(3,5); // 字段通过字段名字区分。它不代表某个特定对象上面的值。而是告诉程序员,这个叫y的变量已经给你取到了。封装成了一个类。 // 类上的变量,不是对象上的变量。不包括私有的。 Field fieldY = p.getClass().getField("y"); // 从特定对象上取值。这个异常说明了,成员是私有的不让访问。 // Exception in thread "main" java.lang.NoSuchFieldException: y // at java.lang.Class.getField(Class.java:1520) // at reflect.FieldDemo.main(FieldDemo.java:10) System.out.println(fieldY.get(p)); // 获取所有申明的变量。包括private类型。 Field fieldX = p.getClass().getDeclaredField("x"); // java.lang.IllegalAccessException: Class reflect.FieldDemo can not access a member of class reflect.ReflectPoint with modifiers "private" // 上面异常的出现说明了,没有获取私有变量值的权限。 // 如果想要获取的话,需要进行暴力反射。 fieldX.setAccessible(true); System.out.println(fieldX.get(p)); // Class c = String.class; // String s = (String) c.newInstance(); // // String s1 = String.class.newInstance(); } } 将一个对象上所有的String类型的值中含有a的,进行替换。 private static void changeValue(ReflectPoint p) throws IllegalArgumentException, IllegalAccessException { // 获取ReflectPoint中所有申明的字段。 Field[] fs = p.getClass().getDeclaredFields(); // 遍历字段。 for(Field f:fs){ // getType获取Field的类型,用==好,因为字节码只有一份。如果是String类型的话,就进行操作。 if(f.getType()==String.class){ String oldValue = (String)f.get(p); String newValue = oldValue.replace("b", "a"); f.set(p,newValue); System.out.println(newValue); } } } } 反射的作用:你给我一个对象我能把他里面的值都改掉。例如Spring框架中用的就是这个技术。你给我一个类,我就能用你给的资源来做些事情。。 6. Method类 // 通过方法名字,和参数列表来确定方法。导包的时候看到com...这种包是内部用的(不要导),看到java...这就是外部用的。 String str = "abc"; Method methodCharAt = String.class.getMethod("charAt", int.class); // 已知Method,调用谁的Method并且还要给它传参数。 Character ch = (Character) methodCharAt.invoke(str, 2); System.out.println(ch); // 静态方法的调用,因为静态方法不需要对象。第一个参数应该是null。所以: // Character ch2 = (Character) methodCharAt.invoke(null, 2); String className= args[0]; invokeMain(className); } // 专家模式:只要类中有这个私有的数据,对这个数据的操作只能是我这个类的方法。 // 谁享有数据,谁就对这个数据有操作的权利。 7. 调用其他类的main方法。 为什么要用反射的方式调用main。 main的参数是String数组,数组里面可以装类名字符串。 获取这这些类的名字。通过反射的原理可以获得各个类中的main方法。 分别执行这几个类。 private static void invokeMain(String className) throws Exception { Method main = Class.forName(className).getMethod("main", String[].class); // main是静态,所以第一个参数是空的。 // java.lang.IllegalArgumentException: wrong number of arguments jdk1.4特点,给进去一个数组会将数组拆掉,拆掉后的值作为参数造成的。导致参数变多了。 main.invoke(null, new Object[]{new String[]{"1","2","3"}}); // main.invoke(null, (Object)new String[]{"1","2","3"}); } 8. 数组的反射。 package reflect; import java.lang.reflect.Array; import java.util.Arrays; public class ArrayReflectDemo { public static void main(String[] args) { int[] a = new int[3]; int[] a2 = new int[4]; int[][] a3 = new int[2][3]; String[] a4 = new String[3]; // 数组class是否相同:1.数据类型2数组的维数 System.out.println(a.getClass() == a2.getClass()); // 数组的父类是Object System.out.println(a4.getClass().getSuperclass().getName()); // Object aObj1 = a; Object aObj2 = a2; // 因为a是一维数组,里面装的是int型变量,不是Object子类。不行。 // Object[] obj1=a; // 二维数组,数组里面套数组。内层数组(一维数组)相当于是Object。可以 Object[] aobj3 = a3; // String数组里面装的是String类型的变量。可以 Object[] aobj4 = a4; System.out.println(Arrays.asList(a)); System.out.println(Arrays.asList(a4)); // 数组的反射。 printObjcet(a4); } private static void printObjcet(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)); } } } }
发表评论
-
黑马程序员——内省
2012-11-23 15:39 510-------------- ... -
黑马程序员——泛型
2012-11-23 09:06 667----------------- android培训、ja ... -
黑马程序员——枚举
2012-11-22 09:54 572----------------- android培训、jav ... -
黑马程序员——银行业务调度系统
2012-11-21 21:31 500----------------- an ... -
黑马程序员——交通灯管理系统
2012-11-20 10:28 697----------------- android培训、ja ... -
黑马程序员——TCP协议
2012-11-17 09:19 722----------------------------an ... -
黑马程序员——网络编程概述和UDP
2012-11-17 09:07 657----------------- android培训,jav ... -
黑马程序员——File和特殊流对象
2012-11-03 14:38 763-------------------------- an ... -
黑马程序员——Java_IO操作
2012-10-31 20:48 930--------------------------- ...
相关推荐
黑马程序员——Android移动开发源码
NULL 博文链接:https://xianglachigen.iteye.com/blog/1564376
黑马程序员入学Java知识——精华总结
|--aidl之结合反射获取应用缓存大小等空间占用 |--aidl调用系统service未公开的方法挂电话 |--aidl调用系统未公开的方法代码示例2 |--android dp和px之间转换 |--android INSTALL_PARSE_FAILED_MANIFEST_MALFORMED |...
正在自学黑马程序员Java全套,目前只学了Javase,接下来是Javaweb,把自己整理的笔记分享一下。
黑马程序员Javaweb教材源代码,适合学习配套使用
黑马程序员 C语言提高课程配套课件 黑马程序员 C语言提高课程配套课件
黑马程序员c++配套课件 《轻松搞定c++语言》 黑马程序员c++配套课件 《轻松搞定c++语言》
《JavaWeb程序设计任务教程》一书源代码,中国工信出版社出版,黑马程序员编著,传智播客旗下高端教育品牌“黑马程序员”项目实战配套用书
黑马程序员,C++核心编程
Javaweb基础全课程笔记,黑马程序员上课笔记,主要涉及前端 jsp和servlet等
layui ajax 没有node.js功能都可用,高度类似。 黑马刘龙彬老师主讲的大事件项目,整体看完,给...最后,再次给黑马程序员和刘老师点个赞。 说明--ShowDoc https://www.showdoc.com.cn/escook?page_id=3707158761215217
黑马程序员入学面试题,复习必备,事半功倍。
本人参加黑马程序员考试的题目加上本人的解答!不是让谁作弊,因为题库的题目对每个人会有些许的变化。题库题目的难度很类似,就当是你参加模拟考试了!哈哈,附本人的详解的哦!
黑马程序员网上图书商城中的毕业设计资料,代码,数据库设计论文等
《JavaWeb程序开发进阶》-黑马程序员配套资源ppt。
Netty基础,用于学习Netty,参考黑马程序员的netty教程
《MySQL数据库原理、设计与应用》课后习题及答案 黑马程序员编著 答案都是正确的,因为是老师给的资源。 如果不想下载,也可以去我的博客看,一模一样的。 ...
月薪过万的入门必知知识,黑马程序员入学Java精华总结
黑马程序员JavaEE49期