编程技术是改变世界的力量。
本站
当前位置:网站首页 > 后端语言 > 正文

Java 反射使用总结,看完这一篇就足够了

gowuye 2024-04-04 11:57 10 浏览 0 评论

反射机制是什么

反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

反射机制能做什么

反射机制主要提供了以下功能:

  • 在运行时判断任意一个对象所属的类;
  • 在运行时构造任意一个类的对象;
  • 在运行时判断任意一个类所具有的成员变量和方法;
  • 在运行时调用任意一个对象的方法;
  • 生成动态代理。

反射机制的相关API

定义一个接口 InterFace

package com.app;
public interface InterFace {
 void read() ;
}

定义一个 Person 类

package com.app;
public class Person implements InterFace {
 private String id ;
 private String name ;
 public String age ;
 //构造函数1
 public Person( ){
 }
 //构造函数2
 public Person( String id ){
 this.id = id ;
 }
 //构造函数3
 public Person( String id , String name ){
 this.id = id ;
 this.name = name ;
 }
 public String getId() {
 return id;
 }
 public void setId(String id) {
 this.id = id;
 }
 public String getName() {
 return name;
 }
 public void setName(String name) {
 this.name = name;
 }
 public String getAge() {
 return age;
 }
 public void setAge(String age) {
 this.age = age;
 }
 /**
 * 静态方法
 */
 public static void update(){
 }
 @Override
 public void read() {
 }
}
  • 获取类:3种方法
package com.app;
public class T1 {
 public static void main(String[] args) {
 //第一种方法:forName
 try {
 Class<?> class1 = Class.forName("com.app.Person");
 System.out.println( class1 );
 } catch (ClassNotFoundException e) {
 e.printStackTrace();
 }
 //第二张方法:class
 Class<?> class2 = Person.class; 
 //第三种方法:getClass
 Person person = new Person(); 
 Class<?> class3 = person.getClass();
 System.out.println( class2 );
 System.out.println( class3 );
 }
}

运行结果:

class com.app.Person
class com.app.Person
class com.app.Person
  • 获取所有的方法:getMethods( )
package com.app;
import java.lang.reflect.Method;
public class T1 {
 public static void main(String[] args) {
 try {
 //创建类
 Class<?> class1 = Class.forName("com.app.Person");
 //获取所有的公共的方法
 Method[] methods = class1.getMethods() ;
 for (Method method : methods) {
 System.out.println( method );
 }
 } catch (ClassNotFoundException e) {
 e.printStackTrace();
 }
 }
}

运行结果:

//自定义方法
public static void com.app.Person.update()
public java.lang.String com.app.Person.getName()
public void com.app.Person.read()
public java.lang.String com.app.Person.getId()
public void com.app.Person.setName(java.lang.String)
public void com.app.Person.setId(java.lang.String)
//父类Object类方法
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
  • 获取所有实现的接口:getInterfaces()
package com.app;
public class T1 {
 public static void main(String[] args) {
 try {
 //创建类
 Class<?> class1 = Class.forName("com.app.Person");
 //获取所有的接口
 Class<?>[] interS = class1.getInterfaces() ;
 for (Class<?> class2 : interS ) {
 System.out.println( class2 );
 }
 } catch (ClassNotFoundException e) {
 e.printStackTrace();
 }
 }
}

运行结果:

interface com.app.InterFace
  • 获取父类:getSuperclass()
package com.app;
public class T1 {
 public static void main(String[] args) {
 try {
 //创建类
 Class<?> class1 = Class.forName("com.app.Person");
 //获取父类
 Class<?> superclass = class1.getSuperclass() ;
 System.out.println( superclass );
 } catch (ClassNotFoundException e) {
 e.printStackTrace();
 }
 }
}

运行结果:

//父类是Object类
class java.lang.Object
  • 获取所有的构造函数:getConstructors()
