Java学习记录之反射

反射的概念

        反射(Reflection),允许程序获取任何类的内部信息,并且能够直接操作任意对象的内部属性及方法。反射机制是动态语言的关键

反射的功能

  • 判断任意对象所属的类
  • 构造任意类的对象
  • 判断任意一个类具有的成员变量和方法
  • 调用任意一个对象的成员变量和方法
  • 生成动态代理

反射的基础——“Class”类

import person.Person;

/*
 * 《java.lang.Class》
 * 反射机制的源头。
 * 当创建一个类的时候,通过编译(javac.exe),生成对应的.class文件。
 * 之后使用java.exe加载(JVM的类加载器进行加载)此.class文件,加载到
 * 内存之后,就是一个“运行时类”,存在缓存区。
 * 1.每一个运行时类只加载一次!
 * 2.有了Class的实例之后,可以进行如下操作:
 * ->创建对应的运行时类的对象
 * ->获取运行时类的完整结构
 *  (属性、方法、构造器、父类、所在包、异常)
 * ->调用运行时类的指定结构(属性、方法、构造器)
 * ->反射的应用:动态代理
 */

public class TestClass {
	public TestClass() {
	}
	public static void main(String[] args) throws Exception {
		//1.调用运行时类本身的.class属性
		Class<?> cls1 = Person.class;
		System.out.println(cls1.getName());
		
		Class<?> cls2 = String.class;
		System.out.println(cls2.getName());
		
		//2.通过运行时类的对象获取
		Person p = new Person();
		Class<?> cls3 = p.getClass();
		System.out.println(cls3.getName());
		
		//3.通过Class的静态方法获取
		String className = "person.Person";
		Class<?> cls4 = Class.forName(className);
		System.out.println(cls4.getName());
	}
}

反射相关的API

  • java.lang.Class
    代表一个类
  • java.lang.reflect.Method
    代表类的方法
  • java.lang.reflect.Field
    代表类的成员变量
  • java.lang.reflect.Constructor
    代表类的构造方法

反射机制运用举例

自定义的person.Person类,包含属性及其get、set方法,还有一个空的构造器。

public class Person {
	
	public String name;
	private int age;
	
	public Person() {	
	}

	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;
	}
	
	//更改了toString方法即改变了print呈现。
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
	public void show() {
		System.out.println("show方法:"+this);
	}
}

运用反射机制创建一个类,并调用其类内部方法

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.junit.Test;
import person.Person;

/*
 * 《反射机制》
 * 	  动态语言的关键,允许程序获得任何类的内部信息,并且能够直接操作
 * 任意对象的内部属性及方法。
 */


public class TestReflection {

	public TestReflection() {
	}
	
	//以之前实例化对象的方式创建类
	@Test
	public void test1(){
		Person p = new Person();
		p.setAge(10);
		p.setName("kola");
		//因为是重写了toString方法,所以调用print是重写了的
		System.out.println(p);
		p.show();
	}
	
	//使用反射的方式创建一个对象,并调用其中的属性与方法
	@Test
	public void test2() throws InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
		//创建一个person类的对象,可以使用<>修饰符限定;
		Class<Person> cls1 = Person.class;
		System.out.println(cls1);
		//1.创建cls1对应的<>内的类对象
		Person p1 = cls1.newInstance();
		System.out.println(p1);
		
		//创建一个不用修饰符修饰的Class类
		Class cls2 = Person.class; 
		System.out.println(cls2);
		//1.如果在创建Class时没有限定类,那么就要用强制转换符转换。
		Person p2 = (Person)cls2.newInstance();
		System.out.println(p2);
		
		//2.通过反射调用类的指定属性
		//这里只能用可访问的属性
		Field f1 = cls1.getField("name");
		//改成大写
		f1.set(p1, "KOLA");
		System.out.println(p1);
		
		//若要访问被保护或私有的属性,使用.getDeclaredField
		//并且设置.setAccessible(true)。
		Field f2 = cls1.getDeclaredField("age");
		f2.setAccessible(true);
		f2.set(p1, 20);  
		System.out.println(p1);
		
		//3.通过反射调运类的指定方法
		//调用无输入的方法
		Method m1 = cls1.getMethod("show");
		m1.invoke(p1);
		//调用有输入的方法
		Method m2 = cls1.getMethod("setName", String.class);
		m2.invoke(p1, "Kola");
		m1.invoke(p1);
	}
}

总结

        在我看来反射机制是Java提供给程序员一种极度抽象地调用各种类及类属性和方法的机制,让程序员可以以一种统一的编写方式调用各种不同的类。这种方式十分切合动态代理的思想,这也就让动态代理成为了反射的一个重要应用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值