Python工程师Java之路(l)反射

本文详细解读了Java类加载的过程,包括加载、连接、验证和初始化,同时介绍了如何通过Class类获取信息、创建对象、操作私有属性、调用方法及解析注解。此外,讲解了各类类加载器的作用和使用类的不同场景下类不初始化的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、类加载

类在内存中的生命周期:

加载
使用
卸载

1.1、类的加载过程

当程序主动使用某个类时,如果该类还未被加载到内存中,系统会通过【加载、连接、初始化】三个步骤来对该类进行初始化

  1. 加载(load):将类型的class字节码数据读入内存
  2. 连接(link)
    • 验证:校验合法性等
    • 准备:准备对应的内存,创建Class对象,为类变量赋默认值,为静态常量赋初始值
    • 解析:把字节码中的符号引用替换为对应的直接地址引用
  3. 初始化(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()); //打印结果:这这这这这这这这这是个注解
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小基基o_O

您的鼓励是我创作的巨大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值