Java基础知识之——反射
来源:互联网 发布:海陆丰制毒 知乎 编辑:程序博客网 时间:2024/06/06 14:16
决定从现在开始养成写博客记录学习过程的习惯,所以把最近学的反射相关知识整理一下。
首先,什么是反射?
从概念上说,反射主要是指程序可以访问、检测和修改它自身状态或行为的一种能力。
而我的理解是:常规操作一个类需要实例化它的对象,然后操作它的数据成员或成员函数,在逻辑是是由上而下的;
而反射不同,它是反过来获取类的类类型(Class Type),而后再进行操作,有一种由下而上的感觉。
区别在哪里呢?
打个比方,大多数包装好的类他们的对象都是一个宝库,但我们往往只会用到其中的一部分,由多变少;
而反射则是通过仅仅一个对象获取到整个类的全部信息,由少变多。
换个说法:对象照了下镜子,反射 出了它作为一个类的全貌。
同时,反射机制在java中是动态的,你完全可以写一个可能根本不存在的class交给编译器处理,而且能够通过编译。
即:程序运行时,允许改变程序结构或变量类型
java虽然一般归类为静态语言,但是它有反射这样一个动态的机制。
其次,反射具体是什么?
java里万事万物皆对象,这句话大家应该都知道,Object类是这句话的一个保证,它是java里所有类的父类。
Class类是Object的一个特别的子类,是一个描述类自身的类,也是反射(Reflection)的起源。
一个类应当有些什么呢?数据成员?成员函数?构造器?
Class类封装了描述数据成员的Field、描述方法的Method和描述构造器的Constructor等属性。
在
java.lang.Class
java.lang.reflect.Field
java.lang.reflect.Method
java.lang.reflect.Constructor
java.lang.reflect.Modifier
五个类的API中我们可以了解到反射的绝大多数操作方法。
再次,反射有什么用?
从最简单的开始,作为一个菜鸟程序员,我很好奇编写java的大牛是怎么定义String的
那么我首先要得到String类的类类型,有三种方法可以做到这一点:
//通过Class的forName方法Class c1 = Class.forName("String");//通过每个类的class成员获取Class c2 = String.class;//通过该类的一个对象获取Class c3 = new String().getClass();
“现在,我的手里掌握了String的全部。”
/* * 万事万物皆对象,数据成员当然也是变量,java.lang.reflect.Field类封装了关于成员变量的操作 * 想看String的数据成员?可以用getField方法 获取所有public的数据成员 * 但是往往private的东西是我们更想看的,所以用getDeclaredFields获取所有自己声明的数据成员 */Field[] fs = c.getDeclaredFields();//现在Field的数组fs中就包含了String类的所有数据成员的信息//通过getType获取它们的类型Class fieldType = field.getType(); //通过getType获取它们的名称Class fieldName = field.getName();/* * 或者也可以写一个遍历来输出它们的类型和名称 * for(Field field:fs){ *Class fieldType = field.getType(); *//输出成员变量的类型以及名称 *System.out.println(fieldType.getName()+" "+field.getName()); * } */
类似的,可以通过Method类等类封装的方法来操作该类的成员方法等,在此不再赘述。
最后,通过反射深入研究泛型。
随意声明一个只能限制String类型的ArrayList
ArrayList<String> list = new ArrayList<String>();//我们可以自由地往里面加字符串list.add("233");//但是不能往里加其他类型的对象,如int//list.add(233); 报错
让我们做个实验,再声明一个无限制的ArrayList
ArrayList arr = new ArrayList();//获取它们俩的类类型Class c1 = list.getClass();Class c2 = arr.getClass();//输出它们是否相同System.out.println(c1==c2);//结果为true(可自行验证)事实上反射都是在编译后的操作(运行时处理), 即程序通过编译过后运行时泛型是不泛型的,java的泛型仅是防止错误输入。
仅在编译阶段有效 。
而反射获取的是.class,可以理解为获取了编译之后的字节码文件,也就是说:反射是在编译之后的操作(运行时处理)
这也反映了反射的动态性质,通过这个性质,我们可以绕过编译(为所欲为)。
try{//通过Method类的getMethod方法获取ArrayList的add方法Method m = c1.getMethod("add", Object.class);//再通过invoke方法,反向操作list对象,使其添加非String元素m.invoke(list, 233);//为所欲为!System.out.println(list);//但是不能通过for each来遍历现在的list,会有类型转换的错误} catch (Exception e) {e.printStackTrace();}
(水平尚浅,有何错误、不妥之处欢迎指教)
- Java基础知识之——反射
- java基础知识—Java中的反射机制
- java基础——反射基础知识
- Java基础知识——反射机制
- (Java 基础知识) Java反射
- 黑马程序员——java基础知识篇——>反射
- Java基础知识总结(八)——反射
- java反射基础知识
- Java基础知识_反射
- Java基础知识:反射
- Java基础知识:反射
- Java中的反射基础知识
- java反射基础知识汇总
- java基础知识-反射机制
- JAVA反射基础知识整理
- java反射基础知识总结
- java反射基础知识总结
- java反射基础知识
- 一道趣题(数学)
- imx6ul linux读取DS18B20温度
- 通过opencv训练自己的人脸分类器
- poj1113-graham学习
- iPhone is busy: Preparing debugger support for iPhone
- Java基础知识之——反射
- tensorflow笔记 :常用函数说明
- truncate 与 delete 使用上的区别
- Direct3D中的光照
- Linux下 环境变量/etc/profile、/etc/bashrc、~/.bashrc的区别
- 241. Different Ways to Add Parentheses
- 【我的Java笔记】第二课
- .NET开发常用工具大汇总
- 不同版本(2.3-3.1)web.xml文件的schema头部声明