学习要点

  • 反射概念
  • 反射的应用

反射概述

1  反射机制

定义

Java反射机制是指在程序在运行状态中,动态获取信息以及动态调用对象方法的功能。

Java反射的动态性质:运行时生成对象实例、运行期间调用方法、运行时更改属性。

Java程序执行过程

反射执行过程

1)  Java反射机制是在编译时并不确定哪个类被加载了,而是在程序运行的时候才加载、探知、使用。

2)  Java反射机制能够知道类的基本结构,这种对Java类结构的探知能力,称为Java类的“自审”。例如开发环境eclipse或者myeclipse中的代码自动提示功能,就是利用了Java的反射机制,对所创建对象的探知和自审。

3)  通过Java反射,可以实现以下功能:

  • 在运行时判断任意一个对象所属的类。
  • 在运行时构造任意一个类的对象。
  • 在运行时判断任意一个类所具有的方法和属性。
  • 在运行时调用任意一个对象的方法。

2  Java反射常用API

ava反射常用核心类位于java.lang.reflect包,常用类:

1)  Class类—可获取类和类的成员信息

2)  Field类—可访问类的属性

3)  Method类—可调用类的方法

4)  Constructor类—可调用类的构造方法

使用反射的基本步骤

1)  导入java.lang.reflect.*

2)  获得需要操作的类的Java.lang.Class对象

3)  调用Class的方法获取Field、Method等对象

4)  使用反射API进行操作 (设置属性﹑调用方法)

反射的应用

1  获取类的信息

Java类加载机制

Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数,属性和方法等,Java允许用户借由这个Class相关的元信息对象间接调用Class对象的功能。

虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。

获取Class对象

1)  调用对象的getClass( )方法

定义学生信息类

/** 学生信息类 */public class Student {private int sid;// 学号private String sname;// 姓名private char sgender;// 性别private int sage;// 年龄//构造函数(略)//属性封装(略)}

定义测试类获得学生信息类的Class对象

Student student=new Student();Class clazz=student.getClass();

  

2)  调用类的Class属性(推荐使用:类型安全、性能高)

Class clazz = Student.class;

3)        使用Class类的forName()静态方法

Class clazz = Class.forName("com.etc.demo.Student");// 参数是类全名

  

从Class对象获取信息

1)  访问Class对象对应类所包含的构造方法

方法

说明

Constructor getConstructor(Class[] params)

返回指定参数的public构造方法

Constructor[] getConstructors()

返回所有public构造方法

Constructor getDeclaredConstructor(Class[] params)

返回指定参数的构造方法,与访问级别无关

Constructor[] getDeclaredConstructors()

返回所有构造方法,与访问级别无关

示例代码

Constructor constructors[] =clazz.getDeclaredConstructors();//返回所有构造方法Constructor constructors[] =clazz.getConstructors();//返回所有public构造方法//返回指定参数的构造方法,与访问修饰符无关Constructor con = clazz.getDeclaredConstructor(new Class[]{int.class,String.class,char.class,int.class});//简要输出构造方法信息System.out.println(con.toString());

  

2)  访问Class对象对应类所包含的方法

方法

说明

Method getMethod(String name,Class[] params)

返回方法名为name的指定参数列表的public方法

Method[] getMethods()

返回所有public方法

Method getDeclaredMethod(String name,

Class[] params)

返回方法名为name的指定参数列表的所有方法

Method[] getDeclaredMethods()

返回所有方法

3)  访问Class对象对应类所包含的属性

方法

说明

Field getField(String name)

返回public指定名称为name的属性

Field getFields()

返回全部public属性

Field getDeclaredField(String name)

返回指定名称属性

Field[] getDeclaredFields()

返回全部属性

4)  访问Class对象对应类所包含的注解

方法

说明

<A extends Annotation>A getAnnotation

(Class<A>  annotationClass)

返回该Class对象所表示类上指定类型的注释,若没有,则返回null

Annotation[] getAnnotations()

返回所有注释

Annotation[] getDeclaredAnnotations()

返回直接存在于此元素上的所有注释

5)  访问Class对象对应类的其他信息

方法

说明

Class[] getDeclaredClasses()

返回Class对象对应类的全部内容类

Class[] getDeclaringClass()

返回Class对象对应类的全部外部类

Class[] getInterfaces()

返回Class对象对应类全部实现的接口

int getModifiers()

返回此类或接口的所有修饰符。使用Modifer工具类方法解码返回值获得访问修饰符

Package getPackage()

获得此类的包

String getName()

返回类的名称

String getSimpleName()

返回类的简称

Class getSuperclass()

返回基类Class对象

示例代码

 Class clazz = Student.class;System.out.println("------类的字段------------");Field fields[] = clazz.getDeclaredFields();for (Field field : fields)System.out.println(field.getName() + " " + field.getType());System.out.println("-------类的方法-----------");Method methods[] = clazz.getDeclaredMethods();for (Method method : methods)System.out.println(method.getName());System.out.println("-------类的构造方法-----------");Constructor constructors[] = clazz.getDeclaredConstructors();for (Constructor constructor : constructors) {System.out.println(constructor);}System.out.println("--------类所在包、完整名称、父类----------");System.out.println(clazz.getPackage().getName());System.out.println(clazz.getName());System.out.println(clazz.getSuperclass());

  

