[19/04/17-星期三] Java的动态性_反射(Reflection)机制
一、前言
动态语言:程序运行时,可以改变程序结构或变量类型。典型的代表:Python,ruby,JavaScript
如JavaScript代码:
function test(){
var s="var a=3;var b=5;alert(a+b)"
eval(s)
}
但是 C、C++、Java不是动态语言,但是Java有一定的动态性,可以称之为准动态语言,可以利用反射机制、字节码操作获得类似动态语言的特性。
Java的动态性让编程更加灵活。
二、反射的概念
指的是程序已经运行起来了但是依然可以加载、探知、使用编译时完全未知的类。 程序在运行状态时,可以动态加载一个只有名称的类,对于任意一个已加载的类,
都能知道这个类所有的属性和方法,对于任意一个对象,都能够调用它的属性和方法。
Class c=Class.forName("com.sxt.test.User");
加载完类("com.sxt.test.User")之后,在堆的内存中,就产生了一个Class类型的对象c(一个类只有一个Class对象),这个对象c就包含了完整的类的结构信息。
我们可以通过这个对象c看到类("com.sxt.test.User")的结构。这个对象c就是一面镜子,透过这个镜子可以看到类的结构,所以形象的称之为:反射
(通俗理解:把一个类映射成一个对象,以便于好操纵这个类)
【基本概念】
/***
* 反射:把一个类映射成一个对象,以便于好操纵这个类
*/
package cn.sxt.jvm; @SuppressWarnings("all")
public class Test_0417_Reflection {
public static void main(String[] args) throws Exception {
String path="cn.sxt.jvm.Test_0417_User"; Class clz=Class.forName(path);//对象表示或封装一些数据,一个类被加载之后,jVM会创建一个对应于该类的Class对象clz
//类的整个结构信息会被加载到相应的Class对象(clz)中去。这个对象映射了这个类的全部信息。
System.out.println(clz);
System.out.println(clz.hashCode()); Class clz2=Class.forName(path);
System.out.println(clz2.hashCode());//输出结果是一样的,说明一个类只能对应一个反射对象(汽车图纸)。 Class strClass=String.class;//获取常用的 String类的映射对象
System.out.println(strClass);
Class strClass2=path.getClass();//path是个字符串对象,通过对象.getClass()获取映射对象
System.out.println(strClass2);
System.out.println(strClass==strClass2);//输出为真,说明获得的是同一个映射对象 Class intClass=int.class; int arr01[]=new int[10];
int arr02[]=new int[20];
int arr03[][]=new int[5][3];
double arr04[]=new double[10];
System.out.println(arr01.getClass().hashCode());
System.out.println(arr02.getClass().hashCode());//arr01[]和arr02[]输出结果是一样的,说明映射对象与数组大小无关
System.out.println(arr03.getClass().hashCode());//输出结果不一样,而是与维数(一维or二维)相关
System.out.println(arr04.getClass().hashCode());//输出结果不一样,映射对象与数据类型相关 }
}
【反射的作用】
/**
利用反射的API获取类的信息(名字、属性、方法、构造器)
*
*/
package cn.sxt.jvm; import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@SuppressWarnings("all")
public class Test_0417_Reflection2 {
public static void main(String[] args) throws Exception {
Class clz=Class.forName("cn.sxt.jvm.Test_0417_User"); //获得类信息
System.out.println(clz.getName());//获取类的完整路径(包括包名+类名)
System.out.println(clz.getSimpleName());//获取类的简单路径(仅给出类名) //获得属性信息
Field[] fields=clz.getFields();//获取公开(public修饰的)的属性信息
Field[] fields2=clz.getDeclaredFields();//获取所有属性信息(包括public和private修饰的) Declared:宣布的,定义的
System.out.println(fields.length);//输出0 ,表示数组中没东西
System.out.println(fields2.length);//输出3 表示获得了3个私有的属性
for (Field temp : fields2) {
System.out.println("属性:"+temp);
}
System.out.println("获得单个属性:"+clz.getDeclaredField("name"));//获得单个属性name //获得方法(不含构造方法)信息
Method[] methods =clz.getDeclaredMethods();//获得所有方法(公开+私有的方法)
System.out.println(methods.length);//输出结果为6 即6个get和set方法
Method method=clz.getDeclaredMethod("setName", String.class);//参数为(方法的名字,方法中传进去参数的类型)
System.out.println(method); //获得构造方法的信息
Constructor[] constructors=clz.getDeclaredConstructors();
System.out.println(constructors.length);//输出为2
System.out.println(clz.getDeclaredConstructor(null));//获取所有的构造器中无参数的构造器
System.out.println(clz.getDeclaredConstructor(int.class,String.class,int.class));//获取所有的构造器中有如下参数的构造器 }
}
/***
* 通过反射API调用构造方法 构造对象、普通方法、属性
*/
package cn.sxt.jvm; import java.lang.reflect.Field;
import java.lang.reflect.Method; @SuppressWarnings("all")
public class Test_0417_Reflection3 {
public static void main(String[] args) throws Exception {
Class clz=Class.forName("cn.sxt.jvm.Test_0417_User"); //通过反射API调用构造方法 构造对象.
Test_0417_User user=(Test_0417_User)clz.newInstance();//其实是调用Test_0417_User的无参构造方法 Test_0417_User user2=(Test_0417_User)clz.getDeclaredConstructor(int.class,String.class,int.class).
newInstance(1001,"小李",18);//通过调用有参数的构造方法实例化一个对象
System.out.println(user2.getAge()); //通过反射API动态调用普通方法
Test_0417_User user3=(Test_0417_User)clz.newInstance();
Method method=clz.getDeclaredMethod("setName", String.class);//"setName"这里可以灵活多变,需要什么传什么
method.invoke(user3, "小王");//后2行代码等价于user3.setName("小王"); invoke:激活
System.out.println(user3.getName()); //通过反射API操作属性
Test_0417_User user4=(Test_0417_User)clz.newInstance();
Field field=clz.getDeclaredField("name");
field.setAccessible(true);//意思是访问name这个属性不用做安全检查,直接访问(否则name属性是私有的外边的类访问不了)
field.set(user4, "小张");//通过反射直接写属性的值
System.out.println(user4.getName());//通过反射直接读属性的值
System.out.println(field.get(user4));//输出结果一样
}
}
[19/04/17-星期三] Java的动态性_反射(Reflection)机制的更多相关文章
- [19/04/18-星期四] Java的动态性_动态编译(DynamicCompiler,Dynamic:动态的,Compiler:编译程序)
一.概念 应用场景:如在线评测系统,客户端编写代码,上传到服务器端编译运行:服务器动态加载某些类文件进行编译 /*** * */ package cn.sxt.jvm; import java.io. ...
- [19/04/20-星期六] Java的动态性_字节码操作(Javassist类库(jar包),assist:帮助、援助)
一.概念 [基本] /** * */ package cn.sxt.jvm; import javassist.ClassPool; import javassist.CtClass; import ...
- [19/04/19-星期五] Java的动态性_脚本(Script,脚本)引擎执行JavaScript代码
一.概念 Java脚本引擎是jdk 6.0之后的新功能. 使得Java应用程序可以通过一套固定的接口与各种脚本引擎交互,从而达到在Java平台上调用各种脚本语言的目的. Java脚本API是连接Jav ...
- [19/04/03-星期三] IO技术_其它流(RandomAccessFile 随机访问流,SequenceInputStream 合并流)
一.RandomAccessFile 随机访问流 [版本1] /* *RandomAccessFile 所谓随机读取就是 指定位置开始或指定位置结束 的读取写入文件 * 实现文件的拆分与合并 模拟下载 ...
- [19/04/02-星期二] IO技术_字符流分类总结(含字符转换流InputStreamReader/ OutputStreamWriter,实现字节转字符)
一.概念 ------->1.BufferedReader/BufferedWriter [参考19.03.31文章] *Reader/Writer-------->2.InputStre ...
- [19/04/01-星期一] IO技术_字节流分类总结(含字节数组(Array)流、字节数据(Data)流、字节对象(Object)流)
一.字节流分类概括 -->1.ByteArrayInputStream /ByteArrayOutputStream(数组字节输入输出) InputStream/OutputStr ...
- [19/04/13-星期六] 网络编程_基本概念(关注传输层、数据传输,TCP和UDP)
一.概念 ▪ 什么是计算机网络? 计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统, 网络管理软件及网络通信协议的管理和协调下,实现资源共享和信 ...
- JDK1.7新特性(4):java语言动态性之反射API
直接通过一个代码示例来熟悉java中通过反射来对构造函数/域以及方法处理的相关API: package com.rampage.jdk7.chapter2; import java.lang.refl ...
- Java之注解与反射
Java之注解与反射 注解(Annotation)简介 注解(Annotation)是从JDK5.0引入的新技术 Annotation作用:注解(Annotation)可以被其他程序如编译器等读取 A ...
随机推荐
- 阿里云服务器windows server流量不大的情况下,tomcat经常出现访问阻塞,手动ctrl+c或者点击右键又访问正常
我被这个问题折磨了好几天,因为这两天要帮别人做推广,不能再出现这样的情况了,不然广告费就白烧了,所以特意查了一下资料,结果解决方案被我找出来了. 问题发生原因是因为打开编辑选项后,一不小心点到dos窗 ...
- 撩课-Java每天5道面试题第9天
撩课Java+系统架构 视频 点击开始学习 76.XML技术的作用? XML技术用于数据存储. 信息配置. 数据交换三方面. 可以将数据存储在XML中, 通过节点. 元素内容. 属性标示数据内容及关系 ...
- Java线程入门第二篇
Java线程通信方法 0.(why)每个线程都有自己的栈空间,我们要线程之间进行交流,合作共赢. 1.synchronized和volatile关键字 a) 看下面的synchronized关键字 ...
- Eclipse3.2查找jre的问题
前几天遇到一个问题,最开始电脑上使用的是解压的JDK(带jre),但是不能打开jar文件.所以从网上下载了一个jre1.8,然后问题来了,Eclipse打开就报错,弹出一个框,在eclipse的目录下 ...
- Ubuntu16.04下安装MATLAB 2016b!完美运行
目录 1.下载MATLAB 2016b 2.挂载iso 3.安装MATLAB 4.破解 5.快捷键与运行 1.下载MATLAB 2016b 下载matlab 2016b for linux(可以百度搜 ...
- 原生javascript实现类似jquery on方法的行为监听
原生javascript有addEventListener和attachEvent方法来注册事件,但有时候我们需要判断某一行为甚至某一函数是否被执行了,并且能够获取前一行为的参数,这个时候就需要其他方 ...
- Hibernate详讲
一 概述 1.JPA Java Persistence API,是Java EE为ORM框架定义的规范,任何使用java语言的ORM框架都必须实现该规范.Hibernate/Mybatis都是是JPA ...
- bootstrap学习笔记细化(标题)
bootstrap中的排版: 标题(h1~h6/.h1~.h6) h1:36px;h2:30px;h3:24px;h4:18px;h5:14px;h6:12px; 副标题(small) 小练习(标题大 ...
- 转:问题解决:The project cannot be built until build path errors are resolved
转自:http://blog.csdn.net/marty_zhu/article/details/2566299 今天在eclipse里遇到这个问题,之前也遇到过,不过,通过clean一下项目,或者 ...
- 改bug后 fix bug 时,一个不错的修复描述模板
*问题原因:* 问题出现的原因.*解决方法:* 问题的解决方案.*影响分支:* 影响哪些分支. *相关修改:* 具体的修改文件列表.*自测结果:* 自行测试了哪些用例,将大概步骤描述出来. *影响功能 ...