文章目录
1、类加载
类在内存中的生命周期:
1.1、类的加载过程
当程序主动使用某个类时,如果该类还未被加载到内存中,系统会通过【加载、连接、初始化】三个步骤来对该类进行初始化
- 加载(load):将类型的class字节码数据读入内存
- 连接(link)
- 验证:校验合法性等
- 准备:准备对应的内存,创建Class对象,为类变量赋默认值,为静态常量赋初始值
- 解析:把字节码中的符号引用替换为对应的直接地址引用
- 初始化(initialize):执行
<clinit>
类初始化方法
1.2、类初始化
1.2.1、哪些使用类的操作,但是不会导致类的初始化?
使用某个类的静态的常量(static final)
class A {
static {System.out.println("静态代码块");}
static final int a = 2;
}
public class Hello {
public static void main(String[] args) {
System.out.println(A.a); // 只打印2
}
}
通过子类调用父类的静态变量,静态方法,只会导致父类初始化,不会导致子类初始化
package d.e.f;
class A {
static {System.out.println("静态代码块A");}
static int a = 2;
public static void m() {System.out.println("静态方法");}
}
class B extends A {
static {System.out.println("静态代码块B");}
}
public class Hello {
public static void main(String[] args) {
System.out.println(B.a);
B.m();
// 静态代码块B没有打印出来
}
}
用某个类型声明数组并创建数组对象时
class B {}
public class Hello {
public static void main(String[] args) {
B[] arr = new B[5]; // 什么都不打印
}
}
1.3、类加载器
-
(1)引导类加载器(Bootstrap Classloader)又称为根类加载器
-
负责加载
jre/rt.jar
核心库
(2)扩展类加载器(Extension ClassLoader)
-
负责加载
jre/lib/ext
扩展库
是ClassLoader
的子类
(3)应用程序类加载器(Application Classloader)
-
它负责加载项目的classpath路径下的类
是ClassLoader
的子类
(4)自定义类加载器
-
当程序需要加载“特定”目录下的类,可以自定义类加载器;
当程序的字节码文件需要加密时,那么往往会提供一个自定义类加载器对其进行解码
完后可能会学: tomcat中的自定义类加载器
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
System.out.println(classLoader);
System.out.println(classLoader.getParent());
System.out.println(classLoader.getParent().getParent());
上面代码打印结果
2、java.lang.Class
打印一些示例
Class.class // class java.lang.Class
String.class // java.lang.String
int.class // int
int[].class // class [I
Override.class // interface java.lang.Override
Comparable.class // interface java.lang.Comparable
Field.class // class java.lang.reflect.Field
2.1、获取Class对象方式
4种
package a.b.c;
public class Cat {
public static void main(String[] args) {
// 第1种
Class c1 = Cat.class;
System.out.println(c1); // class a.b.c.Cat
// 第2种
Class c2 = (new Cat()).getClass();
System.out.println(c1 == c2); // true
// 第3种(常用)
try {
Class c3 = Class.forName("a.b.c.Cat");
System.out.println(c1 == c3); // true
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 第4种
ClassLoader cl = Cat.class.getClassLoader(); // 获取类加载器
try {
Class c4 = cl.loadClass("a.b.c.Cat");
System.out.println(c1 == c4); // true
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
3、反射
3.1、获取本类信息
package a.b.c;
public class Hello {
public static void main(String[] args) {
(new Hello()).getThisClass();
}
private void getThisClass() {
Class c = this.getClass();
System.out.println(c);
// class a.b.c.Hello
System.out.println(c.getSimpleName());
// Hello
System.out.println(c.getName());
// a.b.c.Hello
System.out.println(c.getTypeName());
// a.b.c.Hello
System.out.println(c.getPackage());
// package a.b.c
System.out.println(c.getResource("/"));
// file:/C:/Users/yellow/IdeaProjects/JavaProject/out/production/JavaProject/
System.out.println(c.getResource(""));
// file:/C:/Users/yellow/IdeaProjects/JavaProject/out/production/JavaProject/a/b/c/
System.out.println(c.getResource("").getPath());
// /C:/Users/yellow/IdeaProjects/JavaProject/out/production/JavaProject/a/b/c/
}
}
3.2、创建任意引用类型的对象
class A {}
public class Hello {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("A");
Object a = clazz.newInstance();
System.out.println(a);
}
}
3.3、修改私有属性
import java.lang.reflect.Field;
class A {
private int aa = 2;
}
public class Hello {
public static void main(String[] args) throws Exception {
//1、获取A的Class对象
Class clazz = Class.forName("A");
//2、获取属性对象
Field aField = clazz.getDeclaredField("aa");
//3、设置允许
aField.setAccessible(true);
//4、创建实例对象
Object a = clazz.newInstance();
//5、获取属性值
Object value = aField.get(a);
System.out.println(value); //打印结果:2
//6、修改(设置)属性值
aField.set(a, 999);
value = aField.get(a);
System.out.println(value); //打印结果:999
}
}
3.4、调用任意类型的方法
import java.lang.reflect.Method;
class A {
void methodA(Integer i) { System.out.println("aa" + i); }
}
public class Hello {
public static void main(String[] args) throws Exception {
// 1、获取对象
Class<?> clazz = Class.forName("A");
//2、获取方法对象
Method method = clazz.getDeclaredMethod("methodA", Integer.class);
//3、创建实例对象
Object a = clazz.newInstance();
//4、调用方法
method.invoke(a, 22); //打印结果:aa22
}
}
3.5、读取注解信息
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
//自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface MyAnnotation {String value();}
//使用注解
@MyAnnotation("这这这这这这这这这是个注解")
class MyClass {}
public class Hello {
public static void main(String[] args) {
// 需求:可以获取MyClass类的注解
// 1、获取Class对象
Class<MyClass> clazz = MyClass.class;
// 2、获取注解对象
MyAnnotation my = clazz.getAnnotation(MyAnnotation.class);
// 3、获取配置参数值
System.out.println(my.value()); //打印结果:这这这这这这这这这是个注解
}
}