首页 > 编程语言 >Java反射专题

Java反射专题

时间:2024-10-13 11:52:10浏览次数:3  
标签:反射 专题 Java 对象 System cls Class 加载

目录

一.反射机制

1.Java Reflection

2.反射相关的主要类

3.反射的优缺点

4.反射调用优化—关闭访问检查

二.Class类

1.基本介绍

2.常用方法

3.获取Class对象的方式

4.那些类型有Class对象

三.类加载

1.介绍

2.类加载时机

3.类加载各阶段

四.获取类结构的信息

1. java.lang.Class类

2. java.lang.reflect.Field类

五.反射暴破

1.介绍

2.反射暴破构造器

3.反射暴破操作属性

4.反射暴破操作方法


一.反射机制

1.Java Reflection

反射机制允许程序在执行期借助于ReflectionAPI获取任何类的内部信息(比如成员变量,构造器,成员方法等),并能操作对象的属性及方法。反射在设计模式和框架底层都会用到。

加载完类后,在堆中就产生了一个Class类型的对象,这个对象包含了类的完整结构信息。通过这个对象得到类的结构。

下面是反射的原理图:

后面的内容也会用到这个图。

2.反射相关的主要类

说明

java.lang.Class代表一个类,Class对象表示某个类加载后在堆中的对象
java.lang.reflect.Method代表类的方法,Method对象表示某一个类的方法
java.lang.reflect.Field代表类的成员变量,Field对象表示某个类的成员变量
java.lang.reflect.Constructor代表类的构造方法,Constructor对象表示构造器

3.反射的优缺点

优点:可以动态的创建和使用对象(也是框架底层核心),使用灵活,没有反射机制,框架技术就失去底层支撑。

缺点:使用反射基本是解释执行,对执行速度有影响。

4.反射调用优化—关闭访问检查

Method、Field和Constructor对象都有setAccessible()方法。setAccessible()的作用是启动和禁用访问安全检查的开关。参数为true表示反射的对象在使用是取消访问检查,提高反射的效率。参数为false则表示反射的对象执行访问检查。

二.Class类

1.基本介绍

Class也是类,也继承于Object类。Class类不是new出来的,而是系统创建的。对于某一个类的Class对象,在内存中只有一份,因此类只加载一次。每个类的实例都会记得自己是由哪个Class实例所完成。通过Class对象可以完整地得到一个类的完整结构。类的字节码二进制数据,是放在方法区的。

2.常用方法

方法说明
forName(String name)返回指定类名 name 的 Class 对象
newInstance()调用缺省构造函数,返回给Class对象的一个实例
getName()返回此Class对象所表示的实体名称
getSuperClass()返回当前Class对象的父类的Class对象
getInterfaces()获取当前Class对象的接口
getClassLoader()返回该类的类加载器
getSuperclass()返回表示此Class所表示的实体的超类的Class
getConstructors()返回一个包含某些Constructor对象的数组
getDeclaredFields()返回Field对象的一个数组
getMethod(String name,Class ...paramType)返回一个Method对象,此对象的形参类型为paramType

应用示例:

String classAllPath="newBag.Cat";
//1.获取Cat类 对应的Class对象
Class<?> cls = Class.forName(classAllPath);
//2.输出cls
System.out.println(cls);    //显示cls对象,是哪个类的Class对象
System.out.println(cls.getClass());     //输出cls运行类型
//3.得到包名
System.out.println(cls.getPackage().getName());
//4.得到全类名
System.out.println(cls.getName());
//5.通过cls创建对象实例
Cat cat=(Cat) cls.newInstance();
System.out.println(cat);
//6.通过反射获取属性brand
Field name = cls.getField("name");
System.out.println(name.get(cat));
//7.通过反射给属性赋值 name
name.set(cat,"大橘");
System.out.println(name.get(cat));
//8.得到所有的属性(字段)
Field[] fields = cls.getFields();
for(Field f:fields){
    System.out.println(f.getName());
}

3.获取Class对象的方式

1)已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法 forName() 获取。应用场景:多用于配置文件,读取类全路径,加载类。

补充:全类名(Fully Qualified Class Name)是一个类的完整名称,它包含了类所在的包名以及类名本身。全类名的目的是在整个Java程序或Java环境中唯一地标识一个类。

String classAllPath="newBag.Cat";
Class cls=Class.forName(classAllPath);

2)若已知具体的类,通过类的class获取,该方法最为安全可靠,程序性能最好。应用场景:多用于参数传递,比如通过反射得到对应构造器对象。

Class cls=类名.class;
Class cls= Cat.class;

3)已知某个类的实例,调用该实例的getClass()方法获取。应用场景:通过创建好的对象,获得Class对象。

Cat cat = new Cat();
Class cls = cat.getClass();

4)通过类加载器获取。

ClassLoader cl=对象.getClass().getClassLoader();
Class clazz=cl.loadClass("类的全类名");

