Java反射是什么?我对Java反射的理解

反射是什么?
将类的各个组成部分封装成其他对象,这就是反射机制。

类各个组成部分是什么?
类里面的成员变量,构造方法,成员方法等。

反射:将类的成员变量,构造方法,成员方法等封装成各个独立的对象,这就是反射。

反射的好处:
可以在程序运行的过程中,操作这些对象。
可以解耦,提高程序的可扩展性。

框架设计的灵魂就是反射。
框架:半成品软件,可以在框架的基础上进行软件开发,简化编码,通过配置文件进行反射,实现对象功能。

Java代码在计算机中经历的三个阶段:
在这里插入图片描述

1.源代码阶段:创建好的xxx.java文件,通过javac编译器编译成xxx.class字节码文件。
2.class类对象阶段:xxx.class字节码文件通过类加载器,加载到内存中,并生成对应的类对象(Class类对象),类对象通过一些数组对象存储了源代码中各个组成部分。
3.运行时阶段:通过类对象的一些行为方法创建我们需要的对象,调用对象方法,最终实现我们的具体需求。

只要获取到Class类对象,我们就可以通过Class类的成员方法来获取各个组成部分的信息。

如何获取Class类对象?
三种方式:
1.Class.forName(“全类名”):将字节码文件加载进内存,返回Class类对象。
适用场景:多用于配置文件,将类名定义在配置文件中。读取文件,加载类

2.类名.class :通过类名的属性class获取Class类对象。
适用场景:多用于参数的传递。

3.对象.getClass():Object类的成员方法getClass(),通过它同样可以返回Class类对象。
适用场景:多用于对象的获取字节码的方式。

准备一个类:

public class Student {
	/* 成员变量 */
	public String school_public;
	public String city;
	protected String school_protect;
	String school_default;
	private String name;
	private int age;
	
	/* 无参构造 */
	public Student() {
		super();
	}
	
	/* 有参构造 */
	public Student(String school_public, String name, int age) {
		super();
		this.school_public = school_public;
		this.name = name;
		this.age = age;
	}
	
	/* 成员方法 */
	public void study() {
		System.out.println("好好学习,天天向上");
	}
	
	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;
	}
	
}



public class GetClass {

	public static void main(String[] args) throws ClassNotFoundException {
		//方式一
		Class cla1= Class.forName("com.fanshe.Student");
		
		//方式二
		Class cla2=Student.class;
		
		//方式三
		Student student = new Student();
		Class cla3 = student.getClass();
		
		boolean b1=(cla1==cla2);
		boolean b2=(cla1==cla3);
		System.out.println("cla1==cla2:"+b1);
		System.out.println("cla1==cla3:"+b2);
		
	}

}

输出:
cla1== cla2:true
cla1== cla3:true

结论:同一个字节码文件(xxx.class)在一次程序运行过程中,只会被加载一次,不论通过哪种方式获取到的Class类对象都是同一个!

获取到了Class类对象,我们能干啥?
1.获取成员变量们
Field[] getFields() :获取所有public修饰的成员变量
Field getField(String name) :获取指定名称的public修饰的成员变量

Field[] getDeclaredFields() :获取所有成员变量,不限修饰符
Field getDeclaredField(String name) :获取指定名称的成员变量,不限修饰符

public class GetClassFileds {

	public static void main(String[] args) throws Exception {
		Class clas = Class.forName("com.fanshe.Student");
		//getFields()  获取所有public修饰的成员变量
		Field[] fields = clas.getFields();
		for (Field field : fields) {
			System.out.println(field);
		}
		//getField(String name) 获取指定public修饰的成员变量
		System.out.println("---------------分界线---------------");
		Field field = clas.getField("school_public");
		System.out.println(field);
	}
}

输出:
public java.lang.String com.fanshe.Student.school_public
public java.lang.String com.fanshe.Student.city
---------------分界线---------------
public java.lang.String com.fanshe.Student.school_public
(只能获取public修饰的成员变量)



public class GetDeclaredFields {

	public static void main(String[] args) throws Exception {
		Class clas = Class.forName("com.fanshe.Student");
		//getDeclaredFields() 获取所有成员变量
		Field[] declaredFields = clas.getDeclaredFields();
		for (Field field : declaredFields) {
			System.out.println(field);
		}
		
		System.out.println("---------分界线-----------");
		
		//getDeclaredField(String name)  获取指定名字的成员变量
		Field declaredField = clas.getDeclaredField("school_protect");
		System.out.println(declaredField);
	}
}

