当前课程知识点:JAVA程序设计进阶 >  第八章 反射与代理机制 >  8.1 Java反射机制 >  Video

返回《JAVA程序设计进阶》慕课在线视频课程列表

Video在线视频

Video

下一节:Video

返回《JAVA程序设计进阶》慕课在线视频列表

Video课程教案、知识点、字幕

那这一节我们将首先介绍

Java的反射机制reflection

当我们的Java程序在运行过程当中

需要去识别它到底每一个对象

是什么样一个类型

那这种类型信息的识别

我们一般说来有两种办法

第一种办法叫RTTI

英文就叫Run-Time Type Identification

也就是运行时的类型的识别

那第二种办法就是利用Java的反射机制

我们先看一下RTTI

那我们为什么需要RTTI呢

那因为我们在运行过程当中

是需要识别每一个对象

它到底是属于什么类型

我们看这张PPT当中的一个图片

我们有一个类叫shape

也就是这个形状

它里面有方法draw

然后它有三个子类

一个叫circle

一个叫square

一个叫triangle

那假设我们的Java程序当中

有一个数组

要去保存这种shape类型的这种元素

但实际上在我们往里面存

这些元素的时候

存的都是它的底下

具体的子类类型

比如你存一个circle

一个square 或者一个triangle

那当我们从数组当中

把这些元素取出来的时候

那Java虚拟机会自动

把它的这个类型转型回shape

也就是转回它的这个

复类的这个类型

这个就是我们的RTTI

最基本的使用形式

因为在Java当中所有的类型转换

都是在运行的时候进行操作

并且进行正确性的检查的

那对于我们写代码来说

在很多情况下

都尽量可能少的去了解对象的

一种具体的类型

而只是与对象家族中的

一个最通用的表示方式来进行打交道

那在我们这个例子当中

它最通用的表现方式

实际上就是它的这个共同的复类shape

那这样写出来代码会更容易一些

也容易读 而且便于维护

设计也容易实现也容易理解

那我们今天想重点介绍的

实际上是我们的Java反射机制

那什么是Java的反射机制

它指的是在Java的运行过程当中

对于任意一个类

我们都能够知道这个类的

所有属性和方法

然后对任意一个对象

我们都能够调用

这个对象的方法和属性

这种动态获取信息

以及动态调用对象方法的功能

称之为Java语言的反射机制

我们看一下Java当中

有一个类叫Class

大家必须注意

是有一个类叫Class

就跟我们在最早最早

介绍Java最顶上的一个类叫Object

所以我们Java当中

所有的东西都是对象

但是在Java当中

最顶上那个类就叫Object

那个类名注意是以大写字母开头

我们看这一页PPT当中

最右边是我们最常见的这个

Object这个类

那它里面有一些方法

比如说hashCode

也就是说获得我们任意一个

这个Object这个对象的它的哈希值

还有equals

用来比较两个对象

是不是同一个对象

clone就是我们克隆出

我们一个对象

toString那就是把我们的一个对象

转换成字符串

notify那就是通知

和wait等待

那这些方法都是我们这个Object

这个类中的常见的这个方法

那我们再看看左边

那我们有个类就叫Class

注意是一个类

是大写字母C开头的这个Class

这个类也是Java当中的一个基础类

那当我们的Java虚拟机

在运行过程当中

装载这个一个新类的时候

就会在Java的堆当中

创建一个Class这个类的实例

注意是Class这个类

我们大写字母开头的

Class这个类实例

这个实例就代表了这个Class类型

那我们通过这个实例

就可以获取它的类型信息

那这些类中

它既然是一个类

它肯定也有它的一些方法

就和我们在这一页PPT最右边

我们Object这个类有些方法一样

那在我们Class这个类当中

也有一些方法

大家看看我们左边

左下角的这几个方法

第一个方法叫Method

然后是中括号然后get Methods

这个方法大家看也蛮有意思

首先Method是大写字母开头

其实表明它是一个类

大家注意了

在Java当中有一个类

它的名字就叫Method

然后中括号代表它是一个数组

数组

那实际上表示说是

我们这个get Method这个方法

它返回的返回值

是一个Method的数组

那get Method这个方法

到底想干什么呢

实际上它就是要返回

我们这个Class这个类

它的这个实例当中所有的方法

也就是说你通过这个get Method

能够知道某一个这个Class类的实例

它代表的这个对象当中

到底都有哪些方法

好 我们看第二个方法Field

getFields

Field大家注意

Field后面带一个中括号

表示它是一个数组

当然Field

Field的话也是大写字母开头

表示的是Field也是一个类

而这个Field

其实在Java当中

实际上表示的就是

我们一个类的成员变量

就是说我们定义了一个类的话

里面可能包含成员变量

那这个时候我们通过getFields

这个方法我就能知道