String classAllPath="newBag.Cat";
Cat cat = new Cat();
ClassLoader classLoader = cat.getClass().getClassLoader();
Class cls = classLoader.loadClass(classAllPath);

5)基本数据(int等)使用 Class cls=基本数据类型.class;

Class cls=基本数据类型.class;
Class<Integer> integerClass = int.class;

基本数据类型对应的包装类,使用 Class cls=包装类.TYPE;

Class cls=包装类.TYPE;
Class<Integer> type = Integer.TYPE;

4.那些类型有Class对象

1)外部类,成员内部类,静态内部类,局部内部类,匿名内部类;2)interface:接口;3)数组;4)enum:枚举;5)annotation:注解;6)基本数据类型;7)void。

三.类加载

1.介绍

反射机制是Java实现动态语言的关键,也就是通过反射实现类动态加载。

加载有两种类型:

静态加载:编译时加载相关的类,如果没有则报错,依赖性太强。

例子:

public static void main(String[] args){
    Scanner scan=new Scanner(System.in);
    String str=scan.nextLine();
    switch (str){
        case "1":
            Dog dog=new Dog();
            break;
        case "2":
            System.out.println("输入了2");
            break;
    }
}

我们并没有写Dog类,搜易编译器会报错,告诉我们没有Dog类。这就是静态加载,即在编译时就加载了,没有写直接告诉我们错了。

动态加载:运行时加载需要的类,如果运行时不用该类,即使不存在也不会报错,降低了依赖性。

例子:

public static void main(String[] args) throws ClassNotFoundException {
    Scanner scan=new Scanner(System.in);
    String str=scan.nextLine();
    switch (str){
        case "1":
            System.out.println("输入了1");
            break;
        case "2":
            Class cat = Class.forName("Cat");
            break;
    }
}

我们没有写Cat类,但是编译器不会报错。接着我们运行代码,只要我们不选2,就不会报错。只有选了2,才会出现错误。这就是动态加载,不用就没事。

2.类加载时机

1)当创建对象时(new)进行静态加载;

2)当子类被加载时,父类也加载(静态加载);

3)调用类中的静态成员时进行静态加载;

4)通过反射加载类是动态加载。

3.类加载各阶段

3.1 加载

JVM在该阶段的主要目的是将字节码从不同的数据源(可能是class文件、jar包等)转化为二进制字节流加载到内存中,并生成一个代表该类的java.lang.Class对象

3.2 验证

目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机本身的安全。包含:文件格式验证(是否以oxcafebabe开头)、元数据验证、字节码验证和符合引用验证

3.3 准备

JVM会在该阶段对静态变量,分配内存并默认初始化(对应数据类型的默认初始值,如0、0L、null、false等)。这些变量所使用的内存都将在方法区中进行分配

//n1是实例属性,不是静态变量,在准备阶段不会分配内存
public int n1=10;
//n2是静态变量,分配内存;n2默认初始化为0,而不是10
public static int n2=10;

3.4 解析

虚拟机将常量池内的符号引用替换为直接引用的过程

3.5 初始化

到初始化阶段,才真正开始执行类中定义的Java程序代码,此阶段是执行<clinit>()方法的过程。

什么是<clinit>()方法呢?

<clinit>()方法是由编译器按语句在源文件中出现的顺序,依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,并进行合并。

四.获取类结构的信息

1. java.lang.Class类

方法说明
getName()获取全类名
getSimpleName()获取简单类名
getFields获取所有public修饰的属性,包含本类以及父类的
getDeclaredFields获取本类中的所有属性
getMethods获取所有public修饰的方法,包含本类以及父类的
getDeclaredMethods获取本类中所有方法
getConstructors获取所有public修饰的构造器,包含本类,没有父类
getDeclaredConstructors获取本类中所有构造器
getPackage以Package形式返回 包信息
getSuperClass以Class形式返回父类信息
getInterfaces以Class[]形式返回接口信息
getAnnotations以Annotation[]形式返回注解信息

2. java.lang.reflect.Field类

方法说明
getModifiers以int形式返回修饰符 ,返回0是默认修饰符,1是public,2是private,4是protected,8是static,16是final
getType以Class形式返回类型
getName返回属性名

五.反射暴破

1.介绍

首先我要知道这个反射暴破是干什么的?

暴破即暴力破解,我们可以通过暴破操作一些私有属性(private)的构造器、属性和方法。

2.反射暴破构造器

Class类相关方法:

newInstance:调用类中的无参构造器,获取对应类的对象

getConstructor(Class...):根据参数列表,获取对应的构造器对象

getDecalaredConstructor(Class...):根据参数列表,获取对应构造器对象

Constructor类相关方法:

setAccessible:暴破

newInstance(Object...):调用构造器

//例子
Class<?> cls = Class.forName("User");

