由Java泛型看Kotlin的泛型

参考链接:

《深入理解Java泛型》
《Kotlin 泛型》
《Kotlin中文文档》
《无界通配符》
《Kotin实战》泛型章节
《Effective Java》泛型章节

什么是泛型

泛型的目的是让我们写一套代码可以支持不同的数据类型,下面我们实现一个简单的集合。

1
2
3
4
5
6
7
8
9
10
11
12
13
class MyList{

private int size;
private Object[] elements = new Object[10];

public void add(Object item) {
elements[size++]=item;
}

public Object get(int index) {
return elements[index];
}
}

我们实现的集合可以添加任意类型的数据(因为Java中Object是所有类的超类)

1
2
3
4
5
MyList myList = new MyList();
myList.add("A");
myList.add(1);
System.out.println(myList.get(0));
System.out.println((String)myList.get(1));

但是这样的代码有着很大的缺陷,因为需要类型的强制转换,这种转换错误是在编译期间发现不了的,在Java 1.5之前是没有泛型的,就是这样做的。泛型同样可以实现这个需求,但是通过面向对象的多态特性避免了类型强转,而且在编译期间就能发现类型问题。

Android开发中Kotlin的扩展库及实现Parcelable

参考链接:

《Kotlin文档–Kotlin Android 扩展》
《Kotlin Android扩展和findViewById说再见》

在使用Kotlin开发Android中我们可以使用安卓扩展库来方便Android开发。

1
2
3
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions' //扩展库

Kotlin开发Android的奇技淫巧记录

参考链接:

《聊一聊Kotlin扩展函数run,with,let,also和apply的使用和区别》

前面几篇我们了解了kotlin的语法和概念的东西,接下来我们在实际使用中看看kotlin带给我们的惊喜。

扩展函数的利用

现象

先来看一段代码:

1
2
3
val avaliableTime: String?
avaliableTime = R.string.avaliable_time.resToString("3年")
println(avaliableTime)

其中 avaliable_time 资源的定义如下

1
<string name="avaliable_time">有效期%s</string>

最终打印结果为:有效期3年

上面这个特点就是Kotlin扩展函数带给我们的福利。

Kotlin中的object关键字

参考链接

《知乎-kotlin学习之路》
《Kotlin中文文档》

Kotlin中使用object关键字来代替Java中的匿名内部类实现。

在Java中很多时候我们需要一个一次性对象,可以使用匿名内部类来实现,如下:

1
2
3
4
5
6
7
Thread thread = new Thread(){

@Override
public void run(){
System.out.println("hello world");
}
}

在Kotlin中也支持同样的写法:

1
2
3
4
5
val thread: Thread = object : Thread(){
override fun run(){
println("hello world")
}
}

Kotlin的数据类型和集合

参考链接

《Kotlin实战》

基本类型

在Kotlin中并不区分基本数据类型和包装类型,例如:

1
2
3
4
5
6
val i: Int = 1
val list: List<Int> = listOf(1, 2, 3)

fun showProgress(progress: Int){
val percent = progress.coerceIn(0, 100)
}

大多数情况下Kotlin的Int类型会被编译成Java的基本数据类型,用作泛型类型参数的基本类型会被编译成Java的包装类型。

在Kotlin中的可空类型不能用Java的基本类型表示(例如:Int?、Boolean?),这个时候会被编译成对应的Java包装类型。

1
var list: List<Int> = listOf(1, 2, 3)

上面代码的listOf集合类的参数是泛型,所以会编译成java的包装类型,所以要高效的存储基本类型建议用数组来存储。

Kotlin的可空性

参考链接

《Kotlin实战》

可空性是Kotlin的一个重要特性,可以帮助我们避免发生NullPointerException.

可空类型

1
2
3
int strLen(String s){
return s.length();
}

上面的Java代码如果我们传入空参数就会导致NullPointerException.

但是,和上面等价含义的Kotlin语句在编译期就能标记出错误,如下:

1
2
3
4
fun strLen(s: String) = s.length

>>> strLen(null)
ERROR: Null can not be a value of non-null type String

函数参数被声明为String类型,所以必须包含一个非null的String实例,这样在Kotlin中就保证了不会在运行时抛出NullPointerException.

Kotlin中的by关键字

参考链接

《Kotlin - By 关键字介绍》
《Kotlin实战》
《Kotlin中文文档》
《java_my_life的博客》

装饰器模式

装饰器模式又名包装模式,来以对客户透明的方式(客户端并不觉得修饰前后的区别)扩展对象的功能,是继承关系的一种替代方案。

在装饰模式中的角色有:

  • 抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。
  • 具体构件(ConcreteComponent)角色:定义一个将要接收附加责任的类。
  • 装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
  • 具体装饰(ConcreteDecorator)角色:负责给构件对象“贴上”附加的责任。

