如何使用 Java 反射?反射的用法及案例

4 篇文章 2 订阅

博主声明:

转载请在开头附加本文链接及作者信息,并标记为转载。本文由博主 威威喵 原创,请多支持与指教。

本文首发于此   博主威威喵  |  博客主页https://blog.csdn.net/smile_running

· 简介

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

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

· 例子

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

package com.test;

public class Person<T> {

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

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

  • 8
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 20
    评论
Java反射可以让我们在运行时获取和操作类的信息,包括类的属性、方法、构造函数等。下面是一个使用Java反射的简单案例: 假设我们有一个类Person: ```java public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public void sayHello() { System.out.println("Hello, my name is " + name + ", I am " + age + " years old."); } } ``` 现在,我们可以使用反射来获取和调用Person类的构造函数和方法: ```java import java.lang.reflect.Constructor; import java.lang.reflect.Method; public class ReflectionExample { public static void main(String[] args) throws Exception { // 获取Person类的Class对象 Class<Person> personClass = Person.class; // 获取Person类的构造函数 Constructor<Person> constructor = personClass.getConstructor(String.class, int.class); // 使用构造函数创建Person对象 Person person = constructor.newInstance("Tom", 20); // 获取Person类的sayHello方法 Method sayHelloMethod = personClass.getMethod("sayHello"); // 调用sayHello方法 sayHelloMethod.invoke(person); } } ``` 以上代码中,我们首先通过`Person.class`获取了Person类的Class对象,然后使用`getConstructor`方法获取了Person类的构造函数,并使用构造函数创建了一个Person对象。接着,我们使用`getMethod`方法获取了Person类的`sayHello`方法,并使用`invoke`方法调用了该方法。最终,我们输出了`Hello, my name is Tom, I am 20 years old.`。 这只是一个简单的反射案例,实际上Java反射还可以做很多其他的事情,比如动态代理、注解处理等等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值