当前位置: 首页 > 编程日记 > 正文

java反射用在哪里_Java反射

昨天去参加比赛了,所以没有进行博客迁移。人生中的第一场健体比赛,虽然没得奖,但是收获和带来的思考颇丰。意外地进入了男子B组(174以上)的半决赛,然后在半决赛的时候还被裁判员点名出去单独比较,这个很让我惊喜。最后不意外地止步决赛。事后看视频感觉自己没发挥好,有些遗憾,下一次比赛要更加认真的对待!

废话少说,进入今天的主题:Java反射。

这篇文章是根据马士兵老师的Java视频课程所整理的。感谢马士兵老师,很有个人魅力的一个人。

前言

我们写程序时一直在使用各种各样不同的类来生成对象,但是却从没想过为什么可以这样做。所谓的类,只不过是.java文件中的一些文本罢了,我们知道很多事情JVM帮我们做了,但却并不知道JVM做了什么。

类的加载机制

学Java的人都知道这样一句话:

在Java中,一切都是对象。

所谓的类,其实在JVM中也是对象,它的类型就是类类型。说起来有点拗口,但确实

所有的类都是通过ClassLoader这个类加载到内存中的CodeSegment中去的。但是类也分等级,比如核心类,如String;拓展类,如xxx(具体类名不记得了..);还有自己定义的类,如Student。这些类是被不同的ClassLoader加载进来的,

通过下列程序来查看Java的类加载过程:

class TestClassLoader{

public static void main(String[] args){

new A();

System.out.println("--------");

new B();

new C();

new C();

}

class A{

}

class B{

}

class C{

static {

System.out.println("ccccccccc");

}

}

}

运行上述程序,打印verbose日志,发现JVM的类加载过程如下:

1. JVM首先使用bootstrap classloader和extension classloader去加载一些核心类,如String类这些,可以认为这些类是Java程序运行所必须的类。

2. 使用application classloader去加载TestClassLoader这个我们创建的类。然后其中的代码从main方法开始执行,首先碰到的是方法参数中的String类,这个时候applicationclassloader会问extensionclassloader有没有加载过String类,如果extensionclassloader不知道,它会再向上询问bootstrapclassloader,并最终得到结果并告诉applicationclassloader。如果没加载过,那么applicationclassloader会去找String类进行加载,如果已经加载过了,就不再加载。否则每次遇见类就加载的话,我们就可以让程序加载我们的自己写的和某些核心类同名的类了,相当于是将java中的核心类替换成了我们自己的类,这是极不安全的。因此classloader的这种逐级向上询问的方式可以防止开发者篡改核心类的代码,开发核心病毒。

3. 一个类只会被加载一次,原因如上所述。

4. 静态代码块是在类加载的时候执行的,所以上述代码中虽然new了两个C对象,但是其静态代码块只会执行一次。即只会输出一次ccccccccc

关于上面提到的三种classLoader

bootstrap class loader

implemented by native language (C, C++)

load core classes of jdk

extension class loader

load classed from jre/lib/ext

application class loader

load user-define classes

other class loaders

SecureClassLoader

URLClassLoader

这三种classloader并不是继承关系,而是层次关系,比如你load我,我再load他,这样子。

思考这样一个问题:

写一个方法,这个方法的签名为Object fun(String className){}。要求在方法体中实现根据传入的类名生成一个该类的对象,并返回。

对于人来说,这个任务非常简单,但是对于计算机来说,这个任务就非常麻烦了,因为方法得到的类名是一个String对象,如何将这个String对象转换成类的类型呢?这个时候就必须要用到反射了。理解反射机制也必须理解上面所讲的类加载机制。

插一句:其实万物都有始。我们不了解类加载机制也不妨碍我们写一些应用层的代码,但是不代表类的加载是无缘无故完成,它必定有一个过程,必定有一个开始的地方。

TestReflect.java

