反射(reflect)

1. Class对象

1.1 什么是Class对象

当JVM加载某个class文件的时候,会自动创建一个唯一的Class对象(注意:由同一个类加载器加载的class文件),这个Class对象包含了整个class类的信息(例如:类的名称、访问修饰符、字段、字段描述、方法等等一切信息)。当使用new关键字创建这个类的实例时,jvm都会使用这个Class对象来创建类的实例。

1.1 获取Class对象方式

方式 说明
Test.class 通过类名.class直接获取
t1.getClass() 通过对象的getClass()方法获取
Class.forName("...") 使用Class类的forName静态方法获取,参数给的是完整类名(包名+类名)

2. 反射

2.1 什么是反射

所谓的反射,是在程序运行时动态获得任何一个Class对象的成员信息(类信息、字段、构造方法、成员方法等),并且能在运行时依据某个Class对象创建当前类的实例。

2.2 Class常用API

方法 说明
newInstance() 创建类实例
getName() 获取类的完整类名
getSimpleName() 获取类的简单类名
getPackage() 获取类对应的包信息
getSuperclass() 获取父类的Class对象
getInterfaces() 获取实现的所有接口
getClassLoader() 获取当前类的类加载器
getConstructor(..) 获取公共且明确参数类型的构造方法
getDeclaredConstructor(..) 获取受保护且明确参数类型的构造方法
getConstructors() 获取所有公共的构造方法
getDeclaredConstructors() 获取所有(包括受保护)的构造方法
getField(..) 根据字段名称获取某一个公共的字段
getDeclaredField(..) 根据字段名称获取当前类某一个的字段(包括受保护的)
getFields() 获取所有公共的字段,包括继承自父类的公共字段
getDeclaredFields 获取当前类所有字段,包括受保护的(不包括继承父类的字段)
getMethod(..) 根据方法名以及参数类型获取一个公共的方法
getDeclaredMethod(..) 根据方法名以及参数类型获取当前类的一个受保护的方法
getMethods() 获取所有公共的方法(包括继承自父类的公共方法)
getDeclaredMethods() 获取当前类的所有方法,包括受保护的(不包括继承父类的方法)
isAnnotation() 此Class是否是一个注解
isAnnotationPresent(..) 当前Class时是否定义了某个注解
getAnnotation(..) 获取当前类上定义的某个注解
getAnnotations() 获取当前类上定义的所有注解
isEnum() 此Class是否是一个枚举
isArray() 此Class是否是一个数组类型
isInterface() 此Class是否是一个接口
... 其他API请参照官方文档
public class TestClass {

public static void main(String[] args) throws Exception{
Class<?> clazz = Class.forName("edu.nf.reflect.Users");
//通过Class对象来创建实例,当前类必须提供一个公开并且无参的构造方法
Users user = (Users) clazz.newInstance();
//获取类的完整类名
System.out.println(clazz.getName());
//获取类的简单类名
System.out.println(clazz.getSimpleName());
//获取类所在的包名
System.out.println(clazz.getPackage().getName());
//获取当前类的父类的Class
System.out.println(clazz.getSuperclass());
//获取当前类实现的所有接口
System.out.println(clazz.getInterfaces());
//获取加载这个类的类加载器
System.out.println(clazz.getClassLoader());
//获取公共并且参数类型为String的构造方法
clazz.getConstructor(String.class);
//获取私有并且参数为int类型的构造方法
clazz.getDeclaredConstructor(Integer.TYPE);
//获取所有公共的构造方法
Constructor[] consArray1 = clazz.getConstructors();
//获取所有构造方法,包括公共和是有的
Constructor[] consArray2 = clazz.getDeclaredConstructors();
//获取某一个公共的字段,参数指定字段的名字
Field f1 = clazz.getField("address");
System.out.println(f1.getName());
//获取某一个受保护的字段
Field f2 = clazz.getDeclaredField("tel");
System.out.println(f2.getName());
System.out.println("-----------------------");
//获取所有公共的字段,包括继承自父类的公共字段
Field[] fieldArray1 = clazz.getFields();
for (Field field : fieldArray1) {
System.out.println(field.getName());
}
System.out.println("-----------------------");
//获取所有字段,包括受保护的(不包括继承父类的字段)
Field[] fieldArray2 = clazz.getDeclaredFields();
for (Field field : fieldArray2) {
System.out.println(field.getName());
}
System.out.println("-----------------------");
//获取某一个公共的方法(第一个参数指定方法名,第二个参数指定方法参数的类型,这是一个可变参数,有多少个参数就要指定多少个类型)
Method m1 = clazz.getMethod("say", String.class);
System.out.println(m1.getName());
//获取某一个受保护的方法
Method m2 = clazz.getDeclaredMethod("call");
System.out.println(m2.getName());
System.out.println("-----------------------");
//获取所有公共的方法(包括继承自父类的公共方法)
Method[] methodArray1 = clazz.getMethods();
for (Method method : methodArray1) {
System.out.println(method.getName());
}
System.out.println("-----------------------");
//获取本类的所有方法,包括受保护的(不包括父类的方法)
Method[] methodArray2 = clazz.getDeclaredMethods();
for (Method method : methodArray2) {
System.out.println(method.getName());
}
}
}

