Kotlin中的"静态方法"
在Kotlin中,弱化了静态方法这个概念,使得我们想要创建静态方法变得不那么直观,并且,有些方式创建出来的"静态方法"还不是真正的静态方法,这里一一介绍
假的静态方法
使用这类方式创建出来的"静态方法"只是在调用上看起来像是静态方法,但在jvm看来并不是
单例类 object
使用object
关键字标注的类会被视为单例类,Kotlin会保证这个类在运行时不会有两个及以上的实例存在,例如:
在Kotlin中,弱化了静态方法这个概念,使得我们想要创建静态方法变得不那么直观,并且,有些方式创建出来的"静态方法"还不是真正的静态方法,这里一一介绍
使用这类方式创建出来的"静态方法"只是在调用上看起来像是静态方法,但在jvm看来并不是
object
使用object
关键字标注的类会被视为单例类,Kotlin会保证这个类在运行时不会有两个及以上的实例存在,例如:
大部分DBMS都会采用B+树实现索引,这种数据结构可以提高查询时的效率,假设有如下表:
PID | BID | AMOUNT |
---|---|---|
1001 | B1 | 5000 |
1005 | B2 | 3000 |
1010 | B3 | 9000 |
我们可以对PID建立索引(若PID为主键,数据库会为我们自动创建索引),索引呈现出来的树结构如下:
1 | [1005] |
对于任意一个非叶子结点,左子树结点的值都比其小,右子树结点的值都比其大(若为字符串则根据字符串顺序,其他数据类型类似),根据这个特性,比如我们要查找1010,首先进入1005结点,发现1010比1005大,则向右子树查找,直接就找到了1010,仅需比较2次。而如果不使用索引,则会顺序查找,需要比较3次,对于大数据量时,使用索引的效率提升会更加明显。
Isolate就是Dart中的多线程,之所以不称为Thread,而是称为Isolate,是因为它与传统线程的概念有所区别,见如下表格
特性 | Isolate | Thread |
---|---|---|
内存共享 | 不共享内存 | 可以共享内存 |
通信方式 | ReceivePort和SendPort | 共享变量或synchronized关键字 |
数据竞争 | 无数据竞争 | 可能有数据竞争 |
开销 | 开销较大 | 相对轻量 |
任务调度 | Dart运行时管理,适合CPU密集型任务 | 由操作系统管理 |
Isolate的创建之所以比Thread开销要大,是因为Isolate在创建时需要创建更多的资源,例如事件循环队列、微任务队列,独立的内存堆以及独立的垃圾回收器,并且每个 Isolate 需要单独初始化 Dart 运行时环境,包括 Dart 代码执行上下文,而线程只需要共享进程的执行上下文。
使用场景:需要耗时计算时
除了向服务器发起请求验证token是否过期以外,一些类型的token是直接将过期时间储存在token之中的,我们可以通过这一点在客户端本地验证token是否过期。
token其实就是三个东西以小数点分隔开的字符串
对于需要频繁登录操作的服务器,每次都要输入服务器用户的密码显得过于麻烦,幸好SSH允许我们通过密钥来实现免密登录,本以为配置起来挺简单的,但还是遇到一些坑,所以记录一下
首先要在你想免密登录的服务器的用户的主目录创建目录.ssh
来存放密钥文件,cd
到.ssh
目录,然后使用以下命令生成密钥:
1 | ssh-keygen -t rsa |
也可以不用rsa算法生成,但一定要保证待会在自己电脑上生成密钥的算法和在服务端的算法一致,这点很重要,因为有可能服务器的ssh版本与你电脑上的版本不一致,如果没有指定-t
参数,就会使用默认的算法生成,而两者的默认算法并不一定一样。所以无论你想用什么算法,都明确指定-t
参数。
从Java14开始,引入了新的关键字record,该关键字的能让我们快速地编写一些数据类(Data Class):
1 | public record User(String username, String password){} |
上一篇文章中,我们讲完了一些基本概念,包括,注册,事件系统和游戏的两个端,这一篇教程我们会添加第一个自定义物品——闪电剑,要实现的效果是,左键攻击到生物实体时,会在生物的位置降下闪电,右键一个方块时,会在方块的位置降下闪电。本篇教程与前一篇跨度比较大,没有Java基础的朋友可以直接走了。
本教程可能在有些读者看来略显啰嗦,但是我仍然不准备像其他教程那样,直接甩一堆代码上来让大家理解,我会带大家从原版代码出发,一步步分析,模仿原版的实现,这样才能让大家对Minecraft的底层知识有更深刻的理解,并且写出更符合Minecraft本身的风格的模组。
.gitignore
语法规则#
来编写注释,注释的内容不会被git视为忽略规则/
结尾表示忽略的对象是一个目录,而不是文件/
开头则表示忽略的对象的路径是相对于项目的根目录,如果某个规则的开头不是/
,那么这条规则的匹配路径会相对于当前.gitignore
文件的位置!
表示不忽略该规则指定的对象(相当于取反)本教程的游戏版本为1.20.4
,模组加载器为NeoForge,NeoForge版本为20.4.238
,如果你要跟随本教程,请务必保持版本一致。还有一点需要说明,Minecraft的模组编写的API变化相当地快,可能在下一个版本,本教程的代码就会部分失效,但是核心的内容不会变,你可以以本教程的代码作为参考,希望能为你提供一些宝贵的思路。在编写代码的时候,如果你对某个游戏效果或者机制的实现感到很困难,你可以仔细看看原版中有无类似机制的实现,大部分时候,你都能从原版中借鉴到解决方法。
由于NeoForge中引入了大量的函数式编程的API,所以作为Java知识的一些补充,你可能还需要去了解一下Java的函数式编程语法以及相关的一些类,这里不再赘述。
建议直接去看NeoForge官网的环境准备章节:https://docs.neoforged.net/docs/1.20.4/gettingstarted/
唯一的建议:配置一下gradle的魔法,否则你可能等上几天都下不完依赖文件
目前市面上存在许多压缩格式,例如gz,tar等,当然,更为常见的是zip、rar、7z等压缩格式,面对众多的压缩格式,每个不同的格式都有相应的命令,例如有zip、unzip、gzip、gunzip等等,而tar命令则可以通过调用这些命令来实现一站式压缩/解压缩