当前位置: 首页 > news >正文

Java SPI思想梳理

原文出处:https://zhuanlan.zhihu.com/p/28909673

 

为什么要使用spi

面向的对象的设计里,我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则,如果需要替换一种实现,就需要修改代码。为了实现在模块装配的时候不用在程序里动态指明,这就需要一种服务发现机制。java spi就是提供这样的一个机制:为某个接口寻找服务实现的机制。这有点类似IOC的思想,将装配的控制权移到了程序之外。

以上文字从别处复制而来,想必你还是一脸懵逼,但不要慌,去搜一下spi你就会感觉更懵逼,因为你搜出来的只会是这个:

那到底啥是spi思想呢?

spi的概念

 

 

首先放个图:我们在“调用方”和“实现方”之间需要引入“接口”,可以思考一下什么情况应该把接口放入调用方,什么时候可以把接口归为实现方。

先来看看接口属于实现方的情况,这个很容易理解,实现方提供了接口和实现,我们可以引用接口来达到调用某实现类的功能,这就是我们经常说的api,它具有以下特征:

  1. 概念上更接近实现方
  2. 组织上位于实现方所在的包中
  3. 实现和接口在一个包中

当接口属于调用方时,我们就将其称为spi,全称为:service provider interface,spi的规则如下:

  1. 概念上更依赖调用方
  2. 组织上位于调用方所在的包中
  3. 实现位于独立的包中(也可认为在提供方中)

如下图所示:

(上图来自:设计原则:小议 SPI 和 API)

 

开源的案例

接下来从几个案例总结下java spi思想

 

Jdk

在jdk6里面引进的一个新的特性ServiceLoader,从官方的文档来说,它主要是用来装载一系列的service provider。而且ServiceLoader可以通过service provider的配置文件来装载指定的service provider。当服务的提供者,提供了服务接口的一种实现之后,我们只需要在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。
可能上面讲的有些抽象,下面就结合一个示例来具体讲讲。

jdk spi案例

我们现在需要使用一个内容搜索接口,搜索的实现可能是基于文件系统的搜索,也可能是基于数据库的搜索。

先定义好接口

package com.cainiao.ys.spi.learn;import java.util.List;public interface Search {public List<String> searchDoc(String keyword);   
}

文件搜索实现

package com.cainiao.ys.spi.learn;import java.util.List;public class FileSearch implements Search{@Overridepublic List<String> searchDoc(String keyword) {System.out.println("文件搜索 "+keyword);return null;}
}

数据库搜索实现

package com.cainiao.ys.spi.learn;import java.util.List;public class DatabaseSearch implements Search{@Overridepublic List<String> searchDoc(String keyword) {System.out.println("数据搜索 "+keyword);return null;}
}

接下来可以在resources下新建META-INF/services/目录,然后新建接口全限定名的文件:com.cainiao.ys.spi.learn.Search,里面加上我们需要用到的实现类

com.cainiao.ys.spi.learn.FileSearch

然后写一个测试方法

package com.cainiao.ys.spi.learn;import java.util.Iterator;
import java.util.ServiceLoader;public class TestCase {public static void main(String[] args) {ServiceLoader<Search> s = ServiceLoader.load(Search.class);Iterator<Search> iterator = s.iterator();while (iterator.hasNext()) {Search search =  iterator.next();search.searchDoc("hello world");}}
}

可以看到输出结果:文件搜索 hello world

如果在com.cainiao.ys.spi.learn.Search文件里写上两个实现类,那最后的输出结果就是两行了。
这就是因为ServiceLoader.load(Search.class)在加载某接口时,会去META-INF/services下找接口的全限定名文件,再根据里面的内容加载相应的实现类。

这就是spi的思想,接口的实现由provider实现,provider只用在提交的jar包里的META-INF/services下根据平台定义的接口新建文件,并添加进相应的实现类内容就好。

