java的反射(reflection)机制_腹部反射区图解

java的反射(reflection)机制_腹部反射区图解1.什么是java反射java的反射机制是指在运行状态中,      对于任意一个类,都能知道这个类的所有属性和方法;      对于任意一个对象,都能够调用它的任意一个属性和方法;      这种动态获取的类的信息,和动态调用对象的方法的功能就是反射机制。2.反射的作用     在运行时,构造任意一个类的对象      在运行时,判断任意一个类的完整结构,比如属性,方法,内…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

1.什么是java反射

java的反射机制是指在运行状态中,

        对于任意一个类,都能知道这个类的所有属性和方法;

        对于任意一个对象,都能够调用它的任意一个属性和方法;

        这种动态获取的类的信息,和动态调用对象的方法的功能就是反射机制。

2.反射的作用

        在运行时,构造任意一个类的对象

        在运行时,判断任意一个类的完整结构,比如属性,方法,内部类,实现接口等

        在运行时,判断任意一个对象所属的类

        在运行时,调用任意一个对象的属性和方法

        在运行时,生成动态代理

3.关键类

java的反射(reflection)机制_腹部反射区图解

Class类是反射类的基础,在java.lang包下,有四种方式可以获取Class类对象

Field,Method,Constructor 都在java.lang.reflect包下

Field是获取Class对象中的属性

Method是获取Class对象中的方法(不包含构造方法)

Construct是获取Class对象中的构造函数

4.测试代码

四种获取Class类的方法:

		Person p = new Person();
		// 方法一 : 调用运行时类的.class属性
		Class c1 = Person.class;
		System.out.println("方法一 : 调用运行时类的.class属性: "+c1.toString());
		
		// 方法二 : 通过运行时类的对象,调用getClass()方法
		Class c2 = p.getClass();
		System.out.println("方法二 : 通过运行时类的对象,调用getClass()方法: "+c2.toString());
		
		// 方法三 : 调用Class的静态方法forName
		Class c3 = Class.forName("reflect.Person");
		System.out.println("方法三 : 调用Class的静态方法forName: "+c3.toString());
		
		// 方法四 :通过类的加载器
		ClassLoader classLoader = Person.class.getClassLoader();
		Class c4 = classLoader.loadClass("reflect.Person");
		System.out.println("方法四 :通过类的加载器: "+c4.toString());

Jetbrains全家桶1年46,售后保障稳定

运行结果是:

方法一 : 调用运行时类的.class属性: class reflect.Person
方法二 : 通过运行时类的对象,调用getClass()方法: class reflect.Person
方法三 : 调用Class的静态方法forName: class reflect.Person
方法四 :通过类的加载器: class reflect.Person

获取Class中的构造函数:

	    System.out.println("getConstructors为获取类的public的构造方法 ");
	    Constructor[] constructors1 = c1.getConstructors();
	    for(int i=0;i<constructors1.length;i++){
	        System.out.println("constructors ["+i+"] :"+constructors1[i]);
	    }
		Class<? extends Object> c1 = Person.class;
		
		//调用指定的构造器创建运行时类的对象
	    //我们指定public类型的构造方法Person(String name)来创建对象
	    Constructor<?> constructor = c1.getDeclaredConstructor(String.class);
	    Person person = (Person) constructor.newInstance("xl");
	    System.out.println("调用指定的构造器(public)创建运行时类的对象 --person: "+person);	    
	    
	    //我们指定private类型的构造方法Person(String name)来创建对象
	    constructor = c1.getDeclaredConstructor(String.class,String.class);
	    constructor.setAccessible(true);
	    person = (Person) constructor.newInstance("xl2","15");
	    System.out.println("调用指定的构造器(private)创建运行时类的对象 --person: "+person);

运行结果是:

getConstructors为获取类的public的构造方法 
constructors [0] :public reflect.Person(java.lang.String)
constructors [1] :public reflect.Person()
调用指定的构造器(public)创建运行时类的对象 --person: [name : xl ][age : null]
调用指定的构造器(private)创建运行时类的对象 --person: [name : xl2 ][age : 15]