package com.app;
import java.lang.reflect.Constructor;
public class T1 {
 public static void main(String[] args) {
 try {
 //创建类
 Class<?> class1 = Class.forName("com.app.Person");
 //获取所有的构造函数
 Constructor<?>[] constructors = class1.getConstructors() ;
 for (Constructor<?> constructor : constructors) {
 System.out.println( constructor );
 }
 } catch (ClassNotFoundException e) {
 e.printStackTrace();
 }
 }
}

运行结果:

public com.app.Person(java.lang.String,java.lang.String)
public com.app.Person(java.lang.String)
public com.app.Person()
  • 获取所有的属性:getDeclaredFields();
package com.app;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class T1 {
 public static void main(String[] args) {
 try {
 //创建类
 Class<?> class1 = Class.forName("com.app.Person");
 //取得本类的全部属性
 Field[] field = class1.getDeclaredFields();
 for (Field field2 : field) {
 System.out.println( field2 );
 }
 } catch (ClassNotFoundException e) {
 e.printStackTrace();
 }
 }
}

运行结果:

private java.lang.String com.app.Person.id
private java.lang.String com.app.Person.name

可以看出属性的修饰符是: private , 数据类型:String ,名字:id/name

  • 创建实例:newInstance()
package com.app;
public class T1 {
 public static void main(String[] args) {
 try {
 //创建类
 Class<?> class1 = Class.forName("com.app.Person");;
 //创建实例化:相当于 new 了一个对象
 Object object = class1.newInstance() ;
 //向下转型
 Person person = (Person) object ;
 } catch (ClassNotFoundException e) {
 e.printStackTrace();
 } catch (InstantiationException e) {
 e.printStackTrace();
 } catch (IllegalAccessException e) {
 e.printStackTrace();
 }
 }
}

getDeclaredFields 和 getFields 的区别

getDeclaredFields()获得某个类的所有申明的字段,即包括public、private和proteced,但是不包括父类的申明字段。getFields()获得某个类的所有的公共(public)的字段,包括父类。

小例子

package com.app;
import java.lang.reflect.Field;
public class T1 {
 public static void main(String[] args) {
 try {
 //创建类
 Class<?> class1 = Class.forName("com.app.Person");;
 //获得所有的字段属性:包括 
 Field[] declaredFields = class1.getDeclaredFields() ;
 Field[] fields = class1.getFields() ;
 for( Field field : declaredFields ){
 System.out.println( "de-- " + field );
 }
 for( Field field : fields ){
 System.out.println( "fields-- " + field );
 }
 } catch (ClassNotFoundException e) {
 e.printStackTrace();
 }
 }
}

运行结果:

de-- private java.lang.String com.app.Person.id
de-- private java.lang.String com.app.Person.name
de-- public java.lang.String com.app.Person.age
fields-- public java.lang.String com.app.Person.age

实战1:通过反射,获取对象实例,并且操作对象的方法

package com.app;
public class T1 {
 public static void main(String[] args) {
 try {
 //创建类
 Class<?> class1 = Class.forName("com.app.Person");;
 //创建实例化:相当于 new 了一个对象
 Object object = class1.newInstance() ;
 //向下转型 
 Person person = (Person) object ;
 person.setId( "100");
 person.setName( "jack") ; 
 System.out.println( "id: " + person.getId() + " name: " + person.getName() );
 } catch (ClassNotFoundException e) {
 e.printStackTrace();
 } catch (InstantiationException e) {
 e.printStackTrace();
 } catch (IllegalAccessException e) {
 e.printStackTrace();
 }
 }
}

运行结果:

id: 100 name: jack


实战2:通过反射获取对象字段属性,并且赋值

package com.app;
import java.lang.reflect.Field;
public class T1 {
 public static void main(String[] args) {
 try {
 //创建类
 Class<?> class1 = Class.forName("com.app.Person");
 //创建实例
 Object person = class1.newInstance();
 //获得id 属性
 Field idField = class1.getDeclaredField( "id" ) ;
 //给id 属性赋值
 idField.set( person , "100") ;
 //打印 person 的属性值
 System.out.println( idField.get( person ));
 } catch (InstantiationException e) {
 e.printStackTrace();
 } catch (IllegalAccessException e) {
 e.printStackTrace();
 } catch (NoSuchFieldException e) {
 e.printStackTrace();
 } catch (SecurityException e) {
 e.printStackTrace() ;
 } catch (ClassNotFoundException e) {
 e.printStackTrace();
 }
 }
}