那为什么配置文件为什么要放在META-INF/services下面?
可以打开ServiceLoader的代码,里面定义了文件的PREFIX如下:

private static final String PREFIX = "META-INF/services/"

以上是我们自己的实现,接下来可以看下jdk中DriverManager的spi设计思路

DriverManager spi案例

DriverManager是jdbc里管理和注册不同数据库driver的工具类。从它设计的初衷来看,和我们前面讨论的场景有相似之处。针对一个数据库,可能会存在着不同的数据库驱动实现。我们在使用特定的驱动实现时,不希望修改现有的代码,而希望通过一个简单的配置就可以达到效果。

我们在使用mysql驱动的时候,会有一个疑问,DriverManager是怎么获得某确定驱动类的?

我们在运用Class.forName("com.mysql.jdbc.Driver")加载mysql驱动后,就会执行其中的静态代码把driver注册到DriverManager中,以便后续的使用。
代码如下:

package com.mysql.jdbc;public class Driver extends NonRegisteringDriver implements java.sql.Driver {public Driver() throws SQLException {}static {try {DriverManager.registerDriver(new Driver());} catch (SQLException var1) {throw new RuntimeException("Can't register driver!");}}
}

这里可以看到,不同的驱动实现了相同的接口java.sql.Driver,然后通过registerDriver把当前driver加载到DriverManager中
这就体现了使用方提供规则,提供方根据规则把自己加载到使用方中的spi思想

这里有一个有趣的地方,查看DriverManager的源码,可以看到其内部的静态代码块中有一个loadInitialDrivers方法,在注释中我们看到用到了上文提到的spi工具类ServiceLoader

/**
* Load the initial JDBC drivers by checking the System property
* jdbc.properties and then use the {@code ServiceLoader} mechanism
*/
static {loadInitialDrivers();println("JDBC DriverManager initialized");
}

点进方法,看到方法里有如下代码:

ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
Iterator<Driver> drivers = loadedDrivers.iterator();
println("DriverManager.initialize: jdbc.drivers = " + loadedDrivers);

可见,DriverManager初始化时也运用了spi的思想,使用ServiceLoader把写到配置文件里的Driver都加载了进来。

我们打开mysql-connector-java的jar包,果然在META-INF/services下发现了上文中提到的接口路径,打开里面的内容,可以看到是com.mysql.jdbc.Driver

其实对符合DriverManager设定规则的驱动,我们并不用去调用class.forname,直接连接就好.因为DriverManager在初始化的时候已经把所有符合的驱动都加载进去了,避免了在程序中频繁加载。

但对于没有符合配置文件规则的驱动,如oracle,它还是需要去显示调用classforname,再执行静态代码块把驱动加载到manager里,因为它不符合配置文件规则:

最后总结一下jdk spi需要遵循的规范

插件体系

eclipse插件

其实最具spi思想的应该属于插件开发,我们项目中也用到的这种思想,后面再说,这里具体说一下eclipse的插件思想。

Eclipse使用OSGi作为插件系统的基础,动态添加新插件和停止现有插件,以动态的方式管理组件生命周期。

一般来说,插件的文件结构必须在指定目录下包含以下三个文件:

  • META-INF/MANIFEST.MF: 项目基本配置信息,版本、名称、启动器等
  • build.properties: 项目的编译配置信息,包括,源代码路径、输出路径
  • plugin.xml:插件的操作配置信息,包含弹出菜单及点击菜单后对应的操作执行类等

当eclipse启动时,会遍历plugins文件夹中的目录,扫描每个插件的清单文件MANIFEST.MF,并建立一个内部模型来记录它所找到的每个插件的信息,就实现了动态添加新的插件。

这也意味着是eclipse制定了一系列的规则,像是文件结构、类型、参数等。插件开发者遵循这些规则去开发自己的插件,eclipse并不需要知道插件具体是怎样开发的,只需要在启动的时候根据配置文件解析、加载到系统里就好了,是spi思想的一种体现。

 