public class TestReflect {

public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, IllegalArgumentException, InvocationTargetException {

//假设现在程序知道了有一个类的名字叫做Student,现在要创建它的对象

String s = "Reflect.Student";//一定要用完全限定名,这点和马士兵视频中的不同,可能是jdk版本的原因

//首先要根据类名去寻找这个类文件,并将其加载到内存中来,加载后以一个Class对象的方式存在与内存中

Class c = Class.forName(s); // throws ClassNotFoundException

//根据加载进来的类对象创建这个类的对象

Object student = c.newInstance(); // throws InstantiationException and IllegalAccessException

//探知这个类的属性

Field[] fields = c.getFields();

System.out.println("探知到的属性数 = "+fields.length);

for(Field field : fields){

System.out.println(field.getName());

}

//探知这个类的方法

Method[] methods = c.getMethods();

System.out.println("探知到的方法数 = "+methods.length);

for (Method method : methods){

System.out.println(method.getName());

//调用这个类的方法

if (method.getName().equals("fun1")){

method.invoke(student);//throws IllegalArgumentException

}

//甚至还能调用Method的getParameterTypes()和getReturnType()拿到方法的参数类型和返回值类型。具体的可以参考Java的API文档

}

}

}

Student.java

class Student {

public String i = "public";

protected String s = "protected";

String ss = "default";

private String sss = "private";

static String kk = "static";

static {

System.out.println("class Student has been loaded");

}

Student(){

System.out.println("object Student has been constructed");

}

public void fun1(){

System.out.println("public function fun1() has been invoked");

}

protected void fun2(){

System.out.println("protected function fun2() has been invoked");

}

void fun3(){

System.out.println("default function fun3() has been invoked");

}

private void fun4(){

System.out.println("private function fun4() has been invoked");

}

}

输出:

class Student has been loaded

object Student has been constructed

探知到的属性数 = 1

i

探知到的方法数 = 10

fun1

public function fun1() has been invoked

wait

wait

wait

equals

toString

hashCode

getClass

notify

notifyAll

从上面的输出可以看出,利用反射动态加载的类,只能使用其public属性和方法,其他三种修饰符的一律不可以使用。

总结

所谓反射,其实跟中文中的词汇“反射”没什么特别大的联系,在Java中只是一种用于动态加载和生成类对象并使用之的技术手段。

在哪里会用到反射?

当一个程序的运行依赖于配置文件时,这个程序极有可能使用了反射。因为程序从配置文件中读到的只能是字符串,要根据字符串实现不同的逻辑,很可能涉及到不同的类,而要根据字符串生成不同的类,则必须用到反射。当然也可以在程序内写很多分支判断语句,但是这种做法会产生大量的不运行代码,而且,除非分支语句能够穷尽所有的可能,否则这个程序总存在bug。尤其是当程序运行所依赖的外部参数多于一个时,分支语句的个数简直是成指数增加,几乎不可能穷尽。

后记:我试着学习鸿洋和郭霖的文风,而尽量避免stormzhang的风格,因为我个人感觉前者的文章看着更加舒服。但我深知自己离他们任何一个人的水平都还差太远,所以如果文章中出现哪些技术性错误,请一定告诉我错在哪里,谢谢!

如果这篇文章有帮到你,请在下方留言,这将是对我莫大的鼓励。

相关文章:

html中锚点的应用【本页面跳转】

设置锚点 <a name"top"></a> 同页跳转 <a href"#top">返回顶部</a> 不同页跳转 <a href"test.htm#top>跳转到test.htm页面顶部</a> 转载于:https://www.cnblogs.com/wangmars/p/3241855.html

SQL2005CLR函数扩展-正则表达式

用过Oracle的人都知道Oracle有四个正则表达函数REGEXP_LIKE、REGEXP_INSTR、REGEXP_SUBSTR、和EGEXP_REPLACE&#xff0c;而SQLServer却无法完全实现上面的功能。以前我们知道用sp_OAxxx系列函数来调用js组建实现正则&#xff0c;现在我们可以通过CLR扩展来借助.Net实现。 ※ 代…

