博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java反射(Reflection)获取运行时类的结构
阅读量:7065 次
发布时间:2019-06-28

本文共 5171 字,大约阅读时间需要 17 分钟。

目     录(本篇字数:1358)


· 简介

    Java Reflection,称为 Java 反射,是Java基础部分的一个比较难的点。Reflection(反射)是被视为动态语言的关键,通过反射机制,我们可以在运行时(runtime)获取类的完整结构。例如,可以获取到类的变量名、方法、构造器、内部类、接口、注解等等,并且通过反射机制可以对类内部进行操作。

    Java反射机制在实际开发中是非常常用的,强大一词完全可以用来形容它。作为Java基础内容的一部分,并且在很多开源框架(jdbc、spring、hibermate...)都使用到反射,可谓反射的重要性。

· 例子

首先,定义一个 Person 类及 Student 类,Student 继承自 Person 类,代码非常简单。如下:

package com.test;public class Person
{ public String weight; public String height; public Person() { super(); } public Person(String weight, String height) { super(); this.weight = weight; this.height = height; } public String getWeight() { return weight; } public void setWeight(String weight) { this.weight = weight; } public String getHeight() { return height; } public void setHeight(String height) { this.height = height; } @Override public String toString() { return "Person [weight=" + weight + ", height=" + height + "]"; }}
package com.test;import java.io.Serializable;public class Student extends Person
implements Serializable, Runnable { public String stuNo; private String stuName; public Student() { super(); } public Student(String stuNo, String stuName) { super(); this.stuNo = stuNo; this.stuName = stuName; } public String getStuNo() { return stuNo; } public void setStuNo(String stuNo) { this.stuNo = stuNo; } public String getStuName() { return stuName; } public void setStuName(String stuName) { this.stuName = stuName; } private int exam(String str, Integer tag) throws NoSuchMethodException { System.out.println(str); return tag; } @Override public String toString() { return "Student [stuNo=" + stuNo + ", stuName=" + stuName + "]"; } @Override public void run() { }}

有了这两个类,我们就可以开始利用反射来获取类的内部结构了。我们常规的创建对象操作:

@Test	public void test() {		Student student = new Student();		student.setStuNo("01");		student.setStuName("张三");	}
  • 反射4种方式

在开始之前,我们来学习如何利用反射的方式来获取类的结构,反射的方式有这样 4 种。

* 反射的4种获取方式,反射的源头就是获取到一个 Class 对象进行操作类的内部方法和获取类的结构。

  注意:父类中声明为 public 的变量、方法、接口等也可以被获取到。

@Test	public void test() throws Exception {		/** 第一种反射方式 */		Class clazz1 = new Student().getClass();		/** 第二种反射方式 */		Class clazz2 = Student.class;		/** 第三种反射方式 */		// 先声明 xxx 类所在包的完整名		String className = "com.test.Student";		Class clazz3 = Class.forName(className);		/** 第四种反射方式 */		Class clazz4 = this.getClass().getClassLoader().loadClass(className);	}

以下都是利用反射来获取类结构的例子。

  • 获取类中的变量,并进行赋值

@Test	public void test() throws Exception {		Class clazz = Student.class;		Student student = (Student) clazz.newInstance();		/** 声明为 public 类型的变量可以这样获取 **/		Field field1 = clazz.getField("stuNo");		field1.set(student, "01");		System.out.println(student);		/** 其他类型变量只能通过如下获取 **/		Field field2 = clazz.getDeclaredField("stuName");		field2.setAccessible(true);		field2.set(student, "张三");		System.out.println(student);	}
  • 获取变量的权限修饰符(private、protected、public)

@Test	public void test() throws Exception {		Class clazz = Student.class;		Student student = (Student) clazz.newInstance();		Field field1 = clazz.getField("stuNo");		Field field2 = clazz.getDeclaredField("stuName");			/** 获取 权限修饰符 **/		String str = Modifier.toString(field1.getModifiers());		System.out.println(str);		String str2 = Modifier.toString(field2.getModifiers());		System.out.println(str2);	}
  • 获取类中的方法,并调用该方法(需注意权限修饰符)

  • 获取类中方法的返回值

  • 获取类中方法形参列表

  • 获取类中方法异常类型

@Test	public void test() throws Exception {		Class clazz = Student.class;		Student student = (Student) clazz.newInstance();			Method method = clazz.getMethod("setStuNo", String.class);		method.invoke(student, "02");		System.out.println(student);		/** 获取方法的返回值类型 */		Class returnType = method.getReturnType();		System.out.println(returnType);		Method method2 = clazz.getDeclaredMethod("exam", String.class, Integer.class);		method2.setAccessible(true);		method2.invoke(student, "invoke exam method", 1);		/** 获取方法的形参列表 */		Class[] params = method2.getParameterTypes();		for (Class param : params) {			System.out.println(param);		}		/** 获取方法的异常类型 */		Class[] exceptions =method2.getExceptionTypes();		for(Class excp : exceptions) {			System.out.println(excp);		}	}
  • 获取类的完整包名、

  • 类中所有的构造器、

  • 类中实现的所有接口

@Test	public void test() throws Exception {		Class clazz = Student.class;		Student student = (Student) clazz.newInstance();		//获取包名		System.out.println(clazz.getPackage());		/**		 * 获取 所有构造器		 */		Constructor[] constructor = clazz.getDeclaredConstructors();		for(Constructor cons : constructor) {			System.out.println(cons);		}		/**		 * 获取 所有接口		 */		Class[] interfaces =clazz.getInterfaces();		for( Class its:interfaces) {			System.out.println(its);		}	}
  • 获取父类的结构

@Test	public void test() throws Exception {		Class clazz = Student.class;		Student student = (Student) clazz.newInstance();		//获取父类		System.out.println(clazz.getSuperclass());		//获取带泛型的父类		Type type = clazz.getGenericSuperclass();		System.out.println(type);				/**		 * 获取父类的泛型		 */		Type type2 = clazz.getGenericSuperclass();		ParameterizedType args = (ParameterizedType)type2;		Type[] types = args.getActualTypeArguments();		String t_Type = (String)types[0].getTypeName();		System.out.println(t_Type);	}

  以上的几个例子可以让我们知道反射的作用,反射能够在运行时状态下获取类的完整结构,在框架里显得尤为重要。

©原文链接:

@作者博客:

@更多博文:

转载于:https://www.cnblogs.com/xww0826/p/10359482.html

你可能感兴趣的文章
八数码问题
查看>>
关于malloc的一个未解决的疑问
查看>>
java内存管理机制
查看>>
用R分析时间序列(time series)数据
查看>>
CCF201609-1 最大波动(100分)
查看>>
Vue-devtools 安装浏览器调试
查看>>
postman环境变量的设置
查看>>
百度--买帽子
查看>>
SDWebImage的使用
查看>>
PC端和移动端测试区别
查看>>
TCP/IP中的四元组、五元组、七元组
查看>>
用代码告诉你“问世间情为何物,直教人生死相许”
查看>>
(PHP)设置修改 Apache 文件根目录 (Document Root)(转帖)
查看>>
使用sqlite保存数据返回主键
查看>>
js循环生成多个easyui datagrid数据网格时,初始化表格
查看>>
Python编程笔记(第三篇)【补充】三元运算、文件处理、检测文件编码、递归、斐波那契数列、名称空间、作用域、生成器...
查看>>
获取用户信息
查看>>
洛谷P3952 时间复杂度
查看>>
Leetcode | Parentheses 相关
查看>>
Ajax分页问题
查看>>