2.3 Class对象中的成员

成员 说明
Constructor 用于描述类的构造方法
Field 用于描述类的字段
Method 用于描述类的方法
Parameter 用于描述方法或构造方法的参数信息

2.3.1 Constructor常用API

API 说明
getName() 获取当前构造方法的名称
getParameterCount() 获取构造方法的参数个数
getDeclaringClass() 获取声明此构造方法的Class类
setAccessible(..) 设置访问开关
newInstance(..) 使用当前的Constructor构建实例
... 其他API请参照官方文档
public class TestCons {
public static void main(String[] args) throws Exception{
//加载Users的class信息,并构建Class对象
Class<?> clazz = Class.forName("edu.nf.reflect.Users");
//通过class对象访问构造方法信息,
// 根据构造方法的参数类型获取某一个公共的构造方法
Constructor cons1 = clazz.getConstructor(int.class);
// 访问受保护的构造方法
Constructor cons2 = clazz.getDeclaredConstructor(int.class);
//构造方法的名称
System.out.println(cons1.getName());
//获取构造方法的参数个数
System.out.println(cons1.getParameterCount());
//获取定义这个构造方法的Class类
System.out.println(cons1.getDeclaringClass());
//通过构造方法来创建类的实例
//由于构这个造方法是私有的,因此必须强制打开访问开关
cons1.setAccessible(true);
//然后通过newInstance方法来创建类的实例,并传入构造方法所需的参数
Users user = (Users)cons1.newInstance(21);
//获取所有的构造方法(包括私有和公有的)
Constructor[] cons = clazz.getDeclaredConstructors();
for (Constructor con : cons) {
System.out.println("参数个数: "+con.getParameterCount());
}
}
}
 

2.3.2 Field常用API

API 说明
getType() 获取当前字段类型
getName() 获取当前字段名称
get(..) 获取当前字段的值
set(..) 给当前字段赋值
setAccessible(..) 设置访问开关
... 其他API请参照官方文档
public class TestField {

public static void main(String[] args) throws Exception{
Class<?> clazz = Class.forName("edu.nf.reflect.Users");
//创建类的实例
Object instance = clazz.newInstance();
//获取一个受保护的字段
Field f = clazz.getDeclaredField("tel");
//打开访问开关
f.setAccessible(true);
//给字段赋值(第一个参数指定当前类的实例,第二个参数是具体的值)
f.set(instance, "123456");
//取值(get方法的参数也是指定当前类的实例)
System.out.println(f.get(instance));
//获取字段的类型
System.out.println(f.getType());
//获取字段的名称
System.out.println(f.getName());
}
}

2.3.3 Method常用API

API 说明
getName() 获取当前方法名称
getReturnType() 获取当前方法的返回值
getParameterCount() 获取当前方法参数的个数
getParameters() 获取当前方法的参数对象
getParameterTypes() 获取当前方法的所有参数类型
setAccessible(..) 设置访问开关
invoke(..) 回调当前的method
... 其他API请参照官方文档
public class TestMethod {

public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("edu.nf.reflect.Users");
//构建当前类的实例
Object instance = clazz.newInstance();
//获取受保护的call方法
Method method = clazz.getDeclaredMethod("call", String.class);
//获取方法的名称
System.out.println(method.getName());
//获取方法的返回值类型
System.out.println(method.getReturnType());
//获取方法参数的个数
System.out.println(method.getParameterCount());
//获取方法的所有参数对象
System.out.println(method.getParameters());
//获取方法中所有参数的类型
Class<?>[] paramsType = method.getParameterTypes();
for (Class<?> aClass : paramsType) {
System.out.println(aClass);
}
//调用当前方法(第一个参数是当前类的实例,第二个参数开始是方法所需的参数)
//invoke方法返回的是当前调用的方法的返回值
//这个方法是受保护的,因此需要先打开访问开关
method.setAccessible(true);
Object returnValue = method.invoke(instance, "12345678");
System.out.println(returnValue);
}
}

2.3.4 Parameter常用API

API 说明
getType() 获取参数类型
getName() 获取参数的名称(说明:JDK8默认编译的时候是不会将参数名信息保存在字节码中,如果想要获取参数名,那么在编译时就需要加上编译参数 ,如:javac -parameters Users.java)
... 其他API请参照官方文档
public class TestParameter {

public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("edu.nf.reflect.Users");
//先获取指定的受保护的方法
Method callMethod = clazz.getDeclaredMethod("call", String.class);
//获取该方法的参数信息
Parameter[] params = callMethod.getParameters();
for (Parameter param : params) {
//获取参数的类型
System.out.println(param.getType());
//获取参数的名称(在JDK8之前是没有办法获取参数名的,必须通过第三方字节码工具来获取)
//JDK8默认编译的时候是不会讲参数名信息保存在字节码中
//如果想要获取参数名,那么在编译时就需要加上编译参数
//如:javac -parameters Users.java
System.out.println(param.getName());
}
}
}
 