Spring

Spring中运用到spi思想的地方也有很多,下面随便列举几个

scan

我们在spring中可以通过component-scan标签来对指定包路径进行扫描,只要扫到spring制定的@service、@controller等注解,spring自动会把它注入容器。

这就相当于spring制定了注解规范,我们按照这个注解规范开发相应的实现类或controller,spring并不需要感知我们是怎么实现的,他只需要根据注解规范和scan标签注入相应的bean,这正是spi理念的体现。

Scope

spring中有作用域scope的概念。
除了singleton、prototype、request、session等spring为我们提供的域,我们还可以自定义scope。

像是自定义一个 ThreadScope实现Scope接口
再把它注册到beanFactory中

Scope threadScope = new ThreadScope();
beanFactory.registerScope("thread", threadScope);

接着就能在xml中使用了

<bean id=".." class=".." scope="thread"/>

spring作为使用方提供了自定义scope的规则,提供方根据规则进行编码和配置,这样在spring中就能运用我们自定义的scope了,并不需要spring感知我们scope里的实现,这也是平台使用方制定规则,提供方负责实现的思想。

自定义标签

扩展Spring自定义标签配置大致需要以下几个步骤

  1. 创建一个需要扩展的组件,也就是一个bean
  2. 定义一个XSD文件描述组件内容,也可以给bean的属性赋值啥的
  3. 创建一个文件,实现BeanDefinitionParser接口,用来解析XSD文件中的定义和对组件进行初始化,像是为组件bean赋上xsd里设置的值
  4. 创建一个Handler文件,扩展自NamespaceHandlerSupport,目的是将组件注册到Spring容器,重写其中的的init方法

这样我们就边写出了一个自定义的标签,spring只是为我们定义好了创建标签的流程,不用感知我们是如何实现的,我们通过register就把自定义标签加载到了spring中,实现了spi的思想。

 

ConfigurableBeanFactory

spring里为我们提供了许多属性编辑器,这时我们如果想把spring配置文件中的字符串转换成相应的对象进行注入,就要自定义属性编辑器,这时我们可以按照spring为我们提供的规则来自定义我们的编辑器

自定义好了属性编辑器后,ConfigurableBeanFactory里面有一个registerCustomEditor方法,此方法的作用就是注册自定义的编辑器,也是spi思想的体现

 

Hotspot

我们打开hotspot的源码,可以看到,代码分为shared和其他,shared属于引擎层,os属于不同行业的实现

点开os,可以发现里面有不同操作系统的不同实现:

不同的厂商会提供hotspot的不同实现,在hotspot启动的时候,会判断当前是什么系统来启动不同的实现,这也是一种spi的思想。

在hotspot启动时会去执行shared里的代码,除了shared的其他三个包相当于是外部的一些实现,是不同操作系统开发人员加载到hotspot中,这种分层思想已经算是spi的思想
接着我们可以在shared里看到一个createThread接口,这个接口在不同的os下实现肯定是不一样的,这就代表着hotspot制定接口,不同的os开发者去捐献实现,hotspot不用感知是如何实现的,只需要在运行时直接调用接口就好,也是spi的思想。

还有像是Jetty/Tomcat中自定义sessionManager、自定义线程池,dubbo的扩展机制等内容也属于spi

 

总结

其实在这里就可以发现,只要是能满足用户按照系统规则来自定义,并且可以注册到系统中的功能点,都带有着spi的思想

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

elementUI-Tree 树形控件的使用

elementUI-Tree 树形控件的使用 实现效果&#xff1a; 控件的官方使用说明 控件要求返回的数据结构 {"success": true,"code": 20000,"message": "成功","data": {"items": [{"id": "1394579386…...

Unity笔记--Canvas-网格重建

