Java reflect 反射学习笔记
1. class 类的使用
- 万事万物皆对象 (基本数据类型, 静态成员不是面向对象), 所以我们创建的每一个类都是对象, 即类本身是java.lang.Class类的实例对象, 但是这些对象不需要 new 出来, 因为java.lang.Class类的构造方法是私有的;
- 任何一个类都是Class类的实例对象.这个实例对象有_三种表达方式_: (我们新建一个Student类)
Class c1 = Student.class; // 实际告诉我们任何一个类都有一个隐含的静态成员变量class(知道类名时用)
Student stu = new Student();
Class c2 = stu.getClass(); // 已知该类的对象通过getClass方法(知道对象时用)
try {
Class c3 = Class.forName("com.cnblogs.reflect.Student");// 会有一个ClassNotFoundException异常
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
ps: 官网解释说, c1, c2表示 Student类的类类型(class type), 类也是对象, 是Class类的实例对象, 这个对象我们称之为该类的_类类型_
这里有一点值得注意的是: 当我们执行System.out.println(c1 == c2)
时, 结果是true
, 这是为什么? 原因是不管c1, c2都代表了Student类的类类型, 一个类可能是Class类的一个实例对象.
我们完全可以通过类的类类型创建该类的对象实例, 即通过c1或者c2创建Student的实例;
Student stu = (Student) c1.newInstance(); // 前提是Student里必须要有无参构造方法, 否则会报异常
2. 动态加载类
- 编译时加载类是静态加载类
new 创建对象是静态加载类, 在编译时刻就需要加载所有可能使用到的类, 如果有一个缺失, 那么整个文件都无法通过编译; - 运行时加载类是动态加载类
3. 获取方法信息
- 基本的数据类型,
void
关键字都存在类类型
Class c1 = int.class; // int的类类型
Class c2 = String.class; // String的类类型, 可以理解为编译生成生成的那个String.class字节码文件
Class c3 = double.class;
Class c4 = Double.class;
Class c5 = void.class;
- Class类的基本API操作
public static void printClassMessage(Object obj) {
Class c = obj.getClass();
// 获取类的类名称;
System.out.println("类的名称是: " + c.getName());
System.out.println("---------------------------------");
Method[] methods = c.getMethods();
for (Method method : methods) {
// 得到方法返回值类型的类类型
Class returnType = method.getReturnType();
System.out.println("returnType = " + returnType.getName());
// 得到方法的名称
System.out.println("method = " + method.getName());
// 获取参数类型 -> 得到的是参数列表的类类型
Class<?>[] parameterTypes = method.getParameterTypes();
for (Class parameterClass : parameterTypes) {
System.out.println("parameterClass = " + parameterClass.getName());
}
System.out.println("---------------------------------");
}
}
4. 获取成员变量构造函数信息
public static void printFieldMessgae(Object obj) {
Class<?> c = obj.getClass();
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
// 得到成员变量的类型的类类型
Class<?> fieldType = field.getType();
String typeName = fieldType.getName();
System.out.println("typeName = " + typeName);
// 得到成员变量的名称
String fieldName = field.getName();
System.out.println("fieldName = " + fieldName);
}
/**
* 获取构造函数
*/
Constructor<?>[] constructors = c.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println("constructor = " + constructor.getName());
/**
* 获取构造函数的参数的类类型
*/
Class<?>[] parameterTypes = constructor.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println("parameterType = " + parameterType.getName());
}
}
}
5. 方法反射的基本操作
- 如何获取某个方法
方法的名称和方法的参数列表才能决定某个方法
Method m = c.getDeclaredMethod("方法名", 可变参数列表(参数类型.class))
- 方法的反射操作
m.invoke(对象, 参数列表)
方法如果没有返回值, 返回null, 如果有返回值, 返回Object,
然后再强转为原函数的返回值类型;
6. 通过反射了解集合泛型的本质
ArrayList list1 = new ArrayList();
ArrayList<String> list2 = new ArrayList();
Class c1 = list1.getClass();
Class c2 = list2.getClass();
System.out.println(c1 == c2); // -> true
Ps: 因为反射的操作都是编译之后的操作, 也就是运行时的操作, c1 == c2
返回true
, 说明编译之后集合的泛型是去泛型化的.
那么我们可以理解为, Java集合中的泛型, 是用于泛指错误类型元素输入的, 比如在list2中我们add一个int, add(10)就会编译保错, 那么这个泛型就可以只在编译阶段有效, 通过了编译阶段, 泛型就不存在了. 可以验证, 我们绕过编译, 用反射动态的在list2中add一个int是可以成功的. 只是这时因为list2中存储了多个不同类型的数据(String和int), 就不能用for-each来遍历了, 会抛出类型转换错误.
Java reflect 反射学习笔记的更多相关文章
- Java虚拟机内存溢出异常--《深入理解Java虚拟机》学习笔记及个人理解(三)
Java虚拟机内存溢出异常--<深入理解Java虚拟机>学习笔记及个人理解(三) 书上P39 1. 堆内存溢出 不断地创建对象, 而且保证创建的这些对象不会被回收即可(让GC Root可达 ...
- 《深入理解Java虚拟机》学习笔记
<深入理解Java虚拟机>学习笔记 一.走近Java JDK(Java Development Kit):包含Java程序设计语言,Java虚拟机,JavaAPI,是用于支持 Java 程 ...
- JAVA GUI编程学习笔记目录
2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...
- Java多线程技术学习笔记(二)
目录: 线程间的通信示例 等待唤醒机制 等待唤醒机制的优化 线程间通信经典问题:多生产者多消费者问题 多生产多消费问题的解决 JDK1.5之后的新加锁方式 多生产多消费问题的新解决办法 sleep和w ...
- Java安全防御学习笔记V1.0
Java安全防御学习笔记V1.0http://www.docin.com/p-766808938.html
- java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)
java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...
- java之jvm学习笔记三(Class文件检验器)
java之jvm学习笔记三(Class文件检验器) 前面的学习我们知道了class文件被类装载器所装载,但是在装载class文件之前或之后,class文件实际上还需要被校验,这就是今天的学习主题,cl ...
- java之jvm学习笔记五(实践写自己的类装载器)
java之jvm学习笔记五(实践写自己的类装载器) 课程源码:http://download.csdn.net/detail/yfqnihao/4866501 前面第三和第四节我们一直在强调一句话,类 ...
- java之jvm学习笔记四(安全管理器)
java之jvm学习笔记四(安全管理器) 前面已经简述了java的安全模型的两个组成部分(类装载器,class文件校验器),接下来学习的是java安全模型的另外一个重要组成部分安全管理器. 安全管理器 ...
随机推荐
- 微信小程序之下拉加载和上拉刷新
微信小程序下拉加载和上拉刷新两种实现方法 方法一:onPullDownRefresh和onReachBottom方法实现小程序下拉加载和上拉刷新 首先要在json文件里设置window属性 ...
- ACtiveMQ中间件-发布订阅模式
前言:ActiveMQ学习心得 1.MQ是什么 MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过读写出入队列的消息(针对应用程序的数据)来通信, ...
- 【慕课网实战】Spark Streaming实时流处理项目实战笔记三之铭文升级版
铭文一级: Flume概述Flume is a distributed, reliable, and available service for efficiently collecting(收集), ...
- 记录:CSS选择器学习
常用选择器:标签选择器.类选择器.ID选择器 子选择器(Child selectors) 还有一个比较有用的选择器子选择器,即大于符号(>),用于选择指定标签元素的第一代子元素. .con> ...
- python特殊方法定制类
#coding:utf-8class RoundFloat(object): def __init__(self,val): assert isinstance(val, float),"v ...
- Javaweb异常提示信息统一处理
Java异常封装(自己定义错误码和描述,附源码) 2016年01月29日 22:30:54 小宝鸽 阅读数:23262 标签: java异常 更多 个人分类: Java基础 所属专栏: Java工作实 ...
- 最长上升子序列 and 最长公共子序列 问题模板
两种求最长上升子序列问题 第一种:定义dp[i]=以a[i]为末尾的最长上升子序列问题的长度 第二种:定义dp[i]=长度为i+1的上升 子序列 中末尾元素的最小值 #include <cstd ...
- hdu 5092 线裁剪(纵向连线最小和+输出路径)
http://acm.hdu.edu.cn/showproblem.php?pid=5092 给一个m*n的矩阵,找到一个纵向的"线"使得线上的和最小并输出这条线,线能向8个方向延 ...
- 合成的默认构造函数定义为delete的一种情况(针对C++11标准)
1. 默认初始化 如果定义变量时没有指定初值,则变量会被默认初始化,此时变量被赋予了"默认值". 对于类类型的变量来说,初始化都是依靠构造函数来完成的.因此,即使定义某个类的变量( ...
- play framework - 初识
背景 研发代码框架是play-framework框架,想看代码的话,需要学习下play框架.IDE工具的话之前一直用的idea,所以本文涉及的idea play的配置 和 一些play的简单知识 认识 ...