运行结果:

java.lang.IllegalAccessException: Class com.app.T1 can not access a member of class com.app.Person with modifiers "private"
 at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
 at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(Unknown Source)
 at java.lang.reflect.AccessibleObject.checkAccess(Unknown Source)
 at java.lang.reflect.Field.set(Unknown Source)
 at com.app.T1.main(T1.java:20)

程序崩溃,原因是:id 这个属性的是 private 私有的,不能修改它的值。

改进:

添加 idField.setAccessible( true );

完整的代码为:

package com.app;
import java.lang.reflect.Field;
public class T1 {
 public static void main(String[] args) {
 try {
 //创建类
 Class<?> class1 = Class.forName("com.app.Person");
 //创建实例
 Object person = class1.newInstance();
 //获得id 属性
 Field idField = class1.getDeclaredField( "id" ) ;
 //打破封装 实际上setAccessible是启用和禁用访问安全检查的开关,并不是为true就能访问为false就不能访问 
 //由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的 
 idField.setAccessible( true );
 //给id 属性赋值
 idField.set( person , "100") ;
 //打印 person 的属性值
 System.out.println( idField.get( person ));
 } catch (InstantiationException e) {
 e.printStackTrace();
 } catch (IllegalAccessException e) {
 e.printStackTrace();
 } catch (NoSuchFieldException e) {
 e.printStackTrace();
 } catch (SecurityException e) {
 e.printStackTrace() ;
 } catch (ClassNotFoundException e) {
 e.printStackTrace();
 }
 }
}

运行结果:

100


实战3:综合训练,反射操作属性和方法

package com.app;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class T1 {
 public static void main(String[] args) {
 try {
 //创建类
 Class<?> class1 = Class.forName("com.app.Person");
 //创建实例
 Object person = class1.newInstance();
 //获得id 属性
 Field idField = class1.getDeclaredField( "id" ) ;
 //打破封装 实际上setAccessible是启用和禁用访问安全检查的开关,并不是为true就能访问为false就不能访问 
 //由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的 
 idField.setAccessible( true );
 //给id 属性赋值
 idField.set( person , "100") ;
 //获取 setName() 方法
 Method setName = class1.getDeclaredMethod( "setName", String.class ) ;
 //打破封装 
 setName.setAccessible( true );
 //调用setName 方法。
 setName.invoke( person , "jack" ) ;
 //获取name 字段
 Field nameField = class1.getDeclaredField( "name" ) ;
 //打破封装 
 nameField.setAccessible( true );
 //打印 person 的 id 属性值
 String id_ = (String) idField.get( person ) ;
 System.out.println( "id: " + id_ );
 //打印 person 的 name 属性值
 String name_ = ( String)nameField.get( person ) ;
 System.out.println( "name: " + name_ );
 //获取 getName 方法
 Method getName = class1.getDeclaredMethod( "getName" ) ;
 //打破封装 
 getName.setAccessible( true );
 //执行getName方法,并且接收返回值
 String name_2 = (String) getName.invoke( person ) ;
 System.out.println( "name2: " + name_2 );
 } catch (IllegalArgumentException e) {
 e.printStackTrace();
 } catch (InvocationTargetException e) {
 e.printStackTrace();
 } catch (NoSuchMethodException e) {
 e.printStackTrace();
 } catch (InstantiationException e) {
 e.printStackTrace();
 } catch (IllegalAccessException e) {
 e.printStackTrace();
 } catch (NoSuchFieldException e) {
 e.printStackTrace();
 } catch (SecurityException e) {
 e.printStackTrace() ;
 } catch (ClassNotFoundException e) {
 e.printStackTrace();
 }
 }
}