参考&#xff1a;&#xff08;五&#xff09;UGUI源码分析之Rebuild&#xff08;布局重建、图形重绘&#xff09; 网格重建 网格重建大体包括布局重建和图形重建两部分。 public enum CanvasUpdate{Prelayout,Layout,PostLayout,PreRender,LatePreRender,MaxUpdateValue,}每一…...

实训第一天以及第二天所学记录

实训第一天以及第二天所学记录 浏览器内核 IE&#xff1a;Trident Firefox&#xff1a;Gecko Chrome&#xff1a;Webkit / Blink Safari&#xff1a;Webkit Opera&#xff1a;Presto / Blink 在VScode中使用注释的快捷键 按住键盘的Ctrl/ 元素 &#xff08;标签 标记&…...

跨域请求

/* * Description: 配置文件 */ module.exports { publicPath: "./", devServer: { open: true, proxy: "http://106.15.179.105/api" //跨域路径 }, }; // proxy是代理的意思 // 代理跨域就是在欺骗浏览器 让浏览器认为你访问的还是 同…...

Mac os下通过Anaconda在远程服务器配置python虚拟环境

一、SSH管理软件 这里推荐一款本人正在使用的软件&#xff0c;Termius。Termius是一款非常好用而且漂亮的SSH客户端&#xff0c;能快速远程控制服务器&#xff0c;可以定制自己喜欢的主题.Termius不仅涵盖了Windows、Linux、OSX&#xff0c;还变态得支持Android和iOS&#xff…...

Android性能优化之APK优化,看看这篇文章吧!

前言 想要成为一名优秀的Android开发&#xff0c;你需要一份完备的知识体系&#xff0c;在这里&#xff0c;让我们一起成长为自己所想的那样~。 学算法真的很痛苦&#xff0c;虽然大数据现在很火&#xff0c;但找到适合自己定位的职业也未尝不是一种合理选择。 投百度的经历非…...

5G音视频时代还不学NDK开发吗?面试必问

想要成为一名优秀的Android开发&#xff0c;你需要一份完备的知识体系&#xff0c;在这里&#xff0c;让我们一起成长为自己所想的那样。 本文参考了目前大部分 Android 应用启动优化的方案&#xff0c;将大家的方案做一个汇总&#xff0c;如果你有这方面的需求&#xff0c;只…...

Labview需求(部分)

本人从事工控行业多年,有一些资源,目前labview的单子干不过来了,想找几个靠谱的labview工程师跟我合作,想做兼职,接单的labview工程师可以私聊我,另外我有一些项目还需要跟单片机工程师,plc工程师,fpga工程师合作,欢迎大家找我合作!以下是手里比较着急的项目,需要外包 需求1&am…...

2021java1年经验公司面试真题

1面我就省略了&#xff0c;主要就是看你的以前工作情况&#xff0c;以前工作内容能不能清晰表达&#xff0c;还有一些简单的java基础问题&#xff0c;大概20多分钟。二面就是40分钟基础&#xff0c;20分钟业务&#xff0c;10分钟个人情况。下面是二面问题 1.自我介绍 做一下自…...

Unity基础之C#核心篇笔记4:多态

Unity基础之C#核心篇笔记4&#xff1a;多态多态1.多态的概念2.解决的问题3.多态的实现4.总结抽象类和抽象方法1.抽象类2.抽象函数3.总结4.练习题接口1.接口的概念2. 接口的申明3.接口的使用4.接口可以继承接口5.显示实现接口6.总结7.练习题密封方法1.密封方法基本概念2.实例3.总…...

LeetCode每日一题 - 有多少小于当前数字的数字

题目&#xff1a; 给你一个数组 nums&#xff0c;对于其中每个元素 nums[i]&#xff0c;请你统计数组中比它小的所有数字的数目。 换而言之&#xff0c;对于每个 nums[i] 你必须计算出有效的 j 的数量&#xff0c;其中 j 满足 j ! i 且 nums[j] < nums[i] 。 以数组形式返回…...

用Python爬取彼岸图网图片

用Python爬取彼岸图网图片 *使用了 四个模块 import time import requests from lxml import etree import os 没有的话自行百度安装。 #encoding utf-8 import time import requests from lxml import etree import os# http://www.netbian.com/ 爬虫 if __name__ __mai…...

02.xshell连不上虚拟机linux的解决办法

虚拟机使用的NAT模式&#xff0c;用Xshell一直连接不上虚拟机上的Linux&#xff0c;最后百度搜索之后&#xff0c;解决步骤如下&#xff1a; 1.在虚拟机里面输入ifconfig&#xff0c;查询虚拟机ip地址 2.打开网络连接&#xff0c;修改VMnet1 IP地址改为与虚拟机同一网段 比如…...

第k个数(快速选择)

算法思路 快速选择&#xff1a; 1.即任意选一个数&#xff0c;将数组划分为二。 2.最终根据该数所在的位置&#xff0c;即第&#xff1f;大&#xff0c;选择第k大的数字所在区间进行划分。 时间复杂度分析&#xff0c;第一次划分n,下一次划分期望n/2&#xff0c;n/4…累加和小…...

2021年茶艺师(中级)模拟考试及茶艺师(中级)模拟考试系统

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 茶艺师&#xff08;中级&#xff09;模拟考试是安全生产模拟考试一点通总题库中随机出的一套茶艺师&#xff08;中级&#xff09;模拟考试系统&#xff0c;在公众号安全生产模拟考试一点通上点击茶艺师&#xff08;中…...

yolov5 detect.py报错

新手求助 yolov5训练了自己的数据集后&#xff0c;test没问题&#xff0c;但是运行detect.py就报错了&#xff0c;一直找不到问题所在&#xff0c; 求大佬指点指点...

DEX 争霸战火升级,BabySwap 会否成为下一代黑马?

在 AMM机制大力推动下&#xff0c;DEX的群雄争霸比预想中来得要快且凶猛。伴随着诸如高盛等主流资本逐步认可DeFi 的意义&#xff0c;在真正的去中心化金融爆发的前夜&#xff0c;可以说谁抢占了DEX 红海的先机&#xff0c;谁就赢得了未来。 从早期以太坊的Uniswap和DoDo&…...

flutter 常用的第三方组件

引用文章链接&#xff1a; https://www.jianshu.com/p/a523e5f131b2 1、格式化日期时间组件&#xff1a;https://pub.dev/packages/date_format 2、日期选择组件&#xff1a;https://pub.dev/packages/flutter_cupertino_date_picker 3、轮播图组件&#xff1a;https://pub.…...

nginx隐藏x-real-ip头配置

实现隐藏X-Real-Ip头&#xff0c;可通过配置server{} proxy_set_header实现。 server { listen 10.10.98.10:8080 backlog20480; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_…...

8.文本处理(编码解码/文件操作)

本章主要从文本处理、系统监控、日志、FTP、邮件监控、微信监控等方面来介绍基础运维的相关知识。 8.1 文本处理 在日常的运维工作中一般都离不开与文本,如日志分析、编码转换、ETL加工等。本节从编码原理、文本操作、读写配置文件、解析XML等实用编程知识出发,希望能抛砖引…...

odoo14 wkhtmltopdf 安装错误

如果出现错误 odoo.exceptions.UserError: 系统中未找到 WKhtmltopdf &#xff0c;因此无法创建 PDF。 - - - 的错误&#xff0c;是因为需要使用0.12.1版本的插件 centos 需要使用yum install安装&#xff0c;unbuntu使用apt-get install安装 wkhtmltox-0.12.1_linux-centos…...

Android面试必刷的200道真题,吐血整理

&#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;&am...

Java岗大厂面试官常问的那些问题,涨姿势!

前言 分布式&#xff0c;是程序员必备技能之一&#xff0c;在面试过程中属于必备类的&#xff0c;在工作中更是会经常用到。而Kafka是一个分布式的基于发布订阅的消息队列&#xff0c;目前它的魅力是无穷的&#xff0c;对于Kafka的奥秘&#xff0c;还需要我们细细去探寻。 要…...

论文解读:3D U-Net: Learning Dense Volumetric Segmentation from Sparse Annotation

要点 1. 提出了3D U-Net&#xff1a;从稀疏标注的体素图像中学习的立体分割网络。 2. 有两个方案&#xff1a;第一是&#xff0c;在待分割立体图像中标注其中的一些切片&#xff0c;网络从这些标注中学习&#xff0c;再为这个空间提供密集的3D分割&#xff1b;第二是&#xff…...

Redis的lru算法

LRU&#xff1a;least Recently Used的缩写&#xff0c;最近最少使用&#xff0c;是一种常用的页面置换算法&#xff0c;选择最近最久未使用的数据予以淘汰。 package com.example.demo.algorithm;import software.amazon.awssdk.services.emr.model.HadoopStepConfig;import …...

Java后端社招面试经历,不愧是大佬

前言 很多人在打算自学Java的时候或许都没有思考过Java的应用方向&#xff0c;市场需要什么样的人才&#xff0c;企业对你有什么要求等等一系列问题&#xff1b;或许你只听说这个行业薪资高…然后懵懵懂懂的上路&#xff0c;不得要害。 对于零基础来学习Java&#xff0c;你或…...

GitHub 迁移

从一个企业内部的GitHub仓库迁移到另外一个&#xff0c;企业版的GitHub仓库内过程&#xff0c;同时需要保存&#xff0c;工程代码中所有的元数据信息&#xff0c;如git log信息。 所有操作都采用的是 GitBash.exe 客户端操作。 1 克隆要迁移的仓库作为裸仓库&#xff1b;这将…...

997页字节跳动Java面试真题解析火爆全网,系列教学

前言 最近刷到了一句耐人寻味的话&#xff0c;“解决雪崩问题的最好办法是不发生雪崩”。 不论是在硅谷互联网公司里还是在国内的互联网平台上&#xff0c;曾多次遇到过海量规模的交易瞬间吞噬平台的悲惨故事。 核心的解决方案大同小异&#xff0c;都是通过缓存&#xff0c;…...

Android性能优化之APK优化,看看这篇文章吧!

前言 想要成为一名优秀的Android开发&#xff0c;你需要一份完备的知识体系&#xff0c;在这里&#xff0c;让我们一起成长为自己所想的那样~。 学算法真的很痛苦&#xff0c;虽然大数据现在很火&#xff0c;但找到适合自己定位的职业也未尝不是一种合理选择。 投百度的经历非…...

推荐系统召回模型之YouTubeNet

召回的主要工作是从全体商品库中筛选出用户感兴趣的商品&#xff0c;此过程要求检索速度快&#xff0c;并且所检索出的商品与用户的历史行为和偏好相关。所以召回模型和特征都较为简单 1、问题建模 我们把推荐问题建模成一个“超大规模多分类”问题。即在时刻ttt&#xff0c;…...

前端页面的性能测试

介绍 随着 Web 应用的空前发展&#xff0c;前端业务逐渐复杂&#xff0c;为了处理这些复杂业务&#xff0c;前后端分离&#xff0c;出现了专门应对这种分离架构的应用开发框架&#xff0c;比如 Angular&#xff0c;React&#xff0c;Vue 等&#xff0c;从而也导致 Web 应用的复…...

物体重心的特点是什么_重心是什么的交点?

重心是三角形三条中线的交点。当几何体为匀质物体时&#xff0c;重心与形心重合。三角形重心是三角形三边每一边的三条中线的交点。当几何体为匀质物体时&#xff0c;重心与形心重合。三条中线必相交&#xff0c;交点命名为重心&#xff1b;重心分割中线段&#xff0c;线段之比…...

10个人的成绩存放在score数组中,编写函数int fun(int score[ ],int below[ ]), 功能是将低于平均分的人数作为函数值返回,将低于平均分的分数放在below中。

#include <stdio.h> #include <math.h> #include <string.h> int main(){ int fun(int score[ ],int below[ ]); int score[10],below[10]; int i,n; for(i0;i<10;i){ scanf("%d",&score[i]); } printf("低于平均分的有…...

求十个学生的成绩的平均数以及低于平均数的有几个人

import java.util.Scanner;public class test01 {public static void main(String[] args) {System.out.println("请输入10个学生的成绩&#xff1a;");double[] arrnew double[10];Scanner sc new Scanner(System.in);int j,n0,m0;double sum 0,avg 0;for ( j 0…...

某企业发放的奖金根据利润提成。利润I低于或等于100000时,奖金可提10%;利润高于100000元,低于200000元(100000<I<=200000)时,低于100000元的部分仍按10%提成

#include<stdio.h> int main() {double i,a;int b;scanf("%lf",&i);if(i<100000){b1;}else if(100000<i<200000){b2;}else if(200000<i<400000){b3;}else if(400000<i<600000){b4;}else if(600000<i<1000000){b5;}else if(i&g...

题目:企业发放的奖金根据利润提成。利润(I)低于或等于10万元时,奖金可提10%;利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可提成7.5%;20万到40万

题目&#xff1a;企业发放的奖金根据利润提成。利润(I)低于或等于10万元时&#xff0c;奖金可提10%&#xff1b;利润高于10万元&#xff0c;低于20万元时&#xff0c;低于10万元的部分 按10%提成&#xff0c;高于10万元的部分&#xff0c;可提成7.5%&#xff1b;20万到40万之间…...

PTA 数组 7-1 计算平均分并输出低于平均分的成绩

计算全班n个&#xff08;n≤30&#xff09;学生的平均分&#xff0c;输出平均分以及低于平均分的成绩。 输入格式: 先输入整数n&#xff0c;再依次输入n个整数成绩&#xff0c;以空格间隔。 输出格式: 在第一行以格式averageresult输出平均分&#xff08;result保留小数点后两…...

2.企业发放的奖金根据利润提成。①利润低于或等于10万元时,奖金可提10%;② 利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可提成 7.5%;

题目&#xff1a; 企业发放的奖金根据利润提成。 ①利润低于或等于10万元时&#xff0c;奖金可提10%&#xff1b; ② 利润高于10万元&#xff0c;低于20万元时&#xff0c;低于10 万元的部分按10%提成&#xff0c;高于10万元的部分&#xff0c; 可提成 7.5%&#xff1b; ③20…...

企业发放的奖金根据利润提成。利润(I)低于或等于10万元时,奖金可提10%;利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可提成7.5%;20万到40万之间时,

企业发放的奖金根据利润提成。利润(I)低于或等于10万元时&#xff0c;奖金可提10%&#xff1b;利润高于10万元&#xff0c;低于20万元时&#xff0c;低于10万元的部分按10%提成&#xff0c;高于10万元的部分&#xff0c;可提成7.5%&#xff1b;20万到40万之间时&#xff0c;高于…...

C++ 统计平均成绩及低于平均值的人数输入 10 名同学的成绩

输入 10 名同学的成绩&#xff0c;计算平均成绩并统计低于平均成绩的人数&#xff0c;例如‪‬‪‬‪‬‪‬‪‬‮‬‭‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬‪‬‪‬‪‬…...

企业发放的奖金根据企业的当年利润决定。当利润I低于或等于100000元时,奖金可提成10%;利润大于100000元,小于200000元(100000<I≤200000)时,低于100000元的部分按1

企业发放的奖金根据企业的当年利润决定。当利润I低于或等于100000元时&#xff0c;奖金可提成10%&#xff1b;利润大于100000元&#xff0c;小于200000元&#xff08;100000<I≤200000&#xff09;时&#xff0c;低于100000元的部分按10%提成&#xff0c;高于100000元的部分…...

输出低于平均分的学生序号和成绩

本题要求输出低于平均分的学生序号和成绩。 输入一组学生(最大30&#xff09;的成绩&#xff08;实数&#xff09;&#xff0c;以-1结束或输入已满&#xff08;达到30人&#xff09;时结束&#xff1b; 输出低于平均分的学生序号&#xff08;从0开始&#xff09;和成绩&#xf…...

python求低于平均分的人数

低于平均分的人数① 输入班级人数② 录入学生成绩③ 计算平均分④ 循环遍历所有学生成绩,找出低于平均分的人数# ① 输入班级人数 num int(input(请输入班级人数:)) # ② 录入学生成绩 scores [] for i in range(num):score int(input(请输入第str(i)个学生的成绩:))if(scor…...

程序员必做50题第2题:企业发放的奖金根据利润提成。利润(I)低于或等于10万元时,奖金可提10%;利润高于10万元...

文章目录第二题一、代码二、结果展示三、注意总结第二题 本题基本是计算题,不用过多纠结 题目: 企业发放的奖金根据利润提成。利润(I)低于或等于10万元时&#xff0c;奖金可提10%;利润高于10万元&#xff0c;低于20万元时&#xff0c;低于10万元的部分按10%提成&#xff0c;高…...

JAVA: 1.企业发放的奖金根据利润提成。利润(I)低于或等于10万元时,奖金可提10%;//#//# 利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,//#

import java.util.Scanner;public class Work8 {public double jiangjin1(double a) {return a * 0.1;}public Double jiangjin2(double a) {double b = jiangjin1(10);return b + (a - 10) * 0.075;}public Double jiangjin3(double a) {double b = jiangjin2(20);return b...

验证集loss低于训练集loss原因分析

我在模型训练的过程中出现了验证集loss低于训练集loss的情况&#xff0c;通过搜集资料&#xff0c;总结归纳如下原因&#xff1a; 原因1&#xff1a;在训练中应用正则化&#xff0c;但在验证/测试中未应用正则化 如果在验证/测试期间添加正则化损失&#xff0c;则损失值和曲线…...

企业发放的奖金根据利润提成。利润I低于或等于100000元的,奖金可提10%;利润高于100000元,低于或等于200000元

企业发放的奖金根据利润提成。利润I低于或等于100000元的&#xff0c;奖金可提10%&#xff1b;利润高于100000元&#xff0c;低于或等于200000元&#xff08;100000<I≤200000&#xff09;时&#xff0c;低于或等于100000元的部分按10%提成&#xff0c;高于100000元的部分&a…...

C语言求学生成绩,并输出低于平均分的人数

// 统计是个学生成绩&#xff0c;并输出低于平均分的人数 // &#xff08;1&#xff09;学生的成绩要求通过键盘输入&#xff1b; // &#xff08;2&#xff09;函数的调用和结果的输出由主函数main处理 // &#xff08;3&#xff09;统计计算过程在自定义函数TJ中完成 // 例如…...

【MySQL】把成绩低于总平均成绩的女同学的的成绩提高5%

在MySQL中&#xff0c; 把成绩低于总平均成绩的女同学的的成绩提高5% #首先我们需要确定[成绩表]里是否存在[外键]&#xff0c; 如果不存在&#xff0c;那么我们直接进行update语句即可&#xff0c; 如果存在[外键]&#xff0c;我们是没办法进行更改成绩的&#xff0c; 那…...

打印所有低于平均分的分数

题目描述 输入n个成绩&#xff0c;打印出所有低于平均分的分数(注意&#xff1a;ave s/n中s 为float或ave (float)s/n)。 输入 多个测试数据每个测试数据一行&#xff0c;在这行中先输入分数的个数n(1<n<100),然后紧跟着输入n个整数&#xff08;代表分数&#xff09…...