获取Class中全部Method:

		Person person = new Person();
		Class<? extends Object> c1 = person.getClass();
		
		//getMethods此方法为获取类的public方法,包括父类的public方法
	    System.out.println("getMethods此方法为获取类的public方法,包括父类的public方法 ");
	    Method[] method1 = c1.getMethods();      
	    for(int i=0;i<method1.length;i++){
	        System.out.println("method1 ["+i+"] :"+method1[i]);
	    }

	    //getDeclaredMethods此方法为获取类本身声明的所有方法,包括private
	    System.out.println("getDeclaredMethods此方法为获取类本身声明的所有方法,包括private ");
	    Method[] method2 = c1.getDeclaredMethods();      
	    for(int i=0;i<method2.length;i++){
	        System.out.println("method2 ["+i+"] :"+method2[i]);
	    }
	    
	    //1.对private类型的方法进行操作
	    System.out.println("getDeclaredMethod 方法获取类本身声明的方法,包括private类型的方法,以setName(私有)方法为例:");
	    Method m1 = c1.getDeclaredMethod("setName", String.class);
	    m1.setAccessible(true);
	    System.out.println("修改前的person:"+person);
	    m1.invoke(person, "xl");
	    System.out.println("修改后的person:"+person);

运行结果是:

getMethods此方法为获取类的public方法,包括父类的public方法 
method1 [0] :public java.lang.String reflect.Person.toString()
method1 [1] :public java.lang.String reflect.Person.getName()
method1 [2] :public void reflect.Person.setName(java.lang.String)
method1 [3] :public void reflect.Person.setAge(java.lang.String)
method1 [4] :public java.lang.String reflect.Person.getAge()
method1 [5] :public final void java.lang.Object.wait() throws java.lang.InterruptedException
method1 [6] :public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
method1 [7] :public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
method1 [8] :public boolean java.lang.Object.equals(java.lang.Object)
method1 [9] :public native int java.lang.Object.hashCode()
method1 [10] :public final native java.lang.Class java.lang.Object.getClass()
method1 [11] :public final native void java.lang.Object.notify()
method1 [12] :public final native void java.lang.Object.notifyAll()
getDeclaredMethods此方法为获取类本身声明的所有方法,包括private 
method2 [0] :public java.lang.String reflect.Person.toString()
method2 [1] :public java.lang.String reflect.Person.getName()
method2 [2] :public void reflect.Person.setName(java.lang.String)
method2 [3] :void reflect.Person.getSex()
method2 [4] :public void reflect.Person.setAge(java.lang.String)
method2 [5] :public java.lang.String reflect.Person.getAge()
getDeclaredMethod 方法获取类本身声明的方法,包括private类型的方法,以setName(私有)方法为例:
修改前的person:[name : null ][age : null]
修改后的person:[name : xl ][age : null]

获取Class类中Field

		Class<? extends Object> c1 = Person.class;

	    System.out.println("getFields此方法为获取类的public属性,包括父类的public属性 ");
	    Field[] field1 = c1.getFields();     
	    for(int i=0;i<field1.length;i++){
	        System.out.println("field1 ["+i+"] :"+field1[i]);
	    }
	    
	    System.out.println("getDeclaredFields此方法为获取类的本身声明的所有属性,包括private ");
	    Field[] field2 = c1.getDeclaredFields();     
	    for(int i=0;i<field2.length;i++){
	        System.out.println("field2 ["+i+"] :"+field2[i]);
	    }

运行结果是:

getFields此方法为获取类的public属性,包括父类的public属性 
field1 [0] :public java.lang.String reflect.Person.age
getDeclaredFields此方法为获取类的本身声明的所有属性,包括private 
field2 [0] :private java.lang.String reflect.Person.name
field2 [1] :public java.lang.String reflect.Person.age

对Field进行处理:

	    Person person = new Person("zj");
	    Class<? extends Object> c1 = person.getClass();
	    
	    System.out.println("对public类型的属性进行操作,以类本身的private属性name为例");
	    Field f1 = c1.getDeclaredField("name");
	    f1.setAccessible(true);
	    String name = (String)f1.get(person);
	    System.out.println("修改前person对象name:"+name);
	    
	    f1.set(person, "xl");
	    name = (String)f1.get(person);
	    System.out.println("修改后person对象的name:"+name);

运行结果是:

对public类型的属性进行操作,以类本身的private属性name为例
修改前person对象name:zj
修改后person对象的name:xl

还有一些对内部类、接口进行的一些操作,这里就不一一列举了。

5.用例:重写Object的toString方法

public class Person {
	
	private String name;
	
	private String age;

