Java基础教程:反射基础

引入反射

反射是什么

  能够动态分析类能力的程序称为反射。反射是一种很强大且复杂的机制。

Class类

  在程序运行期间,Java运行时系统始终为所有对象维护一个被称为运行时的类型标识。这个对象追踪着每个对象所属的类。虚拟机利用运行时类的信息选择相应的方法执行

  我们可以通过专门的Java类访问这些信息。保存这些信息的类称为Class。

直接获取

Class cl1 =Date.class;
Class cl2 = Integer.class;

根据对象获得类信息

MyClass myClass;
.....
Class cl = myClass.getClass();
cl.getName(); //获得类名

调用静态方法forName获得类名相应的Class对象。

String className = 'java.util.Date';
Class cl = Class.forName(className);

注意:

  虚拟机为每一个类型管理一个Class对象。因此使用==可以实现两个类对象比较的操作

利用反射分析类的能力

API函数举例

  • getDeclaredFields():获得此类对象所表示的类或接口所声明的所有字段。
  • getFields():输出类以及其所继承的父类的 public 字段
  • getDeclaredMethods():获得此类对象所表示的类或接口所声明的所有方法,包括公共、保护、私有但不包括继承。
  • getDeclaredConstructors() :返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。
  • getName():获得此class所表示实体的名称。

示例:输出字段

  GetFields只会输出publicStr,GetDeclaredFields则会忽略访问控制符输出所有字段

public class MyClass{

    public String publicStr;
private String privateStr;
protected String protectedStr; public static void main(String[] args) {
//获取Class类
Class c1 = MyClass.class;
//调用GetFields()
for(Field field : c1.getFields()){
System.out.println(field.getName());
}
System.out.println("=============");
//调用GetDeclaredFields()
for(Field field : c1.getDeclaredFields()){
System.out.println(field.getName());
}
}
}

示例:输出方法

  getDeclaredMethods只会输出本类的所有方法!

public class MyClass{