2  创建对象

通过反射创建对象有两种形式:

  • 使用Class对象的newInstance()方法创建对象
  • 使用Constructor对象创建对象

使用newInstance()创建对象

要求Class对象对应的类有默认构造方法。

示例代码

Class clazz=Student.class;Student student=(Student)clazz.newInstance();student.setSname("张三");student.setSage(21);student.sayHello();

  

使用Constructor对象指定构造方法创建对象

示例代码

Class clazz=Student.class;Constructor constructor=clazz.getConstructor(int.class,String.class,char.class,int.class);Student student=(Student) constructor.newInstance(1001,"张三",'男',22);student.sayHello();

  

3  访问类的属性

使用Field对象可以获取对象的属性。通过Field对象可以对属性进行取值或赋值操作。主要方法如下:

方法

说明

Xxx getXxx(Object obj)

Xxx对应Java的8个基本数据类型,如int。obj为该属性所在的对象。

Object get(Object obj)

获得引用类型属性值。

void setXxx(Object obj,Xxx val)

将obj对象该属性设置为val值。

void set(Object obj,objcet val)

将obj对象该属性设置为val值。针对引用类型。

void setAccessible(bool flag)

对获取到的属性设置访问权限。参数为true,可以对私有属性取值和赋值。

示例代码

/** 人类 */class Person {private String name;// 姓名private int age;// 年龄/** 重写toString()方法 */public String toString() {return "my name is" + name + ",age is" + age;}}/** 测试代码 */Person p = new Person();// 创建Person对象Class clazz = Person.class;// 获取Person对应的Class对象// 获取Person类的name属性,使用getDeclaredField()方法获取各种访问级别的属性Field nameField = clazz.getDeclaredField("name");// 设置通过反射访问该Field时取消权限检查nameField.setAccessible(true);// 使用set方法为p对象指定Field设置值nameField.set(p, "andy");//同理设置age属性Field ageField=clazz.getDeclaredField("age");ageField.setAccessible(true);ageField.setInt(p,21);//输出结果System.out.println(p.toString());

4  访问类的方法

使用Method对象可以调用对象的方法。在Method类中包含一个invoke()方法,方法的定义如下:

Object invoke(Object obj,Object… args);

obj:执行该方法的对象

args:执行该方法时传入该方法的参数列表

示例代码

/** 计算器类 */public class Calculator {/** 加法 */public int add(int a, int b) {return a + b;}/** 减法 */private int sub(int a, int b) {return a - b;}}/** 测试代码 */// 获取Calculator对应的Class对象Class clazz = Calculator.class;// 创建Calculator对象Calculator calculator = new Calculator();// add方法调用Method methodAdd = clazz.getMethod("add", int.class, int.class);int result1 = (int) methodAdd.invoke(calculator, 10, 12);System.out.println("10+12=" + result1);// sub方法的调用Method methodSub = clazz.getMethod("sub", int.class, int.class);// 报错如何处理?int result2 = (int) methodSub.invoke(calculator, 13, 4);System.out.println("13-4=" + result2);

  

注意:invoke()方法调用对应的方法时,java会检查权限。

解决方案:如果是调用private方法,是用setAccessible()方法设置允许调用。

// sub方法的调用Method methodSub = clazz.getDeclaredMethod("sub", int.class, int.class);methodSub.setAccessible(true);int result2 = (int) methodSub.invoke(calculator, 13, 4);System.out.println("13-4=" + result2);

  

5  Array类

在java.lang.reflect包下提供了一个Array类。

Java反射技术除了可以在运行时动态地决定要创建什么类型的对象,访问哪些成员变量,方法,还可以动态地创建各种不同类型,不同维度的数组。

动态创建数组的步骤如下:

1)        创建Class对象,通过class属性、forName(String)方法或者getClass()方法指定数组元素的类型。

2)        调用Array.newInstance(Class, length_of_array)动态创建数组。

操作动态数组常用方法

1)        访问动态数组元素的方法和通常有所不同,它的格式如下所示,注意该方法返回的是一个Object对象

    Array.get(arrayObject, index)

2)        为动态数组元素赋值的方法也和通常的不同,它的格式如下所示, 注意最后的一个参数必须是Object类型

      Array.set(arrayObject, index, object)

示例代码:

import java.lang.reflect.Array;public class Test {public static void main(String[] args) throws Exception {// 创建一个元素类型为String,长度为10的数组Object arr = Array.newInstance(String.class, 10);// 依次为数组中index为7、8的元素赋值Array.set(arr, 7, "China");Array.set(arr, 8, "German");// 依次取出数组中index为7、8的元素的值Object obj1 = Array.get(arr, 7);Object obj2 = Array.get(arr, 8);// 输出元素的值System.out.println(obj1.toString() + "  PK  " + obj2.toString());}}

上机练习

需求说明

  • 使用反射修改和查询Student类的姓名属性(public)和年龄属性(private)。
  • 使用反射动态执行Student类输出信息的方法。

转载于:https://www.cnblogs.com/rask/p/8254184.html

JavaSE-22 反射相关推荐

  1. [javaSE]反射机制

    Java反射 没有反射就没有任何EE框架! 对象的正向处理是什么呢?就是根据类产生对象,举一个简单的日期类为例 Date date=new Date();System.out.println(date ...

  2. 【JavaSE】反射与注解

    Java反射(没有反射就没有任何EE框架) 1.认识反射 反射指的是对象的反向处理.根据对象倒推类的组成,通过Java反射机制,可以访问程序中已经加载进内存的Java对象描述 反射由JDK1.0产生 ...

  3. 黑马程序员_java之反射

    android培训.物联云计算培训. java培训.期待与您交流! ---------- 反射 透彻分析反射的基础_Class类 JAVA类用于描述一类事物的共性,JAVA程序中的各个JAVA类属于同 ...

  4. 【达内课程】Java反射介绍

    文章目录 什么是反射 举个栗子:通过new和反射分别创建类 反射常用API 获取 Class 类对象有三种方法 通过反射创建类对象的两种方法 方法介绍 一些疑问 getFields() 方法和 get ...

  5. 反射机制详解(重点).

    目录: 一.反射机制概述     获取Class的三种方式必须掌握 二.通过读属性文件实例化对象 [重点 框架的时候常用] 三.只让静态代码块执行可以使用Class.forName [重点 JDBC技 ...

  6. JVM笔记(三)类与类加载

    类与类加载 前面我们讲解了JVM的内存结构,包括JVM如何对内存进行划分,如何对内存区域进行垃圾回收.接下来,我们来研究一下类文件结构以及类的加载机制. 类文件结构 在我们学习C语言的时候,我们的编程 ...

  7. 室外建筑表现3Dmax和vray常用材质参数设置

    一. 木纹材质调整方法: 1. 木纹材质的肌理调整: A.使用过度色通道贴图后加入凹凸通道贴图,使木纹有凹凸感,肌理更明显凹凸通道强度通常为30% B.材质球的高光强度(specular level: ...

  8. springmvc入门学习

    2017.05.24: spring控制器 Controller控制器,是MVC中的部分C,为什么是部分呢?因为此处的控制器主要负责功能处理部分: 1.收集.验证请求参数并绑定到命令对象: 2.将命令 ...

  9. Java创建对象小结

    Java SE中必可避免的会学到new关键字(用以创建对象),之后又了解到了克隆以及反射都可以创建对象..今天又学到了静态工厂以及构建器,所以呢,在此做一个小结. 下面我先以创建对象的几种方式开始讲起 ...

  10. Hive 3.x详细笔记

    Hive 数据仓库 概念 数据仓库(Data Warehouse,简称数仓.DW),是一个用于存储,分许,报告的数据系统. 数据仓库的目的是构建面向分析的集成数据环境,分析结果为企业提供决策支持. 数 ...

最新文章

  1. 大众点评数据平台架构变迁
  2. 写在 Dubbo go 的第五年
  3. linux下,MySQL默认的数据文档存储目录为/var/lib/mysql。
  4. php接收16进制数据,PHP_PHP 通过Socket收发十六进制数据的实现代码,最近在php下做关于Socket通讯的 - phpStudy...
  5. 前端学习(500):水平居中布局得第二种方式
  6. C++编程积累——C++实现十进制与二进制之间的互相转换
  7. 【特别关注】2021数据技术嘉年华直播观看指南
  8. MyEclipse在删除文件后servers报错问题解决
  9. 从入门到入土:Python实现爬取刷新微博推荐和最新好友微博|cookie调用|模拟登录
  10. 技术人不会学习,35 岁必然要焦虑!
  11. 中琛源携手台江县积极践行山区青少年体育公益
  12. java就业凉_【哔哩哔哩】秋招凉经 Java篇
  13. 神舟战神调节风扇热键_神舟HASEE笔记本电脑开机进入BIOS的方法与bios设置图解(F2)...
  14. 51单片机用c语言在液晶1602上显示汉字,51单片机LCD1602显示汉字(中文)源程序...
  15. 非常好用且快速的Youtube下载命令行工具yt-dlp
  16. HoloLens开发的需求与标准总结
  17. 某地区现代男科医院营销策划方案
  18. 田忌赛马 贪心 注意细节
  19. SpringBoot+Vue项目在线学习网站
  20. matlab实验大纲,matlab实验教学大纲.doc

热门文章

  1. JavaScript入门→HTML引用JS、变量、表达式操作符、数组Array数组对象、选择结构循环结构、函数、JavaScript与JAVA区别
  2. UnityShader30:预编译指令multi_complie和shader_feature
  3. C++中实现精度的控制和输出 showpoint<<或者fixed<<setprecision()用法
  4. [PyTorch] PyTorch版本不兼容问题+更新日志链接
  5. Java实现简单的计算器
  6. Latex除法a/b \frac{a}{b}
  7. pycharm怎么修改python路径
  8. 微信小程序(mpvue)—解决视频播放bug的一种方式
  9. Tomcat从socket到java Servlet
  10. jquery事件绑定与事件委托