作为一门面向对象的编程语言,Java认为一切皆是对象,每个对象都能归属于某个类,甚至每个类均可提取出一种特殊的类型,即Class类型。早在前面介绍多态的时候,就提到每个类都存在独一无二的基因,通过比较实例的类基因与具体类名的类基因,即可分辨某个实例是否属于目标类。例如,若想获取公鸡类的类型,则可通过“类名.class”得到该类的Class对象,详细的获取代码如下所示:

		// 第一种方式:通过“类名.class”获取
Class clsFromClass = Cock.class;
System.out.println("clsFromClass name = " + clsFromClass.getName());

相对应的,若想获取公鸡实例的类型,则可通过“实例名.getClass()”得到该实例的Class对象,详细的获取代码如下所示:

		// 第二种方式:通过“实例名.getClass()”获取
Cock cock = new Cock();
Class clsFromInstance = cock.getClass();
System.out.println("clsFromInstance name = " + clsFromInstance.getName());

既然Class也是一种数据类型,那么Class对象也能调用该类型的实例方法,比如上面两段例子代码都调用了Class的getName方法,该方法返回的是Class对象蕴含着的目标类类名,而且是包含完整包路径的类名。假如分别运行前面的两段示例代码,就会依次观察到如下的日志信息,从中可见getName方法确实返回了完整的类名:
clsFromClass name = com.addition.reflect.Cock
clsFromInstance name = com.addition.reflect.Cock
除了通过“类名.class”或者“实例名.getClass()”获得Class对象,甚至还能反向操作,只要提供一个保存完整类名的字符串,即可由该字符串生成目标类的Class对象,具体的获取代码格式形如“Class.forName("完整类名")”。通过类名字符串获取Class对象的代码示例如下,注意需要捕捉forName方法可能扔出的“类型未找到异常”ClassNotFoundException:

		// 第三种方式:通过该类的完整路径字符串获取
try {
Class clsFromString = Class.forName("com.addition.reflect.Cock");
System.out.println("clsFromString name = " + clsFromString.getName());
} catch (ClassNotFoundException e) { // 捕捉到类型未找到异常
e.printStackTrace();
}

上述这种通过字符串反向获得Class对象的操作被称为“反射”,仿佛光线照到镜子表面反射回来那样,看起来像是一种逆向操作。只是反射远非逆向操作这么简单,它还洞悉面向对象不为人知的各种奥秘,因此经常出现于一些高级的应用场合。
构成反射技术的基石主要有类型Class、字段Field、方法Method这三个好汉,其中尤以Class最为重要,它既是从其它类中提取出来的基因类型,又是一种可以直接访问的普通类型。之所以说Class普通,是因为它拥有若干可以被开发者访问的方法,使用体验与其它类型相比并没有什么差异。下面是Class常见的方法说明:
equals:判断当前类型是否与目标类型相等。
getDeclaredFields:获得当前类型已声明的所有字段(字段即属性)。
getDeclaredField:根据指定的字段名称获得对应的字段(字段即属性)。
getDeclaredMethods:获得当前类型已声明的所有方法。
getDeclaredMethod:根据指定的方法名称以及参数类型列表获得对应的方法。
getName:获取当前类型包括包名在内的完整类名。
getPackage:获取当前类型所在的包名。
getSimpleName:获取当前类型的类名(不包括包名)。
getSuperclass:获取当前类型的父类类型。
以上的说明文字中,字段指的是Field类型,方法指的是Method类型,有关它们的详细用法将在后面的文章中加以阐述。

更多Java技术文章参见《Java开发笔记(序)章节目录

