JAVA反射

前沿:Java反射在框架中有用到,比如Spring的IOC,根本技术就是反射。

一、JAVA反射是什么

1.Java反射是把类中的成员映射成相对应的Java中的类型。反射用到一个类叫Class,它表示Java的字节码文件,它的对象表示某一个字节码文件。

二、学习JAVA反射

1.获取Class类

有三种方式获取Class类

  1. 对象.getClass();
  2. Class.forName()里面的参数是类的全路径:包名+类名
  3. 类名.class

2.Class类中有哪些Java类型

Class类中有4种java类型

  • Package
  • Constructor
  • Field
  • Method

3.Package

首先建立一个Persion类,后面的内容都会使用Persion类。

public class Persion {
	String name = "张三";
	public float height = 186.5F;
	protected int age = 18;
	private char sex = '男';

	public Persion() {

	}

	public Persion(String name, float height, int age, char sex) {
		this.name = name;
		this.height = height;
		this.age = age;
		this.sex = sex;
	}

	public void work(double money) {
		System.out.println("工作得到了" + money + "元");
	}

	@Override
	public String toString() {
		return "Persion [name=" + name + ", height=" + height + ", age=" + age + ", sex=" + sex + "]";
	}

}

获取Persion字节码文件

		Class c = Persion.class;

得到它的Package

		Package p = c.getPackage();

你可以打印p,会得到它的包名,Package的用处不是很大。

4.Constructor

获取Persion字节码文件

		Class c = Persion.class;

得到所有构造器

	@Test
	public void test() {
		Class c = Persion.class;
		Constructor[] ct = c.getConstructors();
		for (Constructor constructor : ct) {
			System.out.println(constructor);
		}
	}

结果为:
public testList.Persion()
public testList.Persion(java.lang.String,float,int,char)
获取其中一个构造器并且new出对象,这里用无参构造器

	@Test
	public void test() throws Exception {
		Class c = Persion.class;
		Constructor ct = c.getConstructor();
		Persion p = (Persion) ct.newInstance();
		System.out.println(p);
	}

通过反射得到对象比直接new要慢得到,所以用Spring框架比直接用Servlet要慢,虽然方便得多。注意:代码里虽然没有new关键字来得到对象,但是底层还是用了new关键字。

5.Field

获取Persion字节码文件

		Class c = Persion.class;

获取所有字段

	@Test
	public void test() throws Exception {
		Class c = Persion.class;
		Field[] f = c.getDeclaredFields();
		for (Field field : f) {
			System.out.println(field);
		}
	}

结果为
java.lang.String testList.Persion.name
public float testList.Persion.height
protected int testList.Persion.age
private char testList.Persion.sex
可以看到并没有得出字段的值,因为Class的对象表示某一个类的字节码文件,而字段的值是属于对象的。
下面获取一个字段,并且改变它的值。

	@Test
	public void test() throws Exception {
		Class c = Persion.class;
		Persion p = (Persion) c.getConstructor().newInstance();
		Field f = c.getDeclaredField("name");
		System.out.println(f.get(p));
		f.set(p, "李四");
		System.out.println(f.get(p));
	}

结果为
张三
李四

5.1暴力反射

前面可以访问一个字段并且修改它的值,那么private修饰的字段怎么访问?就要用到暴力反射。以sex字段为例子。

	@Test
	public void test() throws Exception {
		Class c = Persion.class;
		Persion p = (Persion) c.getConstructor().newInstance();
		Field f = c.getDeclaredField("sex");
		f.setAccessible(true);
		System.out.println(f.get(p));
		f.set(p, '女');
		System.out.println(f.get(p));
	}

结果为


暴力反射就是用setAccessible()这个方法,里面参数填true,那么就能访问被pricate修饰的字段,如果里面参数填false或者不用这个方法,那么就访问不到。

5.2访问控制修饰符小知识

Java里的访问控制修饰符含有一个底层的知识。getModifiers()方法为获取访问控制修饰符
看一下代码

	@Test
	public void test() throws Exception {
		Class c = Persion.class;
		Persion p = (Persion) c.getConstructor().newInstance();
		Field f = c.getDeclaredField("name");
		System.out.println(f.getModifiers());
		Field f1 = c.getDeclaredField("height");
		System.out.println(f1.getModifiers());;
		Field f2 = c.getDeclaredField("age");
		System.out.println(f2.getModifiers());;
		Field f3 = c.getDeclaredField("sex");
		System.out.println(f3.getModifiers());;
	}

结果为
0
1
4
2
可以看出默认:0,public:1,private:2,protected:4。数字3去哪了?
0的二进制是:00000000
1的二进制是:00000000
2的二进制是:00000010
4的二进制是:00000100
如果用3来表示protected,那么会稍微减少程序运算速度,因为3的二进制为00000011。

6.Method

获取Persion字节码文件

		Class c = Persion.class;

获取所有方法

public class text02 {
	@Test
	public void test() throws Exception {
		Class c = Persion.class;
		Method[] m = c.getMethods();
		for (Method method : m) {
			System.out.println(method);
		}
	}

}

结果为
public java.lang.String testList.Persion.toString()
public void testList.Persion.work(double)
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
Persion里只有work方法,怎么有这么多?因为Object类是所有类的父类所以多的方法是Object类里的方法。
获取单个方法

	@Test
	public void test() throws Exception {
		Class c = Persion.class;
		Persion p = (Persion) c.getConstructor().newInstance();
		Method m =  c.getMethod("work", double.class);
		m.invoke(p, 20);
	}

结果为
工作得到了20.0元
通过反射调用实例方法必须得知道方法名,如果不知道,则可以通过前面讲到得打印所有方法来查看。

7.总结

反射的基础内容大概就是这些,学技术不仅要知其然更得知其所以然。

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值