《Java基础知识》Java 反射详解
定义
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
用途
在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法。当然,也不是所有的都适合反射,之前就遇到一个案例,通过反射得到的结果与预期不符。阅读源码发现,经过层层调用后在最终返回结果的地方对应用的权限进行了校验,对于没有权限的应用返回值是没有意义的缺省值,否则返回实际值起到保护用户的隐私目的。
案例:(重要)
public class Demo1 {
//创建一个自己本身的公共变量
public static demo.knowledgepoints.reflect.Demo1 demo1; private static final boolean flag = true ; //将其私有化,保证不能通过New的方式创建。
private Demo1(){} //创建get方法,用于告知使用者,不能被new,不能被获取。
public static Demo1 getDemo1() throws Exception{
if(flag){
throw new Exception("抱歉,该类不通过new 的方式创建!");
}
return demo1;
} public void print(){
System.out.println("恭喜成功获取Demo1!");
} //通过静态代码块创建实体类。
static {
demo1 = new Demo1();
}
}
public class Demo2 {
//创建一个自己本身的私有变量
private static demo.knowledgepoints.reflect.Demo2 demo2; private static final boolean flag = true ; //将其私有化,保证不能通过New的方式创建。
private Demo2(){} //创建get方法,用于告知使用者,不能被new,不能被获取。
public static Demo2 getDemo2() throws Exception{
if(flag){
throw new Exception("抱歉,该类不通过new 的方式创建!");
}
return demo2;
} public void print(){
System.out.println("恭喜成功获取Demo2!");
} //通过静态代码块创建实体类。
static {
demo2 = new Demo2();
}
}
public class Reflect {
public static void main(String[] args) {
Demo1 demo1 = null;
Demo2 demo2 = null;
try {
//发现new ,编译报错。
//demo1 = new Demo1();
//demo2 = new Demo2(); //发现get方法也获取不到,执行会报异常。
demo1 = Demo1.getDemo1();
demo2 = Demo2.getDemo2();
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
通过上述代码,我们知道通过普通方法是无法获取到Demo1 和 Demo2。但是看Demo1 和 Demo2的写法,在静态代码块中是new了对象的。说明肯定有办法可以获取到实例。
这里说的方法就是反射。
import java.lang.reflect.Field; public class Reflect {
public static void main(String[] args) {
Demo1 demo1 = null;
Demo2 demo2 = null;
try {
//首先通过Field,获取需要的类,Field包在jdk的反射包中:java.lang.reflect
Field field1 = Demo1.class.getDeclaredField("demo1");
//获取之后,强制转换成Demo1。
demo1 = (Demo1)field1.get(null);
demo1.print(); //然后我们再来创建一个Demo2.
Field field2 = Demo2.class.getDeclaredField("demo2");
//私有方法需要将:field2.setAccessible(true) ,才能获取到实例类
field2.setAccessible(true);
demo2 = (Demo2)field2.get(null);
demo2.print();
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
通过上述代码,我们通过反射,获取到Demo1和Demo2的公共属性和私有属性,成功获取到对象。
讲讲反射原理:
通过到class所在目录下,执行javap -c Book.class,可以查看字节码。可以看到一些公共的方法,私有的看不到,不过不影响JVN获取。
下面介绍一下反射的基础类和方法
类名 | 用途 |
Class类 | 代表类的实体,在运行的Java应用程序中表示类和接口 |
Field类 | 代表类的成员变量(成员变量也称为类的属性) |
Method类 | 代表类的方法 |
Constructor类 | 代表类的构造方法 |
方法见JDK-API文档。
package demo.knowledgepoints.reflect; public class Book {
private final static String TAG = "BookTag"; private String name;
private String author; @Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
'}';
} public Book() {
} private Book(String name, String author) {
this.name = name;
this.author = author;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getAuthor() {
return author;
} public void setAuthor(String author) {
this.author = author;
} private String declaredMethod(int index) {
String string = null;
switch (index) {
case 0:
string = "I am declaredMethod 1 !";
break;
case 1:
string = "I am declaredMethod 2 !";
break;
default:
string = "I am declaredMethod 1 !";
} return string;
}
}
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method; public class Reflect {
public static void main(String[] args) {
reflectNewInstance();
reflectPrivateConstructor();
reflectPrivateField();
reflectPrivateMethod();
} /**
* 通过反射获取对象
*/
public static void reflectNewInstance() {
try {
Class<?> classBook = Class.forName("demo.knowledgepoints.reflect.Book");
Object objectBook = classBook.newInstance();
Book book = (Book) objectBook;
book.setName("Java进阶之光");
book.setAuthor("蕾蕾");
System.out.println("reflectNewInstance book = " + book.toString());
} catch (Exception ex) {
ex.printStackTrace();
}
} // 反射私有的构造方法
public static void reflectPrivateConstructor() {
try {
Class<?> classBook = Class.forName("demo.knowledgepoints.reflect.Book");
Constructor<?> declaredConstructorBook = classBook.getDeclaredConstructor(String.class,String.class);
declaredConstructorBook.setAccessible(true);
Object objectBook = declaredConstructorBook.newInstance("Java开发艺术探索","磊磊");
Book book = (Book) objectBook;
System.out.println("reflectPrivateConstructor book = " + book.toString());
} catch (Exception ex) {
ex.printStackTrace();
}
} // 反射私有属性
public static void reflectPrivateField() {
try {
Class<?> classBook = Class.forName("demo.knowledgepoints.reflect.Book");
Object objectBook = classBook.newInstance();
Field fieldTag = classBook.getDeclaredField("TAG");
fieldTag.setAccessible(true);
String tag = (String) fieldTag.get(objectBook);
System.out.println("reflectPrivateField tag = " + tag);
} catch (Exception ex) {
ex.printStackTrace();
}
} // 反射私有方法
public static void reflectPrivateMethod() {
try {
Class<?> classBook = Class.forName("demo.knowledgepoints.reflect.Book");
Method methodBook = classBook.getDeclaredMethod("declaredMethod",int.class);
methodBook.setAccessible(true);
Object objectBook = classBook.newInstance();
String string = (String) methodBook.invoke(objectBook,1); System.out.println("reflectPrivateMethod string = " + string);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
运行结果:
参考:https://www.jianshu.com/p/9be58ee20dee
《Java基础知识》Java 反射详解的更多相关文章
- Java基础13:反射详解
本节主要介绍Java反射的原理,使用方法以及相关的技术细节,并且介绍了关于Class类,注解等内容. 具体代码在我的GitHub中可以找到 https://github.com/h2pl/MyTech ...
- Java基础-面向接口编程-JDBC详解
Java基础-面向接口编程-JDBC详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.JDBC概念和数据库驱动程序 JDBC(Java Data Base Connectiv ...
- java基础(3)--详解String
java基础(3)--详解String 其实与八大基本数据类型一样,String也是我们日常中使用非常频繁的对象,但知其然更要知其所以然,现在就去阅读源码深入了解一下String类对象,并解决一些我由 ...
- Linux基础知识之挂载详解(mount,umount及开机自动挂载)
Linux基础知识之挂载详解(mount,umount及开机自动挂载) 转载自:http://www.linuxidc.com/Linux/2016-08/134666.htm 挂载概念简述: 根文件 ...
- 学习Spring必学的Java基础知识(1)----反射(转)
引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓"登高必自卑,涉远必自迩".以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系 ...
- 学习Spring必学的Java基础知识(1)----反射
引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓"登高必自卑,涉远必自迩".以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系 ...
- JAVA基础知识|java虚拟机(JVM)
一.JVM简介 java语言是跨平台的,兼容各种操作系统.实现跨平台的基石就是虚拟机(JVM),虚拟机不是跨平台的,所以不同的操作系统需要安装不同的jdk版本(jre=jvm+类库:jdk=jre+开 ...
- [java基础知识]java安装步骤
jre: java运行环境. jre = java虚拟机 + 核心类库(辅助java虚拟机运行的文件).如果只是运行java程序,只需要安装jre. jdk: java开发工具集 jd ...
- java基础知识——Java的定义,特点和技术平台
(作者声明:对于Java编程语言,很多人只知道怎么用,却对其了解甚少.我也是其中一员.所以菜鸟的我,去查询了教科书以及大神的总结,主要参考了<Java核心技术>这本神作.现在分享给大家!) ...
- 计算机基础知识和tcp详解
计算机基础知识 作为应用软件开发程序员是写应用软件的,而应用软件必须应用在操作系统之上,调用操作系统接口,由操作系统控制硬件 比如客户端软件想要基于网络发送一条消息给服务端软件,流程是: 1.客户端软 ...
随机推荐
- 关闭Eslint检查
Eslint是一个JavaScript的校验插件,通常用来校验语法或代码的书写风格.不过有点过于严格,通常缩减不同也会报错... 这会影响工作效率啊,最好就是在创建项目的时候不要ESlint(选择No ...
- python_07
破解极限滑动认证 from selenium import webdriver from selenium.webdriver import ActionChains from PIL import ...
- python gui tkinter快速入门教程 | python tkinter tutorial
本文首发于个人博客https://kezunlin.me/post/d5c57f56/,欢迎阅读最新内容! python tkinter tutorial Guide main ui messageb ...
- applicationContext-dao.xml 配置错误
https://www.captainbed.net/ 配置文件报错: 不允许有匹配 "[xX][mM][lL]" 的处理指令目标. 错误原因: 由于大部分都是搬砖,所以格式没注意 ...
- SpringAOP之使用切入点创建通知
之前已经说过了SpringAOP中的几种通知类型以及如何创建简单的通知见地址 一.什么是切入点 通过之前的例子中,我们可以创建ProxyFactory的方式来创建通知,然后获取目标类中的方法.通过不同 ...
- 原创001 | 搭上SpringBoot自动注入源码分析专车
前言 如果这是你第二次看到师长的文章,说明你在觊觎我的美色!O(∩_∩)O哈哈~ 点赞+关注再看,养成习惯 没别的意思,就是需要你的窥屏^_^ 本系列为SpringBoot深度源码专车系列,第一篇发车 ...
- linux创建文件名添加当前系统日期时间的方法
使用`date +%y%m%d` Example: mkdir `date +%y%m%d` tar cfvz /tmp/bak.`date +%y%m%d`.tar.gz /etc YmdHM代表年 ...
- js对象的浅拷贝与深拷贝
浅拷贝和深拷贝都是对于JS中的引用类型而言的,浅拷贝就只是复制对象的引用(堆和栈的关系,原始(基本)类型Undefined,Null,Boolean,Number和String是存入堆,直接引用,ob ...
- 使用cookies弹出层每24小时弹出一次
第一步:下载cookies的库 https://github.com/js-cookie/js-cookie 第二步:设置Cookies的失效时间,这里有两种方法,按天计算和按小时计算 functio ...
- [Abp vNext 源码分析] - 13. 本地事件总线与分布式事件总线 (Rabbit MQ)
一.简要介绍 ABP vNext 封装了两种事件总线结构,第一种是 ABP vNext 自己实现的本地事件总线,这种事件总线无法跨项目发布和订阅.第二种则是分布式事件总线,ABP vNext 自己封装 ...