我这个类当中都有哪些成员变量

Field有时候在我们中文翻译中

也会翻译成域

好 我们看一下第三个方法

Constructor后面也是一个中括号

表示的是它是一个数组

getDeclaredConstructors

那这个方法就是要获得

我们这个Class类的这个实例

所代表那个类的所有的构造方法

那其实大家看到这个三个方法

getMethod getFields

getDeclaredConstructors

那实际上它就帮助大家

获得了某一个类的

它的所有的方法

它的所有的成员变量

还有它的构造方法

那你取到这些了以后

你用来干啥呢

你可能会需要去调用它

那怎么调用它

我们马上就会介绍到

那我们看看怎么利用Class类

来创建一个实例

那实际上Class类注意它

大家要明白

Class类的这个类型的对象

它是表达了一个类的引用

我们看一下这个第二行的

那个代码Class cls等于

Class.forName Airplane

大家看看首先等号右边是Class

这是一个类的名字

因为是大写字母开头

.forName .forName那应该是

大家能猜出来

这是它的一个static的方法

也就是它是一个静态方法

然后给了一个参数Airplane

实际上Airplane的话

实际上是我们一个类的名字

那这个时候我们等号左边

就是cls这个实例

它实际上是属于这个Class

这个类的一个实例

然后它所代表的是

我们airplane这个类型

所以这一行代码的作用就是这样

那紧接着我怎么能够去

创建出一个airplane

这个类的一个实例呢

再往下大家看看cls.newInstance

我们通过newInstance这个方法

当然注意这个方法

是属于Class这个类的方法

那我们这里是cls这个对象

调用它的newInstance方法

就创建了一个实例

那大家想想那newInstance这个方法

它的返回值是什么

它返回值实际上是一个实例

但这个实例是什么类型的呢

我告诉大家这个实例

是Airplane这个类型的

那在调用newInstance

创建实例过程当中

一般调用的是Airplane

这个类它的默认的构造方法

所以通过这两句代码

我们就可以利用一个字符串的名字

注意一个类字符串

就是我们现在Airplane这个类

它是一个类名

但是它现在是字符串

我们就可以利用这个字符串

来去创建出它的这个一个实例

那我们再往下看一下

这个一个稍微完整的例子

ClassAirplane

public String to String

return in airplane

然后我们这个Airplane这个类

就定义完了

那这些个类当中呢

我们实际上只是重写了

它的toString方法

那在toString里面

我们就是指返回数

我在飞机里面

好 这是一个类Airplane的定义

下面我们看一下

我们怎么利用Class这个类

来去创建Airplan的一个实例

我们往下看

public class createInstance

然后紧接着public static void main

String args throws Exception

然后我们看一下Class c1等于空

我们构造了一个Class

这个类的一个对象叫c1

然后初始值为空

然后Object ap

我们定义了声明了一个Object对象

叫ap

再往下看c1=Class.forName Airplane

这一句我们是创建了一个

这个Class类型的对象

那实际上这个Class类型对象呢

它所表示的这个类的类型

是这个Airplane

然后紧接着把它赋值给我们的c1

也就是说c1它所表示的

是一个Airplane这个类的一个类型

好 紧接着我们打印一下

system.out.printIn c1

大家想想打印c1

它到底会打印什么东西呢

自己琢磨一下

再往下看ap=c1.newInstance

我们利用c1这个对象

然后调用它的newInstance方法

那我们创建了这么一个实例

那这个实例大家想想

那个newInstance这个方法

它返回的这个实例是什么类型呢

当然现在我们直接是把它

这个赋到等号左边的话

ap是Object

紧接着我们往下调用

System.out.printIn ap.to String

就把它打印这个出来

当然ap.toString应该调用哪个方法

因为我们往上看

就是Class Airplane里面

有一个toString方法

那就应该调用这里面的方法

那其实我们做一下对比

我们传统的创建实例的办法

是像这样的

大家看比如我们有Airplaneap

等于new Airplane

因为我们是之前定了一个类

叫Airplane

那我们现在要创建它这个实例

就直接通过new

然后后面跟着它的构造方法

这时候我们就创建出一个实例来了

但是大家看这个例子

在我们这个左边

这个程序代码例子当中

我们是把Airplane这个类名

当做一个字符串

然后通过我们创建Class

这个类的一个对象c1

调用了Class.forName

然后后面跟着这个Airplane这个字符串

我们就创建了这么一个类型的

这个类的对象c1

然后再通过c1的newInstance方法

我们就创建出我们的这一个

这个实例来

然后这个实例的类型

实际上它是属于Airplane的

大家对比一下这两种方式

你会发现利用Class类

来创建实例的话

它会更加灵活更加方便

你只要把这个类

你要想要创建的这个对象的类的名字

当做字符串传进来

在我们这个例子当中

就是Airplane这个类

