Java核心技术笔记——第 12 章 反射

转载自:[https://www.cnblogs.com/chanshuyi/p/head_first_of_reflection.html]

12 反射

1. 引入反射

通常情况下,调用一个类的方法的步骤如下:

  1. 创建该类的对象。
  2. 调用该对象的方法。

通过这种方式调用方法时,必须要知道类的定义以及类的所有属性和方法。代码如下:

Apple apple = new Apple(); //直接初始化,「正射」
apple.setPrice(4);

另一种调用类方法的方式是:反射。示例如下:

//获取类的class对象
Class clz = Class.forName("com.chenshuyi.reflect.Apple");
//获取类的指定方法的method对象
Method method = clz.getMethod("setPrice", int.class);
//获取类的默认构造器
Constructor constructor = clz.getConstructor();
//创建类的对象
Object object = constructor.newInstance();
//调用方法
method.invoke(object, 4);

上面两段代码的执行结果,其实是完全一样的。但是其思路完全不一样,第一段代码在未运行时就已经确定了要运行的类(Apple),而第二段代码则是在运行时通过字符串值才得知要运行的类(com.chenshuyi.reflect.Apple)。

2. 反射定义

反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。

3. 示例的完整代码

public class Apple {private int price;public int getPrice(){return price;}public void setPrice(int price) {this.price = price;}public static void main(String[] args) throws Exception{//正常的调用Apple apple = new Apple();apple.setPrice(5);System.out.println("Apple Price:" + apple.getPrice());//使用反射调用Class clz = Class.forName("com.chenshuyi.api.Apple");Method setPriceMethod = clz.getMethod("setPrice", int.class);Constructor appleConstructor = clz.getConstructor();Object appleObj = appleConstructor.newInstance();setPriceMethod.invoke(appleObj, 14);Method getPriceMethod = clz.getMethod("getPrice");System.out.println("Apple Price:" + getPriceMethod.invoke(appleObj));}
}

4. 反射调用的步骤

一般情况下我们使用反射获取一个对象的步骤:

  1. 获取类的 Class 对象实例

    Class clz = Class.forName("com.zhenai.api.Apple");
  2. 根据 Class 对象实例获取 Constructor 对象

    Constructor appleConstructor = clz.getConstructor();
  3. 使用 Constructor 对象的 newInstance 方法获取反射类对象

    Object appleObj = appleConstructor.newInstance();

如果要调用某一个方法,则需要经过下面的步骤:

  1. 获取方法的 Method 对象

    Method setPriceMethod = clz.getMethod("setPrice", int.class);
  2. 利用 invoke 方法调用方法

    setPriceMethod.invoke(appleObj, 14);

5. 反射常用的 API

1. 获取反射中的 Class 对象

在反射中,要获取一个类或调用一个类的方法,我们首先需要获取到该类的 Class 对象。在 Java API 中,获取 Class 类对象有三种方法:

  • 使用 Class.forName 静态方法。当你知道类的全路径名时,你可以使用该方法获取 Class 类对象。

    Class clz = Class.forName("java.lang.String"); 
  • 使用 类型名.class 。

    Class clz = String.class;
  • 使用类对象的 getClass() 方法。

    String str = new String("Hello");
    Class clz = str.getClass();

2. 通过反射创建类对象

通过反射创建类对象主要有两种方式(newInstance() 的返回值是 Object):

  • 通过 Class 对象的 newInstance() 方法

    Class clz = Apple.class;
    Apple apple = (Apple)clz.newInstance();
  • 通过 Constructor 对象的 newInstance() 方法。

    Class clz = Apple.class;
    Constructor constructor = clz.getConstructor();
    Apple apple = (Apple)constructor.newInstance();

通过 Constructor 对象创建类对象可以选择特定构造方法,而通过 Class 对象则只能使用默认的无参数构造方法。下面的代码就调用了一个有参数的构造方法进行了类对象的初始化:

Class clz = Apple.class;
Constructor constructor = clz.getConstructor(String.class, int.class);
Apple apple = (Apple)constructor.newInstance("红富士", 15);

3. 通过反射获取类属性、方法、构造器

获取类的属性

  • Field getField(String name):获取 Class 对象对应类的指定公有属性。
  • Field[] getFields():获取 Class 对象对应类的所有公有属性(包括从父类中继承的公有属性),无法获取类的私有属性。
  • Field[] getDeclaredFields():获取 Class 对象对应类的所有属性(仅限本类中定义的公有、默认、保护、私有属性,不包括从父类中继承的属性)。
  • Field getDeclaredField(String name):获取 Class 对象对应类的指定属性(仅限本类中定义的公有或默认或保护或私有属性,不包括从父类中继承的属性)。

获取类的方法

  • Method getMethod(String name, Class<?>... parameterTypes):获取 Class 对象对应类的指定公有方法。
  • Method[] getMethods(): 获取 Class 对象对应类的所有公有方法(包括从父类中继承的公有方法),无法获取类的私有方法。
  • Method[] getDeclaredMethods():获取 Class 对象对应类的所有方法(仅限本类中定义的公有、默认、保护、私有方法,不包括从父类中继承的方法,以及本类的构造器)。
  • Method getDeclaredMethod(String name, Class<?>... parameterTypes):获取 Class 对象对应类的指定公有方法(仅限本类中定义的公有或默认或保护或私有方法,不包括从父类中继承的方法)。

获取类的构造器

  • Constructor<T> getConstructor(Class<?>... parameterTypes):获取 Class 对象对应类的指定公有构造器。
  • Constructor<?>[] getConstructors():获取 Class 对象对应类的所有公有构造器。
  • Constructor<?>[] getDeclaredConstructors():获取 Class 对象对应类的所有构造器。
  • Constructor<?>[] getDeclaredConstructor(Class<?>... parameterTypes):获取 Class 对象对应类的指定构造器(公有或私有)。

转载于:https://www.cnblogs.com/echie/p/9785676.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/249278.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML5知识点汇总

1、HTML5新特性 用于绘画的canvas标签用于媒介回放的video和audio元素对本地离线储存的更好支持新的特殊内容元素&#xff0c;如&#xff1a;article、footer、header、nav、section、aside、hgroup、figure新的表单控件&#xff0c;如&#xff1a;calendar、date、time、emai…

实用网站

https://blog.csdn.net/devcloud/article/details/103121883

网络(图)(数学)

转载于:https://www.cnblogs.com/fengxunling/p/9781575.html

DES加解密时 Given final block not properly padded 的解决方案

事情的经过是这个样子的。。。。。。 先说说问题是怎么出现的。根据客户需求&#xff0c;需要完成一个一键登录的功能&#xff0c;于是我的项目中就诞生了DesUtil&#xff0c;但是经过几百次测试&#xff0c;发现有一个登录直接报错&#xff01;难道又遇到神坑啦&#xff01;&a…

java 算法优化向导

一.什么是数据结构&#xff1f;什么是算法 不必像学生时代深究定义。以一个简单的例子说明。 数据结构&#xff0c;图书馆的书怎么摆列&#xff0c;按照书的类型&#xff0c;作者&#xff0c;出版时间&#xff0c;语言等等放置&#xff0c;这就是数据的结构。 算法&#xff0c…

appium工作原理

Appium原理 面试的时候&#xff0c;被问到appium原理&#xff0c;一点不会&#xff0c;实在尴尬。大家可以直接翻看原作https://blog.csdn.net/jffhy2017/article/details/69220719 appium运行时安装的2个应用&#xff1a;Appium Settings和Unlock。 一、appium加载的过程图解&…

LeetCode 21. Merge Two Sorted Lists

LeetCode 21. Merge Two Sorted Lists 分析 难度&#xff1a;易 题目 Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists. Example: Input: 1->2->4, 1->3->4 Out…

Mac OS X 下 TAR.GZ 方式安装 MySQL

Mac OS X 下 TAR.GZ 方式安装 MySQL 注意: 本篇文章适用与 MySQL 5.6 版本的安装, 但已不再适用 5.7 的安装, 5.7 的安装方式请参见:《Mac OS X 下 TAR.GZ 方式安装 MySQL 5.7》 在 Mac 系统上, 安装 MySQL Server 一般是用 DMG 包在图形化界面下按提示安装, 此外 MySQL 还提供…

快排再改进

快排再改进 #include <iostream> using namespace std;void mySwap(int &a, int &b) {int temp a;a b;b temp; }void insertSort(int a[], int left, int right) {int tmp;int in 0;int out 0;for (out left 1; out < right; out) {tmp a[out];in ou…

【Linux基础】crontab定时命令详解

周期执行的任务一般由cron这个守护进程来处理[ps -ef|grep cron]。cron读取一个或多个配置文件&#xff0c;这些配置文件中包含了命令行及其调用时间。cron的配置文件称为“crontab”&#xff0c;是“cron table”的简写。 一、cron服务  cron是一个linux下 的定时执行工具&a…

5个Vue.js项目的令人敬畏的模板

开发人员查看使用SPA&#xff0c;Webpack&#xff0c;身份验证&#xff0c;GraphQL&#xff0c;文档和测试的Vue开发人员的资源。 你准备开始一个重要的Vue项目吗&#xff1f;为了确保从坚实的基础开始&#xff0c;您可以使用模板&#xff08;也就是样板&#xff0c;骨架&#…

测试多个输入条件的方法

转载于:https://www.cnblogs.com/www-qcdwx-com/p/10641281.html

问题规模

问题规模本身并没有非常精准的定义吧一般都是指运行时间t和输入参数个数n的关系用O(n)表示比如max([x])就是O(n)而冒泡排序则是O(n^2)

SSM+mybatis单元测试

初学SSMmybatis单元测试遇到的问题&#xff0c;dao注入后为nullDao层注入失败&#xff0c;查看后&#xff0c;发现注解都写的无误&#xff0c;经朋友的指点&#xff0c;在测试类上加了一句“RunWith(SpringJUnit4ClassRunner.class) ContextConfiguration(locations{“classpat…

Sublime text 2/3 中 Package Control 的安装与使用方法

Package Control 插件是一个方便 Sublime text 管理插件的插件&#xff0c;但因为 Sublime Text 3 更新了 Python 的函数&#xff0c;API不同了&#xff0c;导致基于 Python 开发的插件很多都不能工作&#xff0c;Package Control 原来的安装方法都失效了。 网上有2种使用 Git…

接口测试

集成&#xff1a; 接口&#xff0c;代码级&#xff0c;service层 unit-》service-》UI 接口测试和界面没有任何关系 A->B  数据流向 理论 我们学过&#xff0c;集成测试主要测接口&#xff0c;通过学习集成测试&#xff0c;我们发现是把单元测试通过后的方法直接需要对接的…

React-Router ---withRouter

import React from react import { withRouter } from react-router const Hello (props) > { return ( <div><button onClick{ () > props.history.push(/about) }>Hello</button></div> ) } const WithRouterHello withRouter(Hello);//也可…

vue从入门到精通之进阶篇(一)vue-router基础

路由原理 传统开发方式 url改变后 立刻发起请求&#xff0c;响应整个页面&#xff0c;渲染整个页面SPA 锚点值改变后 不会发起请求,发起ajax请求,局部改变页面数据 页面不跳转 用户体验更好 SPA single page application(单页应用程序)前端路由 锚点值监视ajax获取动态数据…

自动计算请假工时 排除周六周日

/*** 请假工时计算* starttime 开始时间 "2019-03-28 16:02", endtime 结束时间 "2019-03-29 16:02"*/ function leaveTime(starttime, endtime) {var start new Date(starttime); //start Thu Mar 28 2019 16:02:00 GMT0800 (中国标准时间)var end new…

垃圾回收与内存管理

垃圾回收机制 Javascript采用 自动垃圾收集机制&#xff0c;执行环境会负责跟踪代码执行过程中使用的内存&#xff0c;而在C和C类的语言中&#xff0c;需要开发人员手工跟踪内存的使用情况。 该机制的实现原理&#xff1a;找出那些不再继续使用的变量&#xff0c;然后释放其占用…