Java基础:反射

目录

      • 一 概述
      • 二 反射的三种方式
        • 1、通过已实例化的java对象获取:xxx.getClass()
        • 2、通过类名获取:xxx.class
        • 3、通过类的全路径获取:Class.forName("xxx")
      • 三 获取并使用类的构造方法
        • 1、获取构造方法:
        • 2、调用构造方法:
      • 四 获取并设置类的成员变量
      • 五 获取并调用类的成员方法
        • 1、获取指定方法:
        • 2、调用指定方法:
      • 六 获取并调用主函数
      • 七 反射的其他用法
        • 1、通过反射运行配置文件内容
          • ——示例:
        • 2、通过反射越过泛型检查

一 概述

Java反射说的是在运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性。对于任何一个对象,我们都能够对它的方法和属性进行调用。我们把这种动态获取对象信息和调用对象方法的功能称之为反射机制。

所谓反射其实是获取类的字节码文件,也就是.class文件,通过Class这个对象进行获取。

Class 类的实例表示正在运行的 Java类和接口,jvm中每个类都有且只有一个class对象。(包括基本数据类型)

Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass 方法自动构造的。也就是这不需要我们自己去处理创建,JVM已经帮我们创建好了。

二 反射的三种方式

获取类的字节码文件有三种方式:

1、通过已实例化的java对象获取:xxx.getClass()

getClass()是Object的一个方法,Class继承了Object,所以我们可以直接使用

Travel travel=new Travel();
Class c=travel.getClass();

2、通过类名获取:xxx.class

Class c=Travel.class;

3、通过类的全路径获取:Class.forName(“xxx”)

        try {Class c=Class.forName("com.suixing.pojo.Travel")} catch (ClassNotFoundException e) {e.printStackTrace();}

因为运行期间一个类只会有一个class对象产生,所以用不同方式多次获取同一个类的class对象,所获取到是同一个class对象

三 获取并使用类的构造方法

1、获取构造方法:

1)批量的方法
public Constructor[] getConstructors():所有”公有的”构造方法
public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)

2)获取单个的方法,并调用
public Constructor getConstructor(Class… parameterTypes):获取单个的”公有的”构造方法:
public Constructor getDeclaredConstructor(Class… parameterTypes):获取”某个构造方法”可以是私有的,或受保护、默认、公有;

2、调用构造方法:

Constructor对象.newInstance(Object… initargs)

newInstance(Object… initargs):使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
它的返回值是T类型,所以newInstance是创建了一个构造方法的声明类的新实例对象。并为之调用

