Java基础知识之——反射
2017-10-09 15:04
309 查看
决定从现在开始养成写博客记录学习过程的习惯,所以把最近学的反射相关知识整理一下。
首先,什么是反射?
从概念上说,反射主要是指程序可以访问、检测和修改它自身状态或行为的一种能力。
而我的理解是:常规操作一个类需要实例化它的对象,然后操作它的数据成员或成员函数,在逻辑是是由上而下的;
而反射不同,它是反过来获取类的类类型(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类的类类型,有三种方法可以做到这一点:
“现在,我的手里掌握了String的全部。”
类似的,可以通过Method类等类封装的方法来操作该类的成员方法等,在此不再赘述。
最后,通过反射深入研究泛型。
随意声明一个只能限制String类型的ArrayList
让我们做个实验,再声明一个无限制的ArrayList
仅在编译阶段有效 。
而反射获取的是.class,可以理解为获取了编译之后的字节码文件,也就是说:反射是在编译之后的操作(运行时处理)
这也反映了反射的动态性质,通过这个性质,我们可以绕过编译(为所欲为)。
(水平尚浅,有何错误、不妥之处欢迎指教)
首先,什么是反射?
从概念上说,反射主要是指程序可以访问、检测和修改它自身状态或行为的一种能力。
而我的理解是:常规操作一个类需要实例化它的对象,然后操作它的数据成员或成员函数,在逻辑是是由上而下的;
而反射不同,它是反过来获取类的类类型(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基础视频教程笔记(26 反射)
- Java基础知识_框架的概念以及用反射开发框架的原理
- java 基础知识(java 反射 用法总结)
- Java基础知识 十七 (关于反射一些方法的总结)
- JAVA反射基础知识整理
- java反射基础知识汇总
- Java中的反射基础知识
- java反射基础知识(一)
- java反射基础知识(五)反射应用实践
- java反射基础知识总结
- java基础知识---网络编程、反射技术、正则表达式
- 学习Spring必学的Java基础知识(1)----反射
- java基础——反射基础知识
- JAVA常用基础知识点[继承,抽象,接口,静态,枚举,反射,泛型,多线程...]
- 反射-----学习Spring必学的Java基础知识之一
- 学习Spring必学的Java基础知识(1)----反射
- java基础知识—Java中的反射机制
- Java基础知识:反射
- java基础知识巩固-----类加载机制与反射机制
- JAVA开发基础知识:解析并创建XML文件和Java的反射