Java开发笔记(七十八)面向对象的后门——反射的更多相关文章

  1. Java开发笔记(十八)上下求索的while循环

    循环是流程控制的又一重要结构,“白天-黑夜-白天-黑夜”属于时间上的循环,古人“年复一年.日复一日”的“日出而作.日落而息”便是每天周而复始的生活.计算机程序处理循环结构时,给定一段每次都要执行的代码 ...

  2. Java开发笔记(九十八)利用Callable启动线程

    前面介绍了如何利用Runnable接口构建线程任务,该方式确实方便了线程代码的复用与共享,然而Runnable不像公共方法那样有返回值,也就无法将线程代码的处理结果传给外部,造成外部既不知晓该线程是否 ...

  3. Java开发学习(二十八)----拦截器(Interceptor)详细解析

    一.拦截器概念 讲解拦截器的概念之前,我们先看一张图: (1)浏览器发送一个请求会先到Tomcat的web服务器 (2)Tomcat服务器接收到请求以后,会去判断请求的是静态资源还是动态资源 (3)如 ...

  4. Java学习笔记二十八:Java中的接口

    Java中的接口 一:Java的接口: 接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明.一个类通过继承接口的方式,从而来继承 ...

  5. Java学习笔记(十八)——Java DTO

    [前面的话] 在和技术人员的交流中,各种专业术语会出现,每次都是默默的记录下出现的术语,然后再去网上查看是什么意思.最近做项目,需要使用到DTO,然后学习一下吧. 这篇文章是关于Java DTO的,选 ...

  6. 【Java学习笔记之十八】Javadoc注释的用法

    Javadoc注释的用法 Java 文档 // 注释一行/* ...... */ 注释若干行/** ...... */ 注释若干行,并写入 javadoc 文档 通常这种注释的多行写法如下: /*** ...

  7. Java开发笔记(十九)规律变化的for循环

    前面介绍while循环时,有个名叫year的整型变量频繁出现,并且它是控制循环进出的关键要素.不管哪一种while写法,都存在三处与year有关的操作,分别是“year = 0”.“year<l ...

  8. 安卓开发笔记(十八):实现button按钮事件的三种方法

    Android开发中有三种主要的方式用于设置View的点击事件,1.创建内部类:2.主类中实现OnClickListener接口:3.使用匿名内部类.这三种方式都用到了OnClickListener接 ...

  9. Java开发笔记(十)一元运算符的技巧

    前面讲到赋值运算符的时候,提到“x = x+7”可以被“x += 7”所取代,当然Java编程中给某个变量自加7并不常见,常见的是给某变量自加1,就像走台阶,一般都是一级一级台阶地走,犯不着一下子跳上 ...

  10. Java开发笔记(十二)布尔变量论道与或非

    在编程语言的设计之初,它们除了可以进行数学计算,还常常用于逻辑推理和条件判断.为了实现逻辑判断的功能,Java引入了一种布尔类型boolean,用来表示“真”和“假”.该类型的变量只允许两个取值,即t ...

随机推荐

  1. 详解 vue-cli 的打包配置文件代码(给大家写写注释)

    一.前言 对于webpack基础不好,node指令不通的童鞋.估计对自己搭建Vue.react脚手架是相当头疼的,有种无从下手的感觉.然而,从头看这2块,耗时太长,而且说实话得练才行,不练练手看不明白 ...

  2. Java解析json字符串和json数组

    Java解析json字符串和json数组 public static Map<String, String> getUploadTransactions(String json){ Map ...

  3. MySql解除安全模式:Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column.

    在修改一条数据字段时报错: Error Code: 1175. You are using safe update mode and you tried to update a table witho ...

  4. SSIS - 4.使用表达式任务和脚本任务实现更改变量和输出变量值

    一.脚本任务 脚本任务是SSIS包中功能很强大的组件,尤其当内置的任务无法实现我们需要的功能的时候,我们都可以使用脚本任务来实现.脚本任务使用VSTA(Microsoft Visual Studio ...

  5. Senparc之OAuth原理

    今天学习了网易云课堂的 盛派的微信开发课程之OAuth微信网页授权:OAuth原理,边听边来波笔记: 1.什么是OAuth? OAuth 你的接口提供给别人使用,你需要提供Oauth,可以让被人使用, ...

  6. FCC(ES6写法) Make a Person

    用下面给定的方法构造一个对象. 方法有 getFirstName(), getLastName(), getFullName(), setFirstName(first), setLastName(l ...

  7. Python 爬虫入门(二)——爬取妹子图

    Python 爬虫入门 听说你写代码没动力?本文就给你动力,爬取妹子图.如果这也没动力那就没救了. GitHub 地址: https://github.com/injetlee/Python/blob ...

  8. ubuntu 16.04 更改默认Python版本

    一般Ubuntu默认的Python版本都为2.x, 如何改变Python的默认版本呢?假设我们需要把Python3.5设置为默认版本: 首先查看Python默认版本: ubuntu@user~$:py ...

  9. 机器学习入门17 - 嵌套 (Embedding)

    原文链接:https://developers.google.com/machine-learning/crash-course/embeddings/ 嵌套是一种相对低维的空间,可以将高维矢量映射到 ...

  10. Python内置函数(12)——compile

    英文文档: compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1) Compile the source i ...