public static void main(String[] args) throws NoSuchMethodException {try {Class c=Class.forName("com.suixing.pojo.TestPojo");System.out.println("***************所有公有构造方法******************");Constructor[] constructors=c.getConstructors();for(Constructor constructor : constructors){System.out.println(constructor);}System.out.println("*********所有的构造方法(包括:私有、受保护、默认、公有)*********");constructors = c.getDeclaredConstructors();for(Constructor constructor : constructors){System.out.println(constructor);}System.out.println("**********获取公有、无参的构造方法***************");Constructor constructor = c.getConstructor(null);//因为是无参的构造方法所以类型是一个null,不写也可以System.out.println(constructor);System.out.println("***********获取私有构造方法,并调用*************");constructor = c.getDeclaredConstructor(Integer.class);System.out.println(constructor);constructor.setAccessible(true);//暴力访问(忽略掉访问修饰符)Object o= constructor.newInstance(21);System.out.println(o.toString());System.out.println("**************获取并调用多参数的公有构造方法***********");constructor=c.getConstructor(new Class[]{String.class,String.class,Integer.class});o= constructor.newInstance("ximou","661",21);System.out.println(o.toString());} catch (ClassNotFoundException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}

四 获取并设置类的成员变量

            //c是Class类的对象System.out.println("************获取所有公有的字段********************");Field[] fields=c.getFields();for(Field field:fields)System.out.println(field);System.out.println("************获取所有的字段********************");fields=c.getDeclaredFields();for(Field field:fields)System.out.println(field);System.out.println("**************获取私有字段并调用**************");Field field=c.getDeclaredField("name");field.setAccessible(true);field.set(o,"change name");System.out.println(o.toString());

设置字段时:需要传递两个参数,一个是实体类对象,一个是要设置的值

//f是Field对象
Object obj = stuClass.getConstructor().newInstance();
f.set(obj, “刘德华”);

五 获取并调用类的成员方法

            System.out.println("***********获取所有的”公有“方法*************");c.getMethods();Method[] methodArray = c.getMethods();for(Method m : methodArray){System.out.println(m);}System.out.println("*************获取所有的方法,包括私有的***********");methodArray = c.getDeclaredMethods();for(Method m : methodArray){System.out.println(m);}System.out.println("***************获取公有的show1()方法*******************");Method method=c.getMethod("show1",String.class);Object result=method.invoke(o,("123456"));System.out.println("return "+result);System.out.println("***************获取私有的show4()方法******************");method=c.getDeclaredMethod("show4",int.class);method.setAccessible(true);result=method.invoke(o,123);System.out.println("return "+result);System.out.println("***************获取默认的、多个参数的show3()方法******************");method=c.getDeclaredMethod("show3",String.class,int.class);method.setAccessible(true);result=method.invoke(o,"sss",123);System.out.println("return "+result);

1、获取指定方法:

需要传入至少两个参数,第一个是调用的方法名称,第二个到第n个是方法的形参类型,切记是类型。

m = stuClass.getDeclaredMethod(“show4”, int.class);

2、调用指定方法:

需要至少两个参数,一个是要调用的对象,其他的是实参

m.setAccessible(true);//对非公有方法解除私有限定
Object result = m.invoke(obj, 20);

六 获取并调用主函数

            Method method=c.getMethod("main",String[].class);method.invoke(null,(Object)new String[]{"a","b"});

七 反射的其他用法

1、通过反射运行配置文件内容

假设有两个业务类:

public class Service1 {public void doService1(){System.out.println("业务方法1");}
}
public class Service2 {public void doService2(){System.out.println("业务方法2");}
}

当需要从第一个业务方法切换到第二个业务方法的时候,若使用非反射方式,则必须修改代码,并且重新编译运行,才可以达到效果

public class CommonTest {public static void main(String[] args) {//new Service1().doService1();//必须重新修改代码new Service2().doService2();}
}

而使用反射方式则方便很多

——示例:

spring.txt

class=reflection.Service1
method=doService1

测试类

public class ReflectTest {@SuppressWarnings({ "rawtypes", "unchecked" })public static void main(String[] args) throws Exception {Properties pro= new Properties();FileReader in = new FileReader("spring.txt");//获取输入流,从spring.txt中获取类名称和方法名称pro.load(in);in.close();String className = (String) pro.get("class");String methodName = (String) pro.get("method");//根据类名称获取类对象Class clazz = Class.forName(className);//根据方法名称,获取方法对象Method m = clazz.getMethod(methodName);//获取构造器Constructor c = clazz.getConstructor();//根据构造器,实例化出对象Object service = c.newInstance();//调用对象的指定方法m.invoke(service);         }
}

2、通过反射越过泛型检查

泛型是在编译期间起作用的。在编译后的.class文件中是没有泛型的。所有比如T或者E类型啊,本质都是通过Object处理的。所以可以通过使用反射来越过泛型。

public class GenericityTest {public static void main(String[] args) throws Exception{ArrayList<String> list = new ArrayList<>();list.add("this");list.add("is");//list.add(5);报错/********** 越过泛型检查    **************///获取ArrayList的Class对象,反向的调用add()方法,添加数据Class listClass = list.getClass(); //获取add()方法Method m = listClass.getMethod("add", Object.class);//调用add()方法m.invoke(list, 5);//遍历集合for(Object obj : list){System.out.println(obj);}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/73638.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Expected a mapping or list of mappings for merging, but found scalar

最近&#xff0c;在将项目转移到CircleCI时&#xff0c;遇到了这样一个错误&#xff0c;经过调查发现都说可能的原因缩进的问题导致的&#xff0c; 例如&#xff1a; definitions:steps:- step: &prepare-build-envname: Prepare build env 这里的name和- step 行之间应…

如何使用CSS实现一个响应式图片幻灯片(Responsive Image Slider)效果?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 响应式图片幻灯片⭐ HTML结构⭐ CSS样式⭐ JavaScript交互⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个…

Astro建站教程:安装nodejs,npm下载Astro,安装扩展

下载Nodejs LTS版&#xff1a;https://nodejs.org/en 安装步骤全默认即可&#xff0c;安装路径可以根据自己的爱好更改在桌面右键打开cmd或powershell&#xff0c;输入node -v和npm -v测试是否安装成功 浏览器打开https://docs.astro.build/en/install/auto/ 复制里面的npm cre…

糖生物学要点.4- 学习指南

学习指南 转到&#xff1a; 第1章 历史背景与概述 哪些因素阻碍了聚糖生物学&#xff08;“糖生物学”&#xff09;研究与传统分子和细胞生物学的整合&#xff1f; 为什么进化反复选择聚糖作为所有细胞表面的主要分子&#xff1f; 解释细胞外聚糖和核/胞质聚糖之间的区别。 影响…

安全狗陈奋:数据安全需要建立在传统网络安全基础之上

8月22日-23日&#xff0c;由创业邦主办的“2023 DEMO WORLD 企业开放式创新大会”在上海顺利举行。 作为国内云原生安全领导厂商&#xff0c;安全狗受邀出席此次活动。 本次大会以“拥抱开放”为主题&#xff0c;聚焦开放式创新&#xff0c;通过演讲分享、专场对接、需求发布…

你用过 Maven Shade 插件吗?

文章首发地址 Maven Shade插件是Maven构建工具的一个插件&#xff0c;用于构建可执行的、可独立运行的JAR包。它解决了依赖冲突的问题&#xff0c;将项目及其所有依赖&#xff08;包括传递依赖&#xff09;合并到一个JAR文件中。 下面是对Maven Shade插件的一些详解&#xff…

day 53 | 25. K 个一组翻转链表

25. K 个一组翻转链表 面试真的碰到了&#xff0c;可惜没a出来。 没啥特殊的算法&#xff0c;就是很难绕出来感觉。 /*** Definition for singly-linked list.* type ListNode struct {* Val int* Next *ListNode* }*/ func reverseKGroup(head *ListNode, k int) *L…

初学python的感受

目录 初学感受学习计划学习目标 初学感受 刚学python的我惊讶的发现编程语言之间竟有如此多的相似之处,因此在学python的时候相对于学C语言时要轻松的多,虽然二者也有一些不同之处,但是我想只要对二者稍微区分的话应该不会搞混的,并且在学习的过程中也可以借鉴学C语言的方法去…

MySQL知识笔记——初级基础(实施工程师和DBA工作笔记)

老生长谈&#xff0c;MySQL具有开源、支持多语言、性能好、安全性高的特点&#xff0c;广受业界欢迎。 在数据爆炸式增长的年代&#xff0c;掌握一种数据库能够更好的提升自己的业务能力&#xff08;实施工程师&#xff09;。 此系列将会记录我学习和进阶SQL路上的知识&#xf…

同一台Windows机器中启动多个Memcached服务

假设Memcached在如下目录&#xff1a;C:\memcached\memcached.exe 在CMD中执行如下命令即可再安装一个Memcached服务&#xff08;记得换个端口号啊&#xff01;&#xff09;&#xff1a; sc create "Memcached Server1" start auto binPath "C:\memcached\mem…

Revit SDK 介绍:RayTraceBounce 光线反弹

前言 这个例子模拟光线反弹。 内容 通过修改参数&#xff0c;从&#xff08;0&#xff0c;0&#xff0c;0&#xff09;点向&#xff08;1&#xff0c;0&#xff0c;0&#xff09;方向射出光线&#xff0c;经过若干次反弹之后的结果。如图所示&#xff1a; 在Revit API 中&…

Codeforces-Round-895-Div-3

A. Two Vessels 题目翻译 你有两个装有水的容器。第一个容器含有 a a a克水&#xff0c;第二个容器含有 b b b克水。这两艘船都非常大&#xff0c;可以容纳任意数量的水。 您还有一个空杯子&#xff0c;最多可容纳 c c c克水。 一次&#xff0c;您可以从任何容器中舀出多 c…

go语言基本操作--四

面向对象编程 对于面向对象编程的支持go语言设计得非常简洁而优雅。因为&#xff0c;Go语言并没有沿袭面向对象编程中诸多概念&#xff0c;比如继承(不支持继承&#xff0c;尽管匿名字段的内存布局和行为类似继承&#xff0c;但它并不是继承)、虚函数、构造函数和析构函数、隐…

HTTP代理如何设置

HTTP代理是一种非常重要的网络工具&#xff0c;它可以帮助我们在访问互联网时提高访问速度&#xff0c;保护用户隐私等等。在使用HTTP代理时&#xff0c;需要先进行设置。下面就来介绍一下HTTP代理如何设置。 一、了解HTTP代理 在开始设置HTTP代理之前&#xff0c;我们需要先了…

html 标签简介

概述 标签的效果不重要&#xff0c;重要的是标签的语义。 文本标签 文本标签用于包裹&#xff1a;词汇、短语等。排版标签&#xff0c;比如div,p,h1等。排版标签更宏观&#xff08;大段的文字&#xff09;&#xff0c;文本标签更微观&#xff08;词汇、短语&#xff09;。文…

python实现根据词根词缀查询四级英语词汇

# !/usr/bin/env python # -*-coding:utf-8 -*- # File : 四级英语词汇学习.py # Time &#xff1a;2023/9/9 11:57 # Author &#xff1a;QQ736592720 import re from time import sleep from bs4 import BeautifulSoup import requests import jsondef get_w…

是的,决定放弃算法去机器学习了

可是梦想啊&#xff01;~她永存心间&#xff01;&#xff01;&#xff01; 我啊~本是执着于这些算法的怪咖&#xff0c;梦想是icpc&#xff0c;ccpc~ 可是啊~ 在以后的科研和工作中&#xff0c;这些算法很多都是用不到的&#xff0c;学习算法更重要的目的是锻炼编程能力和分析…

西门子LAD编程扫描周期带来的步序跳转问题

一、程序目的 按一下启动&#xff0c;程序进入第一步。延时五秒之后进入第二步进行自加1&#xff0c;然后回到第一步继续延时5秒循环&#xff0c;依次类推。 二、出现的问题 第一次程序进入第一步时&#xff0c;定时器正常定时&#xff0c;计数正常加1&#xff0c;但从第二轮开…

文件上传漏洞-upload靶场5-12关

文件上传漏洞-upload靶场5-12关通关笔记&#xff08;windows环境漏洞&#xff09; 简介 ​ 在前两篇文章中&#xff0c;已经说了分析上传漏的思路&#xff0c;在本篇文章中&#xff0c;将带领大家熟悉winodws系统存在的一些上传漏洞。 upload 第五关 &#xff08;大小写绕过…

【DataV/echarts】vue中使用,修改地图和鼠标点击部分的背景色

引入&#xff1a;使用 DataV 引入地图的教程是参考别人的&#xff0c;主要介绍修改地图相关的样式&#xff1b; 引入地图 是参考别人的&#xff0c;这里自己再整理一遍&#xff0c;注意需要安装 5 版本以上的 echarts&#xff1b; DataV 网址&#xff1a;https://datav.aliyun.…