声明函数要用用 fun 关键字,就像声明类要用 class 关键字一样
「函数参数」的「参数类型」是在「参数名」的右边
函数的「返回值」在「函数参数」右边使用 : 分隔,没有返回值时可以省略
fun main(){
println("123")
}
fun sum(x:Int,y:Int):Int{
println("123")
}
var x: Int= 1
val username:String = "username"
val user:User = User()
在变量声明的基础上,如果表达式右边的类型是可以推断出来,那么类型可以省略:
var age = 18
val name = "Hello"
val user = User()
继承类和实现接口都是用的 : ,如果类中没有构造器 ( constructor ),需要在父
类类名后面加上 () :
class MainActivity : AppCompatActivity(),View.OnClickListener{
}
Java中是这样的
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
}
Kotlin 中的类型分为「可空类型」和「不可空类型」:
val username: EditText
val username: EditText?
!!
强行调用符?.
安全调用符lateinit 关键字表示变量可以在其初始化表达式被执行之后进行初始化
lateinit
只能修饰 var
可读可写变量,因为 val 定义了变量是不可变的,必须在声明时进行初始化lateinit
关键字声明的变量的类型必须是「不可空类型」lateinit
声明的变量不能有「初始值」lateinit
声明的变量不能是「基本数据类型」lateinit
关键字在类型后面面加上一个感叹号的类型是「平台类型」
Java 中可以通过注解减少这种平台类型的产生
@Nullable
表示可空类型@NotNull
@NonNul l
表示不可空类型MainActivity::class
startActivity(Intent(this,test::class.java))
在 Kotlin 声明属性的时候(没有使用 private
修饰),会自动生成一个私有属性和一对公开的 setter/getter
函数。
在写 setter/getter
的时候使用 field
来代替内部的私有属性(防止递归栈溢
出)
class User {
var username : String?= null
var password : String?= null
set(value) {
field = value
}
get() {
return field
}
//构造器
constructor(){
}
constructor(username : String?,password : String?){
this.username = username
this.password = password
}
}
为什么 EditText.getText() 的时候可以简化,但是 EditText.setText() 的时候不能和
TextView.setText() 一样简化? 因为 EditText.getText() 获得的类型是 Editable ,对应的如果
EditText.setText() 传入的参数也是 Editable 就可以简化了。val newEditable= Editable.Factory.getInstance().newEditable("Kotlin") et_username.text = newEditable
使用 constructor 关键字声明构造器
//构造器
constructor(){
}
constructor(username : String?,password : String?){
this.username = username
this.password = password
}
如果我们在构造器主动调用了了父类构造,那么在继承类的时候就不能在类的后面加上小括号
constructor(context: Context) : this(context, null)
// 主动调用用了父类的构造器
constructor(context: Context, attr: AttributeSet?) :
super(context, attr)
通过 @JvmField 注解可以让编译器只生成一个 public 的成员属性,不生成对应的 setter/getter 函数
@JvmField
var username : String?= null
User user = new User();
String username = user.username;
class User : Any {}
fun get():Unit{}
使用 arrayof() 来创建数组,基本数据类型使用对应的 intArrayOf() 等
val list:Array<String> = arrayOf("1", "2", "3", "4")
val Intlist:IntArray = intArrayOf(1, 2, 3, 4)
companion object
其中,「顶层函数」直接在文件中定义函数和属性,会直接生成静态的,在 Java 中
通过「文件名Kt」来 访问,同时可以通过 @file:JvmName
注解来修改这个「类
名」。
需要注意,这种顶层函数不要声明在 module
内最顶层的包中,至少要在一个
包中例如 com
。不然不能方便使用。
object
和 companion object
都是生成单例例对象,然后通过单例对象访问
函数和属性的。
通过这个注解将 object
和 companion object
的内部函数和属性,真正生成为静态的。
通过 object
关键字实现
// 单例
object Singleton {
}
// 匿名内部类
object : Callback {
}
通过 ${}
的形式来作为字符串模版
val number = 100000000
val text = "支付宝收款${number}元。"
// 如果只是单一的变量,可以省略掉 {}
val text2 = "支付宝收款$number元。
多行字符串
val s = """
我是第一行
我是第二行
我是第三行
""".trimIndent()
200…299 表示 200 -> 299 的区间(包括 299 )
300…399 表示 300 -> 399 的区间(包括 399 )
Java 当中的 switch
的高级版,分支条件上可以支持表达式
Kotlin 不需要使用 try-catch
强制捕获异常
// 声明抽象类
abstract class
// 声明接口
interface
// 声明注解
annotation class
// 声明枚举
enmu class
记得让 IDE 来帮助生成 for 循环
for(item in items)
在 Kotlin
当中,内部类默认是静态内部类
通过 inner
关键字声明为嵌套内部类
默认的可⻅性修饰符是 public
新增的可⻅性修饰符 internal
表示当前模块可⻅
注释中可以在任意地方使用 [] 来引用目标,代替 Java 中的 @param @link
等。
可空类型强制类型转换成不可空类型可以通过在变量后面加上 !! ,来达到类型转
换。
Kotlin 中的类和函数,默认是被 final
修饰的 ( abstract
和 override
例外)
kotlin编译器会默认创建构造函数吗
在Kotlin中,构造函数与类的其他部分一样,需要进行显式声明。如果你没有声明构造函数,Kotlin编译器会为你生成一个默认的无参构造函数。这个默认构造函数不会调用任何代码,即它是一个空函数
var username : String?= “123”
声明一个名为 username 的可变变量,它的类型是 String?(可空字符串),并初始化为 “123”。如果你需要改变 username 的值,你可以直接给它赋值一个新的字符串或者 null
public var age : Int = 0
在 Kotlin 中,public var age : Int = 0
和 @JvmField var age : Int = 0
都可以用来在 Kotlin 中声明一个公共的、可变的、初始化为 0 的整型变量。然而,这两者并不完全等价。
public var age : Int = 0
是直接在 Kotlin 中声明变量,其默认的可见性就是 public
,也就是可以被任何其他代码访问。
而 @JvmField var age : Int = 0
是使用注解 @JvmField
,这会生成一个在 Java
中可见的字段。@JvmField
的目的是让 Kotlin 中的变量在 Java 代码中以字段的形式表现出来,而不是通过 getter
和 setter
方法访问。
这两者的主要区别在于,如果你需要在 Java 中直接访问 Kotlin 变量(而不是通过 getter 和 setter),那么你需要使用 @JvmField
。如果你只是在 Kotlin 内部或者在其他支持 Kotlin 的地方使用这个变量,那么你可以直接使用 public var age : Int = 0
。
总的来说,这两者并不是互为替代的关系,而是根据具体的使用场景来选择使用哪一种。
class Person {
var name: String = "John"
@JvmField var age: Int = 0
}
如果你使用 @JvmField,你可以在 Java 中直接访问和修改 age 变量,如下所示:
Person person = new Person();
person.age = 25; // 可以直接修改 age 变量
int age = person.age; // 通过字段获取 age 值
但是,如果你移除 @JvmField 并使用 public var age: Int = 0,你仍然可以在 Kotlin 中直接访问和修改 age 变量,但是在 Java 中需要通过 getter 和 setter 方法访问它:
Person person = new Person();
person.setAge(25); // 通过 setter 方法修改 age 值
int age = person.getAge(); // 通过 getter 方法获取 age 值
因此,使用 @JvmField 的主要目的是为了在 Java 中直接访问 Kotlin 属性,而无需使用 getter 和 setter 方法。如果你只在 Kotlin 中使用该属性,那么使用 public var age: Int = 0 就足够了。然而,如果你需要与 Java 代码进行互操作,并希望在 Java 中直接访问 Kotlin 属性,那么使用 @JvmField 是更合适的选择。
class MyClass {
var name: String? = null
fun printName() {
println(this.name)
}
}
在这个例子中,this关键字引用的是正在执行的对象实例,该实例的name属性被打印出来。
class MyClass {
var name: String? = null
fun printName() {
println(this.name)
}
}
在这个例子中,this关键字引用的是正在执行的对象实例,该实例的name属性被打印出来。
fun outerFunction() {
val x = 10
val action = object : Action<Int> {
override fun run(input: Int) {
println("Value of x from outer function: $x") // Here, 'this' refers to the outer function's 'x' variable.
}
}
action.run(5)
}
在这个例子中,this关键字引用的是外部函数的变量x。
val outer = /* 外部类引用 */
如果你想在 Kotlin 中获取对外部类的引用,你需要首先将该外部类定义为可访问的,然后你可以在内部类中直接引用它。
例如,假设你有一个名为 OuterClass 的外部类,并且你想在内部类 InnerClass 中获取该类的引用。你可以这样做:
class OuterClass {
var name: String? = null
}
class InnerClass {
val outer: OuterClass? = null
fun printOuterName() {
outer?.let {
println("Name of the outer class: ${it.name}")
}
}
}
在这个例子中,OuterClass 是一个外部类,InnerClass 是一个内部类。在 InnerClass 中,我们声明了一个
outer 变量,它是 OuterClass 的一个引用。然后,在 printOuterName 方法中,我们通过 outer
变量访问了外部类的 name 属性。
class User : Person()
在您提供的代码中,Person 并不是一个接口,而是一个类。您使用的是 Kotlin 语言,它支持通过冒号(:)来实现接口或类的继承。
在这段代码中,User 类通过使用 : 来继承 Person 类。这表示 User 是 Person 的子类,它继承了 Person 的属性和方法。
如果 Person 是一个接口,那么应该使用 interface Person 来声明。所以在这个代码片段中,Person 不是接口,它是一个类。