课程:宋红康 JAVA
理解Class类并获取Class的实例
类的加载过程:
程序经过javac.exe命令以后,会生成一个或多个字节码文件(.class结尾)。接着我们使用java.exe命令对某个字节码文件进行解释运行。相当于将某个字节码文件加载到内存中。**此过程就称为类的加载**。
加载到内存中的类,我们就称为运行时类,此运行时类,就作为Class的一个实例。换句话说,Class的实例就对应着一个运行时类。
加载到内存中的运行时类,会缓存一定的时间。在此时间之内,我们可以通过不同的方式来获取此运行时类。
获取Class的实例的方式:
调用运行时类的属性:.class
Class clazz1 = Person.class;
通过运行时类的对象,调用getClass()
Person p1 = new Person(); Class clazz2 = p1.getClass();
调用Class的静态方法:forName(String classPath)
Class clazz3 = Class.forName("com.atguigu.java.Person");
使用类的加载器:ClassLoader (了解)
ClassLoader classLoader = ReflectionTest.class.getClassLoader(); Class clazz4 = classLoader.loadClass("com.atguigu.java.Person");
Class类的其他实例
可以作为Class的实例的并非只有类,只要时能加载的类的内存中的可以作为Class类的实例
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; //(void也可以作为Class类的对象)
Class c9 = Class.class; //( Class也可以作为Class类的对象)
int[] a = new int[10];
int[] b = new int[100];
Class c10 = a.getClass();
Class c11 = b.getClass();
// 只要数组的元素类型与维度一样,就是同一个Class
类的加载与ClassLoader的理解
了解类的加载过程:
- 类的加载 load:将类的class文件读入内存,并为之创建一个java.lang.Class对象。此过程由类的加载器完成。
- 类的链接 link:将二进制数据合并到JRE中
- 类的初始化 initialize:jvm负责对类进行初始化
类加载器
作用:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后再堆中生成一个代表着个类的java.lang.Class对象,作为方法区中类数据的访问入口。
类缓存:一旦某个类加载到加载器中,他会维持加载(缓存)一段时间。我么每声明同类型的Class类实际上的同一个对象。
JVM规定的加载器类型:不同的类型会加载不同的类。
- Bootstap Classloader 引导类加载器:用C++编写的。是JVM自带的类加载器。复制Java平台核心库,用来装载核心类库。该加载器无法直接获取
- Extension Classloader 扩展类加载器:它负责加载jre/lib/ext扩展库。它是ClassLoader的子类
- Application Classloader 系统类加载器:它负责加载项目的classpath路径下的类。我们自定义的类就是他负责加载的。
- 自定义类加载器:后面会见到的自定义类加载器:tomcat中
获取类的加载器:
Class的实例 . getClassLoader()
,比如(ClassLoaderTest.class) . getClassLoader()
获取上一级的加载器:
classLoader.getParent()

- 利用类的加载器获取配置文件:
classLoader.getResourceAsStream

创建运行时类的对象:newInstance()

创建运行时类的对象:运行时类.newInstance()
obj:没使用泛型或者强转时,得到的是一个Object类型
Class<Person>
:泛型,指定newInstance()的返回值是Person
获取运行时类的完整结构
获取当前运行时类的属性结构
获取属性的所有信息
getFields()
:获取当前运行时类及其父类中声明为public访问权限的属性
getDeclaredFields()
:获取当前运行时类中声明的所有属性。(不包含父类中声明的属性)


获取属性的:权限修饰符 数据类型 变量名
权限修饰符
getModifiers()
:返回的是一个int型的值Modifier.toString(modifier)
:利用这个方法可以把对应的数字翻译成对应的某个权限
数据类型:
getType()
:返回的是一个类型,如String类型,Person类型,是一个类,需要用Class接收getName()
:值获取类名,如果不用这个方法,会把Class也答应出来
变量名:getName()


获取运行时类的方法结构
获取方法的所有信息
getMethods()
:获取当前运行时类及其所有父类中声明为public权限的方法
getDeclaredMethods()
:获取当前运行时类中声明的所有方法。(不包含父类中声明的方法)



获取方法的单个信息
方法里面包含:注解,权限修饰符 返回值类型 方法名(参数类型1 形参名1,…) throws XxxException{}
- 获取注解:
getAnnotations()
- 获取返回值类型:
getReturnType()
- 获取形参列表:
getParameterTypes()
,也是各种类,所有要用Class接收 - 获取抛出的异常:
getExceptionTypes()
,用Class接收


获取构造器结构
getConstructors()
:获取当前运行时类中声明为public的构造器
getDeclaredConstructors()
:获取当前运行时类中声明的所有的构造器

获取父类
获取运行时类的父类:getGenericSuperclass()


获取父类的泛型
获取运行时类的带泛型的父类的泛型:getActualTypeArguments()
;


获取接口
获取运行时类实现的接口:getInterfaces()

获取包
获取运行时类所在的包,getPackage()

获取注解
获取运行时类声明的注解:getAnnotations()


调用运行时类的指定结构
调用指定属性:
getField())
:不需要掌握,因为只能获取调用public的属性
getDeclaredField(String fieldName)
:需要掌握
- 获取Class的实例
Person.class
- 创建运行时类的对象
clazz.newInstance()
- 获取运行时类中指定变量名的属性
getDeclaredField(String fieldName)
- 保证当前属性是可访问的
setAccessible(true)
- 获取、设置指定对象的此属性值 :
set(p,"Tom")
- 获取当前属性的值
get()

调用指定的方法
getMethod()
:不需要掌握,因为只能获取调用public的属性
getDeclaredMethod(方法名,形参列表)
:需要掌握
- 获取Class的实例
Person.class
- 创建运行时类的对象
clazz.newInstance()
- 获取指定的某个方法
getDeclaredMethod()
- 保证当前方法是可访问的
setAccessible(true);
- 调用方法并获得方法返回值
invoke()
- 静态方法

调用指定的构造器
调用运行时类中的指定的构造器:getDeclaredConstructor(参数)
:指明构造器的参数列表

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1909773034@qq.com