Java反射学习记录

Java反射

好久没写博客了,好久没初尝了,哈哈哈…
最近在学习mybatis,虽然学习的进度还不够深入,但是也有一些小小的思考,在mybatis中,有一个名为动态代理的概念,当时自学的时候听得云里雾里,搞不懂为什么就能够通过相同的方法名就直接定位到对应的操作数据库的方法去,在通过学习了Java的反射机制之后,才有一些理解。

什么是反射:

Java反射机制指的是在Java程序运行状态中,对于任何一个类,都可以获得这个类的所有属性和方法;对于给定的一个对象,都能够调用它的任意一个属性和方法。这种动态获取类的内容以及动态调用对象的方法称为反射机制。
Java的反射机制允许编程人员在对类未知的情况下,获取类相关信息的方式变得更加多样灵活,调用类中相应方法,是Java增加其灵活性与动态性的一种机制。

mybatis中的动态代理就应该是基于反射机制所实现的。
废话不多说,直接上代码:

1.获取反射入口:
首先一个Person类和一个接口:
接口:
package ReflectT;

public interface MyInterface {
	void InterfaceMethod();
}
-------------------------------------------
Person类:
package ReflectT;

public class Person implements MyInterface{
	private String name;
	private int age;
	
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	public Person() {
	}
	
	public Person(String name) {
		this.name = name;
	}
	
	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;
	}
	
	private void Method()
	{
		System.out.println("private Method..");
	}
	
	@Override
	public void InterfaceMethod() {
		// TODO Auto-generated method stub
		System.out.println("Interface Method..");
	}
	
}
-------------------------------------------------------------------
测试:
package ReflectT;

import java.lang.reflect.Method;

public class TestDemo {
	
	//获取反射入口的方法:1.Class.forName();2.类名.class();3.对象.getclass();
	
	public static void Demo01()//通过反射获取类
	{
		try {
			Class<?> person=Class.forName("ReflectT.Person");//使用Class.forname
			Class<?> Person=Person.class;//使用类名.class
			Class<?> per=new Person().getClass();//通过对象.getClass();
			System.out.println(person);
			System.out.println(Person);
			System.out.println(per);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public static void main(String[] args)
	{
		Demo01();
	}
}

结果:


可以看出三种方法均能实现;

2.通过反射获取到类的信息:
在TestDemo中:
public static void Demo02()//通过反射获取类的方法
	{
		Class<?> person=null;
		try {
			person=Class.forName("ReflectT.Person");//使用Class.forname
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		Method[] Methods=person.getMethods();//获取到所有公共方法(包括本类,接口以及父类中的公有方法)
		for(Method method:Methods)
		{
			System.out.println(method);
		}
	}
	public static void main(String[] args)
	{
//		Demo01();
		Demo02();
	}
}

结果:
在这里插入图片描述
我们可以看到我们不仅拿到了Person类中的公有方法,还拿到了接口中的方法以及Object(父类)中的一些公有方法,但是,没有拿到Person类中的私有方法。
那如果我们想拿到私有方法、类的属性、接口等其他内容呢?

获取所有接口:person.getInterfaces();
获取所有父类:person.getSuperclass();
获取所有构造方法:person.getConstructors();
获取所有公共属性:person.getFields();
获取当前类的所有方法(只能是当前类,如Person。但父类和接口都拿不到,且不受修饰符约束,等于拿到所有方法):person.getDeclaredMethods();
获取当前类的所有属性(同上):person.getDeclaredFields();
------------------------------------------------------
获取反射所代表的类的对象:
public static void Demo03() throws InstantiationException, IllegalAccessException//获取反射所代表的类的对象
	{
		Class<?> person=null;
		try {
			person=Class.forName("ReflectT.Person");//使用Class.forname
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		Object instance=person.newInstance();
		Person per=(Person)instance;
		per.InterfaceMethod();
	}
结果:
控制台显示:Interface Method..
3.通过反射操作类的属性:
public static void Demo04() throws InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException
	{
		Class<?> person=null;
		try {
			person=Class.forName("ReflectT.Person");//使用Class.forname
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		Person per=(Person)person.newInstance();
		Field field=person.getDeclaredField("age");
		//由于属性是private,即要进行访问的时候需要修改访问权限;
		field.setAccessible(true);//临时打开权限,默认为false;
		field.set(per,25);
		System.out.println(per.getAge());
	}

结果:
在这里插入图片描述
需要注意的是,在通过反射对类的属性进行修改的时候,如果修改的属性为private,那么就要使用setAccessible进行临时更改权限。 同样的,如果要进行对类的方法调用,使用getDeclaredMethod(“方法名”,“方法参数(如果没有参数,写null)”),后方法设置的时候使用invoke(“对象名”,“参数”)。

4.模拟动态代理:

在Demo项目中新建一个.txt文件:

classname=ReflectT.Person
methodname=InterfaceMethod

接着在TestDemo中进行使用:

public static void Demo05() throws FileNotFoundException, IOException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException
	{
		//将class.txt中的内容导入到反射中去,类似mybatis中的Reader
		Properties pro=new Properties();
		pro.load(new FileReader("class.txt"));
		
		String classnames=pro.getProperty("classname");
		String methodname=pro.getProperty("methodname");
		Class<?> tmp=null;
		try {
			tmp=Class.forName(classnames);//使用Class.forname
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		Method method=tmp.getMethod(methodname);//不知道方法的参数类型,那就不写
		method.invoke(tmp.newInstance());
		
	}

结果:
在这里插入图片描述
如果在class.txt中修改为其他类:

classname=ReflectT.Student
methodname=Say
package ReflectT;

public class Student {
	public void Say()
	{
		System.out.println("here is a student!");
	}
}

结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值