可以用Kotin写项目了--Kotlin基础入门
wptr33 2024-12-03 18:45 33 浏览
1、为什么使用Kotlin开发Android呢?
java被 Oracle收购后,谷歌经常被Oracle告侵权,所以谷歌选择了Kotlin作为Android开发的第一语言,在Android官网上 说Kotlin是免费且开放的,是由一家特别厉害的公司JetBrains开发的静态编程语言,AndroidStudio也是根据他家的IDEA改的,谷歌也贡献了开源代码 Kotlin的优点:
- 富有表现力且极简洁 Kotlin 的现代语言功能让您可以专注于表达自己的想法,少编写样板代码。
- 更安全的代码 借助自身类型系统所含的 @Nullable 和 @NonNull,Kotlin 可帮助您避免 NullPointerExceptions。使用 Kotlin 的 Android 应用发生崩溃的可能性降低了 20%。
- 可互操作 可以和Java代码互通,互相调用
- 结构化并发 Kotlin 协程可简化异步编程,让您能够轻松高效地执行网络调用和数据库更新等常见任务。
2、基础语法
2.1、变量
类型推导 根据初始化的类型进行类型推导 可变变量定义 var 不可变变量定义val 相当于java的final修饰 Kotlin是一个静态语言 ,编译期就决定的东西
class VariableDemo {
// var <标识符> : <类型> = <初始化值>
// val <标识符> : <类型> = <初始化值>
// var userName:String="爱码士"
var name="爱码士"//自动推导为字符串
val age=100//自动推导为 Int
}decompiledJava(用插件先把Kotlin转为字节码,再翻编译成java文件)后的代码
public final class VariableDemo {
@NotNull
private String name = "爱码士";
private final int age = 100;
@NotNull
public final String getName() {
return this.name;
}
public final void setName(@NotNull String var1) {
Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
this.name = var1;
}
public final int getAge() {
return this.age;
}
}由以上代码可以看出var转为java之后是有get和set方法的,而val用了final修饰之后并且没有set方法,说明了用var修饰的变量可读可写,用val修饰的变量可读不可写
2.2、函数
不带返回值的方法void==Unit 可以省略
fun testFun(number1:Int,number2:Int):Unit{
println(number1+number2)
}有返回值返回值 和参数的方法
fun testFun(number1:Int,number2:Int):Int{
println(number1+number2)
return number1+number2
}一种更高级的写法 方法 = 推导返回值类型
fun add(number1: Int,number2: Int) = number1+number2 //返回值推导成Int
fun add3(number1: Int, number2: Int) = "爱码士"//返回值推导成Stringjava里可以有可变参数,Kotlin里也有需要用vararg 关键字来修饰 可变参数(可变长的参数)
fun lenMethod(vararg number:Int){
println(number.size)
}lambda表达式函数(这里先举个例子,以后专门写个文章来学习lambda)
fun main(){
// lambda表达式函数
val addMethod : (Int, Int) -> Int = {number1, number2 -> number1 + number2}
val r= addMethod(9, 9)
println(r)
}2.3、字符串模板
写起来会快一点
val name = "爱码士"
val age = 28
val sex = 'M'
val info = "ABCDEFG"
println("name:$name, age:$age, sex:$sex info:$info")三个双引号,原样输出,换行不需要转义字符,
val infoMesage = """
AAAAAAAAAAA"aaa"
BBBBBBBBBBB
CCCCCCCCCCC
DDDDDDDDDDD
EEEEEEEEEEE
""" // 前置空格
println(infoMesage)//输出来会有前置空格
val infoMesage2 = """
AAAAAAAAAAA
BBBBBBBBBBB
CCCCCCCCCCC
DDDDDDDDDDD
EEEEEEEEEEE
""".trimIndent() // 没空格trimIndent()去掉前置空格,具体什么效果大家可以敲一敲 去试试 显示$999.99 ${‘$’}999
val price = """
${'#39;}99999.99
""".trimIndent()
println(price)2.4 、Kotlin特色之一 null检查机制
var name:String?=null//?会发一个通知,告诉所有调用者,现在这个变量是可以为null的,你们调用者自己去实施补救措施
fun main() {
//name.length//如果不补救则会编译报错,报下图的错
}一共三种补救措施 第一种就是方法内允许返回空值,在返回值返回的后边加一个?,这样的话就将补救措施交给了返回值的调用者
fun main() {
var testStr=test()
//testStr.length
}
fun test():String?{
return null
}这种写法testStr.length报的错误和上面一样的,如果把test方法返回值的?去掉,则这个方法是不允许返回null的,testStr.length是不会报错的 第二种补救措施 调用的这个属性的时候,点前边加一个?,表示如果这个属性为null,则后边的代码不执行
fun main() {
var testStr=test()
testStr?.length//如果testStr为null,则.length不执行
}
fun test():String?{
return null
}第三种补救措施在调用的时候,点前面加两个!!,表示这个属性一定不为null,后面的一定执行
fun main() {
var testStr=test()
testStr!!.length//如果testStr为null,则.length不执行
}
fun test():String?{
return null
}第三种补救措施一定要慎用,在确定这个属性为百分之百不为null的情况下可以这样用,否则会出现空指针异常的情况
2.5、区间
fun sectionTest(){
//区间 .. 只能从小数到大数
for (index in 1..10){
print(index)
}
println("")
//区间 down to 只能从大数到小数
for (index in 10 downTo 1){
print(index)
}
println("")
//step 步幅
for (index in 1..10 step 4){
print(index)
}
//in 和 downTo是闭区间 unitl 半闭半开区间
//半闭半开区间 也是只能从小数到大数
for(index in 1 until 10){
print(index)
}
}输出结果:
3、比较与数组
==比较值本身相当于,equals也能用,但是有黄色波浪线 ===比较对象地址
val name1: String = "爱码士"
val name2: String = "爱码士"
// --- 比较值本身
// == 等价 Java的equals
println(name1.equals(name2))
println(name1 == name2)
// --- 比较对象地址
val test1:Int? = 10000
val test2:Int? = 10000
println(test1 === test2) // false数组 arrayOf泛型 类型推导
val numbers = arrayOf(1, 2, 3, 4, 5, 6, 7, 8)
//取值numbers[index]
numbers[0]
//方式二
val numbers2 = Array<String>(10, {value: Int -> ("aaa") })
// val numbers2 = Array<String>
(10,//数组大小
{value: Int //数组下标-
> ("aaa")//给下标为value的赋值aaa })也可以这样写
val numbers2 = Array<String>(10, {value: Int -> if(value==5) ("666") else ("aaa") })
for (value in numbers2) {
println(value)
}decompiledJava后的代码
public static final void main() {
byte var1 = 10;
String[] var2 = new String[var1];
boolean var5;
for(int var3 = 0; var3 < var1; ++var3) {
var5 = false;
String var8 = var3 == 5 ? "666" : "aaa";
var2[var3] = var8;
}
String[] var11 = var2;
int var4 = var2.length;
for(int var10 = 0; var10 < var4; ++var10) {
String value = var11[var10];
var5 = false;
System.out.println(value);
}
}
4、条件控制
表达式比大小
val age=5;
val age1=10;
val maxValue=if (age>age1) age else age1区间判断
val age=5;
if(age in 1..18){
println("未成年")
}else{
println("已成年")
}switch的升级版when
val age=5;
when(age){
in 1..18->{//判断是否在1到18之间
}
19,21,22,24->{//满足其中一个就执行这个分支
}
else->{//不满足以上条件 走这个分支
}
}when的类型推导
var str= when(age){
in 1..18->{
"年龄为$age,未成年"
}
19,21,22,24->{
"年龄为$age,成年了"
}
else->{
"年龄为$age,其他"
}
}
println(str)如果各个分支的返回类型不相同,str则会被推导成Any类型,相当于Java当中的Object
5、循环与标签
在 Kotlin 中任何表达式都可以用标签来标记。 标签的格式为标识符+ @ 符号,例如:aaa@、bottom@都是有效的标签, 要为一个表达式加标签,我们只要在其前加标签即可。 标签的应用 break
tttt@ for (i in 1..20) {
for (j in 1..20) {
println("i:$i, j:$j")
if (i == 5) {
// break // j循环 给break
break@tttt // i循环 给break
}
}return
fun testLabel(){
var numbers= arrayOf(1,2,3,4,5,6)
testFor@numbers.forEach {
when(it){
5->{
// return //不打印aaa
return@forEach//打印aaa
}
}
}
println("aaa")
}this
class SafeDemo {
val name="爱码士"
inner class SafeDemoInner{
val name="inner 爱码士"
fun test(){
println(this.name)//inner 爱码士
println(this@SafeDemo.name)//"爱码士"
}
}
}for循环
var items = listOf<String>("李四", "张三", "王五")
for (item in items) {
println(item)
}
items.forEach {
println(it)
}
for (index in items.indices) {
println("下标:$index, 对应的值:${items[index]}")
}6、类与对象
先来一个空类
//默认public 所以不用写public
class Test {
}6.1、构造方法
class Test(val age:Int) {//主构造的写法
constructor():this(5)//次构造 次构造 必须调用主构造
constructor(name:String):this(5)//次构造
}
//使用的时候不需要new关键字
fun main() {
Test(0)
}上面这种写法,转成java之后class 是用final修饰的,所以不能被继承,但是我想写一个父类怎么办呢,class前面用open修饰,这个类就可以被继承了,就去掉了final关键字
open class Test(val age:Int) {//主构造的写法
constructor():this(5)//次构造 次构造 必须调用主构造
constructor(name:String):this(5)//次构造
}6.2、属性默认值
在Java中所有的属性值是可以有默认值的,默认为null,是没有什么问题的,但是Kotlini中,如果不给属性赋值,就会报错 解决办法
- ?=允许为空自己去补救
- 自己赋予初始值皆大欢喜
- 用懒加载 lateinit修饰
val number=0;
var id:String ?= null
lateinit var url:String//懒加载的时候用的时候一定要初始化,否则会空指针异常6.3、抽象类和接口
抽象类 和接口 和java的写法相似
interface ICallBack {
fun onCallBack()
}
abstract class TestAbstract {
abstract fun initView()
}
//继承和实现接口都使用:然后用逗号隔开,继承抽象类或者 open修饰的类的时候,要声明主构造
class TestInterface: TestAbstract(),ICallBack{
override fun initView() {
// TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onCallBack() {
// TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}6.4、数据Bean
JavaBean的写法,Kotlin中用dataclass代替了JavaBean,还生成了copy函数
data class UserBean(val userName:String,val password:String)
fun main() {
var user=UserBean("aaa","bbbb")
var (username,password)=user.copy()
var (_,amszlk)=user.copy()//只想copypassword
println("username:$username,password:$password")
println(amszlk)
}转成java的代码
public final class UserBean {
@NotNull
private final String userName;
@NotNull
private final String password;
@NotNull
public final String getUserName() {
return this.userName;
}
@NotNull
public final String getPassword() {
return this.password;
}
public UserBean(@NotNull String userName, @NotNull String password) {
Intrinsics.checkParameterIsNotNull(userName, "userName");
Intrinsics.checkParameterIsNotNull(password, "password");
super();
this.userName = userName;
this.password = password;
}
@NotNull
public final String component1() {
return this.userName;
}
@NotNull
public final String component2() {
return this.password;
}
@NotNull
public final UserBean copy(@NotNull String userName, @NotNull String password) {
Intrinsics.checkParameterIsNotNull(userName, "userName");
Intrinsics.checkParameterIsNotNull(password, "password");
return new UserBean(userName, password);
}
// $FF: synthetic method
public static UserBean copy$default(UserBean var0, String var1, String var2, int var3, Object var4) {
if ((var3 & 1) != 0) {
var1 = var0.userName;
}
if ((var3 & 2) != 0) {
var2 = var0.password;
}
return var0.copy(var1, var2);
}
@NotNull
public String toString() {
return "UserBean(userName=" + this.userName + ", password=" + this.password + ")";
}
public int hashCode() {
String var10000 = this.userName;
int var1 = (var10000 != null ? var10000.hashCode() : 0) * 31;
String var10001 = this.password;
return var1 + (var10001 != null ? var10001.hashCode() : 0);
}
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (var1 instanceof UserBean) {
UserBean var2 = (UserBean)var1;
if (Intrinsics.areEqual(this.userName, var2.userName) && Intrinsics.areEqual(this.password, var2.password)) {
return true;
}
}
return false;
} else {
return true;
}
}
}6.5、Kotlin的Object和伴生对象companion object
Kotlin的単例模式Object类
object ObjectTest {
fun showToast(){
}
}
//调用
fun main() {
ObjectTest.showToast()
}转成Java之后的代码
public final class ObjectTest {
public static final ObjectTest INSTANCE;
public final void showToast() {
}
private ObjectTest() {
}
static {
ObjectTest var0 = new ObjectTest();
INSTANCE = var0;
}
}伴生对象companionobject,为了方便理解咱们先上代码
class CompanionObjectTest {
companion object{
val name="爱码士"
fun show(){
name.length
}
}
}
//调用
fun main() {
CompanionObjectTest.show()
}转Java之后
public final class CompanionObjectTest {
@NotNull
private static final String name = "爱码士";
public static final CompanionObjectTest.Companion Companion = new CompanionObjectTest.Companion((DefaultConstructorMarker)null);
@Metadata(
mv = {1, 1, 15},
bv = {1, 0, 3},
k = 1,
d1 = {"\u0000\u001a\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0002\b\u0003\n\u0002\u0010\u0002\n\u0000\b\u0086\u0003\u0018\u00002\u00020\u0001B\u0007\b\u0002¢\u0006\u0002\u0010\u0002J\u0006\u0010\u0007\u001a\u00020\bR\u0014\u0010\u0003\u001a\u00020\u0004X\u0086D¢\u0006\b\n\u0000\u001a\u0004\b\u0005\u0010\u0006¨\u0006\t"},
d2 = {"Lsimple01/CompanionObjectTest$Companion;", "", "()V", "name", "", "getName", "()Ljava/lang/String;", "show", "", "kotlindemo"}
)
public static final class Companion {
@NotNull
public final String getName() {
return CompanionObjectTest.name;
}
public final void show() {
((CompanionObjectTest.Companion)this).getName().length();
}
private Companion() {
}
// $FF: synthetic method
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}
//调用
public static final void main() {
CompanionObjectTest.Companion.show();
}
// $FF: synthetic method
public static void main(String[] var0) {
main();
}所谓的伴生对象,就是伴随着出生的对象,直接在类初始化的时候,这个伴生对象Companion 也跟着实例化了,并且将伴生对象的属性变成了此类的静态变量,调用方法的时候,也是类直接调用静态属性Companion,然后再调用show方法
kotlin的内部类
class Test {
val I = "AAAA"
// 这个不是一个内部类,所有拿不到外部类的成员
// 嵌套类 = 可以在类的里面再写一个类,但是这个类不是内部类
class Sub {
fun show() {
println()
}
class A {
class B {
class C {
}
}
}
}
// 这个才是内部类,用inner修饰之后才是内部类
inner class Sub2 {
fun show() {
println(I)
}
}
}相关推荐
- oracle数据导入导出_oracle数据导入导出工具
-
关于oracle的数据导入导出,这个功能的使用场景,一般是换服务环境,把原先的oracle数据导入到另外一台oracle数据库,或者导出备份使用。只不过oracle的导入导出命令不好记忆,稍稍有点复杂...
- 继续学习Python中的while true/break语句
-
上次讲到if语句的用法,大家在微信公众号问了小编很多问题,那么小编在这几种解决一下,1.else和elif是子模块,不能单独使用2.一个if语句中可以包括很多个elif语句,但结尾只能有一个...
- python continue和break的区别_python中break语句和continue语句的区别
-
python中循环语句经常会使用continue和break,那么这2者的区别是?continue是跳出本次循环,进行下一次循环;break是跳出整个循环;例如:...
- 简单学Python——关键字6——break和continue
-
Python退出循环,有break语句和continue语句两种实现方式。break语句和continue语句的区别:break语句作用是终止循环。continue语句作用是跳出本轮循环,继续下一次循...
- 2-1,0基础学Python之 break退出循环、 continue继续循环 多重循
-
用for循环或者while循环时,如果要在循环体内直接退出循环,可以使用break语句。比如计算1至100的整数和,我们用while来实现:sum=0x=1whileTrue...
- Python 中 break 和 continue 傻傻分不清
-
大家好啊,我是大田。...
- python中的流程控制语句:continue、break 和 return使用方法
-
Python中,continue、break和return是控制流程的关键语句,用于在循环或函数中提前退出或跳过某些操作。它们的用途和区别如下:1.continue(跳过当前循环的剩余部分,进...
- L017:continue和break - 教程文案
-
continue和break在Python中,continue和break是用于控制循环(如for和while)执行流程的关键字,它们的作用如下:1.continue:跳过当前迭代,...
- 作为前端开发者,你都经历过怎样的面试?
-
已经裸辞1个月了,最近开始投简历找工作,遇到各种各样的面试,今天分享一下。其实在职的时候也做过面试官,面试官时,感觉自己问的问题很难区分候选人的能力,最好的办法就是看看候选人的github上的代码仓库...
- 面试被问 const 是否不可变?这样回答才显功底
-
作为前端开发者,我在学习ES6特性时,总被const的"善变"搞得一头雾水——为什么用const声明的数组还能push元素?为什么基本类型赋值就会报错?直到翻遍MDN文档、对着内存图反...
- 2023金九银十必看前端面试题!2w字精品!
-
导文2023金九银十必看前端面试题!金九银十黄金期来了想要跳槽的小伙伴快来看啊CSS1.请解释CSS的盒模型是什么,并描述其组成部分。...
- 前端面试总结_前端面试题整理
-
记得当时大二的时候,看到实验室的学长学姐忙于各种春招,有些收获了大厂offer,有些还在苦苦面试,其实那时候的心里还蛮忐忑的,不知道自己大三的时候会是什么样的一个水平,所以从19年的寒假放完,大二下学...
- 由浅入深,66条JavaScript面试知识点(七)
-
作者:JakeZhang转发链接:https://juejin.im/post/5ef8377f6fb9a07e693a6061目录...
- 2024前端面试真题之—VUE篇_前端面试题vue2020及答案
-
添加图片注释,不超过140字(可选)...
- 今年最常见的前端面试题,你会做几道?
-
在面试或招聘前端开发人员时,期望、现实和需求之间总是存在着巨大差距。面试其实是一个交流想法的地方,挑战人们的思考方式,并客观地分析给定的问题。可以通过面试了解人们如何做出决策,了解一个人对技术和解决问...
- 一周热门
- 最近发表
-
- oracle数据导入导出_oracle数据导入导出工具
- 继续学习Python中的while true/break语句
- python continue和break的区别_python中break语句和continue语句的区别
- 简单学Python——关键字6——break和continue
- 2-1,0基础学Python之 break退出循环、 continue继续循环 多重循
- Python 中 break 和 continue 傻傻分不清
- python中的流程控制语句:continue、break 和 return使用方法
- L017:continue和break - 教程文案
- 作为前端开发者,你都经历过怎样的面试?
- 面试被问 const 是否不可变?这样回答才显功底
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)
