代码编织梦想

反射机制

        指的是可以于运行时加载、探知、使用编译期间完全未知的类。

        程序在运行状态中,可以动态加载一个只有名称的类,对于任意一个 已加载的类,都能够知道这个类的所有属性和方法;对于任意一个对 象,都能够调用它的任意一个方法和属性:

Class c = Class.forName("Path")

        加载完类之后,在堆内存中,就产生了一个Class类型的对象(一个类只有一个Class 对象),这个对象就包含了完整的类的结构信息,我们可以通过这个对象看到类的结构,这个对象就像一面镜子。所以,我们形象的称之为:反射。

常见用法:

• 动态构造类的反射对象

/*
   测试各种类型对应的java.lang.Class对象的获取方式
 */
@SuppressWarnings("all")
public class Demo01 {

    public static void main(String[] args) {
        String path = "SAMPLE.反射机制.User";
        try {
            //一个类被加载后,JVM会创建一个对应该类的Class对象,类的整个结构信息会放到对应的Class对象中。
            //这个Class对象就像一面镜子一样,通过这面镜子我可以看到对应类的全部信息。
            Class clazz = Class.forName(path);
            //一个类只对应一个Class对象,都具有相同的哈希码
            Class clazz2 = Class.forName(path);
            System.out.println(clazz.hashCode());
            System.out.println(clazz2.hashCode());

            //相同类型为同一个对象
            Class strClazz = String.class;
            Class strClazz2 = "I'm msg".getClass();
            System.out.println(strClazz==strClazz2);

            int[] arr01 = new int[10];
            int[][] arr02 = new int[30][3];
            double[] arr04 = new double[10];
            System.out.println(arr01.getClass().hashCode());
            System.out.println(arr02.getClass().hashCode());
            System.out.println(arr04.getClass().hashCode());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

• 动态获取类的信息(属性、方法、构造器)

import java.lang.reflect.*;
/*
   利用用反射获取类的信息(类的名字、属性、方法、构造器等)
 */
public class Demo02 {
    public static void main(String[] args) {
        String path = "SAMPLE.反射机制.User";
        try {
            Class clazz = Class.forName(path);

            //获取类的名字
            System.out.println(clazz.getName());//获得包名+类名:com.bjsxt.test.bean.User
            System.out.println(clazz.getSimpleName());	//获的类名:User

            //获取属性信息
			Field[] fields = clazz.getFields(); //只能获得public的field

            fields = clazz.getDeclaredFields();//获得所有的field

            Field f = clazz.getDeclaredField("uname");//按命名获取属性

            //获取方法信息
            Method[] methods = clazz.getDeclaredMethods();
            Method m01 = clazz.getDeclaredMethod("getUname", null);//按命名、形参获取方法

            Method m02 = clazz.getDeclaredMethod("setUname", String.class);//如果方法有参,则必须传递参数类型对应的class对象

            //获得构造器信息
            Constructor[] constructors = clazz.getDeclaredConstructors();

            Constructor c = clazz.getDeclaredConstructor(int.class,int.class,String.class);//按构造方法的形参获取

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

• 动态调用类的任意方法、构造器、属性

import java.lang.reflect.*;
import SAMPLE.反射机制.User;
/*
   通过反射对对象进行动态的操作
 */
public class Demo03 {
    public static void main(String[] args) {
        String path = "SAMPLE.反射机制.User";
        try {
            Class<User> clazz = (Class<User>) Class.forName(path);

            //通过反射API调用构造方法,构造对象
            User u = clazz.newInstance();// 其实是调用了User的无参构造方法

            Constructor<User> c = clazz.getDeclaredConstructor(int.class,int.class,String.class);
            User u2 = c.newInstance(1001,18,"name1");
            System.out.println(u2.getUname());

            //通过反射API调用普通方法
            User u3 = clazz.newInstance();
            Method method = clazz.getDeclaredMethod("setUname", String.class);
            method.invoke(u3, "name3");// u3.setUname("name3");
            System.out.println(u3.getUname());

            //通过反射API操作属性
            User u4 = clazz.newInstance();
            Field f = clazz.getDeclaredField("uname");
            f.setAccessible(true); // 这个属性不需要做安全检查了,可以直接访问
            f.set(u4, "name4");	// 通过反射直接写属性
            System.out.println(u4.getUname());	//通过反射直接读属性的值
            System.out.println(f.get(u4));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

• 获取泛型信息

package SAMPLE.反射机制;
import java.lang.reflect.*;
import java.util.*;
/*
   通过反射获取泛型信息
 */
public class Demo04 {
    public void test1(Map<String,User> map,List<User> list){
        System.out.println("Demo04.test1()");
    }

    public Map<Integer,User> test2(){
        System.out.println("Demo04.test2()");
        return null;
    }

    public static void main(String[] args) {
        try {
            //获得指定方法参数泛型信息
            Method m = Demo04.class.getMethod("test1", Map.class,List.class);
            Type[] t = m.getGenericParameterTypes();
            for (Type paramType : t) {
                System.out.println("方法的形参为:"+paramType);
                if(paramType instanceof ParameterizedType){
                    Type[] genericTypes = ((ParameterizedType) paramType).getActualTypeArguments();
                    System.out.println("形参的泛型为:");
                    for (Type genericType : genericTypes) {
                        System.out.println(genericType);
                    }
                }
            }
            System.out.println("----------------");
            //获得指定方法返回值的泛型信息
            Method m2 = Demo04.class.getMethod("test2", null);
            Type returnType = m2.getGenericReturnType();
            System.out.println("返回值类型为:"+returnType);
            if(returnType instanceof ParameterizedType){
                Type[] genericTypes = ((ParameterizedType) returnType).getActualTypeArguments();
                System.out.println("返回值的泛型为:");
                for (Type genericType : genericTypes) {
                    System.out.println(genericType);
                }
            }

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

• 获取注解

import java.lang.annotation.Annotation;
/*
   通过反射获取注解信息
 */
public class Demo05 {
    public static void main(String[] args) {

        try {
            Class clazz = Class.forName("");

            //获得类的所有有效注解
            Annotation[] annotations=clazz.getAnnotations();
            for (Annotation a : annotations) {
                System.out.println(a);
            }
            /*获得类的指定的注解
            注解名称 annotation = (注解名称) clazz.getAnnotation(注解名称.class);
            */

            /*获得类的属性的注解
            Field f = clazz.getDeclaredField("studentName");
            注解名称 annotation = f.getAnnotation(注解名称.class);
            */

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

• 反射效率的比较

import java.lang.reflect.Method;
/*
   通过跳过安全检查,提高反射效率
   三种执行方法的效率差异比较
 */
public class Demo06 {

    public static void test01(){
        User u = new User();

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000L; i++) {
            u.getUname();
        }
        long endTime = System.currentTimeMillis();

        System.out.println("普通方法调用,执行10亿次,耗时:"+(endTime-startTime)+"ms");
    }

    public static void test02() throws Exception{//需执行安全检查
        User u = new User();
        Class clazz = u.getClass();
        Method m = clazz.getDeclaredMethod("getUname", null);

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000L; i++) {
            m.invoke(u, null);
        }
        long endTime = System.currentTimeMillis();

        System.out.println("反射动态方法调用,执行10亿次,耗时:"+(endTime-startTime)+"ms");
    }

    public static void test03() throws Exception{//不需要执行访问安全检查
        User u = new User();
        Class clazz = u.getClass();
        Method m = clazz.getDeclaredMethod("getUname", null);
        m.setAccessible(true);

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000L; i++) {
            m.invoke(u, null);
        }
        long endTime = System.currentTimeMillis();

        System.out.println("反射动态方法调用,跳过安全检查,执行10亿次,耗时:"+(endTime-startTime)+"ms");
    }
    public static void main(String[] args) throws Exception {
        test01();// 2s
        test02();// 60s
        test03();// 15s
    }
}

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_57389269/article/details/119105825

java反射机制初步了解_孤者拥猫的博客-爱代码爱编程

获取字节码文件的三种方法 /*获取class文件对象的三种方法(获取字节码文件对象) * A:Object类的getClass()方法 * B:数据类型的静态属性(所有数据类型都有这个属性) * C:Class类中的静态方法 */ public class Demo3 { public static void main(String[]

java的反射机制初步(java基础复习归纳系列)_cnahyz的博客-爱代码爱编程

目录 一、通过反射查看类信息 1.获得Class对象 2.获取Class中的信息 二、使用反射生成并操作对象 1.创建对象 2.调用方法 3.访问Field 一、通过反射查看类信息         Java程序中的许多对象在运行时都会出现两种类型:编译时类型和运行时类型,如Person p = new Student(),p变量编译时类

java反射初步了解_hai_zhi_wei的博客-爱代码爱编程

原文地址: https://blog.csdn.net/qq_42183409/article/details/88924176 简介 反射机制是指在运行状态中,对于任何一个类,都能够知道这个类的属性和方法;对于任何一个

java类加载机制初步了解_dandanfengyun的博客-爱代码爱编程

转自尚学堂高淇老师 类加载机制 类在运行过程中只会加载一次,类的加载和初始化 JVM将class文件加载到内存,并对数据进行校验解析和初始化,最终形成JVM可以直接使用的Java类型的过程。 加载(Loading)》(验

java之反射初步了解-爱代码爱编程

反射 基本概念 “程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”,如Python,Ruby是动态语言;显然C++,Java,C#不是动态语言,但是JAVA有着一个非常突出的动态相关机制:Reflectio

《java学习笔记》之反射机制初步-爱代码爱编程

反射机制 一.反射机制的作用 二.反射机制相关的重要的类及其常用方法 2.1 java.lang.Class: 代表整个字节码,代表一个类型,代表整个类。 (一)获取class对象的三种方法 /* * 要操作一个类的字节码,首先要获取到这个类的字节码,怎么获取java.lang.Class实例? * 三种方式 *

java反射机制的初步理解-爱代码爱编程

定义及应用场景参考:https://www.cnblogs.com/whoislcj/p/6038511.html   简单的使用: package com.test; import javax.rmi.CORBA.StubDelegate; public class User {     public String getName() {   

JAVA反射机制初步了解-爱代码爱编程

所谓反射即可以通过对象,反射出类的名称。 要了解反射机制首先明白Class类 1,所有类的对象实际上都是Class类的实例,在JAVA中Object类是一切类的父类,所有对象都可以转换为java.lang.class类型表示。2,class 类本身是没有构造方法的,要实例化Class类对象有三种方法: 1,通过使用forName()的静态方法实例化对象。

Java反射机制(初步认识)-爱代码爱编程

反射的实质: 就是在得到Class对象之后,反向获取Class对象的对象。 解读:Class的对象好比一个类,反向获取Class对象(也就是类)的对象。其中类字面常量反射,通过把xxx.class字节码文件反射回去生成编译前的类。 不清楚Class类的可以点击查看本人另一篇博文:Class与class的区别 对Class类解读: 我们通常认为类是对象

Java反射机制-初步(学习笔记)-爱代码爱编程

反射机制 反射的定义 能够分析类能力的程序称为反射(reflective),Java提供了一个反射库(reflection library)用来方便编写可以动态操作Java代码的程序 反射能用来做什么(后面依次介绍) 在运行时分析类的能力 在运行时查看对象 实现通用的数组操作代码 利用Method对象 一、CLASS对象 反射中最基础也是

Java反射机制大全-爱代码爱编程

Java反射机制 理解为什么使用反射 掌握反射的定义 掌握反射常用API及其使用 掌握基于反射获取类信息 掌握基于反射生成类的实例 了解反射优缺点及应用场景 为什么使用反射 通过案例了解为什么使用反射 了解类的执行过程 尤其是:类的加载 编译:.java文件转换成.class二进制字节码文件 加载:.class二进制字节码文件加载到内存中 1.JVM

java反射获取成员变量_java反射机制初步认识获取成员变量-爱代码爱编程

作为一个Java新人,我谈谈自己对Java反射机制的认识,给其他的Java新人以启蒙作用。通俗的讲,java的反射就是,当一个类被加载以后,Java虚拟机就会自动产生一个Class对象。通过这个Class对象我们就能获得加载到虚拟机当中这个Class对象对应的方法、成员以及构造方法的声明和定义等信息。 那么,如何获取这个Class对象呢?通常有以下几

理解java反射机制,java反射机制介绍和理解-爱代码爱编程

Java反射机制是Java程序在运行状态下,动态获取类中的内容以及动态调用对象的方法。此篇是对Java反射机制的一些基础代码操作的简单总结。 1.Java反射机制概述 Java反射机制就是在Java程序运行时,得到一个java类中的属性和方法;并可以调用已经给定对象的类中的构造方法、属性和方法。放射机制就是就像这样动态的获取类中构造方法、属性和方法

JavaBase-Java反射机制-爱代码爱编程

JavaBase-Java反射机制 Java反射机制概述 概述 Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的

JAVA反射作用之初步了解①-爱代码爱编程

开门见山。这篇文章我们来讨论的内容是JAVA反射机制的作用。 当一个类被加载以后,Java虚拟机就会自动产生一个Class对象。通过这个Class对象我们就能获得加载到虚拟机当中这个Class对象对应的方法、成员以及构造方法的声明和定义等信息。 因此通过反射机制我们可以在运行过程中获取某一个对象的所属类的全部信息。这就是最重要的!!!!!!! 你让我