    public void publicFun(int a){}
private void privateFun(int a){}
protected void protectFun(int a){} public static void main(String[] args) {
//获取Class类
Class c1 = MyClass.class; //2.1 获取所有 public 访问权限的方法
//包括自己声明和从父类继承的
//Method[] mMethods = c1.getMethods(); //2.2 获取所有本类的的方法(不问访问权限)
Method[] mMethods = c1.getDeclaredMethods(); //3.遍历所有方法
for (Method method :
mMethods) {
//获取并输出方法的访问权限(Modifiers:修饰符)
int modifiers = method.getModifiers();
System.out.print(Modifier.toString(modifiers) + " ");
//获取并输出方法的返回值类型
Class returnType = method.getReturnType();
System.out.print(returnType.getName() + " "
+ method.getName() + "( ");
//获取并输出方法的所有参数
Parameter[] parameters = method.getParameters();
for (Parameter parameter :
parameters) {
System.out.print(parameter.getType().getName()
+ " " + parameter.getName() + ",");
}
//获取并输出方法抛出的异常
Class[] exceptionTypes = method.getExceptionTypes();
if (exceptionTypes.length == 0) {
System.out.println(" )");
} else {
for (Class c : exceptionTypes) {
System.out.println(" ) throws "
+ c.getName());
}
}
}
}
}

  调用getDeclaredMethods输出结果:

  • public static void main( [Ljava.lang.String; arg0, )
  • protected void protectFun( int arg0, )
  • private void privateFun( int arg0, )
  • public void publicFun( int arg0, )

  调用getMethods输出结果:

  • public static void main( [Ljava.lang.String; arg0, )
  • public void publicFun( int arg0, )
  • public final void wait( ) throws java.lang.InterruptedException
  • public final void wait( long arg0,int arg1, ) throws java.lang.InterruptedException
  • public final native void wait( long arg0, ) throws java.lang.InterruptedException
  • public boolean equals( java.lang.Object arg0, )
  • public java.lang.String toString( )
  • public native int hashCode( )
  • public final native java.lang.Class getClass( )
  • public final native void notify( )
  • public final native void notifyAll( )

在运行时使用反射分析对象

API函数举例

  • setAccessible(boolean flag):为反射对象设置可访问标志。为true使得对象的私有属性也可以被查询和设置。
  • getField(): 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
  • get(Object obj):返回对象中用Field对象表示的域值。
  • set(Object obj,Object newValue):用一个新值设置Obj对象中的Field对象表示的域。

示例:获取并设置对象的私有字段值

public class MyClass{

    private String context = "Hello World";

    public static void main(String[] args) {
//获取Class类
Class c1 = MyClass.class;
try {
//构建对象
Object myClass = c1.newInstance();
//获取私有变量
Field context = c1.getDeclaredField("context");
//获取私有变量访问权
context.setAccessible(true);
//访问私有变量值
System.out.println(context.get(myClass));
//设置私有变量值
context.set(myClass, "Hi Boy!");
System.out.println(context.get(myClass));
} catch (Exception e) {
e.printStackTrace();
}
}
}

利用反射调用任意方法

API函数说明

   public Object invoke(Object obj,Object... args)

  • 参数:obj - 从中调用底层方法的对象args - 用于方法调用的参数
  • 返回:使用参数 args 在 obj 上指派该对象所表示方法的结果

示例:调用私有方法

public class NCConfgCliService {

    private void privateFun(int a){
System.out.println(a);
} public static void main(String[] args) {
//获取Class类
Class c1 = NCConfgCliService.class;
try {
//获取私有方法
Method privateMethod = c1.getDeclaredMethod("privateFun",int.class);
//创建类的实例
Object obj = c1.newInstance();
//调用私有方法
privateMethod.invoke(obj,10);
} catch (Exception e) {
e.printStackTrace();
}
}
}

Java基础教程:反射基础的更多相关文章

  1. Java基础教程——反射机制

    Java反射机制 Java反射机制是Java语言的一个重要特性,使得Java语言具备"动态性": 在运行时获取任意一个对象所属的类的相关信息; 在运行时构造任意一个类的对象: 在运 ...

  2. Java基础教程——网络基础知识

    参考阅读[中国互联网发展史]:https://zhuanlan.zhihu.com/p/61602252 协议 计算机网络中的通信必须有一些约定,这些约定称为"通信协议". 通信协 ...

  3. php基础教程-必备基础知识

    PHP 脚本在服务器上执行. 您应当具备的基础知识 在继续学习之前,您需要对下面的知识有基本的了解: HTML CSS JavaScript 如果您希望首先学习这些项目,请在我们的 首页 访问这些教程 ...

  4. Python笔记_第五篇_Python数据分析基础教程_NumPy基础

    1. NumPy的基础使用涵盖如下内容: 数据类型 数组类型 类型转换 创建数组 数组索引 数组切片 改变维度 2. NumPy数组对象: NumPy中的ndarray是一个多维数组对象,该兑现共有两 ...

  5. C#基础系列 - 反射基础

    反射用于在程序运行过程中,获取类里面的信息或发现程序集并运行的一个过程.通过反射可以获得.dll和.exe后缀的程序集里面的信息.使用反射可以看到一个程序集内部的类,接口,字段,属性,方法,特性等信息 ...

  6. cocos基础教程(4)基础概念介绍

    在Cocos2d-x-3.x引擎中,采用节点树形结构来管理游戏对象,一个游戏可以划分为不同的场景,一个场景又可以分为不同的层,一个层又可以拥有任意个可见的游戏节点(即对象,游戏中基本上所有的类都派生于 ...

  7. .Net程序员之Python基础教程学习----列表和元组 [First Day]

    一. 通用序列操作: 其实对于列表,元组 都属于序列化数据,可以通过下表来访问的.下面就来看看序列的基本操作吧. 1.1 索引: 序列中的所有元素的下标是从0开始递增的. 如果索引的长度的是N,那么所 ...

  8. React-Native基础教程

    React-Native牛刀小试仿京东砍啊砍砍到你手软 React-Native基础教程 *React-Native基础篇作者git *React-Native官方文档 *Demo 几个月前faceb ...

  9. 学习参考《Python基础教程(第3版)》中文PDF+英文PDF+源代码

    python基础教程ed3: 基础知识 列表和元组 字符串 字典 流程控制 抽象(参数 作用域 递归) 异常 魔术方法/特性/迭代器 模块/标准库 文件 GUI DB 网络编程 测试 扩展python ...

随机推荐

  1. html5 的a标签是可以拨电话的,通过其Href属性来实现

    <a href="tel:18700000000">点击给我打电话吧!</a> 注: 1.<a href="tel:18750000000& ...

  2. 阿里CI/CD、DevOps、分层自动化技术

    原文地址:http://www.infoq.com/cn/news/2017/01/alibaba-yunxiao-cicd-devops 在互联网时代,产品快速迭代的重要性不言而喻.不管是传统企业还 ...

  3. Github上的PHP开源资源汇总

    依赖管理 ——用于依赖管理的包和框架 Composer/Packagist : 一个包和依赖管理器 Composer Installers:  一个多框架Composer库安装器 Pickle: 可以 ...

  4. ANDROID L——Material Design具体解释(主题和布局)

    转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990).谢谢支持! Android L: Google已经确认Android L就是Android Lolli ...

  5. setpgid()

    #include<unistd.h> int setpgid(pid_t pid,pid_t pgid); 函数作用:将pid进程的进程组ID设置成pgid,创建一个新进程组或加入一个已存 ...

  6. .net之GridView、DataList、DetailsView(一)

    GridView:两种数据绑定方法 方法一:得到数据后,赋给DataSource属性,然后执行控件的DataBind()方法. BLL.Article bll = new BLL.Article(); ...

  7. Selection Problem (选择问题)

    在一个由n个元素组成的集合中,第i个“顺序统计量(order statistic)”是该集合中第i小的元素.例如,在一个由n个元素组成的集合中,最小值是第1个顺序统计量,最大值是第n个顺序统计量.而“ ...

  8. nginx 查看接口请求时间 每个请求图片的时间或者文件的

    根据nginx的access_log查看接口请求时间 muyuren 发表于 1年前 阅读 2300 收藏 0 推荐 0 评论 0 推荐 收藏 首先修改修改生成日志的格式,在nginx配置文件的htt ...

  9. Linux的各个文件夹名称解释(FHS)

    对于接触和已经接触过一段时间Linux的使用者来说,系统的各个文件夹名字还是挺让人费解的,什么etc,usr,var等等,大部分也是耳濡目染才有一个大概的概念,例如usr是存放自己编译安装的软件,et ...

  10. 并行归并排序——MPI

    并行归并排序在程序开始时,会将n/comm_comm个键值分配给每个进程,程序结束时,所有的键值会按顺序存储在进程0中.为了做到这点,它使用了树形结构通信模式.当进程接收到另一个进程的键值时,它将该键 ...