java反射机制

6、反射机制

动态语言:动态语言是一种在运行时可以改变其结构的语言。
而java是一种静态语言,但是java的反射机制使得java更加灵活,于是Java也是一种“准动态语言”。
反射:反射就像照镜子一样,通过镜子可以看到所有信息。java种通过反射可以获取一个类的所有内部信息。反射虽然灵活,但是也损失了运行速度
反射通过Class对象来实现,每个类只有一个Class实例对象,包括接口,注解,枚举类等都存在Class对象。
获取class对象的方式:
        student  s=new student();
        Class c1=Class.forName("包名");//通过包名获取
        Class c2=person.class; //通过类命获取
        Class c3=s.getClass();//通过对象名
Class类:
对于每个类,JRE都为其保留了一个不变的class类的对象,通过这个对象可以获取该类的属性、方法、构造器、实现的接口等。一个Class类对象包含了特定某个结构的有关信息(class/interface/enum/annotation/primitive type/void/[])
---->Class本身是一个类
---->Class对象只能由系统创建
---->一个加载的类在JVM中只有一个Class实例
---->一个Class对象对应了一个加载到JVM中的class文件
---->通过Class可以完整地得到一个类所加载的结构
---->Class是reflection的根源,对于想要动态加载和运行的类,只有先获得相应的Class对象
 public static void main(String[] args) throws NoSuchMethodException,ClassNotFoundException {
        //每个类都只有一个class,所以同一个类的多个对象他们的class一样。
        student  s=new student();
        Class c1=Class.forName("com.company.reflection.person");//通过包名获取
        Class c2=person.class; //通过类命获取
        Class c3=s.getClass();//通过对象名
        System.out.println(c3.getConstructors());
        System.out.println(c3.getMethods());
        Class c4=c3.getSuperclass(); //通过子类的Class对象
        Class c5=int[].class; //数组
        Class c6=Runnable.class;//接口
        Class c7=void.class;
        Class c8=Integer.TYPE;//int与Integer的Class是一样的
        Class c9=int.class;
        Class c10= Target.class;//注解
        Class c12= ElementType.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);
        System.out.println(c10);
        System.out.println(c12);
        //只要类型和维度一样,Class就是一样的
        //每种类型都只有一个Class实例
        int[] a=new int[10];
        int[] b=new int[20];
        int[][] c=new int[2][4];
        System.out.println(a.getClass().hashCode());
        System.out.println(b.getClass().hashCode());
        System.out.println(c.getClass().hashCode());
    }
}
class person{
    String name;
    public person(){
        this.name="王琴";
    }
}
class student extends person{
    int id;
    public student(){
        this.name="wq";
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
}

7、通过反射获取类的运行时结构

这个过程通过类的Class对象进行获取

 public static void main(String[] args) throws NoSuchMethodException, ClassNotFoundException, NoSuchFieldException {
        //类的主动引用:通过new关键字,调用类的静态成员和静态方法,通过反射调用,
        //customer cs=new customer();//通过new 关键字初始化customer
        //user us=new user(1,"wq");  //通过new 关键字初始化user
        Class<?> c1 = Class.forName("com.company.reflection.customer");//反射会引起子类和父类的初始化
        //customer.print();//类调用静态方法或成员会初始化类
        System.out.println(c1.getName());//获取包名+类名
        System.out.println(c1.getSimpleName());//获取简单类名
        System.out.println(c1.getSuperclass());//获取父类全路径名
        //Constructor constructor = c1.getConstructor(int.class);//获取public的指定构造器
        Constructor declaredConstructor = c1.getDeclaredConstructor(int.class);//获取任意的指定的构造器,不管是public还是private
        Constructor[] constructors = c1.getConstructors();//获取所有的public构造器
        Constructor[] declaredConstructors = c1.getDeclaredConstructors();//获取所有构造器
        //System.out.println(constructor);
        System.out.println(declaredConstructor);
        for (Constructor constructor1 : constructors) {
            System.out.println(constructor1);
        }
        for (Constructor declaredConstructor1 : declaredConstructors) {
            System.out.println(declaredConstructor1);
        }
        Method method = c1.getMethod("print",null);//获取指定的public 方法
        //Method[] methods = c1.getMethods();//获取该类和父类的所有public方法
        Method sb = c1.getDeclaredMethod("sb", null);//获取任意指定的方法
        //Method[] declaredMethods = c1.getDeclaredMethods();//获取本类的所有方法
        System.out.println(method);
        System.out.println(sb);
//        for (Method method1 : methods) {
//            System.out.println(method1);
//        }
//        for (Method declaredMethod : declaredMethods) {
//            System.out.println(declaredMethod);
//        }
        System.out.println("===============================");
        Field p = c1.getField("p");//获取pulic字段
        System.out.println(p);
        Field declaredField = c1.getDeclaredField("cId");//获取任意指定字段
        System.out.println(declaredField);
        System.out.println("===============================");
        Field[] fields = c1.getFields();//获取本类和父类的public字段
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("===============================");
        Field[] declaredFields = c1.getDeclaredFields();//获取本类的所有字段
        for (Field field : declaredFields) {
            System.out.println(field);
        }
    }

8、通过反射动态创建对象

//通过反射动态创建对象
public class test04 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        Class c1=Class.forName("com.company.reflection.user");
        ClassLoader classLoader = c1.getClassLoader();
        //通过Class对象创建实例,只能调用无参构造方法创建
        user us  = (user) c1.newInstance();
        //通过构造器创建实例
        Constructor constructor=c1.getConstructor(int.class,String.class);
        user us2= (user) constructor.newInstance(12,"wq");
        System.out.println(us2);
        //通过反射获取方法,然后操作方法
        Method setId = c1.getMethod("setId", int.class);//(方法名,参数类型)
        setId.invoke(us,14);//激活方法invoke(所属对象,方法要传入的参数值)
        System.out.println(us.getId());
        //获取属性
        Field name = c1.getDeclaredField("name");
        name.setAccessible(true);//关闭权限检查
        name.set(us,"王琴");//设置属性的值
        System.out.println(us);
    }
}

