当前位置:首页 > Java技术 > Java反射机制

Java反射机制

2022年11月09日 09:07:53Java技术6

大家好呀!我是小笙!本节我和大家分享一下反射的基础知识!我们也将结束javaSe基础1.0版本的学习总结

反射

反射机制

什么是反射?

反射就是Reflection,Java的反射是指程序在运行期可以拿到一个对象的所有信息。这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制

反射就是把java类中的各种成分(成员变量,方法,构造器等等类的成员)映射成一个个的Java对象

反射的优缺点

优点:可以动态的创建和使用对象,使用灵活(框架底层核心)

缺点:使用反射基本是解释执行,对执行的效率有很大的影响

class类

Class类的实例表示java应用运行时的类或接口(每个java类运行时都在JVM里表现为一个class对象,可通过类名.class、类型.getClass()、Class.forName(“类名”)等方法获取class对象

// 总结
// 1.注意Class类和class关键字的区别
// 2.私有构造函数,只有 Java 虚拟机会创建 Class 对象
// 3.每个通过关键字class标识的类,在内存中有且只有一个与之对应的Class对象来描述其类型信息,无论创建多少个实例对象,其依据的都是用一个Class对象
public final class Class<T> implements java.io.Serializable,
                              GenericDeclaration,
                              Type,
                              AnnotatedElement,
                              TypeDescriptor.OfField<Class<?>>,
                              Constable {
     
    private static final int ANNOTATION= 0x00002000;
    private static final int ENUM      = 0x00004000;
    private static final int SYNTHETIC = 0x00001000;

    private static final ClassDesc[] EMPTY_CLASS_DESC_ARRAY = new ClassDesc[0];

    private static native void registerNatives();
    static {
     
        registerNatives();
    }

    /*
     * Private constructor. Only the Java Virtual Machine creates Class objects.
     * This constructor is not used and prevents the default constructor being
     * generated.
     * 私有构造函数,只有 Java 虚拟机会创建 Class 对象。不使用此构造函数并阻止生成默认构造函数。
     */
    private Class(ClassLoader loader, Class<?> arrayComponentType) {
     
        // Initialize final field for classLoader.  The initialization value of non-null
        // prevents future JIT optimizations from assuming this final field is null.
        classLoader = loader;
        componentType = arrayComponentType;
    }

类加载阶段

// 代码示例
class Cat{
     
	private String name;
	public Cat(){
     }
	public void hi(){
     }
}

Java反射机制 _ JavaClub全栈架构师技术笔记

类加载的生命周期

类加载的过程包括了加载验证准备解析初始化五个阶段

注意:加载验证准备初始化四个阶段的开始顺序是依次如此,但是在运行中会交叉运行程序(如:相互调用);解析阶段可能会出现在初始化之后(为了支持动态绑定)

Java反射机制 _ JavaClub全栈架构师技术笔记

类的加载示例(图片

Java反射机制 _ JavaClub全栈架构师技术笔记

反射的使用

Class类的对象获取

  • 根据类名:类名.class
  • 根据对象:对象.getClass()
  • 根据全限定类名:Class.forName(全限定类名)
public class Reflection01 {
     
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
     
        // 测试用例
        // 1.forName()
        // (1)获取Class对象的一个引用,但引用的类还没有加载(该类的第一个对象没有生成)就加载了这个类。
        // (2)为了产生Class引用,forName()立即就进行了初始化。
        System.out.println("forName: "+Class.forName("com.Al_tair.reflection.Cat")); // forName: class com.Al_tair.reflection.Cat
        
        // 2.Object-getClass() 获取Class对象的一个引用,返回表示该对象的实际类型的Class引用。
        System.out.println("getClass: "+new Cat().getClass()); // getClass: class com.Al_tair.reflection.Cat
        
        // 3.getName() 取全限定的类名(包括包名),即类的完整名字。
        System.out.println("getName: "+com.Al_tair.reflection.Cat.class); // getName: class com.Al_tair.reflection.Cat
        
        // 4.getSimpleName() 获取类名(不包括包名)
        System.out.println("getSimpleName: "+ new Cat().getClass().getSimpleName()); // getSimpleName: Cat
        
        // 5.getCanonicalName() 获取全限定的类名(包括包名)
        System.out.println("getCanonicalName: "+ new Cat().getClass().getCanonicalName()); // getCanonicalName: com.Al_tair.reflection.Cat
        
        // 6.isInterface() 判断Class对象是否是表示一个接口
        System.out.println("isInterface: "+ new Cat().getClass().isInterface()); // isInterface: false
        System.out.println("isInterface: "+ Fly.class.isInterface()); // isInterface: true
        
        // 7.getInterfaces() 返回Class对象数组,表示Class对象所引用的类所实现的所有接口。
        for (Class list:new Cat().getClass().getInterfaces()){
     
            System.out.println(list); // interface com.Al_tair.reflection.Fly
        }
       
        // 8.getSuperclass() 返回Class对象,表示Class对象所引用的类所继承的直接基类。应用该方法可在运行时发现一个对象完整的继承结构。
        System.out.println("getSuperclass"+new Cat().getClass().getSuperclass()); // getSuperclassclass com.Al_tair.reflection.Animal
        
        // 9. getFields() 获得某个类的所有的公共(public)的字段,包括继承自父类的所有公共字段。 类似的还有getMethods和getConstructors。
        //    getDeclaredFields 获得某个类的自己声明的字段,即包括public、private和proteced,默认但是不包括父类声明的任何字段
        Cat  cat = Cat.class.newInstance();
        for (Field f: cat.getClass().getFields()) {
     
            System.out.print(f.getName()+" "); // name color age 
        }
    }
}
interface Fly{
     
}
class Animal{
     
    public int age;
}
class Cat extends Animal implements Fly {
     
    public String name = "";
    public String color;

    public Cat() {
     
    }

    public Cat(String name, String color, int age) {
     
        this.name = name;
        this.color = color;
        this.age = age;
    }

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

Constructor类及其用法

Class类与Constructor相关的主要方法如下:

Java反射机制 _ JavaClub全栈架构师技术笔记

关于Constructor类本身一些常用方法如下(仅部分,其他可查API)

Java反射机制 _ JavaClub全栈架构师技术笔记

我在这里就不大篇幅的讲述Constructor类的大量方法,用代码举例一些常用方法如下

public class Constructor01 {
     
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
     
        Class cls = new Person().getClass();
        Person p = (Person)cls.newInstance(); // 调用无参构造器
        System.out.println(p); // User{age=18, name='lns'}

        // 调用public修饰的有参构造器
        Constructor con = cls.getConstructor(String.class);
        Person p2 = (Person)con.newInstance("zlr");
        System.out.println(p2); // User{age=18, name='zlr'}

        // 调用非public修饰的有参构造器
        Constructor decCon = cls.getDeclaredConstructor(int.class,String.class);
        decCon.setAccessible(true); // 设置爆破,突破访问权限
        Person p3 = (Person)decCon.newInstance(12,"zlr"); 
        System.out.println(p3); // User{age=12, name='zlr'}
    }
}

class Person {
     
    private int age = 18;
    private String name = "lns";
    public Person() {
     
        super();
    }
    public Person(String name) {
     
        super();
        this.name = name;
    }

    private Person(int age, String name) {
     
        super();
        this.age = age;
        this.name = name;
    }

    public int getAge() {
     
        return age;
    }

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

    public String getName() {
     
        return name;
    }

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

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

Field类及其用法

Class类与Field对象相关方法如下:

Java反射机制 _ JavaClub全栈架构师技术笔记

关于Field类还有其他常用的方法如下:

Java反射机制 _ JavaClub全栈架构师技术笔记

我在这里就不大篇幅的讲述Field类的大量方法,用代码举例一些常用方法如下

public class Field01 {
     
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
     
        Class<?> cls = Class.forName("com.Al_tair.reflection.Student");
        Student s = (Student)cls.newInstance();
        Field age = cls.getField("age");
        // 设置age属性值(public修饰)
        age.set(s,12);
        System.out.println(s.toString()); // Student{age=12, name='lns'}

        Field name = cls.getDeclaredField("name");
        name.setAccessible(true); // 爆破私有属性
        // 设置name属性(私有属性)
        name.set(s,"zlr");
        System.out.println(s.toString()); // Student{age=12, name='zlr'}

    }
}

class Student {
     
    public int age = 18;
    private String name = "lns";

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

Method类及其用法

Class类获取Method对象相关的方法:

Java反射机制 _ JavaClub全栈架构师技术笔记

常用方法如下:

Java反射机制 _ JavaClub全栈架构师技术笔记

我在这里就不大篇幅的讲述Method类的大量方法,用代码举例一些常用方法如下

public class Method01 {
     
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
     
        // method.setAccessible(true) 私有方法爆破
        // 访问: method.invoke(object,实参列表) 注意:静态方法的话object对象可以填写成null
        Class<?> cls = Class.forName("com.Al_tair.reflection.car");
        car c = (car)cls.newInstance();
        System.out.println(c.toString()); // car{OilPer=0.6, name='玛莎拉蒂'}
        // 获取的方法的名字和形参类型
        Method name = cls.getMethod("setName", String.class);
        // 传入形参(该方法是公有方法)
        name.invoke(c, "红旗");
        System.out.println(c.toString()); // car{OilPer=0.6, name='红旗'}

        //  getDeclaredMethod 可以是公有的方法也可以是私有的方法
        Method addOil = cls.getDeclaredMethod("addOil", double.class);
        // 私有方法爆破
        addOil.setAccessible(true);
        // 传入形参(该方法是公有方法)
        addOil.invoke(c,1.0);
        System.out.println(c.toString()); // car{OilPer=1.0, name='红旗'}


    }
}

class car{
     
    private double OilPer = 0.6; // 油量60%
    private String name = "玛莎拉蒂";

    private void addOil(double oilPer){
     
        this.OilPer = oilPer;
    }

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

    @Override
    public String toString() {
     
        return "car{" +
                "OilPer=" + OilPer +
                ", name='" + name + '\'' +
                '}';
    }
}

相关面试题

1. Java反射在实际项目中有哪些应用场景?

  • 使用JDBC时,如果要创建数据库的连接,则需要先通过反射机制加载数据库的驱动程序;
  • 多数框架都支持注解/XML配置,从配置中解析出来的类是字符串,需要利用反射机制实例化;
  • 面向切面编程(AOP)的实现方案,是在程序运行时创建目标对象的代理类,这必须由反射机制来实现。

作者:Al_tair
来源链接:https://blog.csdn.net/Al_tair/article/details/123696745

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。


本文链接:https://www.javaclub.cn/java/68744.html

分享给朋友:

“Java反射机制” 的相关文章

java基础知识讲解(一)数据类型和运算符

java基础知识讲解(一)数据类型和运算符

Java是一种强类型语言,每个变量都必须声明其数据类型。 Java的数据类型可分为两大类:基本数据类型(primitive data type)和引用数据类型(reference data type)。 Java中定义了3类8种基本数据类型 数值型- b...

枚举法 之Java实现凑硬币

问题? 如何利用1元五元十元凑硬币 Scanner in=new Scanner(System.in); int amout ; amout=in.nextInt(); for(int one =0;one<=amout;one+...

java中将英尺换算为身高

java中将英尺换算为身高

直接上代码 如图所示便是身高的换算,你学到了吗?、 int foot; double inch; Scanner in=new Scanner(System.in); foot=in.nextInt(); inch=in.nextDouble...

动车上的书摘-java对象流与序列化

动车上的书摘-java对象流与序列化

动车上的书摘-java对象流与序列化摘要: 摘要: 原创出处: http://www.cnblogs.com/Alandre/ 泥沙砖瓦浆木匠 希望转载,保留摘要,谢谢!钢笔不限贵便宜,书法是来自心对手的交流。-泥沙砖瓦浆木匠 一.对象序列化当需要存储相同类型的数据,选...

java总结文章

java总结文章

java总结文章 原创地址: http://www.cnblogs.com/Alandre/ (泥沙砖瓦浆木匠),需要转载的,保留下! Thanks Talk is cheap. Show me the...

JAVA的文件操作【转】

11.3 I/O类使用          由于在IO操作中,需要使用的数据源有很多,作为一个IO技术的初学者,从读写文件开始学习IO技术是一个比较好的选择。因为文件是一种常见的数据源,而且读写文件也是程...

java IO流学习总结

java IO流学习总结

java IO流学习总结 近期学习了Java的IO流,尝试着总结一下。 java.io 包下的IO流很多: 其中,以Stream结尾的为字节流,以Writer或者Reader结尾的为字符流。所有的输入流都是抽象类IuputStream(字节输入流)或者抽象类R...

JAVA IO 以及 NIO 理解

JAVA IO 以及 NIO 理解

由于Netty,了解了一些异步IO的知识,JAVA里面NIO就是原来的IO的一个补充,本文主要记录下在JAVA中IO的底层实现原理,以及对Zerocopy技术介绍。 IO,其实意味着:数据不停地搬入搬出缓冲区而已(使用了缓冲区)。比如,用户程序发起读操作,导致“ syscall...

Java 单例模式详解

java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种。   单例模式有一下特点:   1、单例类只能有一个实例。   2、单例类必须自己自己创建自己的唯一实例。   3、单例类必须给所有其他对象提供这一实例。 概念:  jav...

Java 基础【06】 Super 用法

     路漫漫其修远兮,吾将上下而求索。——屈原《离骚》      昨天写this用法总结的时候,突然产生了一个问题,请教别人之后,有了自己的一点认识。还是把它写下来,为大家更好的认识提供一点思路。 1)有人写了...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。