Constructor<?> constructor = cls.getDeclaredConstructor(String.class, int.class);

constructor.setAccessible(true);

Object o = constructor.newInstance("Tom", 13);

System.out.println(o);

3.反射暴破操作属性

暴破:setAccessible(true)。

访问:set(o,值)和get(o)。

如果属性是静态的,set和get中的参数o可以写成null。

Class<?> cls = Class.forName("Person");

Object o = cls.getConstructor(String.class, int.class).newInstance("Tom", 0);

Field age = cls.getDeclaredField("age");

age.setAccessible(true);

age.set(o,14);

System.out.println(o);

4.反射暴破操作方法

暴破:setAccessi(true);

访问:invoke(o,参数列表);如果是静态方法,这里的o可以换从null

Class<?> student = Class.forName("Student");

Method getIm = student.getDeclaredMethod("getIm", int.class, String.class);

getIm.setAccessible(true);

getIm.invoke(null,13,"Tom");

//下面是getIm方法
private static void getIm(int age,String s){
    System.out.println(age+" "+s);
}

标签:反射,专题,Java,对象,System,cls,Class,加载
From: https://blog.csdn.net/lllsure/article/details/142703976

相关文章

  • JavaScript中的DOM和Timer(简单易用的基本操作)
    JavaScript中的DOM和Timer基本操作DOM操作传统的选择器选择器idvarelements=document.getElementById(id的名称);例如:varelements=document.getElementById("test");选择id为test的标签选择器classvarelements=document.getElementsByClassName(class的名称);......
  • 基于Java的ATM机模拟程序设计与实现
    一、引言随着金融行业的发展,ATM机已经成为人们日常生活中不可或缺的一部分。为了更好地理解ATM机的工作原理,本文设计并实现了一个基于Java的ATM机模拟程序。该程序通过模拟ATM机的操作流程,使用户能够体验到ATM机的基本功能。二、系统设计与实现1.用户登录模块用户登录模块......
  • 基于Java+SSM的二手车交易网站
    项目说明网络技术和计算机技术发展至今,已经拥有了深厚的理论基础,并在现实中进行了充分运用,尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代,所以对于信息的宣传和管理就很关键。因此二手车交易信息的管理计算机化,系统化是必要的。设计开......
  • 基于Java+SSM的个性化美食推荐系统
    项目说明现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本个性化美食推荐系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提......
  • 【系统架构设计师】案例专题六(8大系统架构设计之8): 大数据架构设计考点梳理
    更多内容请见:备考系统架构设计师-核心总结目录文章目录一、传统数据处理系统存在的问题二、大数据处理系统架构分析1、大数据处理系统面临挑战2、大数据处理系统架构特征三、Lambda架构1、Lambda架构对大数据处理系统的理解2、Lambda架构应用场景3、......
  • 基于Java的百货中心管理系统的设计与实现(源码+文档+部署讲解等)
    文章目录1.前言2.详细视频演示3.程序运行示例图4.文档参考5.技术框架5.1后端采用SpringBoot框架5.2前端框架Vue5.3程序操作流程6.选题推荐7.原创毕设案例8.系统测试8.1系统测试的目的8.2系统功能测试9.代码参考10.为什么选择我?11.获取源码1.前言......
  • 一个月学会Java 第11天 面向对象——多态
    Day11面向对象——多态我们来复习一下面向对象的三大特性分别是什么,面向对象拥有的三大特性分别为继承、封装、多态。继承我们也已经学过了,就是父类和子类、封装其实也学过了其实就是访问修饰符和包,主要的作用为更好的封装我们接下来要讲的多态则是面向对象的最难点,他......
  • 基于springboot的水果商城系统的设计与实现java+vue(源码+lw+部署文档+讲解等)
    背景及意义该校园水果自动售卖系统基于SpringBoot+Vue技术构建,旨在为四川旅游学院的师生提供便捷、高效的水果购买服务。对于学生和教师而言,系统提供了直观友好的用户界面。通过手机或校内的终端设备,用户可以轻松访问系统。在界面上,用户能够清晰地看到各类水果的展......
  • javascript学习——算术运算符
    算术运算符运算符是处理数据的基本方法,用来从现有的值得到新的值。JavaScript提供了多种运算符,覆盖了所有主要的运算。概述JavaScript共提供10个算术运算符,用来完成基本的算术运算。加法运算符:x+y减法运算符:x-y乘法运算符:x*y除法运算符:x/y指数运算符:x**y......
  • 基于springboot的社团管理系统java+vue项目(源码+lw+部署文档+讲解等)
    背景及意义该社团管理系统基于SpringBoot+Vue技术构建,旨在为学校或组织的社团管理提供高效、便捷的解决方案。对于社团成员而言,系统提供了便捷的参与渠道。成员可以通过系统查看社团的详细信息,包括社团简介、宗旨、活动安排等,以便更好地了解社团文化和活动内容。在......