9、类加载器

public class test03 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
    Class c1=Class.forName("com.company.reflection.user");
    ClassLoader classLoader = c1.getClassLoader();
    //获取系统类加载器------>我们自己定义的类的加载器都是系统加载器
    ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
    System.out.println(systemClassLoader);
    //获取系统类加载器的父类--->扩展类加载器
    ClassLoader parent = systemClassLoader.getParent();
    System.out.println(parent);
    //获取扩展类加载器的父类----->根加载器(c/c++编写),java核心类库的加载器获取,无法
    ClassLoader parent1 = parent.getParent();
    //"java.lang.String"类在java核心类库----在rt.jar包中,所以无法获取
    ClassLoader classLoader1 = Class.forName("java.lang.String").getClassLoader();
    System.out.println(parent1);
    System.out.println(classLoader);
    System.out.println(classLoader1);
}
    结果:
        jdk.internal.loader.ClassLoaders$AppClassLoader@63947c6b
        jdk.internal.loader.ClassLoaders$PlatformClassLoader@7ef20235
        null
        jdk.internal.loader.ClassLoaders$AppClassLoader@63947c6b
        null

10、反射调用性能比较

public class performance {
    public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
        test01();
        test02();
        test03();
    }
    //普通方式调用
    public static void test01(){
        user us=new user();
        long start=System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            us.getName();
        }
        long stop=System.currentTimeMillis();
        System.out.println("普通方式耗时"+(stop-start));
    }
    //反射方式调用
    public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        user us=new user();
        Class c=us.getClass();
        Method m = c.getDeclaredMethod("getName");
        long start=System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
           m.invoke(us);
        }
        long stop=System.currentTimeMillis();
        System.out.println("反射方式耗时"+(stop-start));
    }
    //反射方式调用,关闭权限检查
    public static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        user us=new user();
        Class c=us.getClass();
        Method m = c.getDeclaredMethod("getName");
        m.setAccessible(true);
        long start=System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            m.invoke(us);
        }
        long stop=System.currentTimeMillis();
        System.out.println("关闭权限检查方式耗时"+(stop-start));
    }
}

结果分析反射机制确实耗时很大,其中权限检查消耗一半的时间,如果反射调用很多最好关闭权限检查。

我是user
我是无参构造方法
普通方式耗时4
我是无参构造方法
反射方式耗时2329
我是无参构造方法
关闭权限检查方式耗时1104

11、获取泛型信息

public class test05 {
    public Map<String,user> a(Map<String,user> map){
        return map;
    }
    public static void main(String[] args) throws NoSuchMethodException {
        Class c=test05.class;
        Method a = c.getDeclaredMethod("a", Map.class);
        //获取参数类型
        Type[] genericParameterTypes = a.getGenericParameterTypes();
        for (Type t:genericParameterTypes) {
            System.out.println(t);
            if(t instanceof ParameterizedType){//如果泛型是参数化类型
                Type[] actualType=((ParameterizedType) t).getActualTypeArguments();//获取真实类型
                for (Type type : actualType) {
                    System.out.println(type);
                }
            }
        }
        //获取参数类型
        Type genericReturnType = a.getGenericReturnType();
        System.out.println(genericReturnType);
            if(genericReturnType instanceof ParameterizedType){
                Type[] actualType=((ParameterizedType) genericReturnType).getActualTypeArguments();
                for (Type type : actualType) {
                    System.out.println(type);
                }
            }
    }
}

12、通过反射获取注解

//通过反射操作注解
public class test06 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c = Class.forName("com.company.reflection.student2");
        //获取类上的注解
        Annotation[] annotations = c.getDeclaredAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
        //获取注解的值
        Table table= (Table)c.getAnnotation(Table.class);
        System.out.println(table.value());
        //先获取字段,通过字段获取字段上的注解,再获取注解上的值
        Field name = c.getDeclaredField("name");
        Filed annotation = name.getAnnotation(Filed.class);
        System.out.println(annotation.columnName());
        System.out.println(annotation.length());
        System.out.println(annotation.type());
    }
}
@Table("db_student")
class student2{
    @Filed(columnName = "db_id",type = "int",length = 10)
    private int id;
    @Filed(columnName = "db_age",type = "int",length = 4)
    private int age;
    @Filed(columnName = "db_name",type = "varchar",length = 5)
    private String name;
    public student2() {
    }
    public student2(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Table{
    String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Filed{
    String columnName();
    String type();
    int length();
}

13、类的内存分析

  • 加载:将class文件加载到内存中,生成Class对象

  • 链接:将java的字节码文件合并到JVM中,静态变量初始化

  • 初始化:将类变量的赋值动作与静态代码块合并

public class Main {

    public static void main(String[] args) {
   // write your code here
        //获取cpu核数
        //cpu密集型    I/O密集型
        System.out.println(Runtime.getRuntime().availableProcessors());
        A a=new A();
    }
}
class A{

    static {
         m=100;
    }
    private static int m=300;
    public A(){
        System.out.println(m);
    }
}

内存分析:
image

posted @   阿落小世界  阅读(162)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示