java-反射原理

目录

什么是反射?

反射的作用

反射的使用


什么是反射?

反射java语言中的一种机制,通过这种机制可以动态的实例化对象、读写属性、调用方法。

反射就是把java类中的各种成分映射成一个个的Java对象

反射的作用

通过反射可以使程序代码访问装载到JVM 中的类的内部信息

● 获取已装载类的成员变量信息

● 获取已装载类的方法

● 获取已装载类的构造方法信息

简单而言,就是在运行状态时, 能够去内存中通过权限类名找到对应的的Class对象,就能够调用类中的私有化的方法、属性。

反射的使用

首先我们准备一个测试类(Student)

package com.ljq.mymvc.reflect;

/**
 * 测试类
 * 
 * @author 一麟
 *
 */
public class Student {
	private String sid;

	private String sname;

	public Integer age;

	static {
		System.out.println("加载进jvm中!");
	}

	public Student() {
		super();
		System.out.println("调用无参构造方法创建了一个学生对象");
	}

	public Student(String sid) {
		super();
		this.sid = sid;
		System.out.println("调用带一个参数的构造方法创建了一个学生对象");
	}

	public Student(String sid, String sname) {
		super();
		this.sid = sid;
		this.sname = sname;
		System.out.println("调用带二个参数的构造方法创建了一个学生对象");
	}

	@SuppressWarnings("unused")
	private Student(Integer age) {
		System.out.println("调用Student类私有的构造方法创建一个学生对象");
		this.age = age;
	}

	public String getSid() {
		return sid;
	}

	public void setSid(String sid) {
		this.sid = sid;
	}

	public String getSname() {
		return sname;
	}

	public void setSname(String sname) {
		this.sname = sname;
	}

	public void hello() {
		System.out.println("你好!我是" + this.sname);
	}

	public void hello(String name) {
		System.out.println(name + "你好!我是" + this.sname);
	}

	@SuppressWarnings("unused")
	private Integer add(Integer a, Integer b) {
		return new Integer(a.intValue() + b.intValue());
	}

	@Override
	public String toString() {
		return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]";
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

}

如何拿到Class对象?

要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.那么怎么获取呢?有如下三种方法:

1.Class.forName(完整的类名)

2.类名.class

3.对象.getClass()

代码如下:

    	//1、Class.forName() 获取Class
		Class<Student> clazz =(Class<Student>)Class.forName("com.zking.reflect.Student");
		
		//2、类.class
		Class clazz02=Student.class;
		
		//3、对象.getClass
		Student stu = new Student();
		Class clazz03 = stu.getClass();
		
		System.out.println(clazz);
		System.out.println(clazz02);
		System.out.println(clazz03);

 输出的结果为:

获得类的构造:

主要的方法:

1.getConstructor (获得构造器对象)

2.getDeclaredConstructor(获得私有化的构造器对象)

3.newInstance (反射实例化)

/**
		 * 通过反射进行实例化对象
		 */

		// 获得无参构造
		Constructor<Student> c1 = clazz01.getConstructor();
		Student stu02 = c1.newInstance();
		stu02.setSid("3");
		System.out.println("------------无参构造------------");
		System.out.println(stu02 + "2号学生");

		// 有参构造
		Constructor<Student> c2 = clazz01.getConstructor(String.class);
		Student stu03 = c2.newInstance("01");
		stu03.setSname("小明" + "3号学生");
		System.out.println("------------有参构造------------");
		System.out.println(stu03);

		// 多个参数的有参构造
		Constructor<Student> c3 = clazz01.getConstructor(String.class, String.class);
		Student stu04 = c3.newInstance("02", "小美");
		System.out.println("------------多参构造------------");
		System.out.println(stu04 + "4号学生");

		// 调用私有化构造方法
		Constructor<Student> c4 = clazz01.getDeclaredConstructor(Integer.class);
		c4.setAccessible(true);
		Student stu05 = c4.newInstance(18);
		stu05.setSname("牛逼");
		System.out.println("------------私有化构造------------");
		System.out.println(stu05 + "5号学生");

获得类的方法:

主要的方法:

1.getMethod (通过方法名称获取到方法对象,若有参数放名称后面)

2.getMethod (通过方法名称获取到私有化方法对象)

3.invoke  (类实例, "参数");

注:为什么参数放后面,通过查看源代码可以看到后面是一个可变参数 要么只写一个,要么写name后面。

 继续采用上面的Student类,可以看到有三个方法,有参、无参和私有化。那么接下来我们就对这三个方法进行反射动态方法调用 

/**
		 * 获得方法
		 */
		
		// 调用类方法
		Method m1 = clazz01.getMethod("hello");
		System.out.println("------------普通方法------------");
		m1.invoke(stu05);

		// 调用带参数的方法
		Method m2 = clazz01.getMethod("hello", String.class);
		System.out.println("------------有参方法------------");
		m2.invoke(stu05, "27");

		// 调用私有化有参方法
		Method m3 = clazz01.getDeclaredMethod("add", Integer.class, Integer.class);
		m3.setAccessible(true);
		System.out.println("------------私有化方法------------");
		System.out.println(m3.invoke(stu05, 27, 43));

 获得类的属性:

主要的方法:

1.getField (“属性名”)  获得公开的属性

2.getDeclaredField (“属性名”)  既可以获得公开的属性又可以获得私有属性

3.getDeclaredFields (“属性名”)  获得全部

/**
		 * 通过反射机制获取对象属性
		 */

		// 反射公共属性
		Field f1 = clazz01.getField("age");
		f1.set(stu05, 56);
		System.out.println("------------公共属性方法------------");
		System.out.println(stu05 + "属性1");
		System.out.println(f1.get(stu05));

		// 反射私有化属性
		Field f2 = clazz01.getDeclaredField("sname");
		f2.setAccessible(true);
		f2.set(stu05, "aa");
		System.out.println("------------私有属性方法------------");
		System.out.println(stu05);
		System.out.println(f2.get(stu05));

猜你喜欢

转载自blog.csdn.net/m0_67376124/article/details/125659864