【达内课程】Java反射介绍
文章目录
- 什么是反射
- 举个栗子:通过new和反射分别创建类
- 反射常用API
- 获取 Class 类对象有三种方法
- 通过反射创建类对象的两种方法
- 方法介绍
- 一些疑问
- getFields() 方法和 getDeclaredFields () 的区别
- 使用 new 和 newInstance() 创建类的区别
什么是反射
一般情况下,我们使用某个类时必定知道它是什么类,是用来做什么的。于是我们直接对这个类进行实例化,之后使用这个类对象进行操作。例如:
Person person = new Person();
person.setId(22);
而反射则是一开始并不知道要初始化的类对象是什么,自然也无法使用 new 关键字来创建对象了。我们使用 JDK 提供的反射 API 进行反射调用:
Class clz = Class.forName("com.example.testapplication.Person");
Method method = clz.getMethod("setId", int.class);
Constructor constructor = clz.getConstructor();
Object object = constructor.newInstance();
method.invoke(object, 22);;
面两段代码的执行结果,其实是完全一样的。但是其思路完全不一样,第一段代码在未运行时就已经确定了要运行的类(Person),而第二段代码则是在运行时通过字符串值才得知要运行的类(com.example.testapplication.Person)。
所以 Java 反射说的是在运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性。对于任何一个对象,我们都能够对它的方法和属性进行调用。我们把这种动态获取对象信息和调用对象方法的功能称之为反射机制。
所谓反射其实是获取类的字节码文件,也就是.class
文件,那么我们就可以通过 Class 这个对象进行获取。
举个栗子:通过new和反射分别创建类
首先创建 Person 类
class Person {private int id;private String name;public Person() {super();}public Person(int id,String name) {super();this.id = id;this.name = name;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}
Person person = new Person();person.setId(22);Log.d("TTT",person.getId()+"");try {Class clz = Class.forName("com.example.testapplication.Person");Method method = clz.getMethod("setId", int.class);Constructor constructor = clz.getConstructor();Object object = constructor.newInstance();method.invoke(object, 22);Method getPriceMethod = clz.getMethod("getId");Log.d("TTT",getPriceMethod.invoke(object)+"");} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}
输出结果:
从这个简单的例子可以看出,一般情况下我们使用反射获取一个对象的步骤:
1、获取类的 Class 对象实例
Class clz = Class.forName("com.example.testapplication.Person");
2、根据 Class 对象实例获取 Constructor 对象
Constructor constructor = clz.getConstructor();
3、使用 Constructor 对象的 newInstance 方法获取反射类对象
Object object = constructor.newInstance();
而如果要调用某一个方法,则需要经过下面的步骤:
1、获取方法的 Method 对象
Method method = clz.getMethod("setId", int.class);
2、利用 invoke 方法调用方法
method.invoke(object, 22);
反射常用API
获取 Class 类对象有三种方法
在反射中,要获取一个类或调用一个类的方法,我们首先需要获取到该类的 Class 对象。
在 Java API 中,获取 Class 类对象有三种方法:
第一种,使用 Class.forName 静态方法。当你知道该类的全路径名时,你可以使用该方法获取 Class 类对象。
Class clz = Class.forName("java.lang.String");
第二种,使用 .class 方法。这种方法只适合在编译前就知道操作的 Class。
Class clz = String.class;
第三种,使用类对象的 getClass() 方法。
String str = new String("Hello");
Class clz = str.getClass();
通过反射创建类对象的两种方法
通过反射创建类对象主要有两种方式:通过 Class 对象的 newInstance() 方法、通过 Constructor 对象的 newInstance() 方法。
第一种:通过 Class 对象的 newInstance() 方法。
Class clz = Person.class;
Object object = clz.newInstance();
第二种:通过 Constructor 对象的 newInstance() 方法。
Class clz = Person.class;
Constructor constructor = clz.getConstructor();
Object object = constructor.newInstance();
通过 Constructor 对象创建类对象可以选择特定构造方法,而通过 Class 对象则只能使用默认的无参数构造方法。下面的代码就调用了一个有参数的构造方法进行了类对象的初始化。
Class clz = Person.class;
Constructor constructor = clz.getConstructor(int.class,String.class);
Object object = constructor.newInstance(22,"Errol");
方法介绍
创建一个 Person 类
class Person {public int id;private String name;public Person(int id, String name) {super();this.id = id;this.name = name;}
}
MainActivity 中
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Person person = new Person(22, "Errol");//获取Class对象Log.d("TTT", person.getClass() + "");//class com.example.testapplication.Person//获取Class对象所表示的实体Log.d("TTT", person.getClass().getName() + "");//com.example.testapplication.Person//得到类的简写名称Log.d("TTT", person.getClass().getSimpleName() + "");//PersonField[] fields = person.getClass().getFields();for (int i = 0; i < fields.length; i++) {//获取字段的名称,无法获取私有属性//getDeclaredFields()方法则可以获取包括私有属性在内的所有属性Log.d("TTT", fields[i].getName());//id//获取字段修饰符。什么都不加:0;public:1;private:2;protected:4;static:8;final:16Log.d("TTT", fields[i].getModifiers() + "");//1//与某个具体的修饰符进行比较Log.d("TTT", Modifier.isStatic(fields[i].getModifiers()) + "");//false//获取字段的声明类型Log.d("TTT", fields[i].getType() + "");//int//与某个类型进行比较Log.d("TTT", (fields[i].getType() == int.class) + "");//true//获取字段的值try {Object fieldObject = fields[i].get(person);Log.d("TTT", fieldObject.toString());//22} catch (IllegalAccessException e) {e.printStackTrace();}//判断Class是否为原始类型(boolean、char、byte、short、int、long、float、double)Log.d("TTT", (fields[i].getType().isPrimitive()) + "");//true//isAccessible()值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查//setAccessible是启用和禁用访问安全检查的开关,并不是为true就能访问为false就不能访问Log.d("TTT", fields[i].isAccessible() + "");//false}}
}
tips:由于JDK的安全检查耗时较多。所以通过setAccessible(true)
的方式关闭安全检查就可以达到提升反射速度的目的
一些疑问
getFields() 方法和 getDeclaredFields () 的区别
关于获取类的字段有两种方式:getFields()
和getDeclaredFields()
,区别如下:
getFields()
:获得某个类的所有的公共(public)的字段,包括父类中的字段
getDeclaredFields()
:获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段
同样类似的还有getConstructors()
和getDeclaredConstructors()
、getMethods()
和getDeclaredMethods()
,这两者分别表示获取某个类的方法、构造函数
使用 new 和 newInstance() 创建类的区别
在初始化一个类,生成一个实例的时候,newInstance()
方法和new
关键字除了一个是方法,一个是关键字外,最主要有什么区别?
它们的区别在于创建对象的方式不一样,前者是使用类加载机制,后者是创建一个新类。newInstance()
生成对象只能调用无参的构造函数,首先调用Class.forName("")
返回的是类来加载某个类,然后使用Class.forName("").newInstance()
返回的是 object 来实例化。只能调用无参的构造函数。是使用newInstance()
方法的时候,就必须保证:1、这个类已经加载;2、这个类已经连接了。
而使用new
关键字生成对象没有这个限制。new 创建一个类的时候,这个类可以没有被加载。
简言之:
newInstance()
: 弱类型,低效率,只能调用无参构造。你可以对该类一无所知。
new
: 强类型,相对高效,能调用任何 public 构造。必须要知道一个明确的类才能使用。
参考:
大白话说Java反射:入门、使用、原理
【达内课程】Java反射介绍相关推荐
- Java反射-静态/动态加载类
title: Java反射-静态/动态加载类 date: 2019-05-28 18:50:00Java反射-静态/动态加载类 Class 类是对象,是java.lang.Class类的实例对象.任何 ...
- java反射和注解开发(备java基础,javaee框架原理)-任亮-专题视频课程
java反射和注解开发(备java基础,javaee框架原理)-5358人已学习 课程介绍 Java注解是附加在代码中的一些元信息,用于一些工具在编译.运行时进行解析和使用,起到说明. ...
- Java反射详细介绍
反射 目录介绍 1.反射概述 1.1 反射概述 1.2 获取class文件对象的三种方式 1.3 反射常用的方法介绍 1.4 反射的定义 1.5 反射的组成 1.6 反射的作用有哪些 2.反射的相关使 ...
- java getinstance 反射_JAVA类加载和反射介绍
简单的来说,反射机制指的是程序在运行时能够获取自身的信息.在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息. 反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性, ...
- Java反射机制介绍
2019独角兽企业重金招聘Python工程师标准>>> 1. 文档概述 Java反射是Java被视为动态(或准动态)语言的一个关键性质,Java反射机制容许程序在运行时加载.探知.使 ...
- java 反射 int_Java 反射由浅入深 | 进阶必备
原标题:Java 反射由浅入深 | 进阶必备 一.Java 反射机制 参考了许多博文,总结了以下个人观点,若有不妥还望指正: Java 反射机制在程序运行时,对于任意一个类,都能够知道这个类的所有属性 ...
- java 反射api_Java的反射API
java 反射api 如果您曾经问过自己以下问题: –"如何在字符串中仅包含其名称的方法调用?" –"如何动态列出类中的所有属性?" –"如何编写 ...
- Java反射示例教程
Java反射示例教程 Java Reflection提供检查和修改应用程序的运行时行为的能力.Java中的反射是核心java的一个先进主题.使用java反射我们可以检查一个类,在运行时接口,枚举,获取 ...
- Java数据库开发与应用之MySQL数据库、JDBC操作数据库、C3P0数据库连接池,Java反射等
MySQL数据库,JDBC接口,MyBatis框架等,掌握的数据的存放和管理. Java数据库开发基础,介绍MySQL数据库.JDBC操作数据库.C3P0数据库连接池,Java反射等内容,进行油画商城 ...
最新文章
- 第十九章:集合视图(二十一)
- URL、Session、Cookies、Server.Transfer、Application和跨页面传送。
- ajax异步传输代码,Ajax同步与异步传输的示例代码
- boost::random_spanning_tree用法的测试程序
- 【HDU - 1754】I Hate It (线段树模板 单点覆盖更新+区间最大值查询)
- linux 不可中断的进程,不可中断进程和僵尸进程
- 大佬怼国产特斯拉:将必遭这款车型碾压
- 【论文笔记】Simple and Deep Graph Convolutional Networks
- leetcode 786 第K个最小的素数分数
- LooseScan Strategy
- 禅道下载与安装教程(完整版)
- python常用模块之time
- pandas 数据类型及相互转化
- Java线程池ThreadPoolExecutor详解(一篇就够了)
- 跃迁-功利心的学习方法,学的更好,学的更少
- SolidWorks六角螺母添加倒角2种方法
- python镜像安装是什么意思_通过PyPI镜像安装Python包
- 数据结构作业——Sanji(优先队列)
- 20210323第一家量产国产化蓝牙AOA高精度定位基站生态合能培训会上海站现场直播下午内容视频录像回放-深圳核芯物联原厂工程师罗良技术分享
- xamarin android 微信,转换微信SDK为Xamarin绑定库 Android5.5.8 iOS1.8.6.2