21、java中的反射机制

先推荐安装一个 eclipse 的反编译插件  Enhanced Class Decompiler

是什么?

       在说反射之前先说一下编译时类型和运行时类型,大家都知道List是一个接口,它是不可以被实例化的,但是可以通过多态实现:List list = new ArrayList(); 对于变量list来说编译时期他被声明为List类型,但是真正使用的确实ArrayList中的成员(在堆中创建的是ArrayList的对象),所以list的运行时类型是ArrayList,它的运行时类就是ArrayList被编译之后加载到内存的字节码类文件。

       再说反射,反射是java中一种可以在执行期间获取类内部信息的技术,说白一点就是根据加载的类字节码文件去获取类本身的一种技术,之前介绍了类加载,加载过程中会创建一个Class类的对象来表示这个类,每一个Class类的对象都是一个运行时类,所以反射就是根据运行时类获取其本类信息并使用这个类的一种技术,反射号称是java实现动态编程的关键。为什么说反射是实现动态编程的关键呢?我自己的理解是这样的:假设我写了一个方法用于处理很多类,这个时候呢,我不可能为每一个类都写一个方法,可是呢,我知道每一个运行时类都是Class的对象,并且我可以根据class对象获取其本类的对象,所以这个时候,我接受的参数就可以是一个Class类型的参数,这样就使得代码可以高度复用了,这就是反射的魅力。通过使用反射,可以使得代码高度复用,大大的降低代码的耦合性。

有什么用?

       具体说一下反射的能力:使用反射可以在运行时判断任意一个对象所属的类、构造一个类的对象、判断一个类具有的成员变量和方法、用一个对象的成员变量和方法等等。通过使用反射可以通过运行时类去操作类本身的所有属性。

怎么用?

      想要使用反射,就要获取运行时类,那么运行时类如何获取和表示呢?在java中每一个运行时类都是java.lang.Class的对象,所以可以使用Class来声明运行时类,而获取运行时类的方式有四种,代码如下:

public static void main(String[] args) {//1、通过类的.class属性Class<User> c1 = User.class;//2、通过类对象的.getClass方法User user = new User();Class c2 = user.getClass();//3、通过Class类的forName方法,一般用这个try {Class c3 = Class.forName("com.czp.reflection.User");} catch (ClassNotFoundException e) {e.printStackTrace();}//4、通过类的加载器获取(这种一般用的不多)try {Class<?> c4 = ClassLoader.getSystemClassLoader().loadClass("com.czp.reflection.User");} catch (ClassNotFoundException e) {e.printStackTrace();}
}

      这里需要说明的一点是,在一个进程中,一个类的字节码文件添加到内存中后就是一个运行时类,每个运行时类只会加载一次。

      获取了运行时类也就是Class的对象之后可以做些什么呢?如何利用反射?下边具体说一下

获取类的构造方法、创建类的对象:

public class ReflectionTest {public static void main(String[] args) {ReflectionTest test = new ReflectionTest();test.getClassConstructors();}//获取User的运行时类
@SuppressWarnings("unchecked")
public Class<User> getUser()
{String name = "com.czp.reflection.User";Class<User> user= null;try {user = (Class<User>) Class.forName(name);} catch (ClassNotFoundException e) {e.printStackTrace();}return user;
} 
//测试获取类中的构造方法,创建类的实例
public void getClassConstructors() 
{try{Class<User> userClass = getUser();//1、直接调用Class中方法创建类的对象,这种方法的前提是类中必须要有一个公共的无参构造方法User user = userClass.newInstance();//2、通过类中对应的构造方法创建对象// 首先就需要先获取这个类中的构造方法//Declared 有声明之意,可理解为只要是声明的构造方法都可以获取到,获取所有构造方法(不管权限如何)Constructor<?>[] declaredConstructors = userClass.getDeclaredConstructors();//只能获取所有公共的构造方法Constructor<?>[] constructors = userClass.getConstructors();//获取指定参数的构造方法(所有的)Constructor<User> declaredConstructor = userClass.getDeclaredConstructor(String.class);//如果构造方法是私有的,通过setAccessible(true)设置可以使用私有构造方法进行创建对象declaredConstructor.setAccessible(true);User privateUser = declaredConstructor.newInstance("zhangsan");//User [name=zhangsan, age=null]System.out.println(privateUser);//获取指定参数的构造方法(共有的)Constructor<User> constructor = userClass.getConstructor(Integer.class);//再根据构造方法创建类的对象User user2 = constructor.newInstance(5);//User [name=null, age=5]}catch (Exception e) {e.printStackTrace();}
}
}

获取运行时类的成员:

//测试获取类中的成员信息
public void getClassMethods() {try{Class<User> userClass = getUser();User user = userClass.newInstance();//---------------------------处理方法----------------------////1、获取所有的方法Method[] declaredMethods = userClass.getDeclaredMethods();//2、根据方法的名称参数获取方法Method declaredMethod = userClass.getDeclaredMethod("show");//使用方法,如果是私有方法则先强制设置以下declaredMethod.setAccessible(true);declaredMethod.invoke(user, null);//3、获取所有公共的方法(包括父类的)Method[] methods = userClass.getMethods();//4、获取方法,不写了,就是根据名字获取,和上边一样//---------------------------处理变量----------------------////1、获取所有变量Field[] declaredFields = userClass.getDeclaredFields();//2、获取指定变量Field declaredField = userClass.getDeclaredField("name");declaredField.setAccessible(true);declaredField.set(user, "zhangsan");System.out.println(declaredField.get(user));//zhangsan//3、还有两个获取所有共有的变量}catch (Exception e) {e.printStackTrace();}
}

获取运行时类的其他:

public void getClassOther(){try{Class<User> userClass = getUser();User user = userClass.newInstance();//1、可以获取注解Annotation[] declaredAnnotations = userClass.getDeclaredAnnotations();//2、所在包名Package p = userClass.getPackage();//3、获取父类Class<? super User> superclass = userClass.getSuperclass();//4、获取实现的接口Class<?>[] interfaces = userClass.getInterfaces();//还有其他,查看API}catch (Exception e) {e.printStackTrace();}
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/321716.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【北京】BXUG第12期活动基于 .NET Core构建微服务和Xamarin

分享主题&#xff1a;基于 .NET Core构建微服务实战分享分享者&#xff1a;薛锋 北京切尔思科技架构师 兼任东北大学信息安全工程师和技术主播&#xff0c;行业内专注于研究 .NET Core和Web应用&#xff0c;具有比较扎实的技术基础和数年的从业经历。在GitHub上主持数个开…

2017西安交大ACM小学期数据结构 [树状数组,极大值]

Problem D 发布时间: 2017年6月28日 10:51 最后更新: 2017年6月28日 16:38 时间限制: 1000ms 内存限制: 32M 描述 给定一个长度为n的序列a1, a2, ..., an当k满足2≤k≤n−1, ak>ak−1且ak>ak1时, 将元素k称为极大值点, 给出q个操作, 操作分为两种 对于形如1xy的操作…

nssl1448-小智过马路【模拟】

正题 题目大意 nnn个横向道&#xff0c;若干辆车&#xff0c;每辆车速度恒定&#xff0c;给出方向位置长度。 过马路的速度&#xff0c;最早开始时间&#xff0c;最晚开始时间。求最长的可以通过马路的时间段。 解题思路 计算出每辆车限制的时间区间&#xff0c;然后排序找到…

22、java中的注解

注解是什么&#xff1f; 注解可以理解成注释、标记、标签的意思&#xff0c;用来标记类、方法等。就相当于现实生活中的一些事物&#xff0c;上边贴一个标签或者写一些注释性文字来描述它可以用来做什么、怎么用、何时用等信息。Java中的注解也是一样的&#xff0c;用来表示被标…

谈谈ASP.NET Core中的ResponseCaching

前言前面的博客谈的大多数都是针对数据的缓存&#xff0c;今天我们来换换口味。来谈谈在ASP.NET Core中的ResponseCaching&#xff0c;与ResponseCaching关联密切的也就是常说的HTTP缓存。在阅读本文内容之前&#xff0c;默认各位有HTTP缓存相关的基础&#xff0c;主要是Cache-…

2017西安交大ACM小学期数据结构 [树状数组 离散化]

Problem E 发布时间: 2017年6月28日 12:53 最后更新: 2017年6月29日 21:35 时间限制: 1000ms 内存限制: 64M 描述 给定一个长度为n的序列a1, a2, ..., an给定两个整数L, R输出有多少个二元组(x,y),x≤y, 满足L≤∑yixai≤R9104≤n≤105, −109≤ai≤109, −109≤L≤R≤10…

使用 dynamic 类型让 ASP.NET Core 实现 HATEOAS 结构的 RESTful API

上一篇写的是使用静态基类方法的实现步骤: 使用dynamic (ExpandoObject)的好处就是可以动态组建返回类型, 之前使用的是ViewModel, 如果想返回结果的话, 肯定需要把ViewModel所有的属性都返回, 如果属性比较多, 就有可能造成性能和灵活性等问题. 而使用ExpandoObject(dynamic)就…

23、java中的网编基础

什么是网络编程&#xff1f; 在说网络编程之前要先知道什么是网络&#xff0c;网络是一种实现资源共享和数据传输的系统。而网络编程就是使用代码编写程序来进行网络之间数据的传输。使用java进行网络之间数据的传输是比较简单的&#xff0c;java中提供了一些现成的类供我们使…

2017西安交大ACM小学期数据结构 [又是树状数组、异或]

Problem F 发布时间: 2017年6月28日 10:31 最后更新: 2017年6月29日 21:35 时间限制: 2000ms 内存限制: 64M 描述 给定一个nm的矩形, 初始时所有元素都为0给出q个操作, 操作有三种 对于形如1x的操作, 将第x行的所有元素异或1对于形如2y的操作, 将第y列的所有元素异或1对于…

P2717-寒假作业【逆序对,树状数组】

正题 题目链接:https://www.luogu.com.cn/problem/P2717 题目大意 nnn个数&#xff0c;求有多少个连续子序列的平均值大于等于kkk。 解题思路 因为长度会十分干扰&#xff0c;所以我们将所有数减去kkk。问题就变为了求有多少连续子序列的和非负。用前缀和逆序对求就好了。 co…

使用 BenchmarkDotnet 测试代码性能

先来点题外话&#xff0c;清明节前把工作辞了&#xff08;去 tm 的垃圾团队&#xff0c;各种拉帮结派、勾心斗角&#xff09;。这次找工作就得慢慢找了&#xff0c;不能急了&#xff0c;希望能找到个好团队&#xff0c;好岗位吧。顺便这段时间也算是比较闲&#xff0c;也能学习…

24、jdbc操作数据库(1)

什么是jdbc&#xff1f; 看一下官方怎么说&#xff0c;JDBC 英文名Java DataBase Connectivity&#xff0c;使用java连接数据库的工具&#xff0c;就是一组使用java代码来执行SQL语句的API。 Jdbc有什么用&#xff1f; 数据库有多种&#xff0c;并且不同数据库操作时的方式和…

jzoj3918-蛋糕【二分】

正题 题目链接:https://jzoj.net/senior/#contest/show/2953/0 题目大意 n∗mn*mn∗m的矩阵&#xff0c;有数字&#xff0c;横着三刀竖着三刀分成16份使得最小那份最大。 解题思路 暴力枚举竖着的三刀&#xff0c;然后二分答案判定即可。 codecodecode #include<cstdio&g…

2017西安交大ACM小学期数论 [阅兵式]

阅兵式 发布时间: 2017年6月25日 12:53 最后更新: 2017年7月3日 09:27 时间限制: 1000ms 内存限制: 128M 描述 阅兵式上&#xff0c;将士们排成一个整齐的方阵&#xff0c;每个将士面朝前方。问正中心的将士能向前看到几个将士&#xff1f;注意&#xff0c;一条直线上的将…

25、jdbc操作数据库(2)

说一下使用jdbc时涉及到的一些基本的接口和类 java.sql.Driver 是数据库驱动接口&#xff0c;com.mysql.jdbc.Driver是mysql对应的驱动&#xff0c;由数据库供应商实现&#xff0c;用于提供驱动&#xff0c;实现了java.sql.Driver接口。 java.sql.DriverManager 管理驱动的…

jzoj3919-志愿者【换根法,线段树,树形dp】

正题 题目链接:https://jzoj.net/senior/#main/show/3919 题目大意 nnn个点kkk个需要到达的点&#xff0c;然后求每个点出发经过这些点的最短路径。 解题思路 因为不用回去&#xff0c;答案就是以这点为根链接所有点的树减去离这个点最远点的距离。 我们用线段树维护最远点距…

2017西安交大ACM小学期数论 [水题]

水题 发布时间: 2017年6月25日 14:06 最后更新: 2017年7月3日 09:27 时间限制: 1000ms 内存限制: 128M 描述 平均因数个数的统计对于估算数论题目复杂度具有非常重要的意义。小A同学听了今天的课后&#xff0c;于是想要自己写一个程序&#xff0c;求出1到n的平均因数个数…

26、jdbc操作数据库(3)

1、结果集的元数据操作 ResultSetMetaData 是描述ResultSet的元数据对象&#xff0c;可以通过元数据对象获取结果集的列信息&#xff0c;使用方式如下&#xff1a; public void query() {Connection connection DBUtil.getConnection();String sql "SELECT ID,UNAME u,…

jzoj3920-噪音【贪心,dp】

正题 题目链接:https://jzoj.net/senior/#main/show/3920 题目链接 nnn头牛&#xff0c;mmm个牛棚&#xff0c;可以清空kkk次。 每头牛会指定进入一个牛棚&#xff0c;进入后产生牛棚中牛数量的噪音值&#xff0c;然后清空可以清空一个牛棚的牛&#xff0c;求最少噪音值。 解…

2017西安交大ACM小学期数论 [完全平方数]

完全平方数 发布时间: 2017年6月24日 17:01 最后更新: 2017年7月3日 09:27 时间限制: 1000ms 内存限制: 128M 描述 给定正整数b&#xff0c;求最大的整数a&#xff0c;使a(ab)是完全平方数。 输入 多组测试数据&#xff08;不超过10000组&#xff09;。 每组数据一个正整…