运行结果:

id: 100
name: jack
name2: jack

实战4:静态属性、静态方法调用

定义 Util 类

package com.app;
public class Util {
 public static String name = "json" ;
 /**
 * 没有返回值,没有参数
 */
 public static void getTips(){
 System.out.println( "执行了---------1111");
 }
 /**
 * 有返回值,没有参数
 */
 public static String getTip(){
 System.out.println( "执行了---------2222");
 return "tip2" ;
 }
 /**
 * 没有返回值,有参数
 * @param name
 */
 public static void getTip( String name ){
 System.out.println( "执行了---------3333 参数: " + name );
 }
 /**
 * 有返回值,有参数
 * @param id
 * @return
 */
 public static String getTip( int id ){
 System.out.println( "执行了---------4444 参数: " + id );
 if ( id == 0 ){
 return "tip1 444 --1 " ;
 }else{
 return "tip1 444 --2" ;
 }
 }
}

完整小例子:

package com.app;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class T1 {
 public static void main(String[] args) {
 try {
 //创建类
 Class<?> class1 = Class.forName("com.app.Util");
 //获取 nameField 属性
 Field nameField = class1.getDeclaredField( "name" ) ;
 //获取 nameField 的值
 String name_ = (String) nameField.get( nameField ) ;
 //输出值
 System.out.println( name_ );
 //没有返回值,没有参数
 Method getTipMethod1 = class1.getDeclaredMethod( "getTips" ) ; 
 getTipMethod1.invoke( null ) ;
 //有返回值,没有参数
 Method getTipMethod2 = class1.getDeclaredMethod( "getTip" ) ; 
 String result_2 = (String) getTipMethod2.invoke( null ) ;
 System.out.println( "返回值: "+ result_2 );
 //没有返回值,有参数
 Method getTipMethod3 = class1.getDeclaredMethod( "getTip" , String.class ) ; 
 String result_3 = (String) getTipMethod3.invoke( null , "第三个方法" ) ;
 System.out.println( "返回值: "+ result_3 );
 //有返回值,有参数
 Method getTipMethod4 = class1.getDeclaredMethod( "getTip" , int.class ) ; 
 String result_4 = (String) getTipMethod4.invoke( null , 1 ) ;
 System.out.println( "返回值: "+ result_4 );
 } catch (InvocationTargetException e) {
 e.printStackTrace();
 } catch (IllegalArgumentException e) {
 e.printStackTrace();
 } catch (NoSuchMethodException e) {
 e.printStackTrace();
 } catch (IllegalAccessException e) {
 e.printStackTrace();
 } catch (NoSuchFieldException e) {
 e.printStackTrace();
 } catch (SecurityException e) {
 e.printStackTrace() ;
 } catch (ClassNotFoundException e) {
 e.printStackTrace();
 }
 }
}

运行结果:

json
执行了---------1111
执行了---------2222
返回值: tip2
执行了---------3333 参数: 第三个方法
返回值: null
执行了---------4444 参数: 1
返回值: tip1 444 --2

当参数是 int 类型 和 Integer 类型,反射获取方法不一样

  • 当参数是 int 类型时
 /**
 * 没有返回值,有参数
 * @param id
 */
 public static void getTip( int id ){
 }

获取方法的时候需要用:int.class。不能使用 Integer.class. 会报错。

Method getTipMethod4 = class.getDeclaredMethod( "getTip" , int.class ) ; 
String result_4 = (String) getTipMethod4.invoke( null , 1 ) ;
System.out.println( "返回值: "+ result_4 );
  • 当参数是 Integer类型时
 /**
 * 没有返回值,有参数
 * @param id
 */
 public static void getTip( Integer id ){
 }

获取方法的时候需要用:Integer .class。不能使用 int.class. 会报错。

