当前位置:首页 > Java技术 > Java 反射 (Class、ClassLoader、Constructor、Method、Field)

Java 反射 (Class、ClassLoader、Constructor、Method、Field)

2022年08月06日 11:46:14Java技术4

 反射是Java中一个非常重要、非常强大的机制。曾看到一句话“反射是框架的灵魂”,初学时不懂,等到学完框架之后才慢慢理解其意。

什么是反射?我们先通过几个类和示例来初步体会一下反射。 

一、ClassLoader类

什么是类加载器? 

ClassLoader是一个抽象类,它的实例是类加载器。磁盘上存在的xxx.class文件需要被加载进JVM才能执行。类加载器则是负责加载.class文件的对象,然后在JVM中生成该类的Class对象。每一个Class对象都关联着定义它的那个类加载器。数组的类加载器与其元素的加载器是同一个,如果元素类型是基本类型,则数组没有类加载器。

类加载器工作原理

类加载器都有一个与之关联的父加载器,当加载器需要加载一个文件时,它首先将该任务”委派”给父加载器,如果父加载器无法加载该文件,再自己进行加载。JVM的引导加载器(bootstrap class loader)没有父加载器,但可作为父加载器。关于类加载器更详细的分析 点击这里

二、Class类

什么是Class<T>类?

Class不是我们平常声明类时所用的关键字class,它是一个类,它的对象用来描述一个运行状态的类或接口。一个xxx.java文件编译后生成一个xxx.class文件,一个xxx.class文件被JVM加载后生成该类对应的Class对象,该对象包含了该类的所有信息,比如,类中有字段、构造器、方法等信息。一个类有一个对应的Class对象,元素类型相同且长度相同的数组共享一个Class对象,java基本类型包括void也都有各自的Class对象。Class是一个泛型类,如果不加泛型,需要强转。

如何获取一个类的Class对象?

Class没有public构造器,当类被加载时,JVM会通过调用ClassLoader的defineClass方法来自动创建该类的Class对象。

获取一个类的Class对象有三种方式:

1)类名.class

2)  该类的对象.getClass()

3)  Class.forName(String 类名) (包名加类名)  

Class对象有何作用?

下面列出几个Class类的方法:

1)   获取类加载器:

 getClassLoader()

2)  获取Constructor构造器对象:

 getConstructor(Class... parameterType)                               获取具有指定参数的公共构造器对象

 getConstructors()                                                                   获取所有公共构造器对象

 getDeclaredConstructor(Class... parameterType)         获取具有指定参数的构造器对象

 getDdclaredConstructors()                                                     获取所有构造器对象

3)  获取Method对象:

  getMethod(String name,Class...parameterType)        获取具有指定名称和参数的公共方法对象

  getMethods()                                                                               获取所有公共方法对象

  getDeclaredMethod(String name,Class...parameterType)          获取具有指定名称和参数的方法对象

  getDeclaredMethods()                  获取所有的方法对象

4)获取Field字段对象:

  getField(String name)                      获取具有指定名称的公共字段对象

  getFields()                        获取具有所有公共字段对象

  getDeclaredField(String name)               获取具有指定名称的字段对象

  getDeclaredFields()                      获取所有字段对象

 5)获取Class对象所代表的类的一个对象(非常重要的一个方法)

  Object  newInstance()                                                                  用默认的无参数构造器创建一个对象

(带Declared的get方法可以获取任意访问权限的成员,不带Declared的只能获取public成员)

测试Class,更多的测试在其他类的测试中体现。

package cn.edu;

public class User {

	private String username;
	
	private int age;
	
	public User() {
		
	}
	
	public User(String username , int age) {
		this.username = username;
		this.age = age;
	}
	private User(String username) {
		this.username = username;
	}
     public void say(String str) {
        System.out.println(str);
     }

@Override public String toString() { return "User [username=" + username + ", age=" + age + "]"; } }

  

@Test
	public void fun2() throws Exception {
		Class userClass = User.class;
		
		System.out.println(userClass.getName());                   //获取该class对象的类的类名
		
		
		System.out.println(userClass.getClassLoader().toString()); //获取类加载器
		
		User user = (User)userClass.newInstance();                 //调用默认的无参数构造器创建对象
		System.out.println(user.toString());
	}

  运行结果:

Java 反射 (Class、ClassLoader、Constructor、Method、Field) _ JavaClub全栈架构师技术笔记

 

三、Constructor类

构造器类,封装构造器的有关信息。

主要方法 Object newInstance(Object...arg)                                  用指定参数创建对象

测试Constructor

@Test
	public void fun2() throws Exception {
		Class userClass = User.class;

		Constructor userConstructor1 = userClass.getConstructor(String.class , int.class); //有参构造器
		User user1 = (User)userConstructor1.newInstance("小红",18);
		System.out.println(user1.toString());
		
		Constructor userConstructor2 = userClass.getConstructor();                          //无参构造器
		User user2 = (User)userConstructor2.newInstance();
		System.out.println(user2);
		
		Constructor userConstructor3 = userClass.getDeclaredConstructor(String.class);      //私有构造器
		userConstructor3.setAccessible(true);                                               //开启访问权限
		User user3 = (User)userConstructor3.newInstance("小明");
		System.out.println(user3);
	}

  运行结果:

Java 反射 (Class、ClassLoader、Constructor、Method、Field) _ JavaClub全栈架构师技术笔记

默认是不可以访问private成员的,userConstructor3.setAccessible(true)是用于开启访问权限的,这样就可以访问了,感觉是开挂一样!

 

四、Method类 

方法类,封装方法的有关信息

主要方法

Object invoke(Object obj , Object... args)                                     调用obj对象的Method对象代表的方法,args为参数

测试Method:

 

