为什么需要这样写this@MainActivity
this指当前对象。this@label是指this来源的标签label。
class MainActivity() : Activity() {
private fun <T> Intent.openActivity(block: Intent.() -> Unit, clz: Class<T>) {
// MainActivity的this
val intent = Intent(this@MainActivity, clz)
// Intent的this
this.putExtra("name", "open")
intent.block()
startActivity(intent)
}
}
Kotlin函数和Lambda之间的关系
Lambda是函数类型的实例。Kotlin中定义一个函数事实上是在Java中定义一个FunctionN类型的接口
val block:(()->Unit)?=null
反编译成java
private static final Function0 block;
Kotlin安全类型转换
类型转换使用as
fun getMainActivity() = activity as MainActivity
java写法:
protected MainActivity getMainActivity(){
return (MainActivity)getActivity();
}
常规的类型转化可能报ClassCastException,Kotlin中由更加安全的写法as?
fun getMainActivity() = activity as? MainActivity
as?尝试转换目标类,转换失败则返回null。反编译成java
public final MainActivity getMainActivity(){
FragmentActivity activity = this.getActivity();
if(!(activity instanceof MainActivity)){
activity = null;
}
return (MainActivity)activity;
}
Kotlin安全判空
fun main() {
var student:Student?=null
info(student)
}
fun info(student:Student?){
student?.name
}
class Student(var name:String)
在java中的实现
public final class FunKt{
public static final void main(){
Student student =null;
info((Student)student);
}
public static void main(String[] var0){main()}
public static final void info(@Nullable Student student){
if(student!=null){
student.getName();
}
}
}
?.使用了if(student!=null)判断逻辑。?.操作符非空就正常返回,如果是空则返回null。
student?.name?.hashCode()
Kotlin中一个类的无参构造函数,什么时候可以省略constructor关键字
如果在没有注解或可见性修饰符,则可以省略constructor关键字
// 可以省略
class Car{}
// 不可以省略
class Car private constructor(){}
// 不可以省略
class Car @Inject constructor(){}
// 不可以省略
class Car @Inject private constructor(){}
具体化参数类型
是Kotlin结合泛型和内联函数的概念提供的语法糖。在编译期间,将参数类型转化成具体的类型,在运行时不需要考虑泛型擦除机制。在运行时不存在泛型了,就是一个具体的类型。具体化的参数类型,让obj as T或obj is T可以在实际开发中运用
fun main() {
printInfo<BaseFragment>(MainFragment())
}
inline fun <reified T> printInfo(obj:T){
println(T::class.simpleName)
if (obj is BaseFragment){
println("obj is BaseFragment")
}
println("${obj as BaseFragment}")
}
class MainFragment:BaseFragment()
open class BaseFragment
定义一个内联泛型函数printInfo,使用reified关键字修饰泛型T。具体化的参数类型必须在内联函数中声明,在printInfo()方法内部打印了该类型的参数。具体可以反编译java看具体实现。
Kotlin万物皆对象
Java中不是万物皆对象,Java中存在基本数据类型时一种值类型,值类型通常被分配到栈上,它的变量直接包含变量的实例。值类型和基本数据类型包装类之间的相互转换关系,称为装箱和拆箱。所以说Java中基本数据类型并不是对象,而基本数据类型包装类是对象。严谨说,java并不是万物皆对象。
可变参数
在Kotlin中使用vararg关键字来声明,java中又称可变数组。
fun main() {
printInfo("1","2","3")
}
private fun printInfo(vararg array:String){
for (item in array){
println(item)
}
}
java 中的实现
private void test(){
printInfo("1","2","3");
}
private static final void printInfo(String... array){
String[] var = array;
}
Kotlin中使用vararg修饰。java中用ClassName...修饰。
Kotlin中属性,自定义getter和setter访问器
对于final只读的val类型函数,可以自定义get(),但并不是所有的只读属性需要自定义get(),如果该属性没有根据一个动态条件实现的改变,没必要自定义get()。
// 可以不用自定义
val name get() = "test"
// 需要自定义
val name get()=if(...) name = else name=
对于JVM平台,通过默认getter和settter访问私有化属性会被优化,所以不会引入函数调用开销。 如果对于默认就是无法改变的只读属性,完全没有必要自定义getter访问器。对于可变的var属性来说,getter和setter访问器是可以自定义的,因该是按需实现。
apply函数实现:
// apply是顶层函数
// 可以使用拖尾Lambda表达式,apply函数拥有一个函数类型的参数
// 可以在任意对象上调用,apply函数是一个扩展函数
// 拥有一个调用者的返回值
// 拥有当前上下文的作用域
public inline fun <T> T.apply(block: T.() -> Unit):T{
block();
return this;
}
总结
kotlin在Android开发中是十分重要的,需要我们更加深刻的理解其中的语法含义,以及使用场景。