把它的名字当做字符串传进来

我们就可以创建出这个类的一个对象

那我们看看整个这个程序的运行结果

是什么

运行结果是这样的

打印出第一行class Airplane

那这个打印是因为我们

system.out.printIn c1

那c1的话

它所代表的就是这个类Airplane

这么一个类型

所以打印结果就是Class Airplane

然后第二行打印结果

是因为我们调用了

system.out.print ap.to String

那ap.toString的话又会

调用的这个toString这个方法

就是我们这个PPT上面这个

Class Airplane里面的

这个toString方法

那它的返回值就是return In Airplane

所以通过这个例子

我希望同学能够掌握就是

我可以利用一个类它的名字

这个字符串来去创建出它的实例

那这样会非常灵活

在其他很多地方你用起来的话

会很方便

那我们除了能创建一个类的实例

也就是通过一个字符串

创建一个类的实例以外

我们还能不能调用这个实例的方法呢

对不对

因为我们有时候执行功能的时候

是需要调用方法的

这个在Java的反射机制当中

也给大家提供了这种途径

那有个类叫Method类

Method它这个类本身

有一个invoke方法

那这个invoke方法

对带有指定参数的指定对象

调用这个Method对象

表示的这些 这个方法的话

我们就能够把我们目标对象的

这些方法都执行出来

那我们看一下下面的这个例子

import java.lang.reflect.*

注意了你要想反射

你就得引入这个包

java.lang.reflect.*

好了 我们看一下

这个类Class A

public ClassA

然后它里面定义了一个成员方法

叫public voil add

然后add方法我们有两个参数

一个叫Integer param1

第二个叫Integer param2

然后它里面的方法体是干什么呢

system.out. printIn

param1.intValue+param2.intValue

实际上是把这个两个参数的

首先先转换成它的整数值

整数值了以后再把它相加

然后再把结果打印出来

所以这个数是add方法的功能

那我们再看看ClassA的第二个方法

public void StringAdd

然后它的参数是String abc

然后它的结果是什么呢

system.out.printIn out+abc

那这第二个方法的话

就是把这个输入参数abc

再加上前面加上一个out

就把它打印出来

好 我们再往下看它的主方法

主方法里面try

Method mth=ClassA.class.getMethod

add newClass

这个数组然后Integer.class

然后Integer.class

这一行代码显得比较有意思

实际上它是声明了一个对象叫mth

那mth它是什么类型的对象呢

它是Method

就是方法类型的一个对象

也就是说mth它表示的是

某一个方法

那是哪个方法呢

因为我们都知道

你要想知道方法的话

你得知道它属于哪个类

然后以及具体这个类中的

哪个名字的方法

甚至是它的参数的表示

那这些都是在我们等号右边

都给大家提示了

首先它属于ClassA这个类的方法

那它通过ClassA.class

这个成员变量得到了它的类型

再通过getMethod方法

这个getMethod那就是要获得一个方法

那哪个方法呢

方法名字是add就是我们第一个参数

那方法的参数

它实际上是用一个数组

来表示我们add这个方法的参数的

那这个数组里面new Class

它里面是两个元素

一个是Integer.Class

第二个也是Integer.Class

实际上大家拿这两个Integer Class

和我们上面ClassA这个类里面的

方法add对比一下

也就是我们上面这个程序中第三行

public void add

Integer param1 Integer param2

实际上这个add里面它两个参数

第一个参数是Integer

第二个参数是Integer

那实际上这个里面的表示

在我们主要方法里面

就是Method mth等于

ClassA.class.getMethod

然后add new Class

然后后面跟着Integer.class

Integer class

这个是一个意思的 一个意思

好了

mth这个对象表示的是一个方法

已经说清楚了

这个方法属于类ClassA

然后它的方法的名字叫add

那下面我怎么去执行这个方法

好了 那我要执行这个方法

就通过mth的invoke这个方法

来去执行它了

那实际上我们是想执行

我们ClassA中的add方法

那我们怎么执行呢

大家看看invoke后面有两个

有几个参数

第一个参数是ClassA.class.newInstance

也就是说我ClassA

我通过Class这个它的成员变量

我得到它的类型

然后紧接着我去调用它的newInstance

我就获得了这个ClassA的

这么一个实例

然后得到了这个实例了以后

那我还要给它参数对不对

那我的参数是newInteger1

表示是一个Integer这个类型的

一个对象

然后它的值是1

那紧接着newInteger2

这个是第二个参数

然后这些都给全了以后

我们mth.invoke一执行

那实际上执行的就是我们上面这个类

ClassA当中的add方法

好 我们再往下

Method mth1等于

ClassA.class.getMethod

StringAdd newClass 数组

然后String.class

这是我们另外一个方法对象 叫mth1

那它的类型叫就是Method

然后它想表示的是哪一个方法

