首页 文章 精选 留言 我的

精选列表

搜索[SpringBoot4],共10000篇文章
优秀的个人博客,低调大师

Spring Batch(4)——Item概念及使用代码

在 批处理概念 中介绍一个标准的批处理分为 Job 和 Step。本文将结合代码介绍在Step中Reader、Processor、Writer的实际使用。 Reader Reader是指从各种各样的外部输入中获取数据,框架为获取各种类型的文件已经预定义了常规的Reader实现类。Reader通过ItemReader接口实现: public interface ItemReader<T> { T read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException; } read方法的作用就是读取一条数据,数据以泛型T的实体结构返回,当read返回null时表示所有数据读取完毕。返回的数据可以是任何结构,比如文件中的一行字符串,数据库的一行数据,或者xml文件中的一系列元素,只要是一个Java对象即可。 Writer Writer通过ItemWriter接口实现: public interface ItemWriter<T> { void write(List<? extends T> items) throws Exception; } Writer是Reader的反向操作,是将数据写入到特定的数据源中。在Step控制一文已经介绍Writer是根据chunk属性设定的值按列表进行操作的,所以传入的是一个List结构。chunk用于表示批处理的事物分片,因此需要注意的是,在writer方法中进行完整数据写入事物操作。例如向数据库写入List中的数据,在写入完成之后再提交事物。 读写的组合模式 无论是读还是写,有时会需要从多个不同的来源获取文件,或者写入到不同的数据源,或者是需要在读和写之间处理一些业务。可以使用组合模式来实现这个目的: public class CompositeItemWriter<T> implements ItemWriter<T> { ItemWriter<T> itemWriter; public CompositeItemWriter(ItemWriter<T> itemWriter) { this.itemWriter = itemWriter; } public void write(List<? extends T> items) throws Exception { //Add business logic here itemWriter.write(items); } public void setDelegate(ItemWriter<T> itemWriter){ this.itemWriter = itemWriter; } } Processor 除了使用组合模式,直接使用Processor是一种更优雅的方法。Processor是Step中的可选项,但是批处理大部分时候都需要对数据进行处理,因此框架提供了ItemProcessor接口来满足Processor过程: public interface ItemProcessor<I, O> { O process(I item) throws Exception; } Processor的结构非常简单也是否易于理解。传入一个类型I,然后由Processor处理成为O。 Processor链 在一个Step中可以使用多个Processor来按照顺序处理业务,此时同样可以使用CompositeItem模式来实现: @Bean public CompositeItemProcessor compositeProcessor() { //创建 CompositeItemProcessor CompositeItemProcessor<Foo,Foobar> compositeProcessor = new CompositeItemProcessor<Foo,Foobar>(); List itemProcessors = new ArrayList(); //添加第一个 Processor itemProcessors.add(new FooTransformer()); //添加第二个 Processor itemProcessors.add(new BarTransformer()); //添加链表 compositeProcessor.setDelegates(itemProcessors); return processor; } 过滤记录 在Reader读取数据的过程中,并不是所有的数据都可以使用,此时Processor还可以用于过滤非必要的数据,同时不会影响Step的处理过程。只要ItemProcesspr的实现类在procss方法中返回null即表示改行数据被过滤掉了。 ItemStream 在Step控制一文中已经提到了ItemStream。在数据批处理概念中提到过,Spring Batch的每一步都是无状态的,进而Reader和Writer也是无状态的,这种方式能够很好的隔离每行数据的处理,也能将容错的范围收窄到可以空子的范围。但是这并不意味着整个批处理的过程中并不需要控制状态。例如从数据库持续读入或写入数据,每次Reader和Writer都单独去申请数据源的链接、维护数据源的状态(打开、关闭等)。因此框架提供了ItemStream接口来完善这些操作: public interface ItemStream { void open(ExecutionContext executionContext) throws ItemStreamException; void update(ExecutionContext executionContext) throws ItemStreamException; void close() throws ItemStreamException; } 持久化数据 在使用Spring Batch之前需要初始化他的元数据存储(Meta-Data Schema),也就是要将需要用到的表导入到对应的数据库中。当然,Spring Batch支持不使用任何持久化数据库,仅仅将数据放到内存中,不设置DataSource即可。 初始化序列 Spring Batch相关的工作需要使用序列SEQUENCE: CREATE SEQUENCE BATCH_STEP_EXECUTION_SEQ; CREATE SEQUENCE BATCH_JOB_EXECUTION_SEQ; CREATE SEQUENCE BATCH_JOB_SEQ; 有些数据库不支持SEQUENCE,可以通过表代理,比如在MySql(InnoDB数据库)中: CREATE TABLE BATCH_STEP_EXECUTION_SEQ (ID BIGINT NOT NULL); INSERT INTO BATCH_STEP_EXECUTION_SEQ values(0); CREATE TABLE BATCH_JOB_EXECUTION_SEQ (ID BIGINT NOT NULL); INSERT INTO BATCH_JOB_EXECUTION_SEQ values(0); CREATE TABLE BATCH_JOB_SEQ (ID BIGINT NOT NULL); INSERT INTO BATCH_JOB_SEQ values(0); 关于Version字段 某些表中都有Version字段。因为Spring的更新策略是乐观锁,因此在进行数据更新之后都会对表的Version字段进行+1处理。在内存与数据库交互的过程中,会使用采用getVersion、increaseVersion(+1)、updateDataAndVersion的过程,如果在update的时候发现Version不是预计的数值(+1),则会抛出OptimisticLockingFailureException的异常。当同一个Job在进群中不同服务上执行时,需要注意这个问题。 BATCH_JOB_INSTANCE BATCH_JOB_INSTANCE用于记录JobInstance,在数据批处理概念中介绍了他的工作方式,其结构为: CREATE TABLE BATCH_JOB_INSTANCE ( JOB_INSTANCE_ID BIGINT PRIMARY KEY , VERSION BIGINT, JOB_NAME VARCHAR(100) NOT NULL , JOB_KEY VARCHAR(2500) ); 字段 说明 JOB_INSTANCE_ID 主键,主键与单个JobInstance相关。当获取到某个JobInstance实例后,通过getId方法可以获取到此数据 VERSION JOB_NAME Job的名称,用于标记运行的Job,在创建Job时候指定 JOB_KEY JobParameters的序列化数值。在数据批处理概念中介绍了一个JobInstance相当于Job+JobParameters。他用于标记同一个Job不同的实例 BATCH_JOB_EXECUTION_PARAMS BATCH_JOB_EXECUTION_PARAMS对应的是JobParameters对象。其核心功能是存储Key-Value结构的各种状态数值。字段中IDENTIFYING=true用于标记那些运行过程中必须的数据(可以理解是框架需要用到的数据),为了存储key-value结构该表一个列数据格式: CREATE TABLE BATCH_JOB_EXECUTION_PARAMS ( JOB_EXECUTION_ID BIGINT NOT NULL , TYPE_CD VARCHAR(6) NOT NULL , KEY_NAME VARCHAR(100) NOT NULL , STRING_VAL VARCHAR(250) , DATE_VAL DATETIME DEFAULT NULL , LONG_VAL BIGINT , DOUBLE_VAL DOUBLE PRECISION , IDENTIFYING CHAR(1) NOT NULL , constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID) references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) ); 字段 说明 JOB_EXECUTION_ID 与BATCH_JOB_EXECUTION表关联的外键,详见数据批处理概念中Job、JobInstance、JobExecute的关系 TYPE_CD 用于标记数据的对象类型,例如 string、date、long、double,非空 KEY_NAME key的值 STRING_VAL string类型的数值 DATE_VAL date类型的数值 LONG_VAL long类型的数值 DOUBLE_VAL double类型的数值 IDENTIFYING 标记这对key-valuse是否来自于JobInstace自身 BATCH_JOB_EXECUTION 关联JobExecution,每当运行一个Job都会产生一个新的JobExecution,对应的在表中都会新增一行数据。 CREATE TABLE BATCH_JOB_EXECUTION ( JOB_EXECUTION_ID BIGINT PRIMARY KEY , VERSION BIGINT, JOB_INSTANCE_ID BIGINT NOT NULL, CREATE_TIME TIMESTAMP NOT NULL, START_TIME TIMESTAMP DEFAULT NULL, END_TIME TIMESTAMP DEFAULT NULL, STATUS VARCHAR(10), EXIT_CODE VARCHAR(20), EXIT_MESSAGE VARCHAR(2500), LAST_UPDATED TIMESTAMP, JOB_CONFIGURATION_LOCATION VARCHAR(2500) NULL, constraint JOB_INSTANCE_EXECUTION_FK foreign key (JOB_INSTANCE_ID) references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID) ) ; 字段 说明 JOB_EXECUTION_ID JobExecution的主键,JobExecution::getId方法可以获取到该值 VERSION JOB_INSTANCE_ID 关联到JobInstace的外键,详见数据批处理概念中Job、JobInstance、JobExecute的关系 CREATE_TIME 创建时间戳 START_TIME 开始时间戳 END_TIME 结束时间戳,无论成功或失败都会更新这一项数据。如果某行数据该值为空表示运行期间出现错误,并且框架无法更新该值 STATUS JobExecute的运行状态:COMPLETED、STARTED或者其他状态。此数值对应Java中BatchStatus枚举值 EXIT_CODE JobExecute执行完毕之后的退出返回值 EXIT_MESSAGE JobExecute退出的详细内容,如果是异常退出可能会包括异常堆栈的内容 LAST_UPDATED 最后一次更新的时间戳 BATCH_STEP_EXECUTION 该表对应的是StepExecution,其结构和BATCH_JOB_EXECUTION基本相似,只是对应的对象是Step,增加了与之相对的一些字段数值: CREATE TABLE BATCH_STEP_EXECUTION ( STEP_EXECUTION_ID BIGINT PRIMARY KEY , VERSION BIGINT NOT NULL, STEP_NAME VARCHAR(100) NOT NULL, JOB_EXECUTION_ID BIGINT NOT NULL, START_TIME TIMESTAMP NOT NULL , END_TIME TIMESTAMP DEFAULT NULL, STATUS VARCHAR(10), COMMIT_COUNT BIGINT , READ_COUNT BIGINT , FILTER_COUNT BIGINT , WRITE_COUNT BIGINT , READ_SKIP_COUNT BIGINT , WRITE_SKIP_COUNT BIGINT , PROCESS_SKIP_COUNT BIGINT , ROLLBACK_COUNT BIGINT , EXIT_CODE VARCHAR(20) , EXIT_MESSAGE VARCHAR(2500) , LAST_UPDATED TIMESTAMP, constraint JOB_EXECUTION_STEP_FK foreign key (JOB_EXECUTION_ID) references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) ) ; 未填入内容部分见BATCH_JOB_EXECUTION说明。 字段 说明 STEP_EXECUTION_ID StepExecute对应的主键 VERSION STEP_NAME Step名称 JOB_EXECUTION_ID 关联到BATCH_JOB_EXECUTION表的外键,标记该StepExecute所属的JobExecute START_TIME END_TIME STATUS COMMIT_COUNT 执行过程中,事物提交的次数,该值与数据的规模以及chunk的设置有关 READ_COUNT 读取数据的次数 FILTER_COUNT Processor中过滤记录的次数 WRITE_COUNT 吸入数据的次数 READ_SKIP_COUNT 读数据的跳过次数 WRITE_SKIP_COUNT 写数据的跳过次数 PROCESS_SKIP_COUNT Processor跳过的次数 ROLLBACK_COUNT 回滚的次数 EXIT_CODE EXIT_MESSAGE LAST_UPDATED BATCH_JOB_EXECUTION_CONTEXT 该表会记录所有与Job相关的ExecutionContext信息。每个ExecutionContext都对应一个JobExecution,在运行的过程中它包含了所有Job范畴的状态数据,这些数据在执行失败后对于后续处理有中重大意义。 CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT ( JOB_EXECUTION_ID BIGINT PRIMARY KEY, SHORT_CONTEXT VARCHAR(2500) NOT NULL, SERIALIZED_CONTEXT CLOB, constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID) references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) ) ; 字段 说明 JOB_EXECUTION_ID 关联到JobExecution的外键,建立JobExecution和ExecutionContext的关系。 SHORT_CONTEXT 标记SERIALIZED_CONTEXT的版本号 SERIALIZED_CONTEXT 序列化的ExecutionContext BATCH_STEP_EXECUTION_CONTEXT Step中ExecutionContext相关的数据表,结构与BATCH_JOB_EXECUTION_CONTEXT完全一样。 表索引建议 上面的所有建表语句都没有提供索引,但是并不代表索引没有价值。当感觉到SQL语句的执行有效率问题时候,可以增加索引。 索引带来的价值取决于SQL查询的频率以及关联关系,下面是Spring Batch框架在运行过程中会用到的一些查询条件语句,用于参考优化索引: 表 Where条件 执行频率 BATCH_JOB_INSTANCE JOB_NAME = ? and JOB_KEY = ? 每次Job启动执时 BATCH_JOB_EXECUTION JOB_INSTANCE_ID = ? 每次Job重启时 BATCH_EXECUTION_CONTEXT EXECUTION_ID = ? and KEY_NAME = ? 视chunk的大小而定 BATCH_STEP_EXECUTION VERSION = ? 视chunk的大小而定 BATCH_STEP_EXECUTION STEP_NAME = ? and JOB_EXECUTION_ID = ? 每一个Step执行之前 使用案例 下面是Spring Batch一些简单的应用,源码在下列地址的simple工程: Gitee:https://gitee.com/chkui-com/spring-batch-sample Github:https://github.com/chkui/spring-batch-sample Spring Batch提供了2种执行方式:命令行方式或Java内嵌方式。命令行方式是直到需要执行批处理任务的时候才启动程序,内嵌方式是结合Web工程或其他外部化框架来使用。2者最大的差别就是是否直接向IoCs注入一个Job实例。 通用基本配置 两种方式的基本配置都是一样的,通过Reader、Processor、Writer来组装一个Step。代码中Item并不涉及文件或数据库的操作,只是简单的模拟数据读取、处理、写入的过程。实体Record和Msg用于模拟数据转换,基本配置如下: public class BatchDefaultConfig { @Bean //配置Step public Step simpleStep(StepBuilderFactory builder, ItemReader<Record> reader, ItemProcessor<Record, Msg> processor, ItemWriter<Msg> writer) { return builder.get("SimpleStep").<Record, Msg>chunk(10).reader(reader).processor(processor).writer(writer) .build(); } @Bean //配置 Reader public ItemReader<Record> reader() { return new ItemReader<Record>() { private int count = 0; public Record read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException { return ++this.count < 100 ? new Record().setId(this.count).setMsg("Read Number:" + this.count) : null; } }; } @Bean //配置 Processor public ItemProcessor<Record, Msg> processor() { return new ItemProcessor<Record, Msg>() { public Msg process(Record item) throws Exception { return new Msg("MSG GET INFO = " + item.getMsg()); } }; } @Bean //配置 Writer public ItemWriter<Msg> writer() { return new ItemWriter<Msg>() { private int batchCount = 0; public void write(List<? extends Msg> items) throws Exception { System.out.println("Batch Count : " + ++batchCount + ". Data:"); for (Msg msg : items) { System.out.println(msg.getInfo()); } } }; } } 命令行方式运行 有了基本配置之后,命令行运行的方式仅仅是向容器添加一个Job: @Configuration //导入依赖配置 @Import({ BatchDefaultConfig.class }) public class BatchCommondConfig { @Bean public Job simpleJob(Step step, JobBuilderFactory builder) { return builder.get("SimpleJob").start(step).build(); //向容器返回一个Job的Bean } } 然后启动Spring Framework则会自动启用Command Runner运行方式运行——先调用SpringApplication::callRunner方法,然后使用JobLauncherCommandLineRunner::execute运行: public class CommondSample { public static void main(String[] args) throws DuplicateJobException { //模拟测试参数, 这些参数值在执行Java时从外部传入的,比如-Dkey=value String[] argsExt = new String[2]; argsExt[0] = "BuilderParam1=Value1"; argsExt[1] = "BuilderParam2=Value2"; //运行Spring Framework SpringApplication.run(CommondSample.class, argsExt); } } 启用之后观察数据库已经发生了变更。使用命令行需要通过 Java运行参数(-Dkey=value)传递JobParameters的数据,上面的代码模拟实现了相关的过程。 Java内嵌运行 Java内嵌的方式主要是用于搭配外部工程化使用,比如使用Web框架或则统一调度平台管之类的结构化框架来统一管理批处理任务。与命令行执行最大的区别就是不向容器注入Job: @Configuration //导入进出配置 @Import({BatchDefaultConfig.class}) public class BatchOperatoConfig { @Bean //返回JobFactory public JobFactory simpleJob(Step step, JobBuilderFactory builder) { SimpleJobFactory sampleJobFactory = new SimpleJobFactory(); sampleJobFactory.setJob(builder.get("SimpleJob").start(step).build()); return sampleJobFactory; } } 配置代码向容器添加了一个JobFactory的实现类,JobFactory的两个接口一个是获取Job一个是获取Job的名称,SimpleJobFactory实现了JobFactory: public class SimpleJobFactory implements JobFactory { private Job job; public void setJob(Job job) { this.job = job; } @Override public Job createJob() { return job; } @Override public String getJobName() { return job.getName(); } } 最后通过SimpleJobFactory来启动一个Job: @SpringBootApplication @EnableBatchProcessing @EnableScheduling public class OperatorSample { public static void main(String[] args) throws DuplicateJobException { new SuspendThread().run(); //挂起系统一直运行 ConfigurableApplicationContext ctx = SpringApplication.run(OperatorSample.class); Cron cron = ctx.getBean(Cron.class); cron.register(); //注册JobFactory cron.runJobLaunch(); } } @Service class Cron { @Autowired JobLauncher jobLauncher; @Autowired private JobOperator jobOperator; @Autowired private JobRegistry jobRegistry; @Autowired private JobFactory jobFactory; //注册JobFactory void register() throws DuplicateJobException { jobRegistry.register(jobFactory); } //使用JobLaunch执行 void runJobLaunch() { Map<String, JobParameter> map = new HashMap<>(); map.put("Builder", new JobParameter("1")); map.put("Timer", new JobParameter("2")); jobLauncher.run(jobFactory.createJob(), new JobParameters(map)); } @Scheduled(cron = "30 * * * * ? ") void task1() { System.out.println("1"); runOperator(); } //定时任务使用 JobOperator执行 private void runOperator() { jobOperator.start("SimpleJob", "Builder=1,Timer=2"); } } 这里使用了2种执行方式:JobLauncher和JobOperator。JobLauncher简单明了的启动一个批处理任务。而JobOperator扩展了一些用于Job管理的接口方法,观察JobOperator的源码可以发现它提供了获取ExecuteContext、检查JobInstance等功能,如果需要定制开发一个基于Web或者JMX管理批处理任务的系统,JobOperator更合适。JobOperator的第二个参数用于传递JobParameters,等号两端分别是key和value,逗号用于分割多行数据。 在Job配置与运行提及过一个JobInstance相当于Job+JobParameters,因此虽然上面的代码使用了两种不同的运行方式,但是Job和JobParameters是一样的。在运行被定时任务包裹的runOperator方法时,会一直抛出JobInstanceAlreadyExistsException异常,因为同一个实例不能运行2次。如果运行失败可以使用对应的restart方法。 后续会介绍各种Reader和Writer的使用。

优秀的个人博客,低调大师

如何应对勒索软件的4个技巧

【大咖・来了 第7期】10月24日晚8点观看《智能导购对话机器人实践》 在网络安全领域,组织确实有必要采取措施,防止勒索软件并将其数据作为人质是非常重要的。然而,即使是谨慎的准备,一些仍然可以通过。知道如何做,如何应对,如果您的组织成为勒索软件的受害者,以及用于帮助识别和控制的工具可能意味着丢失一台计算机和将整个网络连续数小时,几天甚至几周之间的区别。 以下可以帮助您有效地解决针对您的组织的勒索软件,并尽快恢复正常的业务运营。 大家心里的熟悉的网络安全策略,其实一点都不安全 停止大规模的网络攻击:提高安全性的5个步骤 【RSA2019创新沙盒】Capsule8:混合环境中的实时0day攻击检测、朔源和响应平台 楼下的超市倒闭了,原因是它不懂什么是“DDoS”攻击 发起一次网络攻击要花多少钱?

优秀的个人博客,低调大师

Tensorflow源码解析4 -- 图的节点 - Operation

1 概述 上文讲述了TensorFlow的核心对象,计算图Graph。Graph包含两大成员,节点和边。节点即为计算算子Operation,边则为计算数据Tensor。由起始节点Source出发,按照Graph的拓扑顺序,依次执行节点的计算,即可完成整图的计算,最后结束于终止节点Sink,并输出计算结果。 本文会对节点Operation进行详细讲解。 2 前端节点数据结构 在Python前端中,Operation表示Graph的节点,Tensor表示Graph的边。Operation包含OpDef和NodeDef两个主要成员变量。其中OpDef描述了op的静态属性信息,例如op入参列表,出参列表等。而NodeDef则描述op的动态属性信息,例如op运行的设备信息,用户给op设置的name等。 先来看Operation的数据结构,只列出重要代

优秀的个人博客,低调大师

4. Rxjs 介绍及注意事项

先梳理一些概念:Rx:ReactiveX是Reactive Extensions的缩写,一般简写为Rx,最初是LINQ的一个扩展,由微软的架构师Erik Meijer领导的团队开发,在2012年11月开源,Rx是一个编程模型,目标是提供一致的编程接口,帮助开发者更方便的处理异步数据流,Rx库支持.NET、JavaScript和C++,Rx近几年越来越流行了,现在已经支持几乎全部的流行编程语言了,Rx的大部分语言库由ReactiveX这个组织负责维护,比较流行的有RxJava/RxJS/Rx.NET,社区网站是 reactivex.io。 Observer 和 Observable: 在ReactiveX中,一个观察者(Observer)订阅一个可观察对象(Observable)。观察者对Observable发射的数据或数据序列作出响应。这种模式可以极大地简化并发操作,因为它创建了一个处于待命状态的观察者哨兵,在未来某个时刻响应Observable的通知,不需要阻塞等待Observable发射数据。 Rxjs: 刚才说了Rx是抽象的东西,rxjs就是使用JavaScript语言实现rx接口的类库。 它通过使用 observable 序列来编写异步和基于事件的程序。它提供了一个核心类型 Observable,附属类型 (Observer、 Schedulers、 Subjects) 和受 [Array#extras] 启发的操作符 (map、filter、reduce、every, 等等),这些数组操作符可以把异步事件作为集合来处理。 可以把 RxJS 当做是用来处理事件的 Lodash ReactiveX 结合了 观察者模式、迭代器模式 和 使用集合的函数式编程,以满足以一种理想方式来管理事件序列所需要的一切。 在 RxJS 中用来解决异步事件管理的的基本概念是: Observable (可观察对象): 表示一个概念,这个概念是一个可调用的未来值或事件的集合。 Observer (观察者): 一个回调函数的集合,它知道如何去监听由 Observable 提供的值。 Subscription (订阅): 表示 Observable 的执行,主要用于取消 Observable 的执行。 Operators (操作符): 采用函数式编程风格的纯函数 (pure function),使用像 map、filter、concat、flatMap 等这样的操作符来处理集合。 Subject (主体): 相当于 EventEmitter,并且是将值或事件多路推送给多个 Observer 的唯一方式。 Schedulers (调度器): 用来控制并发并且是中央集权的调度员,允许我们在发生计算时进行协调,例如 setTimeout 或 requestAnimationFrame 或其他。 注意:网上很多例子都是基于rxjs5版本,而最新的rxjs6变化很大,具体参见和中文,后面的例子我都会基于rxjs6。 建议直接看官方文档,毕竟是最新的。 http://reactivex.io/documentation https://rxjs-dev.firebaseapp.com/guide/overview 可结合中文文档 (注意是rxjs5)https://mcxiaoke.gitbooks.io/rxdocs/content/ 学好rxjs的关键是对Operators (操作符)的灵活使用,操作符就是纯函数,我们使用操作符创建,转换,过滤,组合,错误处理,辅助操作Observables。具体参见 下节介绍如何创建 Observables

优秀的个人博客,低调大师

4.Swift学习之数据类型

Swift类型的介绍 Swift中的数据类型也有:整型/浮点型/Bool型/元组/枚举/结构体/对象类型等 基本类型 整型 有符号 Int8 : 有符号8位整型 Int16 : 有符号16位整型 Int32 : 有符号32位整型 Int64 : 有符号64位整型 Int : 和平台相关(默认,相当于OC的NSInteger) 无符号 UInt8 : 无符号8位整型 UInt16 : 无符号16位整型 UInt32 : 无符号32位整型 UInt64 : 无符号64位整型 UInt :和平台相关(默认,相当于OC的NSUInteger) 浮点型 Float : 32位浮点型 Double : 64浮点型(默认) Bool型 true : 真 false : 假 // 定义一个Int类型的变量m,并且赋值为10 var m : Int = 10 // 定义一个Double类型的常量n,并且赋值为3.14 let n : Double = 3.14 //定义一个Bool类型 let t : Bool = true Swift中的类型推导 Swift是强类型的语言,强类型语言也称为强类型定义语言。是一种总是强制类型定义的语言,要求变量的使用要严格符合定义,所有变量都必须先定义后使用 Swift中任何一个变量/常量都有明确的类型 注意: 如果定义一个标识符时有直接进行赋值,那么标识符后面的类型可以省略 Swift有类型推导,会自动根据后面的赋值来决定前面的标识符的数据类型 可以通过option+鼠标左键来查看变量的数据类型 查看类型 // 定义变量时没有指定明确的类型,但是因为赋值给i一个20是一个Int类型的数据.因此i为Int类型 var i = 20 // 错误写法:如果之后赋值给i一个浮点型数值,则会报错 // i = 30.5 // 正确写法 var j = 3.33 j = 6.66 Swift中基本运算 Swift中在进行基本运算时必须保证数据的类型一致,否则会出错 只有相同类型的数据才可以进行运算 Swift中没有隐式转换,数据类型的转化必须显示: 类型() Int类型转成Double类型:Double(标识符) Double类型转成Int类型:Int(标识符) let a = 10 let b = 3.14 // 错误写法 // let c = a + b // let c = a * b // 正确写法 let c = Double(a) + b let d = a + Int(b)

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册