java反射笔记的更多相关文章

  1. java反射笔记(学习尚硅谷java基础教程)

    反射一.概述:Reflection Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性 ...

  2. Java系列笔记(2) - Java RTTI和反射机制

    目录 前言 传统的RTTI 反射 反射的实现方式 反射的性能 反射与设计模式 前言 并不是所有的Class都能在编译时明确,因此在某些情况下需要在运行时再发现和确定类型信息(比如:基于构建编程,),这 ...

  3. 【设计模式】学习笔记17:代理模式之保护代理与Java反射

    本文出自   http://blog.csdn.net/shuangde800 本笔记内容: 1. Java动态代理,反射机制 2. 保护代理 3. 应用保护代理实现的约会系统 ----------- ...

  4. java反射的理解与应用(某大神博客中看到的博文,写的真的太好了,果断转载作为笔记)

    原文地址:http://www.cnblogs.com/jqyp/archive/2012/03/29/2423112.html#undefined 一.什么是反射机制 简单的来说,反射机制指的是程序 ...

  5. Java开发笔记(七十八)面向对象的后门——反射

    作为一门面向对象的编程语言,Java认为一切皆是对象,每个对象都能归属于某个类,甚至每个类均可提取出一种特殊的类型,即Class类型.早在前面介绍多态的时候,就提到每个类都存在独一无二的基因,通过比较 ...

  6. Java开发笔记(七十九)利用反射技术操作私有属性

    早在介绍多态的时候,曾经提到公鸡实例的性别属性可能被篡改为雌性,不过面向对象的三大特性包含了封装.继承和多态,只要把性别属性设置为private私有级别,也不提供setSex这样的性别修改方法,那么性 ...

  7. Java开发笔记(八十)利用反射技术操作私有方法

    前面介绍了如何利用反射技术读写私有属性,不单是私有属性,就连私有方法也能通过反射技术来调用.为了演示反射的逆天功能,首先给Chicken鸡类增加下列几个私有方法,简单起见弄来了set***/get** ...

  8. JAVA学习笔记—review基本知识[反射与异常]

    JAVA学习笔记—review基本知识[反射与异常] 1.异常: 1.1异常的分类: Java会将所有的异常封装成对象,其根本父类为Throwable. Throwable有两个子类:Error 和E ...

  9. Java注解和反射笔记

    Java注解和反射笔记 1 注解 1.1 定义 Annotation是从JDK1.5开始引入的技术 作用 不是程序本身,可以对程序作出解释 可以被其他程序(编译器等)读取 格式 @注释名,可以添加一些 ...

随机推荐

  1. Python快速学习06:词典

    系列文章:[传送门] 上面讲的,特别是对象和类,大家好好体会. Python对象是Python语言的核心部分.今天介绍一个新类:词典(dictionary) 基本概念 字典是Python 中的映射数据 ...

  2. jvm详情——2、Java对象在jvm中的大小

    Java对象的大小 基本数据的类型的大小是固定的,这里就不多说了.对于非基本类型的Java对象,其大小就值得商榷.在Java中,一个空Object对象的大小是8byte,这个大小只是保存堆中一个没有任 ...

  3. 【转载】LINUX 和 WINDOWS 内核的区别

    LINUX 和 WINDOWS 内核的区别 [声明:欢迎转载,转载请注明出自CU ACCESSORY http://linux.chinaunix.net/bbs/thread-1153868-1-1 ...

  4. MyBatis源码解析(三)——Transaction事务模块

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6634151.html 1.回顾 之前介绍了Environment环境类,这其实是一个单例类 ...

  5. Linux下的java虚拟机性能监控与故障处理命令

    java包中提供了很多监控JVM的工具类,作为java程序员必须得掌握常用的几个工具,下面是几个常用的JVM性能监控与故障处理工具的介绍与使用. 1.jstack 该命令用于生成当前时刻虚拟机的线程快 ...

  6. shell的命令替换和命令组合

    bash&shell系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.html Linux中使用反引号"``"(在波浪线的 ...

  7. SHELL脚本--tr命令用法和特性全解

    bash&shell系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.html 1.1 简介 tr主要用于将从标准输入读取的数据进行结果集映射 ...

  8. ORA-28002:the password will expire within 6 days

    1.查看用户的proifle SELECT username,PROFILE FROM dba_users; 2.查看指定概要文件(如default)的密码有效期设置:SELECT * FROM db ...

  9. [转]Docker和Rancher的安装与基本使用

    本文转自:https://blog.csdn.net/wangshouhan/article/details/80405672 一.Docker1.CentOS下Docker安装 安装 $ yum - ...

  10. RNN-LSTM入门

    RNN-LSTM入门 Last Edited: Dec 02, 2018 10:20 PM Tags: 机器学习,论文阅读 RNN-Recurrent Neural Network 概念: 序列数据: ...