@Test
	public void fun2() throws Exception {
		Class userClass = User.class;                                 
		User user = (User)userClass.newInstance();                           //用默认无参数构造方法创建对象
		
		Method method = userClass.getMethod("say",String.class);             //获取名为"say",参数为string的method对象
		method.invoke(user,"hello");                                         //调用user的say方法
	}

  运行结果:

Java 反射 (Class、ClassLoader、Constructor、Method、Field) _ JavaClub全栈架构师技术笔记

 

五、Field类

字段类,封装字段的有关信息

主要方法

Object get(Object obj)                                                                   获取obj对象的此Field对象代表的字段的值

void set(Object obj , Object value)              设置obj对象的此Field对象代表的字段的值

 测试Fidle

@Test
	public void fun2() throws Exception {
		Class userClass = User.class;
		Constructor userConstructor = userClass.getConstructor(String.class,int.class);
		User user = (User)userConstructor.newInstance("小明",18);                                  
		
		System.out.println(user.toString());
		
		Field userField = userClass.getDeclaredField("username");  //获取username字段
		userField.setAccessible(true);                             //开启访问权限
		userField.set(user, "小红");                                //给user对象的该字段设置值
		
		System.out.println(user.toString());
	}

   运行结果:

Java 反射 (Class、ClassLoader、Constructor、Method、Field) _ JavaClub全栈架构师技术笔记

 

 

  到此关于反射的几个类就简单的认识了一下,我们可以不用new关键字来创建对象,调用对象的方法也与传统的调用方式有很大区别,我们甚至可以操作private成员(虽然这样做破坏了封装性),相对于传统的操作方式,反射更像是一种逆向思维,以前操作成员,主体在于对象,而反射的主体在于Class和成员本身。到此我们对反射有了初步的认识。接下在叙述一个重要的概念,有助于我们更好的理解反射。

六、动态加载与静态加载

注意此处所说的加载是针对编译的,将xxx.java转化成xxx.class,而不是运行的加载字节码。Java创建对象的常用方式是使用new 关键字,如 User user  = new User(); 这种是静态加载,即在编译期就已经获取User类的有关信息,如果User类不存在或有错误,编译会报错。动态加载就是用上面的Class.forName("包名.User");来加载User类,如果User类不存在或是有错误,在编译时是不会报错的,因为根本没去加载User类。只有当程序运行到该处,JVM才会去加载User,而动态加载则是依赖反射实现的。

 

好了,可以给出最终概念了,通过上面的重重示例与解析,应该不难理解反射了。

七、反射  

  Java反射机制是指java程序在运行过程中,可以获取任意一个类的相关信息,并且能够调用其方法和属性,这种动态获取信息和动态调用方法的功能叫做Java的反射机制。

      上面写了这么多,总结起来也就这一句话。

 

 本文个人编写,水平有限,如有错误,恳请指出,欢迎讨论分享。

 

作者:随性如风
来源链接:https://www.cnblogs.com/wanghang-learning/p/9142750.html

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。


本文链接:https://www.javaclub.cn/java/18153.html

分享给朋友:

“Java 反射 (Class、ClassLoader、Constructor、Method、Field)” 的相关文章

java反射的应用(Hibernate)

java反射的应用(Hibernate)          Hibernate是一个屏蔽了JDBC,实现了ORM的java框架,利用该框架我们可...

java反射详解之反射作用

java反射详解之反射作用

本文转载两篇文章,前一部分很好的解释了Java 反射在开发中的作用机制,后一部分详细给出了反射的运用案例。 第一部分: 反射作用 Java的反射机制是Java特性之一,反射机制是构建框架技术的基础所在。灵活掌握Java反射机制,对大家以后学习框架技术有很大的帮助。...

Java反射笔记

Java反射笔记

Java反射笔记 1:Class类 同Object,String等类一样,Class也是一个类 构造函数只可由JVM调用,不可由开发者调用。 任何一个类均是Class类的实例对象。 任何继承Object的对象均有 g...

Java异常处理之InvocationTargetException(反射异常)

 Java异常处理之InvocationTargetException(反射异常)   InvocationTargetException异常由Method.invoke(obj, args...)方法抛出。当被调用的方法的内部抛出了异常而没有被捕获时,...

浅谈Java反射的实现原理

从一段示例代码开始 Class clz = Class.forName("ClassA"); Object instance = clz.newInstance(); Method method =...

JAVA中的反射机制以及在Spring中的应用

文章目录 一 反射机制 二 反射机制的使用-Class类 三 为什么要使用反射 3.1 静态编译 3.2 动态编译 3.3 反射的好处...

利用JAVA反射,读取数据库表名,自动生成对应实体类

本代码是利用java反射,读取数据库表自动根据表名生成实体类,数据库采用老牌SQLSERVER 2000,驱动为JTDS,其他数据库可根据情况自定修改。 代码中包含了大部分数据库类型与JAVA类型的转换,少数未包含进去的会在生成代码时打印出来,方面后期查找修改。 本文...

JAVA利用反射映射JSON对象为JavaBean

关于将JSONObject转换为JavaBean,其实在JSONObject中有对于的toBean()方法来处理,还可以根据给定的JsonConfig来处理一些相应的要求,比如过滤指定的属性 [java] vi...

Java反射机制及用途

Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法; 对于任意一个对象,都能够调用它的任意一个方法和属性; class.forName(类名)//获得类      这种动态获取的信息以及...

【译】1. Java反射——引言

【译】1. Java反射——引言

原文地址:http://tutorials.jenkov.com/java-reflection/index.html *By Jakob Jenkov   Java的反射机制使得它可以在运行时检查类、接口、字段、方法,而在编译时并不不知道它们的名称。也可以通过反射...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。