Lambda编程

参考链接

《知乎:Lambda 表达式》
《Kotlin实战》
《Kotlin中文文档》

Lambda表达式本质上就是可以传递给其他函数一小段代码。

有了Lambda可以轻松地把通用代码结构抽取成函数库,Kotlin标准库大量使用了它。

什么是Lambda

我们知道,对于一个Java变量,我们可以赋给其一个“值”。如果你想把“一块代码”赋给一个Java变量,应该怎么做呢?

在Java 8之前,这个是做不到的。但是Java 8问世之后,利用Lambda特性,就可以做到了。

1
2
3
aBlockOfCode = public void doSomeShit(String s){
System.out.println(s);
}

简便写法

1、public和函数名是多余的,因为已经赋值给了aBlockOfCode.
2、编译器可以自动判断参数类型和返回类型。
3、只有一行可以省略大括号。

1
aBlockOfCode = (s) -> System.out.println(s);

这样我们就将一个代码块成功赋值给了变量,那么aBlockOfCode的类型是什么呢?

Ajax Android AndroidStudio Animation Anroid Studio AppBarLayout Babel Banner Buffer Bulma ByteBuffer C++ C11 C89 C99 CDN CMYK COM1 COM2 CSS Camera Raw, 直方图 Chrome Class ContentProvider CoordinatorLayout C语言 DML DOM Dagger Dagger2 Darktable Demo Document DownloadManage ES2015 ESLint Element Error Exception Extensions File FileProvider Flow Fresco GCC Git GitHub GitLab Gradle Groovy HTML5 Handler HandlerThread Hexo Hybrid I/O IDEA IO ImageMagick IntelliJ Intellij Interpolator JCenter JNI JS Java JavaScript JsBridge Kotlin Lab Lambda Lifecycle Lint Linux Looper MQTT MVC MVP Maven MessageQueue Modbus Momentum MySQL NDK NIO NexT Next Nodejs ObjectAnimator Oracle VM Permission PhotoShop Physics Python RGB RS-232 RTU Remote-SSH Retrofit Runnable RxAndroid RxJava SE0 SSH Spring SpringBoot Statubar Style Task Theme Thread Tkinter UI UIKit UML VM virtualBox VS Code VUE ValueAnimator ViewPropertyAnimator Vue Vue.js Web Web前端 Workbench api apk bookmark by关键字 cli compileOnly computed css c语言 databases demo hexo hotfix html iOS icarus implementation init jQuery javascript launchModel logo merge methods mvp offset photos pug query rxjava2 scss servlet shell svg tkinter tomcat transition unicode utf-8 vector virtual box vscode watch webpack 七牛 下载 中介者模式 串口 临潼石榴 主题 书签 事件 享元模式 仓库 代理模式 位运算 依赖注入 修改,tables 光和色 内存 内核 内部分享 函数 函数式编程 分支 分析 创建 删除 动画 单例模式 压缩图片 发布 可空性 合并 同向性 后期 启动模式 命令 命令模式 响应式 响应式编程 图层 图床 图片压缩 图片处理 图片轮播 地球 域名 基础 增加 备忘录模式 外观模式 多线程 大爆炸 天气APP 太白山 头文件 奇点 字符串 字符集 存储引擎 宇宙 宏定义 实践 属性 属性动画 岐山擀面皮 岐山肉臊子 岐山香醋 工具 工厂模式 年终总结 开发技巧 异常 弱引用 恒星 打包 技巧 指令 指针 插件 插值 摄影 操作系统 攻略 故事 数据库 数据类型 数组 文件 新功能 旅行 旋转木马 时序图 时空 时间简史 曲线 杂谈 权限 枚举 架构 查询 标准库 标签选择器 样式 核心 框架 案例 桥接模式 检测工具 模块化 模板 模板引擎 模板方法模式 油泼辣子 泛型 洛川苹果 浅色状态栏 渲染 源码 源码分析 瀑布流 热修复 版本 版本控制 状态栏 状态模式 生活 留言板 相册 相对论 眉县猕猴桃 知识点 码云 磁盘 科学 笔记 策略模式 类图 系统,发行版, GNU 索引 组件 组合模式 绑定 结构 结构体 编码 网易云信 网格布局 网站广播 网站通知 网络 美化 联合 脚手架 膨胀的宇宙 自定义 自定义View 自定义插件 蒙版 虚拟 虚拟机 补码 补齐 表单 表达式 装饰模式 西安 观察者模式 规范 视图 视频 解耦器模式 设计 设计原则 设计模式 访问者模式 语法 责任链模式 贪吃蛇 转换 软件工程 软引用 运算符 迭代子模式 适配器模式 选择器 通信 通道 配置 链表 锐化 错误 键盘 闭包 降噪 陕西地方特产 面向对象 项目优化 项目构建 黑洞
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×