目录
一、Java Reflection概述:
Java反射功能:
二、Reflection API:
1.java.lang.Class:代表一个类
获取Class的实例方式:
Class实例结构:
获取类结构注解:
获取类结构构造方法:
获取类结构属性:
获取类结构方法:
2.java.lang.reflect.Method:代表类的方法
3.java.lang.reflect.Field:代表类的成员变量
4.java.lang.reflect.Constructor:代表类的构造器
三、类的加载过程:
四、类的加载&类加载器ClassLoader理解:
1.类加载器作用:
2.ClassLoader:
五、创建运行时类对象:
一、Java Reflection概述:
Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期间(RUNTIME)借助Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
加载完类之后,在堆内存的方法区中就产生一个Class类型对象(一个类只有一个Class对象),这个对象就包含完整的类的结构信息。我们可以通过这个对象看到类的完整结构。
补充:动态语言&静态语言
Java反射功能:
- 在运行时,判断任意一个对象所属的类
- 在运行时,构造任意一个类的对象
- 在运行时,判断任意一个类所具有的成员变量和方法
- 在运行时,获取泛型信息
- 在运行时,调用任意一个对象的成员变量和方法
- 在运行时,处理注解
- 生成动态代理
public class MyClass {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//传统方式:使用new关键字创建实例:
Demo demo01 = new Demo("demo01", "传统方式创建实例");
//使用反射机制创建实例:
//1.使用.class获得当前类结构:
Class demoClass = Demo.class;
//2.通过Demo类的结构获取该类的构造方法:
Constructor constructor = demoClass.getConstructor(String.class, String.class);
//3.通过获得的构造方法创建实例:
Demo demo02 = constructor.newInstance("demo02", "反射机制创建实例");
System.out.println(demo01.toString());
System.out.println(demo02.toString());
}
}
class Demo{
//两个私有化的成员属性:
private String name;
private String desc;
//构造器:
public Demo(String name, String desc) {
this.name = name;
this.desc = desc;
}
//提供了getter和setter方法:
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
// 重写toString方法:
@Override
public String toString() {
return "demo{" +
"name='" + name + ''' +
", desc='" + desc + ''' +
'}';
}
}
通过反射可以调用类的私有结构!!!
- getDeclaredConstructor(Class>... parameterTypes)
- 这个方法会返回制定参数类型的所有构造器,包括public的和非public的,当然也包括private的。
- getDeclaredConstructors()的返回结果就没有参数类型的过滤了。
- getConstructor(Class>... parameterTypes)
- 这个方法返回的是上面那个方法返回结果的子集,只返回制定参数类型访问权限是public的构造器。
- getConstructors()的返回结果同样也没有参数类型的过滤。
二、Reflection API:
1.java.lang.Class:代表一个类
获取Class的实例方式:
- 方式一:调用运行时类的属性.class
- 方式二:通过运行时类的对象,调用getClass()方法
- 方式三:调用Class的静态方法:forName(String classPath),参数:类的全路径
- 方式四:使用类加载器:ClassLoader
虽然获取的方式不同,但是获取到的实例是同一个实例(运行时类)
加载到内存中的运行时类,会缓存一定时间。在此时间之内,我们可以以通过不同的方式来获取此运行时类。
Class实例结构:
public class ClassDemo {
//Class实例可以是哪些结构的说明:
@Test
public void test2(){
Class c1 = Object.class;
Class c2 = Comparable.class;
Class c3 = String[].class;
Class c4 = int[][].class;
Class c5 = ElementType.class;
Class c6 = Override.class;
Class c7 = int.class;
Class c8 = void.class;
Class c9 = Class.class;
int[] a = new int[10];
int[] b = new int[100];
Class c10 = a.getClass();
Class c11 = b.getClass();
// 只要数组的元素类型与维度一样,就是同一个Class
System.out.println(c10 == c11);
}
}
获取类结构注解:
获取Class的实例方式:
- 方式一:调用运行时类的属性.class
- 方式二:通过运行时类的对象,调用getClass()方法
- 方式三:调用Class的静态方法:forName(String classPath),参数:类的全路径
- 方式四:使用类加载器:ClassLoader
虽然获取的方式不同,但是获取到的实例是同一个实例(运行时类)
加载到内存中的运行时类,会缓存一定时间。在此时间之内,我们可以以通过不同的方式来获取此运行时类。
Class实例结构:
public class ClassDemo {
//Class实例可以是哪些结构的说明:
@Test
public void test2(){
Class c1 = Object.class;
Class c2 = Comparable.class;
Class c3 = String[].class;
Class c4 = int[][].class;
Class c5 = ElementType.class;
Class c6 = Override.class;
Class c7 = int.class;
Class c8 = void.class;
Class c9 = Class.class;
int[] a = new int[10];
int[] b = new int[100];
Class c10 = a.getClass();
Class c11 = b.getClass();
// 只要数组的元素类型与维度一样,就是同一个Class
System.out.println(c10 == c11);
}
}
获取类结构注解:
虽然获取的方式不同,但是获取到的实例是同一个实例(运行时类)
加载到内存中的运行时类,会缓存一定时间。在此时间之内,我们可以以通过不同的方式来获取此运行时类。
public class ClassDemo {
//Class实例可以是哪些结构的说明:
@Test
public void test2(){
Class c1 = Object.class;
Class c2 = Comparable.class;
Class c3 = String[].class;
Class c4 = int[][].class;
Class c5 = ElementType.class;
Class c6 = Override.class;
Class c7 = int.class;
Class c8 = void.class;
Class c9 = Class.class;
int[] a = new int[10];
int[] b = new int[100];
Class c10 = a.getClass();
Class c11 = b.getClass();
// 只要数组的元素类型与维度一样,就是同一个Class
System.out.println(c10 == c11);
}
}
获取类结构注解:
获取类结构构造方法:
获取类结构属性:
获取类结构方法:
2.java.lang.reflect.Method:代表类的方法
3.java.lang.reflect.Field:代表类的成员变量
4.java.lang.reflect.Constructor:代表类的构造器
三、类的加载过程:
程序经过javac.exe命令以后,会生成一个或者多个字节码文件(.class结尾)。接着我们会使用java.exe命令对某个字节码文件进行解释运行。相当于将某个字节码文件加载到内存中。此过程称为类的加载。加载到内存中的类,我们就称为运行时类,此时运行时类,就作为Class的一个实例。
【JAVA】<类加载Class Loade>类的加载&初始化过程分析_范同学的知识分享园地!-CSDN博客类的加载过程:当程序主动使用某个类时,如果该类还没有被加载到内存中,则系统会通过如下三个步骤来对该类进行初始化:1.类的加载:将class文件字节码内容加载到内存中,并将这些静态数据转换成为方法区的运行时数据结构,然后生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口(引用地址)。所有需要访问和使用类数据只能通过这个Class对象。加载过程需要类加载器参与。2.类的链接:类的链接,将Java类的二进制代码合并到JVM的运行状态之...https://blog.csdn.net/weixin_52058417/article/details/122226516?spm=1001.2014.3001.5501
四、类的加载&类加载器ClassLoader理解:
1.类加载器作用:
- 类加载的作用:将class字节码文件内容加载到内存中,并将这些静态数据转换为方法区的运行时数据的访问入口。
- 类缓存:标准的JavaSE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,他将维持加载(缓存)一段时间。不过JVM垃圾回收机制可以回收这些Class对象。
2.ClassLoader:
类加载器作用是用来把类(Class)装载到内存的。JVM规范定义了如下类型的类加载器:
- 引导了加载器会加载扩展类加载器。
- ClassLoader去识别加载配置文件的默认位置是当前module的src目录下
五、创建运行时类对象:
newInstance()方法,创建当前运行时类对象。内部默认调用了运行时类结构的空参构造方法,想要此方法能够正常执行(创建实例)需要满足:
- 运行时类必须提供相应的构造方法。
- 构造方法的调用权限必须满足调用需求。
public class MyClassRuntime {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//创建Class运行时类对象:
Class demoClass = Demo.class;
//获取运行时类结构中的构造方法:
Constructor constructor = demoClass.getConstructor();
//通过constructor构造方法创建实例:
Demo demo = constructor.newInstance();
System.out.println(demo);
}
}
class Demo{
//提供构造方法:
public Demo(){}
}
Class.forName(String classPath) :指定类的全类名,创建该类对象实例。



