Java 反射的基础知识(笔记),用于框架

本文深入讲解Java反射机制,包括如何加载类、获取类的各种组成部分,以及通过实例演示反射构造函数、反射方法和反射字段的具体应用。

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

反射:一个类有多个部分组成,如:成员变量,方法,构造方法等。

反射就是加载类,并解刨出类的各个组成部分

加载类:forName方法用于加载某个类的字节码到内存中,并使用class对象进行封装(常用)

另外两中得到class对象的方式:   类名.class      ;       对象.getClass

解刨类:Class对象提供了如下常用方法:

用于public访问权限

Public Constructor getConstructor(Class<?>..parameterTypes)

Public Method getMethod(String name,Class<?>...parameterTypes)

Public Field getField(String name)


用于private私有访问权限

Public ConstructorgetDeclaredConstructor(Class<?>..parameterTypes)

Public Method getDeclaredMethod(String name,Class<?>...parameterTypes)

Public Field getDeclaredField(String name)


下面用一些例子来具体的理解一下:反射构造函数、反射方法、反射字段。

例子看着比较多,但都比较简单,大同小异,只是有点细节需要注意!

用 JUnit Test 测试运行

 

Person.java

import java.io.InputStream;
import java.util.List;

public class Person {
	//反射类字段(平常说的属性)
	public String name="JAVA";
	private int password=123456;
	private static int age=18;
	
	//反射类的构造函数
	
	public  Person()
	{
		System.out.println("无参数");
	}
	
	public Person(String name)
	{
		System.out.println("String name");
	}
	
	public Person(String name,int age)
	{
		System.out.println(name+"..."+age);
	}
	
	private Person(List list)
	{
		System.out.println("list");
	}
	
	
	//反射类的方法
	public void meth()
	{
		System.out.println("无参方法");
	}
	
	public void meth(String name,int age)
	{
		System.out.println(name+"..."+age);
	}
	
	private void meth(InputStream in)
	{
		System.out.println(in);
	}
	
	public static void meth(int num)
	{
		System.out.println(num);
	}
	
	public Class[] meth(String name,int[] age)
	{
		return new Class[]{String.class};
	}
	
	public static void main(String args[])
	{
		System.out.println("main函数");
	}
}

loadClassTest.java(反射构造函数)

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;  //和Person中导入的包要一致

import org.junit.Test;

//反射类的构造函数,创建类对象
public class loadClassTest {
	//反射构造函数:public Person()
	@Test
	public void test1() throws Exception
	{
		Class clazz=Class.forName("com.yong.reflect.Person");//获得路径,加载类到内存中
		Constructor c=clazz.getConstructor(null); //解析无参的构造函数,并得到对象,括号内为可变参数
		Person p=(Person) c.newInstance(null);//调用构造函数创建Person对象
		
		System.out.println(p.name);	//打印结果:  无参数     JAVA
	}
	
	//反射构造函数:public Person(String name)
	@Test
	public void test2() throws Exception
	{
		Class clazz=Class.forName("com.yong.reflect.Person");
		Constructor c=clazz.getConstructor(String.class);
		Person p=(Person) c.newInstance("创建Person(String name)对象");
		
		System.out.println(p.name); //打印结果:String name	JAVA
	}
	
	//反射构造函数:public Person(String name,int age)
	@Test
	public void test3() throws Exception
	{
		Class clazz=Class.forName("com.yong.reflect.Person");
		Constructor c=clazz.getConstructor(String.class,int.class);
		Person p=(Person) c.newInstance("XXXXX",11);
		
		System.out.println(p.name);   //打印结果: XXXXX...11   JAVA
	}
	
	//反射构造函数:private Person(List list)
	@Test
	public void test4() throws Exception
	{
		Class clazz=Class.forName("com.yong.reflect.Person");
		
		//因为该构造方法私有,因此需要用getDeclaredConstructor方法
		  Constructor c=clazz.getDeclaredConstructor(List.class);
		  
		//暴力反射:无论你是什么权限,都给你打开,让外界访问
		//私有方法外界不能访问,但反射可以!
		c.setAccessible(true);
		
		Person p=(Person) c.newInstance(new ArrayList());
		System.out.println(p.name);  //打印结果:  list  JAVA
	}
	//创建对象的另一种途径
	//test5的代码等效于test1
	@Test
	public void test5() throws Exception
	{
		Class clazz=Class.forName("com.yong.reflect.Person");
		Person p=(Person) clazz.newInstance();
		System.out.println(p.name);  //打印结果:  无参数     JAVA
	}
}

reflectMethod.java(反射方法)

