简单使用java反射

零、类的加载时机&类加载器

1.类的加载时机

当程序要使用某个类时,如果该类还未被加载到内存中,系统会通过加载,连接,初始化三步来实现对这个类进行初始化。其中加载 就是指将class文件读入内存,并为之创建一个Class对象。任何类被使用时系统都会建立一个Class对象。连接分为两步①验证 是否有正确的内部结构,并和其他类协调一致②准备 负责为类的静态成员分配内存,并设置默认初始化值。初始化是指初始化成员变量等等。

总的来说类的加载时机分为以下几种:

  • 创建类的实例
  • 访问类的静态变量,或者为静态变量赋值
  • 调用类的静态方法
  • 初始化某个类的子类
  • 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象

2.类加载器

1.什么是类加载器

类加载器(classloader)主要是负责将.class文件加载到内存中,并为之生成对应的Class对象的一种机制。虽然我们不需要关心类加载机制,但是了解这个机制我们就能更好的理解程序的运行。

2. 类加载器分类
类别 作用
根类加载器 也被称为引导类加载器,负责Java核心类的加载
比如System,String等。在JDK中JRE的lib目录下rt.jar文件中
扩展类加载器 负责JRE的扩展目录中jar包的加载。
在JDK中JRE的lib目录下ext目录
系统类加载器 负责在JVM启动时加载来自java命令的class文件
以及classpath环境变量所指定的jar包和类路径

一、反射

我们首先知道创建一个对象的三个阶段分为:

  1. 源文件阶段 .java的文件
  2. 字节码阶段 .class
  3. 创建对象阶段 new 对象名称

那么什么是反射呢?JAVA反射机制就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态用对象的方法的功能称为java语言的反射机制。想要使用反射,就必须得要获取字节码文件

假设我们有如下一个Person类,我们通过字节码去获取这个类的属性、方法、对象等

public class Person {
	public String name;
	public int age;
	private String gender;
	
	public Person() {
		super();
	}
	public Person(String name, Integer age) {
		super();
		this.name = name;
		this.age = age;
	}
	public void show() {
		System.out.println("姓名 "+ name + "年龄 " + age);
	}
	private void eat(String g) {
		gender = g;
		System.out.println("性别"+gender);
	}
}

1.获取字节码对象

获取字节码对象有三种方法:

  • Object类的getClass()方法,判断两个对象是否是同一个字节码文件
  • 静态属性class,当作静态方法的锁对象
  • Class类中静态方法forName(),读取配置文件
public static void main(String[] args) throws Exception {
		//方法1
		Class clazz = Class.forName("com.thinmoon.reflect.Person");
		//方法2
		Class clazz2 = Person.class;
		//方法3
		Person p = new Person();
		Class clazz3 = p.getClass();
		
	}

2.通过字节码创建对象

1).通过无参构造创建对象
//1.
Class clazz = Class.forName("com.thinmoon.reflect.Person");
Person p = (Person)clazz.newInstance();
p.age = 1;
p.name = "ls";
p.show();
2).通过有参构造创建对象
//2.
Class clazz = Class.forName("com.thinmoon.reflect.Person");
//获取构造器
Constructor c = clazz.getConstructor(String.class, Integer.class);
//通过构造器创建对象
Person p2 = (Person)c.newInstance("lsss", 111);
p2.show();

3.获取字段

1).获取公共字段
//获取公有属性
Field f = clazz.getField("name");
f.set(p2, "ssss");
2).获取私有属性
//获取私有属性
Field f1 = clazz.getDeclaredField("gender");
//去除私有权限
f1.setAccessible(true);
f1.set(p2, "女");

4.获取方法

1).获取公共方法
//获取公共方法
Method m1 = clazz.getMethod("show");
m1.invoke(p2);
2).获取私有方法
//获取私有方法
Method m2 = clazz.getDeclaredMethod("eat", String.class);
m2.setAccessible(true);
m2.invoke(p2, "sssaaaaaaaaa");
原文地址:https://www.cnblogs.com/ThinMoon/p/12368036.html