java反射笔记总结

本文详细介绍了Java反射机制,包括获取Class对象的多种方式、类的内存分析、类初始化过程、类加载器作用以及如何通过反射动态创建对象和执行方法。同时,文章还探讨了反射的性能影响,并通过实例比较了普通方法调用与反射调用的效率差异。

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

认识什么是反射

在这里插入图片描述

​	反射优点和缺点

优点:可以实现动态创建对象和编译,体现出很大的灵活性

缺点:对性能有影响,使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它能满足我们的需求,这些操作总时慢于直接执行相同的操作

在这里插入图片描述

//什么是反射
public class Test02 {
    public static void main(String[] args) {
//        通过反射获取类的Class对象
        try {
            Class c1 = Class.forName("com.tong.reflection.User");
            Class c2 = Class.forName("com.tong.reflection.User");
            Class c3 = Class.forName("com.tong.reflection.User");
//            判断一个类在内存中只有一个Class类
//            一个类被加载后,类的整个结构都会被封装在Class对象中
            System.out.println(c1.hashCode());
            System.out.println(c2.hashCode());
            System.out.println(c3.hashCode());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

}
//实体类:pojo entity
class User{
    private String name;
    private int id;
    private int age;

    public User() {
    }

    public User(String name, int id, int age) {
        this.name = name;
        this.id = id;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", age=" + age +
                '}';
    }
}

通过几种方式来获取Class类

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//测试Class类的创建方式
public class Test03 {
    public static void main(String[] args) {
        Person person = new Student();
        System.out.println("这个人是:"+person.name);
//        获得方式1 通过对象获得Class对象
        Class c1 = person.getClass();
        System.out.println(c1.hashCode());
//        获得方式2 通过forname获得
        try {
            Class c2 = Class.forName("com.tong.reflection.Student");
            System.out.println(c2.hashCode());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
//        获得方式3 通过类名.class
        Class<Student> c3 = Student.class;
        System.out.println(c3.hashCode());
//        获得方式4 基本内置类型的包装类都有有个Type属性
        Class<Integer> c4 = Integer.TYPE;
        System.out.println(c4);//查看是哪个类
//        获得父类类型
        Class c5 = c1.getSuperclass();
        System.out.println(c5);
    }

}
//创建一个人类
class Person{
    public String name;
//下面就是无参构造,有参构造,tostring方法
    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}
class Student extends Person{
    public Student(){
        this.name="学生";
    }
}
class Teacher extends Person{
    public Teacher(){
        this.name="老师";
    }
}

所有类型的Class对象

在这里插入图片描述

//所有类型的Class对象
public class Test04 {
    public static void main(String[] args) {
        Class c1 = Object.class;//类
        Class c2 = Comparable.class;//接口
        Class c3 = String[].class;//数组
        Class c4 = String[][].class;//二维数组
        Class c5 = Override.class;//注解
        Class c6 = ElementType.class;//枚举类型
        Class c7 = Integer.class;//基本数据类型
        Class c8 = void.class;//空类型
        Class c9 = Class.class;//Class类本身
        System.out.println(c1);
        System.out.println(c2);
        System.out.println(c3);
        System.out.println(c4);
        System.out.println(c5);
        System.out.println(c6);
        System.out.println(c7);
        System.out.println(c8);
        System.out.println(c9);
//        只要元素类型和维度一样就是class.
        int [] a = new int[10];
        int [] b = new int[20];
        System.out.println(a.getClass().hashCode());
        System.out.println(b.getClass().hashCode());

    }
}

在这里插入图片描述

Java内存分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//讲解类怎么加载的
public class Test05 {
    public static void main(String[] args) {
        A a = new A();
        System.out.println(A.m);
        /*
        1 加载到内存会,会产生一个类对应的class对象
        2 链接,链接结束后 m=0
        3 初始化
            <clinit>(){
                System.out.println("A类静态代码块初始化");
                   m = 300;
                   m = 100;
            }
            m = 100;
         */
    }
}
class A{
//    静态代码块
    static {
    System.out.println("A类静态代码块初始化");
    m = 300;
    }
    static  int m = 100;
    public A() {
        System.out.println("A类的无参构造初始化");
    }
}
//输出结果
A类静态代码块初始化
A类的无参构造初始化
100

在这里插入图片描述

分析类初始化

在这里插入图片描述

//测试类什么时候会初始化
public class Test06 {
    static {
        System.out.println("main类被加载");
    }

    public static void main(String[] args) {
        //1 主动引用
//        Son son = new Son();
        /*
        输出结果
        main类被加载
        父类被加载
        子类被加载
         */
        // 2 反射也会产生主动引用
//        try {
//            Class.forName("com.tong.reflection.Son");
//        } catch (ClassNotFoundException e) {
//            e.printStackTrace();
//        }
//        3 不会产生类的引用的方法
//        System.out.println(Son.b);
        /*
        输出结果
        main类被加载
        父类被加载
        2
         */
        System.out.println(Son.M);//常量在链接阶段就存入了调用了类的常量池中了,不会引起初始化

    }

}
class Father{
    static int b = 2;
    static {
        System.out.println("父类被加载");
    }
}
class Son extends Father{
    static {
        System.out.println("子类被加载");
        m = 300;
    }
    static int m = 100;
    static final int M = 1;
}

类加载器的作用

在这里插入图片描述

在这里插入图片描述

public class Test07 {
    public static void main(String[] args) {
//        获得系统类的加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);
//        获取系统类加载器的父类加载器--> 扩展类加载器
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println(parent);
//        获取扩展类加载器的父类加载器--> 根加载器(c/c++)写的
        ClassLoader parent1 = parent.getParent();
        System.out.println(parent1);
        /*
        运行结果
        sun.misc.Launcher$AppClassLoader@18b4aac2
        sun.misc.Launcher$ExtClassLoader@1b6d3586
        null
         */
//        测试当前类是哪个加载器加载的
        try {
            ClassLoader classLoader = Class.forName("com.tong.reflection.Test07").getClassLoader();
            System.out.println(classLoader);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
//        测试JDK内部类是谁加载的
        try {
            ClassLoader classLoader = Class.forName("java.lang.Object").getClassLoader();
            System.out.println(classLoader);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }//JDK是根加载器加载的没打印出来
//        如何获得系统类加载器可以加载的路径
        System.out.println(System.getProperty("java.class.path"));


    }
}

如何通过反射获取类运行时类的完整结构

在这里插入图片描述

//获得类的信息
public class Test08 {
    public static void main(String[] args) {
        try {
//            获得名字
            Class c1 = Class.forName("com.tong.reflection.User");
            System.out.println(c1.getName());//包名+类名
            System.out.println(c1.getSimpleName());//单纯类名
            System.out.println("==================================");
//            获得类的属性
            Field[] fields = c1.getFields();//只能找到public属性
            fields = c1.getDeclaredFields();//找到全部属性
            for (Field field : fields) {
                System.out.println(field);
            }
            //获得指定属性的值
            Field name = c1.getDeclaredField("name");
            System.out.println(name);
            System.out.println("==================================");
//            获得类的方法
            Method[] methods = c1.getMethods();//获得本类和父类全部的public全部的方法
            for (Method method : methods) {
                System.out.println("正常的"+method);
            }
            methods = c1.getDeclaredMethods();//获得本类的所有方法
            for (Method method : methods) {
                System.out.println("本类的"+method);
            }
            //获得指定方法
            Method getName = c1.getMethod("getName", null);
            Method setName = c1.getMethod("setName", String.class);
            System.out.println(getName);
            System.out.println(setName);
            System.out.println("==================================");
//            获得类的构造器
            Constructor[] constructors = c1.getConstructors();//获得public方法
            for (Constructor constructor : constructors) {
                System.out.println(constructor);
            }
            constructors = c1.getDeclaredConstructors();//获得本类的全部方法
            for (Constructor constructor : constructors) {
                System.out.println(constructor);
            }
            //获得指定的构造器
            Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
            System.out.println("指定构造器"+declaredConstructor);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

运行结果

com.tong.reflection.User
User
==================================
private java.lang.String com.tong.reflection.User.name
private int com.tong.reflection.User.id
private int com.tong.reflection.User.age
private java.lang.String com.tong.reflection.User.name
==================================
正常的public java.lang.String com.tong.reflection.User.toString()
正常的public java.lang.String com.tong.reflection.User.getName()
正常的public int com.tong.reflection.User.getId()
正常的public void com.tong.reflection.User.setName(java.lang.String)
正常的public void com.tong.reflection.User.setId(int)
正常的public int com.tong.reflection.User.getAge()
正常的public void com.tong.reflection.User.setAge(int)
正常的public final void java.lang.Object.wait() throws java.lang.InterruptedException
正常的public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
正常的public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
正常的public boolean java.lang.Object.equals(java.lang.Object)
正常的public native int java.lang.Object.hashCode()
正常的public final native java.lang.Class java.lang.Object.getClass()
正常的public final native void java.lang.Object.notify()
正常的public final native void java.lang.Object.notifyAll()
本类的public java.lang.String com.tong.reflection.User.toString()
本类的public java.lang.String com.tong.reflection.User.getName()
本类的public int com.tong.reflection.User.getId()
本类的public void com.tong.reflection.User.setName(java.lang.String)
本类的public void com.tong.reflection.User.setId(int)
本类的public int com.tong.reflection.User.getAge()
本类的public void com.tong.reflection.User.setAge(int)
public java.lang.String com.tong.reflection.User.getName()
public void com.tong.reflection.User.setName(java.lang.String)
==================================
public com.tong.reflection.User()
public com.tong.reflection.User(java.lang.String,int,int)
public com.tong.reflection.User()
public com.tong.reflection.User(java.lang.String,int,int)
指定构造器public com.tong.reflection.User(java.lang.String,int,int)

动态创建对象执行方法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

//通过反射动态的创建对象
public class Test09 {
    public static void main(String[] args) {
        try {
            //获得class对象
            Class c1 = Class.forName("com.tong.reflection.User");
//            构造一个对象
            User user = (User )c1.newInstance();//本质上调用了类的无参构造器
            System.out.println(user);
//            通过构造器创建对象
            Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
            User user2 =(User) constructor.newInstance("tom", 01, 22);
            System.out.println(user2);
            System.out.println("============================================");
//            通过反射调用方法
            User user3 = (User )c1.newInstance();
            //通过反射获取一个方法
            Method setName = c1.getDeclaredMethod("setName", String.class);
            // invoke:激活
            //(对象,“方法的值”,
            setName.invoke(user3,"狂神");
            System.out.println(user3.getName());
            System.out.println("============================================");
//            通过反射操作属性
            User user4 = (User )c1.newInstance();
            Field name = c1.getDeclaredField("name");
            //不能直接操作私有属性,需要关闭程序的安全检测,name.setAccessible(true);
            name.setAccessible(true);
            name.set(user4,"狂神2");
            System.out.println(user4.getName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

运行结果

User{name='null', id=0, age=0}
User{name='tom', id=1, age=22}
============================================
狂神
============================================
狂神2

分析性能时间

//分析性能问题
public class Test10 {
//    普通方式
    public static void test01(){
        User user = new User();
        long starTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            user.getName();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("普通方法执行10亿次"+(endTime-starTime)+"ms");
    }
//    反射调用
    public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        Class c1 = user.getClass();
        Method getName = c1.getMethod("getName", null);
        long starTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(user,null);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("反射方法执行10亿次"+(endTime-starTime)+"ms");
    }
//    反射方式调用    关闭检测
    public  static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        Class c1 = user.getClass();
        Method getName = c1.getMethod("getName", null);
        getName.setAccessible(true);
        long starTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(user,null);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("关闭检测执行执行10亿次"+(endTime-starTime)+"ms");
    }

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        test01();
        test02();
        test03();
    }
}

运行结果

普通方法执行10亿次2ms
反射方法执行10亿次2523ms
关闭检测执行执行10亿次1096ms
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值