Method getTipMethod4 = class.getDeclaredMethod( "getTip" , Integer .class ) ; 
String result_4 = (String) getTipMethod4.invoke( null , 1 ) ;
System.out.println( "返回值: "+ result_4 );

创建对象实例

Person 类

package com.app;
public class Person{
 private String id ;
 private String name ;
 //构造函数1
 public Person( ){
 System.out.println( "构造函数 无参" );
 }
 //构造函数2
 public Person( String id ){
 this.id = id ;
 System.out.println( "构造函数 id : " + id );
 }
 //构造函数3
 public Person( String id , String name ){
 this.id = id ;
 this.name = name ;
 System.out.println( "构造函数 id : " + id + " name: " + name );
 }
 public String getId() {
 return id;
 }
 public void setId(String id) {
 this.id = id;
 }
 public String getName() {
 return name;
 }
 public void setName(String name) {
 this.name = name;
 }
}

创建实例实战

package com.app;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class T1 {
 public static void main(String[] args) {
 try {
 //创建类
 Class<?> class1 = Class.forName("com.app.Person");
 //无参构造函数
 Object object = class1.newInstance() ;
 //有参构造函数:一个参数
 Constructor<?> constructor = class1.getDeclaredConstructor( String.class ) ;
 constructor.newInstance( "1000" ) ;
 //有参构造函数:二个参数
 Constructor<?> constructor2 = class1.getDeclaredConstructor( String.class , String.class ) ;
 constructor2.newInstance( "1001" , "jack" ) ;
 } catch (InstantiationException e) {
 e.printStackTrace();
 } catch (IllegalAccessException e) {
 e.printStackTrace();
 } catch (InvocationTargetException e) {
 e.printStackTrace();
 } catch (IllegalArgumentException e) {
 e.printStackTrace();
 } catch (NoSuchMethodException e) {
 e.printStackTrace();
 } catch (SecurityException e) {
 e.printStackTrace() ;
 } catch (ClassNotFoundException e) {
 e.printStackTrace();
 }
 }
}

运行结果

构造函数 无参
构造函数 id : 1000
构造函数 id : 1001 name: jack

总结

  • Class类提供了四个public方法,用于获取某个类的构造方法。
Constructor getConstructor(Class[] params) 根据构造函数的参数,返回一个具体的具有public属性的构造函数
Constructor getConstructors() 返回所有具有public属性的构造函数数组
Constructor getDeclaredConstructor(Class[] params) 根据构造函数的参数,返回一个具体的构造函数(不分public和非public属性)
Constructor getDeclaredConstructors() 返回该类中所有的构造函数数组(不分public和非public属性)
  • 四种获取成员方法的方法
Method getMethod(String name, Class[] params) 根据方法名和参数,返回一个具体的具有public属性的方法
Method[] getMethods() 返回所有具有public属性的方法数组
Method getDeclaredMethod(String name, Class[] params) 根据方法名和参数,返回一个具体的方法(不分public和非public属性)
Method[] getDeclaredMethods() 返回该类中的所有的方法数组(不分public和非public属性)
  • 四种获取成员属性的方法
Field getField(String name) 根据变量名,返回一个具体的具有public属性的成员变量
Field[] getFields() 返回具有public属性的成员变量的数组
Field getDeclaredField(String name) 根据变量名,返回一个成员变量(不分public和非public属性)
Field[] getDelcaredField() 返回所有成员变量组成的数组(不分public和非public属性)

相关推荐

嵌入式C语言中常量的应用实例(嵌入式c语言中常量的应用实例是什么)

常量,我们都知道,就是数值保持不变的量。在C语言中,常量一旦初始化了,它的值将在整个程序运行周期内,不允许发生任何变化。常量与变量是相对的,我们实际项目中经常会用到它。定义常量的两种方式C语言中主要有...

C语言编程基础知识汇总学习,适合初学者!更新常量知识

(二)整型常量整型常量有3种形式:十进制整型常量、八进制整型常量和十六进制整型常量。(注意:c语言中没有直接表示二进制的整型常量,在c语言源程序中不会出现二进制。)书写方式如下:十进制整型常量:123...