输出:
public java.lang.String com.fanshe.Student.school_public
public java.lang.String com.fanshe.Student.city
protected java.lang.String com.fanshe.Student.school_protect
java.lang.String com.fanshe.Student.school_default
private java.lang.String com.fanshe.Student.name
private int com.fanshe.Student.age
---------分界线-----------
protected java.lang.String com.fanshe.Student.school_protect
(获取所有成员变量,不限修饰符)

filed对象操作:
获取成员变量值: Field.get(对象名);

Class clas = Class.forName("com.fanshe.Student");
		Field field = clas.getField("school_public");
		Student student = new Student();
		Object object = field.get(student);
		System.out.println(object);

输出:null (因为student成员变量还没赋值)

设置成员变量值:Filed.set(对象名,变量的值)

Class clas = Class.forName("com.fanshe.Student");
		Field field = clas.getField("school_public");
		Student student = new Student();
field.set(student, "育才中学");
		Object object2 = field.get(student);
		System.out.println(object2);

输出:育才中学

获取私有成员变量并且赋值:暴力反射(先暴力反射,再赋值)




Class clas = Class.forName("com.fanshe.Student");
Field declaredField = clas.getDeclaredField("name");
Student student = new Student();
		Object object3 = declaredField.get(student);
		System.out.println(object3);

报错: java.lang.IllegalAccessException

解决方案:暴力反射

Class clas = Class.forName("com.fanshe.Student");
Field declaredField = clas.getDeclaredField("name");
Student student = new Student();
		declaredField.setAccessible(true);//忽略访问权限安全检查,暴力反射
		Object object3 = declaredField.get(student);
		System.out.println(object3);

输出:null

设置私有成员变量值:

Class clas = Class.forName("com.fanshe.Student");
Field declaredField = clas.getDeclaredField("name");
Student student = new Student();
		declaredField.setAccessible(true);
		declaredField.set(student, "张三");
		Object object3 = declaredField.get(student);
		System.out.println(object3);

输出:张三

2.获取构造方法们
Constructor<?>[] getConstructors() :获取所有public修饰的构造方法
Constructor getConstructor(类<?>… parameterTypes) :
获取指定public修饰的构造方法 (构造方法参数类型-可多个)
如:getConstructor(String.class,String.class,int.class);

Constructor<?>[] getDeclaredConstructors() :获取所有构造方法,不限修饰符
Constructor getDeclaredConstructor(类<?>… parameterTypes) :
获取指定构造方法,不限修饰符 (构造方法参数类型-可多个)

获取public修饰的构造方法

public class GetConstructors {

	public static void main(String[] args) throws Exception {
		Class clas = Class.forName("com.fanshe.Student");
		System.out.println("获取所有public构造方法");
		Constructor[] constructors = clas.getConstructors();
		for (Constructor constructor : constructors) {
			System.out.println(constructor);
		}
		
		System.out.println("--------指定public构造方法------------");
		Constructor constructor = clas.getConstructor(String.class,int.class);
		System.out.println(constructor);
	}

}

输出:
获取所有public构造方法
public com.fanshe.Student(java.lang.String,int)
public com.fanshe.Student()
--------指定public构造方法------------
public com.fanshe.Student(java.lang.String,int)

获取所有构造方法

public class GetDeclaredConstructors {

	public static void main(String[] args) throws Exception {
		Class clas = Class.forName("com.fanshe.Student");
System.out.println("获取所有构造方法");
		Constructor[] declaredConstructors = clas.getDeclaredConstructors();
		for (Constructor constructor : declaredConstructors) {
			System.out.println(constructor);
		}
		System.out.println("--------指定构造方法------------");
		Constructor constructor = clas.getDeclaredConstructor(String.class);
		System.out.println(constructor);
	}

}

输出:
获取所有构造方法
private com.fanshe.Student(java.lang.String)
public com.fanshe.Student(java.lang.String,int)
public com.fanshe.Student()
--------指定构造方法------------
private com.fanshe.Student(java.lang.String)

通过构造方法创建实例:

public class NewInstance {

	public static void main(String[] args) throws Exception {
		Class clas = Class.forName("com.fanshe.Student");
		System.out.println("public构造方法,反射,创建实例");
		
		System.out.println("无参构造");
		Constructor constructor = clas.getConstructor();
		Object newInstance = constructor.newInstance();
		System.out.println("无参构造:"+newInstance);
		
		System.out.println("有参构造");
		Constructor constructor2 = clas.getConstructor(String.class,int.class);
		Object newInstance2 = constructor2.newInstance("张三",18);
		System.out.println("有参构造:"+newInstance2);
		
	}

}