	public Person(String name, String age) {
		this.name = name;
		this.age = age;
	}

	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;
	}

	@Override
	public String toString() {
		StringBuffer result = new StringBuffer();
		try {
			// 1.获取Class类
			Class<? extends Object> clazz = this.getClass();
			// 2.获取全部属性
			Field [] fields = clazz.getDeclaredFields();
			for (Field field : fields) {
				String fieldName = field.getName();
				// 3.除去序列化属性
				if ("serialVersionUID".equals(fieldName)) {
					continue;
				}
				// 4.拼接方法名
				String methodName = "get" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1, fieldName.length());
				Method method;
				Object resultObj;
				// 5.通过方法名获取方法
				method = clazz.getMethod(methodName);
				// 6.get方法没有参数,直接属性对应的值
				resultObj = method.invoke(this);
				if (resultObj != null && !"".equals(resultObj)) {
					result.append("[").append(fieldName).append("]").append(resultObj).append(" ");
				}
			}
		} catch (SecurityException | NoSuchMethodException | IllegalAccessException | IllegalArgumentException
				| InvocationTargetException e) {
			e.printStackTrace();
		}
		return result.toString();
	}
}
public class ReflectTest {
	
	public static void main(String[] args){
	    Person person = new Person("xl","28");
	    System.out.println(person.toString());

	}
}

运行结果是:

[name]xl [age]28 

参考:

java核心技术之reflect(一):一个系统学习reflect的Demo(精)

JAVA深入研究——Method的Invoke方法

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/210131.html原文链接:https://javaforall.net

(0)
上一篇 2025年7月27日 下午12:22
下一篇 2025年7月27日 下午1:01


相关推荐

  • Mac里配置maven环境变量

    Mac里配置maven环境变量从windows转IOS还是有点难度的,就如环境变量来说吧,整整配置了一天啊。说实话网上教程很多,也写的很全,但不是每个人遇到的情况都一样,所以就有我这样的情况出现了,按照网上的教程配了好久,一直不好使。现在我就记录下来,避免以后忘记了。。。先说明下我的问题,我是在fishshell下编辑的profile文件,就是编辑完保存后就会一直报错,不是文件里面“=”不支持,就是git命令不好…

    2022年6月18日
    43
  • 超百个免费api接口,分享给你「建议收藏」

    超百个免费api接口,分享给你「建议收藏」API(应用程序编程接口)API(ApplicationProgrammingInterface,应用程序接口)是一些预先定义的函数,或指软件系统不…

    2022年5月10日
    45
  • opc服务器不显示目录,opc客户端搜不到opc服务器

    opc服务器不显示目录,opc客户端搜不到opc服务器opc客户端搜不到opc服务器内容精选换一换ELB可以针对客户访问的业务为访问者提供个性化的管理策略,制定策略之前需要获取来访者的真实IP。TOA内核模块主要用来获取ELB转化过的访问者真实IP地址(仅支持IPv4),该插件安装在ELB后端服务器。本文档仅适用于四层(TCP协议)服务,当客户需要在操作系统中编译TOA内核模块时,可参考本文档进行配置。Linux内核版本为2.6.32块存储调优主要…

    2022年6月20日
    36
  • 页面跳转javascript操作referer

    页面跳转javascript操作refererReferrer 的重要性 HTTP 请求中有一个 referer 的报文头 用来指明当前流量的来源参考页 例如在 www sina com cn sports 上点击一个链接到达 cctv com 首页 那么就 referrer 就是 www sina com cn sports 了 在 Javascript 中 我们可以通过 document referrer 来获取同样的信息 通过这个信息 我们就可以知道访客是从什么

    2026年3月16日
    2
  • 备份数据库表结构_sql备份表和恢复表

    备份数据库表结构_sql备份表和恢复表##================================================================##需求场景:由于MySQL没有类似于SQLSERVER那样的系统表来存放备份记录,且大规模的MySQL服务器需要集中管理和查看。服务器出现性能问题或复制延迟时,需要先判断是否由数据备份引起。##===========================…

    2025年11月14日
    3
  • Python学习笔记(15)-Python代码转换为exe可执行程序详解

    Python学习笔记(15)-Python代码转换为exe可执行程序详解一,简介Python写完程序,要靠命令执行那么行,太低调了,还不华丽了。再说别人的电脑,都没有Python库,怎么执行,还能不能愉快的一起玩耍了。所以哪怕只会写一个HelloWorld,也要弄成exe程序,方便伟大的代码传播事业。其实很简单,有一个现成的pyInstaller工具,直接用就是了。二,pyInstaller安装配置1,打开网址:pyInstalller下载网址如图:因为我的Pyth

    2022年6月1日
    51

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号