import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;

import org.junit.Test;

//反射类的方法
public class reflectMethod {
	@Test
	//反射类的方法public void meth()
	public void method1() throws Exception
	{
		Person p=new Person();
		Class clazz=Class.forName("com.yong.reflect.Person");
		Method method=clazz.getMethod("meth", null);
		
		method.invoke(p, null);//用invoke让方法跑起来,前面的参数为调用的对象,后面的参数为对象的参数
							   //打印结果:无参数      无参方法      在创建p对象的时候打印无参数
							   //上一句,调用的meth方法,打印的 无参方法
		
	}
	
	@Test
	//反射类的方法public void meth(String name,int age)
	public void method2() throws Exception
	{
		Person p=new Person();
		Class clazz=Class.forName("com.yong.reflect.Person");
		Method method=clazz.getMethod("meth", String.class,int.class);
		method.invoke(p, "流年",90);  //打印结果:无参数     	流年...90
	}
	
	@Test
	//反射类的方法private void meth(InputStream in)
	public void method3() throws Exception
	{
		Person p=new Person();
		Class clazz=Class.forName("com.yong.reflect.Person");
		Method method=clazz.getDeclaredMethod("meth", InputStream.class);//private权限,需要暴力打开
		method.setAccessible(true);
		method.invoke(p, new FileInputStream("c:\\temp.txt")); //c盘目录下要有此文件 
									//打印结果:无参数     	java.io.FileInputStream@1e59128
	}
	@Test
	//反射类的方法public static void meth(int num)
	public void method4() throws Exception
	{
		//注意:静态方法在调用时不需要对象!!!!!!
		//因此不需要创建对象,下面invoke的第一个参数也不需要传入参数!!!!
		Class clazz=Class.forName("com.yong.reflect.Person");
		Method method=clazz.getMethod("meth",int.class);
		
		method.invoke(null,10086);  //打印结果:10086
	}
	
	@Test
	//反射类的方法public Class[] meth(String name,int[] age)
	public void method5() throws Exception
	{
		Person p=new Person();
		Class clazz=Class.forName("com.yong.reflect.Person");
		Method method=clazz.getMethod("meth",String.class,int.class);
		method.invoke(p, "Class数组",89);   //打印结果:无参数     Class数组...89
	}
	
	
	
	@Test
	//反射类方法:public static void main(String args[])
	public void method6() throws Exception
	{
		Class clazz=Class.forName("com.yong.reflect.Person");
		Method method=clazz.getMethod("main",String[].class);
		
		//method.invoke(null,new String[]{"bb","aa"});		报错!!!
		
		/* JDK1.5升级后为了兼容JDK1.4所带来的问题:
		 *JDK1.4: invoke会从数组中取出多个值,将一个个的值取出后(将数组拆成一个个的值),
		 *在赋予到数组的参数上面去,因为传递的数组中是两个值,所以main方法应该是
		 * main(String a1,String a2),但main函数中main(String args[])是一个数组,
		 * 所以需要将整个数组看做一个整个的参数(下面那种写法)
		 */
		method.invoke(null,new Object[]{new String[]{"bb","aa"}}); 		//	打印结果:main函数*/
	}
}

reflectionField.java(反射字段)

import java.lang.reflect.Field;

import org.junit.Test;

//反射字段
public class reflectionField {
	
	@Test
	//反射字段 public String name="JAVA";
	public void test1() throws Exception
	{
		Person p=new Person();
		Class clazz=Class.forName("com.yong.reflect.Person");
		Field f=clazz.getField("name");
		String name=(String) f.get(p);//获得对象中的字段
		System.out.println(name); //打印结果:无参数  JAVA
		
		Class type=f.getType();
		System.out.println(type);  //打印出name的类型:class java.lang.String
		
		//重新设置字段的值
		f.set(p, "XXXXXXXXX");
		System.out.println(p.name);  //打印结果:XXXXXXXXX
	}
	
	@Test
	//反射字段 private int password=123456;
	public void test2() throws Exception
	{
		Person p=new Person();
		Class clazz=Class.forName("com.yong.reflect.Person");
		Field f=clazz.getDeclaredField("password");
		f.setAccessible(true);
		System.out.println(f.get(p)); //打印结果:无参数  123456
	}
	
	@Test
	//反射字段 private static int age=18;
	public void test3() throws Exception
	{
		Person p=new Person();
		Class clazz=Class.forName("com.yong.reflect.Person");
		Field f=clazz.getDeclaredField("age");
		f.setAccessible(true);
		System.out.println(f.get(p)); //打印结果:无参数  18
	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值