输出:
public构造方法,反射,创建实例
无参构造
无参构造:Student [school_public=null, city=null, school_protect=null, school_default=null, name=null, age=0]
有参构造
有参构造:Student [school_public=null, city=null, school_protect=null, school_default=null, name=张三, age=18]

通过私有构造方法,暴力反射,获取实例:

public class NewInstanceDeclared {

	public static void main(String[] args) throws Exception {
		Class clas = Class.forName("com.fanshe.Student");
		Constructor declaredConstructor = clas.getDeclaredConstructor(String.class);
		declaredConstructor.setAccessible(true);
		Object newInstance = declaredConstructor.newInstance("张三");
		System.out.println("private有参构造:"+newInstance);
	}

}

输出:
private有参构造:Student [school_public=null, city=null, school_protect=null, school_default=null, name=张三, age=0]

3.获取成员方法们
Method[] getMethods() :获取所有public修饰的成员方法
Method getMethod(String name, 类<?>… parameterTypes)
获取指定成员方法

Method[] getDeclaredMethods()
Method getDeclaredMethod(String name, 类<?>… parameterTypes)

获取所有public成员方法(包括父类的方法,构造方法除外)

public class GetMethods {

	public static void main(String[] args) throws Exception {
		Class clas = Class.forName("com.fanshe.Student");
		System.out.println("获取所有成员方法");
		Method[] methods = clas.getMethods();
		for (Method method : methods) {
			System.out.println(method);
		}
		
		System.out.println("获取指定成员方法");
		Method method = clas.getMethod("setAge", int.class);
		System.out.println(method);
		
	}

}

输出:
获取所有成员方法
public java.lang.String com.fanshe.Student.toString()
public java.lang.String com.fanshe.Student.getName()
public void com.fanshe.Student.setName(java.lang.String)
public void com.fanshe.Student.setAge(int)
public void com.fanshe.Student.study()
public int com.fanshe.Student.getAge()
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()
获取指定成员方法
public void com.fanshe.Student.setAge(int)

获取所有成员方法,不限修饰符(包括父类的方法,构造方法除外)

public class GetMethodsDeclared {

	public static void main(String[] args) throws Exception {
		Class clas = Class.forName("com.fanshe.Student");
		System.out.println("获取所有成员方法");
		Method[] declaredMethods = clas.getDeclaredMethods();
		for (Method method : declaredMethods) {
			System.out.println(method);
		}
		
		System.out.println("获取指定private修饰的成员方法");
		Method declaredMethod = clas.getDeclaredMethod("eat", String.class,String.class);
		System.out.println(declaredMethod);
	}

}

输出:
获取所有成员方法
public java.lang.String com.fanshe.Student.toString()
public java.lang.String com.fanshe.Student.getName()
public void com.fanshe.Student.setName(java.lang.String)
private void com.fanshe.Student.eat(java.lang.String,java.lang.String)
public int com.fanshe.Student.getAge()
public void com.fanshe.Student.study()
public void com.fanshe.Student.setAge(int)
获取指定private修饰的成员方法
private void com.fanshe.Student.eat(java.lang.String,java.lang.String)

获取方法,反射执行

	/* 定义成员方法:成员方法 */
	public void study() {
		System.out.println("好好学习,天天向上");
	}
	
	public void study(String schoolname,String name) {
		System.out.println(schoolname+name+"好好学习,天天向上");
	}


public class Invoke {

	public static void main(String[] args) throws Exception {
		Class clas = Class.forName("com.fanshe.Student");
		System.out.println("无参");
		Method method = clas.getMethod("study");
		method.invoke(new Student());
		
		System.out.println("有参");
		Method method2 = clas.getMethod("study",String.class,String.class);
		method2.invoke(new Student(), "育才中学","张三");
	}

}

输出:
无参
好好学习,天天向上
有参
育才中学张三好好学习,天天向上

私有成员方法,暴力反射:
私有方法:

	/* 私有成员方法 */
	private void eat(String name,String food) {
		System.out.println(name+"吃饭:"+food);
	}

public class InvokeDeclared {

	public static void main(String[] args) throws Exception {
		Class clas = Class.forName("com.fanshe.Student");
		System.out.println("私有成员方法,暴力反射,执行");
		Method declaredMethod = clas.getDeclaredMethod("eat", String.class,String.class);
		declaredMethod.setAccessible(true);
		declaredMethod.invoke(new Student(), "张三","蛋炒饭");
	}

}

输出:
私有方法,暴力反射,执行
张三吃饭:蛋炒饭

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值