实际它想表示的是

我们ClassA这个类中的第二个方法

然后我们第二个方法的名字

叫StringAdd

然后StringAdd这个方法呢

它的参数只有一个

就是一个字符串

参数字符串

那我们声明了mth1了以后

我们当然也想去执行它了

那怎么执行

调用它的invoke方法

mth1.invoke

然后ClassA.class.newInstance

这是我们实例化出ClassA

这个类的一个对象

然后再给它参数是一个字符串

那字符串里面就是--test

好了 我们的这个主方法的话

基本就结束了

因为下面是一个catch Exception

那这个主方法里面

实际上最重要的是构造了两个对象

一个叫mth 一个叫mth1

那这两个对象它所对应的类型

就是Method这么这个类

也就是表示的一个方法

它既然表示了一个方法以后

我们就想执行这个方法

那怎么执行

就通过它的invoke方法的执行

那我们看看它这个执行结果吧

大家能猜得出来吗

到底执行结果是多少

运行结果第一个结果是3

为什么是3

那是因为我们调用ClassA的

第一个方法add的时候

给它传入了两个参数

一个是1 另外一个是2

那在这个add方法里面

就是把这个1和2加起来

然后并打印

所以它的输出结果是3

然后我们第二个输出结果是out--test

那这个结果的话

实际上就是

因为我们Stringadd这个方法的话

最主要就是把 我们输入字符串

在前面加上一个out

所以通过这个例子

是想告诉大家什么一件事情

也就是说通过Method这个类

你是可以表示任意一个类当中的

它的某一个方法的

然后你通过Method类的invoke

就可以去调用你刚才

想表达的那个方法

把它给执行出来

大家看这种执行是不是很灵活

所以这个也是我们

Java反射的一个例子

也就是说我在Java反射当中

我不仅仅可以通过一个类的

字符串的名字

我去创建出这个类的一个实例

我还可以通过Method类的方法invoke

去调用我原来目标类当中的

它的任意一个方法

这样的话是不是非常的灵活

那这一节的内容我们就介绍到这里

JAVA程序设计进阶课程列表:

第一章 线程(上)

-1.0 导学

--Video

-1.1 线程的基本概念

--Video

-1.1 线程的基本概念--作业

-1.2 通过Thread类创建线程

--Video

-1.2 通过Thread类创建线程--作业

-1.3 线程的休眠

--Video

-1.3 线程的休眠--作业

-1.4 Thread类详解

--Video

-1.5 通过Runnable接口创建线程

--Video

-1.5 通过Runnable接口创建线程--作业

-1.6 线程内部的数据共享

--Video

第二章 线程(中)

-2.0 导学

--Video

-2.1 线程同步的思路

--Video

-2.2 线程同步的实现方式—Synchronization

--Video

-2.3 线程的等待与唤醒

--Video

-2.4 后台进程

--Video

-2.5 线程的生命周期与死锁

--Video

-2.6 线程的调度

--Video

第三章 线程(下)

-3.0 导学

--Video

-3.1 线程安全与线程兼容与对立

--Video

-3.2 线程的安全实现-互斥同步

--Video

-3.3 线程的安全实现-非阻塞同步

--Video

-3.4 线程的安全实现-无同步方案

--Video

-3.5 锁优化

--Video

第四章 网络编程(上)

-4.0 导学

--Video

-4.1 URL对象

--Video

-4.2 URLConnection对象

--Video

-4.3 Get请求与Post请求

--Video

-4.4 Socket通信原理

--Video

-4.5 Socket通信实现

--Video

第五章 网络编程(下)

-5.0 导学

--Video

-5.1 Socket 多客户端通信实现

--Video

-5.2 数据报通信

--Video

-5.3 使用数据报进行广播通信

--Video

-5.4 网络聊天程序

--Video

第六章 Java虚拟机

-6.0 导学

--Video

-6.1 Java虚拟机概念

--Video

-6.2 Java虚拟机内存划分

--Video

-6.3 Java虚拟机类加载机制

--Video

-6.4 判断对象是否存活算法及对象引用

--Video

-6.5 分代垃圾回收

--Video

-6.6 典型的垃圾收集算法

--Video

-6.7典型的垃圾收集器

--Video

第七章 深入集合Collection

-7.0 导学

--Video

-7.1 集合框架与ArrayList

--Video

-7.2 LinkedList

--Video

-7.3 HashMap与HashTable

--Video

-7.4 TreeMap与LinkedHashMap

--Video

-7.5 HashSet

--Video

第八章 反射与代理机制

-8.0 导学

--Video

-8.1 Java反射机制

--Video

-8.2 Java静态代理

--Video

-8.3 Java动态代理

--Video

-8.4 Java 反射扩展-jvm加载类原理

--Video

-8.5 Java进阶课程总结

--Video

Video笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。