常量类
//常量类 单例对象
object Codes {
/**
* 消息中心
*/
const val MESSAGE = "002"
}
Java 和 Kotlin 互调
object Test1 {
@JvmField
val NAME = "nanchen"
@JvmStatic
fun getAge() = 18
}
var :同时有getter和setter 、lateinit(延迟操作) 仅仅能修饰 var 变量
val :只有getter 、只读不可写不可变的变量、用 by lazy (延迟操作)关键字去初始化它
伴生对象通过在类中使用 companion object
来创建,用来替代静态成员,类似于 Java 中的静态变量、内部类。
class CompanionKotlin {
companion object {
val DATA = "CompanionKotlin_DATA"
}
fun getData(): String = DATA
}
延迟属性 Lazy
lazy() 是一个函数, 接受一个 Lambda 表达式作为参数, 返回一个 Lazy <T> 实例的函数,返回的实例可以作为实现延迟属性的委托: 第一次调用 get() 会执行已传递给 lazy() 的 lamda 表达式并记录结果, 后续调用 get() 只是返回记录的结果
lazy()
委托属性可以用于只读属性的惰性加载,但是在使用 lazy()
时经常被忽视的地方就是有一个可选的model参数:
- LazyThreadSafetyMode.SYNCHRONIZED:初始化属性时会有双重锁检查,保证该值只在一个线程中计算,并且所有线程会得到相同的值。
- LazyThreadSafetyMode.PUBLICATION:多个线程会同时执行,初始化属性的函数会被多次调用,但是只有第一个返回的值被当做委托属性的值。
- LazyThreadSafetyMode.NONE:没有双重锁检查,不应该用在多线程下。
lazy()
默认情况下会指定 LazyThreadSafetyMode.SYNCHRONIZED
,这可能会造成不必要线程安全的开销,应该根据实际情况,指定合适的model来避免不需要的同步锁。
仅在第一次使用的时候进行初始化
class Bean {
val str by lazy {
println("Init lazy")
"Hello World"
}
}
fun main() {
val bean = Bean()
println("Init Bean")
println(bean.str)
println(bean.str)
}
Init Bean
Init lazy
Hello World
Hello World
@Keep 混淆
companion 伴生对象(内部维护一个 内部类单例对象)
class HomeIconsFragment{
...
companion object {
/**
* 创建实例.
* @return HomeAssistantFragment
*/
fun newInstance() = HomeIconsFragment()
}
}
lateinit var和by lazy
首先两者的应用场景是略有不同的。
然后,虽然两者都可以推迟属性初始化的时间,但是lateinit var只是让编译期忽略对属性未初始化的检查,后续在哪里以及何时初始化还需要开发者自己决定。
而by lazy真正做到了声明的同时也指定了延迟初始化时的行为,在属性被第一次被使用的时候能自动初始化。但这些功能是要为此付出一丢丢代价的。
constructor 构造函数
Kotlin
基本数据类型:不会装箱拆箱 (Int Float Double)不可空对象
val intArrayOf:IntArray=intArrayOf(1,2,3)
List mapof不可以修改
Java 包装类型(Int Float Double) 可能为null
List mapof可以修改
匿名内部类
//匿名内部类 object
call.enqueue(object:Callback{
})
枚举
//枚举
enum class LoginState(val key: Int) {
/** 未登陆. */
LOGOUT(0x00),
/** 自动登陆中. */
LOGGING_IN_FOR_AUTO(0x11)
}
//简单判断空处理
setText(R.id.tv_date,model.date?:"日期待定")
//以下两个等价
if(user.name==null ||user.username!!.length<4){
toast("用户名不合法")
return false
}
if(user.name?.length ?:0 <4){
toast("用户名不合法")
return false
}
//遍历过滤操作
val playbackLessons=ArrayList<Lesson>()
for(lesson in lessons){
if(it.state==Lesson.State.PLAYBACK){
playbackLessons.add(it)
}
}
lessons.forEach({lesson:Lesson->
if(lesson.state==Lesson.State.PLAYBACK){
playbackLessons.add(it)
}
})
最后一个传入参数是lambda,变成以下小括号移到前面
lessons.forEach(){lesson:Lesson->
if(lesson.state==Lesson.State.PLAYBACK){
playbackLessons.add(it)
}
}
函数参数只有一个lambda,变成以下 去掉小括号
lessons.forEach{
if(it.state==Lesson.State.PLAYBACK){
playbackLessons.add(it)
}
}
//数据集合 filter 过滤操作符
lessons.filter{it.state==Lesson.State.PLAYBACK}
遍历数组
val array=arrayOf(1,23,12,2)
for(i in 0.until(array.size)){
}
repeat(100){
println(it)
}
private set
class BaseAplication:Application(){
companion object{
lateinit var currentApplication:Context
private set
}
}
调用:
BaseAplication:Application.getCurrenttApplication()
或者注解
@JvmStatic
@get:JvmName("currentApplication")
class BaseAplication:Application(){
companion object{
lateinit var currentApplication:Context
private set
}
}
调用:
BaseAplication:Application.currenttApplication()
使用@JvmOverloads对Java暴露重载函数
by 委托
var token:String
set(value){
CacheUtils.save("token",value)
}
get(){
return CacheUtils.get("token")
}
把操作委托给Saver
var token:String by Saver("token")
class Saver(var token:String){
operator fun getValue(test:TestActivity,property:KProperty<*>):String{
return CacheUtils.get(token)!!
}
operator fun setValue(test:TestActivity,property:KProperty<*>,value:String){
CacheUtils.save(token,value)
}
}
apply适合对一个对象做附加操作的时候
let 适合配合空判断的时候
with 适合对同一对象进行多次操作的时候
lesson.state?.let{
setText(R.id.tv_date,it.date)
}
findViewById<RecyclerView>(R.id.list).run{
layoutManager=LinearManager(this@LessonActivity)
adapter=lessonAdapter
...
}
private val paint=Paint().apply{
isAntiAlias=true
style=Paint.Style.STROKE
}
class Test(var temp: Int)
转化后的java的代码是:
public final class Test {
private int temp;
public final int getTemp() {
return this.temp;
}
public final void setTemp(int var1) {
this.temp = var1;
}
public Test(int temp) {
this.temp = temp;
}
}