ROW_NUMBER() OVER函数的基本用法

简单的说row_number()从1开始&#xff0c;为每一条分组记录返回一个数字&#xff0c;这里的ROW_NUMBER() OVER (ORDER BY xlh DESC) 是先把xlh列降序&#xff0c;再为降序以后的没条xlh记录返回一个序号。 2row_number() OVER (PARTITION BY COL1 ORDER BY COL2) 表示根据COL1…

OpenC 仿射变换

仿射变换&#xff08;Affine Transformation&#xff09;又称仿射映射&#xff0c;是指在几何中&#xff0c;一个向量空间进行一次线性变化并加上一个平移&#xff0c;变换位另一个的向量空间的过程。 一个任意的仿射变换都能够表示为乘以一个矩阵&#xff08;线性变换&#xf…

做acm 需要学的算法

做acm 需要学的算法 转一个搞ACM需要的掌握的算法. 要注意,ACM的竞赛性强,因此自己应该和自己的实际应用联系起来. 适合自己的才是好的,有的人不适合搞算法,喜欢系统架构,因此不要看到别人什么就眼红, 发挥自己的长处,这才是重要的. 第一阶段&#xff1a;练经典常用算法&am…

java实现七日股票问题_七日打卡--JAVA资源限制

资源限制资源限制是指在进行并发编程时&#xff0c;程序的执行速度受限于计算机硬件资源或软件资源。 例如服务器的带宽只有2Mb/s&#xff0c;某个资源的下载速度是1Mb/s每秒&#xff0c;系统启动10个线程下载资源&#xff0c;下载速度不会变成10Mb/s&#xff0c;所以在进行并发…

Cassandra 可视化工具

2019独角兽企业重金招聘Python工程师标准>>> 最近开始接触Cassandra&#xff0c;这些天在cassandra的wiki发现了一些可视化工具的推荐。现在也把这个链接推荐给大家&#xff1a;http://wiki.apache.org/cassandra/Administration%20Tools 。 几番折腾之后&#xff0…

Linux软件的安装,更新与卸载

linux软件的安装&#xff0c;更新与卸载 Linux常见的安装为tar&#xff0c;zip&#xff0c;gz&#xff0c;rpm&#xff0c;deb&#xff0c;bin等。我们可以简单的分为三类. 第一&#xff1a;打包或压缩文件tar&#xff0c;zip&#xff0c;gz等&#xff0c;一般解压后即可&#…

因链接静态库先后顺序不正确,引起符号定义找不到

问题 项目中需要链接多个静态库&#xff0c;在编译的时候报错如下 sdi_io.cpp:(.text._ZN13sdi_H264EncIO7DataPopEPm0x30)&#xff1a;对‘H264ENC_StatusGet(H264ENC_Status_t&)’未定义的引用可能原因是符号确实没有定义&#xff0c;而本文出现这个问题的原因是&#…

java中后台是那一部分_一套Java后台管理系统,拿来即用(附项目地址)

前言这套Base Admin是一套简单通用的后台管理系统&#xff0c;主要功能有&#xff1a;权限管理、菜单管理、用户管理&#xff0c;系统设置、实时日志&#xff0c;实时监控&#xff0c;API加密&#xff0c;以及登录用户修改密码、配置个性菜单等技术栈前端&#xff1a;layuijava…

基础 HTML之目录问题(相对路径和绝对路径区别)

一、相对路径和绝对路径 相对路径&#xff1a;以引用文件之网页所在位置为参考基础&#xff0c;而建立出的目录路径。因此&#xff0c;当保存于不同目录的网页引用同一个文件时&#xff0c;所使用的路径将不相同&#xff0c;故称之为相对。 绝对路径&#xff1a;以Web站点根目录…