【C语言】第二章第六节:字符串常量

第二章第六节:字符串常量。下表C语言中的常用转义字符。·字符形式功能:ASCIl码(十进制形式)。→\t水平制表(横向跳格:跳到下一个tab位置)。→\b退格8。→\r回车(不换行,光标移到本行行首)...

「GCTT 出品」Go 系列教程——5. 常量

这是我们Golang系列教程的第五篇。定义在Go语言中,术语”常量”用于表示固定的值。比如5、-89、IloveGo、67.89等等。看看下面的代码:varaint=50v...

每日C语言-常量指针、指针常量、指向常量的指针常量

一、常量指针1)什么是常量指针?通过该指针不可以修改其所指向存储单元中的值指针本身即地址可以被修改2)定义:类型说明符const*指针变量;类型说明符表示指针所指向存储单元中的值得数据类型指针...

C语言-符号常量、常变量、变量之我见

更新内容:新增音频。音频和文章一起更配oHello,大家好,又和大家见面了~~相信很多朋友们听了C语言的“符号常量”、“常变量”、“变量”后还是对这三者一脸懵逼吧。不管老师怎么歇斯底里地讲解,同学们迷...

零基础带你学习C语言:四:探索常量与变量

前言常量与变量学习;一:分析:short、float、long类型#include<stdio.h>intmain(){shortage=18;floatweight=12...

C语言中是如何定义常量的?那定义字符串呢?

常量有整型常量、浮点型常量、字符型常量及字符串常量。‘常量定义是指定义符号常量,用一个标识符来代表一个常量,通过宏定义预处理指令来实现。常量的定义:#definecount60这就定义了一个常量...

C语言符号常量的优点,会是那几点?

符号常量是一个常量,是不变量,所以,在编译的时候,就把符号常量出现的地方,替换为符号常量对应的常量。符号常量一般用户定义一个全局使用的数据,而且要改变该数据的时候,只需要改变符号常量的值,代码中引用符...

嵌入式开发- C语言数据类型-常量(c语言嵌入式是干嘛的)

基本数据类型的常量-掌握**整型常量:**常量是指在程序运行期间其数值不发生变化的数据。整型常量通常简称为整数整数可以是十进制数、八进制数、十六进制数八进制06334十六进制0xd1...

c语言解剖课:只读变量、常量、字面量傻傻分不清?

写在前面本篇主题的缘起,是因为一个计算机专业的大学生在和我讨论c语言问题时,说const常量如何如何,我说变量被const修饰了,还是变量,不是“常量”。他给了我一个截图:他说大模型都是这样回答的,变...

C/C++编程笔记:C数组、字符串常量和指针!三分钟弄懂它

想弄懂C语言中数组和指针的关系吗?这篇文章就占据你三分钟时间,看完你肯定会有收获!数组数组声明为数据类型名称[constant-size],并将一个数据类型的一个或多个实例分组到一个可寻址的位...

C语言入门到精通【第008讲】——C语言常量

C语言常量常量是固定值,在程序执行期间不会改变。这些固定的值,又叫做字面量。常量可以是任何的基本数据类型,比如整数常量、浮点常量、字符常量,或字符串字面值,也有枚举常量。常量就像是常规的变量,只不过常...

这是C语言无法修改得东西,C语言基础教程之常量解析

常量是指程序在执行期间不会改变的固定值。这些固定值也称为文字。常量可以是任何基本数据类型,如整数常量,浮点常量,字符常量或字符串文字,还有枚举常量。常量被视为常规变量,除了它们的值在定义后无法修改。整...

C语言中的单精度、双精度、常量等都有什么意思?

刚接触C语言时,对于常量,变量,浮点,单精度,双精度等问题的理解,大都很模糊不清,其实在程序运行过程中,其值不能改变的量称为常量。如12、0、-3为整型常量,4.6、-1.23为实型常量,'a'、'...

取消回复欢迎 发表评论: