Java反射实践

本文深入探讨Java反射机制的使用方法,包括Class、Field、Method及数组的反射操作。通过实例展示了如何利用反射打破访问限制、获取类信息及操作对象属性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章通过三部分描述反射的用法,class,field和method,array。具体学习可以查看reflect包下的代码:


理论方面的学习,请看这里

先看下面简单的例子,对反射有些映像。

class:

import java.lang.reflect.Constructor;
 
/**
 * 这个例子中,无参构造函数是私有的,但反射可以调用,说明了反射打破了类的访问性。
 * 另一方面,newInstance方法反射依赖无参构造函数,如果沒有无参构造函数,就不能使用这个方法。
 * 但仍然可以获取所有构造函数后调用,不过奇怪的是,这种方法调用构造函数必须是可见的,即private在其他类是不能访问的。
 */
public class Person {
	private String name;
	private int age;
 
	@SuppressWarnings("unused")
	private Person() {
	}
 
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
 
	public String getName() {
		return name;
	}
 
	public void setName(String name) {
		this.name = name;
	}
 
	public int getAge() {
		return age;
	}
 
	public void setAge(int age) {
		this.age = age;
	}
 
	@Override
	public String toString() {
		return "[" + this.name + "  " + this.age + "]";
	}
 
	public static void main(String[] args) {
		Class<?> clazz = null;
		try {
			// 获取类实例
			clazz = Class.forName("advanced.reflections.domian.Person");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		try {
			// 调用构造函数
			Person p = (Person) clazz.newInstance();//
			p.setAge(100);
			p.setName("Nature");
			System.out.println(p);
		} catch (InstantiationException | IllegalAccessException e) {
			e.printStackTrace();
		}
		try {
			// 這種方法構造對象需要構造器是可訪問的。即使在自己的類中定義的main中,如果構造器是私有的,仍然無法訪問。
//			Constructor<?> construct = clazz.getConstructor(new Class[] { String.class, int.class });
			Constructor<?> construct = clazz.getConstructor(String.class, int.class );
			Person p = (Person) construct.newInstance("MyName", 20);
			System.out.println(p);
		} catch (NoSuchMethodException | SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

反射提供了很多get方法,用于获取类的详细的信息,如下:

gets.png
可以获得类的名字,包名,加载器,构造器,域,方法,修饰信息,嵌套类,泛型,父类等类的信息。其中,declared表示这个类中申明的,父类继承的不算。
举例,借用了上面的类:
import java.lang.reflect.Field;
 
/**
 * Declared的用处。
 */
public class Strdent extends Person {
 
	int number;
 
	public String myWord;
 
	public Strdent(String name, int age, int number, String myWord) {
		super(name, age);
		this.number = number;
		this.myWord = myWord;
	}
 
	public static void main(String[] args) {
		Class<?> clazz = Strdent.class;
		{
			System.out.println("declared");
			Field[] fields = clazz.getDeclaredFields();
			for (Field f : fields) {
				System.out.println(f.getName());
			}
		}
		System.out.println("--------------");
 
		{
			System.out.println("public");
			// getFields 返回的是public的
			Field[] fields = clazz.getFields();
			for (Field f : fields) {
				System.out.println(f.getName());
			}
		}
	}
 
}
同时,Class也提供了大量的判断方法,如下图:

iss.png
这样可以判断是够匿名,是否是数组,是够是父类isAssignableFrom,是够是实例,接口等。
举例:
    
System . out . println ( Collection . class . isAssignableFrom ( ArrayList . class ));//返回true

Field 和 Method:

Field:

f.png
Method:

m.png
举例:
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
 
/**
 * Declared的用处。 Field and Method stuff. field. 这里主要关注点就是方法和域的访问和修改。
 * getInt():field是int,且obj中含有这个域。 method.invoke
 */
public class Student extends Person {
 
	private int number;
 
	int id = 12526845;
 
	public String myWord;
 
	public Student() {
	}
 
	public Student(String name, int age, int number, String myWord) {
		super(name, age);
		this.number = number;
		this.myWord = myWord;
	}
 
	public String toString() {
		return "[" + super.getName() + ":" + number + ":" + id + ":" + super.getAge() + "]";
	}
 
	public static boolean isMale(Student std) {
		return (std.id & 1) == 1;
	}
 
	public static void main(String[] args) {
		Class<?> clazz = Student.class;
		Student std = null;
		try {
			std = (Student) clazz.newInstance();
			std.setName("JAKKKK");
			std.setAge(15);
		} catch (InstantiationException | IllegalAccessException e1) {
			e1.printStackTrace();
		}
		System.out.println("==========================\nField");
		{
			{
				System.out.println("declared");
				Field[] fields = clazz.getDeclaredFields();
				for (Field f : fields) {
					System.out.println(f.getName());
					System.out.println(f.getModifiers());
					System.out.println(f.getType());
					try {
						if (f.getName().equals("number")) {
							// 外部无法访问到这个方法,因为是private
							System.out.println("f.getInt()" + f.getInt(new Student()));
							// 要检查f是否可以访问,true表示不检查访问性
							f.setAccessible(false);
							f.set(std, 21321299);
						}
						if (f.getName().equals("id")) {
							System.out.println("f.getInt()" + f.getInt(new Student()));
							f.set(std, 110119120);
						}
					} catch (IllegalArgumentException | IllegalAccessException e) {
						e.printStackTrace();
					}
				}
				System.out.println(std);
			}
			System.out.println("--------------");
 
			{
				System.out.println("public");
				// getFields 返回的是public的
				Field[] fields = clazz.getFields();
				for (Field f : fields) {
					System.out.println(f.getName());
				}
			}
		}
		System.out.println("==========================\nMethod");
		{
			{
				System.out.println("Declared Methods");
				Method[] ms = clazz.getDeclaredMethods();
				for (Method m : ms) {
					System.out.println(m.getName());
				}
			}
			{
				System.out.println("Methods");
				// 所有的公开方法
				Method[] ms = clazz.getMethods();
				for (Method m : ms) {
					System.out.println(m.getName());
					System.out.println(m.getDefaultValue());
					System.out.println(m.getModifiers());
					System.out.println(m.getDeclaringClass());
					System.out.println(m.getParameterTypes());
					System.out.println(m.getReturnType());
					System.out.println(m.isBridge());
					System.out.println(m.isAccessible());
 
				}
			}
		}
		System.out.println("==========================\nMethod.Invoke");
		{
			try {
				Method m1 = clazz.getMethod("toString");
				System.out.println(m1.getName());
				System.out.println(m1.invoke(std));
				Method m2 = clazz.getMethod("getName");
				System.out.println(m2.getName());
				System.out.println(m2.invoke(std));
				System.out.println(clazz.getMethod("isMale", Student.class).invoke(null, std));
			} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			} catch (SecurityException e) {
				e.printStackTrace();
			}
		}
	}
}


Array:


例子:
package advanced.reflections.arrays;
 
import java.lang.reflect.Array;
 
/**
 * 主要探究反射在数组中的应用。关于数组,很多方法并不在class中,而是在Array中。 当然,主要也是get和set方法,但Array都是静态的方法。
 */
public class ArrayStuff {
	public static void main(String[] args) {
		int[] array = { 1, 2, 3, 4, 5 };
		// 返回数组元素的类型
		Class<?> componentType = array.getClass().getComponentType();
		System.out.println("数组类型: " + componentType.getName());
		System.out.println("数组长度  " + Array.getLength(array));
		System.out.println("数组的第一个元素: " + Array.get(array, 0));
		Array.set(array, 0, 100);
		System.out.println("修改之后数组第一个元素为: " + Array.get(array, 0));
		int[] newArr = (int[]) Array.newInstance(componentType, 10);
 
		System.arraycopy(array, 0, newArr, 0, 5);
		print(newArr);
		System.out.println(Array.getInt(array, 3));
		// 这句报错:argument type mismatch 因为int->char不能自动转化
		System.out.println(Array.getChar(array, 3));
	}
 
	private static void print(int[] arr) {
		for (Object o : arr) {
			System.out.print(o + " ");
		}
		System.out.println();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值