[转]android selector 背景选择器

关于listview和button都要改变android原来控件的背景&#xff0c;在网上查找了一些资料不是很全&#xff0c;所以现在总结一下android的selector的用法。首先android的selector是在drawable/xxx.xml中配置的。先看一下listview中的状态&#xff1a;把下面的XML文件保存成你自己…

牛客国庆集训派对Day6 B.Board

链接 [https://www.nowcoder.com/acm/contest/206/B] 分析 只要在n*n范围内随便找一个斜对角的一个格子去计算就知道了 具体看代码体会吧 代码 #include<bits/stdc.h> using namespace std; int a[1010][1010];int main(){int n,i,j,x,y;//freopen("in.txt",&q…

java并发读取相同的文件_高效读取大文件,再也不用担心 OOM 了!

最近阿粉接到一个需求&#xff0c;需要从文件读取数据&#xff0c;然后经过业务处理之后存储到数据库中。这个需求&#xff0c;说实话不是很难&#xff0c;阿粉很快完成了第一个版本。内存读取第一个版本&#xff0c;阿粉采用内存读取的方式&#xff0c;所有的数据首先读读取到…

Cmake 实例学习 一

一. 第一个简单的例子 在一个目录下面实现一个简单的 hello world 程序 使用cmake进行构建的时候&#xff0c;每个目录下面都要有一个 CMakeLists.txt 的文件 如果是一个稍微大的工程&#xff0c;有多级目录&#xff0c;在上级目录中的 CMakeLists.txt 中会有定义要求编译子目…

ORA-19502: write error on file xxxxx, block number xxxx

错误现象&#xff1a; 在ORACLE 10g下为表空间IGNITE_EGVSQL01增加数据文件时&#xff0c;报如下错误&#xff1a; SQL> ALTER TABLESPACE IGNITE_EGVSQL01 ADD DATAFILE /oradata/ignt/ignite_egvsql01_d02.dbf SIZE 4096M AUTOEXTEND OFF; ERROR at line 1: O…

关于Jfinal的分享代码托管GitHub

为什么80%的码农都做不了架构师&#xff1f;>>> Blog中所有的代码已经托管到github. https://github.com/b1412 此blog中关于Jfinal的代码分享不再维护。有兴趣的朋友可以关注我的github。 大家都贡献和分享一点&#xff0c;让jfinal发展的更好~ 转载于:https:…

软件发布版本的业界规则?

文章&#xff1a;8天学通MongoDB——第一天 基础入门 今天看到一篇文章说&#xff1a;业界规则&#xff0c;偶数为“稳定版”&#xff08;如&#xff1a;1.6.X&#xff0c;1.8.X&#xff09;&#xff0c;奇数为“开发版”&#xff08;如&#xff1a;1.7.X&#xff0c;1.9.X)&am…

CMake学习资料

CMake 官方 FAQ https://gitlab.kitware.com/cmake/community/wikis/FAQ CMake 官方文档 https://cmake.org/cmake/help/cmake2.4docs.html CMake 视频教程 https://www.youtube.com/watch?vCLvZTyji_Uw CMake 维基教科书 https://zh.wikibooks.org/w/index.php?titleCMake_入…

MySQL rpm包 二进制区别_Linux环境下安装mysql5.6(二进制包不是rpm格式)

一.准备:1.CentOS release 6.82.mysql-5.6.31-linux-glibc2.5-x86_64.tar.gz3.Linux下MySQL5.6与MySQL5.7安装方法略有不同二.卸载原有的mysqlfind / -name mysqlrm -rf 上边查找到的路径&#xff0c;多个路径用空格隔开三.在安装包存放目录下执行命令解压文件tar -zxvf mysql-…

【心情】 轻装前行

为自己做一份总结吧&#xff0c;从毕业到现在~ 时间过得不快不慢&#xff0c;从毕业到现在挣扎着已经2年多了&#xff0c;2年多经历的了很多事情。 毕业回国不到一个礼拜&#xff0c;就跑到大连工作&#xff0c;一个造船厂&#xff0c;公司在长兴岛开发区&#xff0c;岛上几万人…

Android 马甲包制作流程

一、马甲包的制作流程 1.配置马甲包的applicationId以及应用名称 在app的build.gradle文件中添加马甲包的配置 android {signingConfigs {config {keyAlias ****keyPassword ****storeFile file(D:/qianming/****.jks)storePassword ****}}compileSdkVersion 25buildToolsVersi…

Cmake 交叉编译

转载自 http://zhixinliu.com/2016/02/01/2016-02-01-cmake-cross-compile/ CMake交叉编译 CMake的使用&#xff0c;以及如何将一个项目移植到Android。 CMake的用法 先让我们简单学习回顾一下cmake的基本知识&#xff1a; 基本流程 以linux平台为例&#xff0c;使用 CMak…

利用System.Uri转URL为绝对地址

在使用ASPOSE.Word生成Word文档时可以通过InsertHtml(html)来将图文信息写入Word文档(图片内嵌)&#xff0c;但要求html里图片的src是绝对全路径&#xff0c;所以需要对html进行转化。 获取html可以来自数据库数据或者通过网络抓取&#xff0c;得到之后使用System.Uri来进行替换…

idea上java接口自动化_Java接口自动化之IDEA创建及运行maven项目

本文2564字阅读约需7分钟第195次推送Maven作为一个项目管理工具&#xff0c;是一组标准集合&#xff0c;一个项目的生命周期、一个依赖管理系统&#xff0c;以下主要介绍IDEA创建及运行maven项目。01创建maven项目①打开IDEA&#xff0c;顶部菜单栏依次选择File-->New-->…

.NET面向上下文、AOP架构模式(实现)

.NET面向上下文、AOP架构模式&#xff08;实现&#xff09; 1.上下文Context、面向切面编程AOP模型分析 在本人的.NET面向上下文、AOP架构模式&#xff08;概述&#xff09;一文中&#xff0c;我们大概了解了上下文如何辅助对象在运行时的管理。在很多时候我们急需在运行时能把…

英语之弱元音Schwa

IELTS Speaking - 学会英语Schwa弱元音&#xff0c;你的口语也将充满英伦味 https://baijiahao.baidu.com/s?id1596905156544848616&wfrspider&forpc http://blog.sina.com.cn/s/blog_95e5f8a601017jr4.html https://www.guokr.com/blog/440820/ 打傻方进 百家号04-05…

工厂方法模式和抽象工厂模式

工厂方法模式和抽象工厂模式工厂方法模式抽象工厂模式总结:工厂方法模式 #include <string> #include <iostream>// Abstract class Splitter { private:/* data */ public:Splitter(/* args */);virtual ~Splitter(); public:virtual void split() 0; };Splitte…

关于JQuery中的ajax请求或者post请求的回调方法中的操作执行或者变量修改没反映的问题...

前段时间做一个项目&#xff0c;而项目中所有的请求都要用jquery 中的ajax请求或者post请求&#xff0c;但是开始处理一些简单操作还好&#xff0c;但是自己写了一些验证就出现问题了&#xff0c;比如表单提交的时候&#xff0c;要验证帐号的唯一性&#xff0c;所以要在submit前…

下列关于Java多线程并发控制_下列关于Java多线程并发控制机制的叙述中,错误的是...

下列叙述成都望江楼的造景手法有()。竹文化景观应体现科学性与艺术性的和谐统一&#xff0c;关于既要满足植物的生态习性&#xff0c;又能体现美学价值。在中国传统的审美趣味、多线伦理道德上&#xff0c;竹在造园中被拟人化为( )的代表。程并错误下列不属于竹文化旅游的发展趋…