文章目录
kotlin的历史Kotlin的工作原理 语言类型 编译型解释型 Java的语言类型Kotlin的运行原理 创建Kotlin项目语法 变量 变量的声明基本类型var和val的本质区别 函数 函数的声明声明技巧函数的调用 if语句 ifwhen 循环语句类和对象 类的创建和对象的初始化继承构造 主构造次构造无主构造 接口 接口的定义接口的继承 权限修饰符数据类和单例类 数据类单例类 Lambda 集合的创建和遍历 ListSetMap Lambda的使用 Java函数式API的使用空指针检查机制 判空辅助工具 ?.?:!! let函数全局判空注意事项 内嵌表达式函数的参数默认值kotlin的历史
Kotlin由JetBrains公司开发设计,公布第一版,开源。
发布1.0正式版,并且JetBrains在IDEA加入对Kotlin的支持,安卓自此又有新的选择。
谷歌宣布Kotlin
成为安卓第一开发语言,安卓程序员由java
转Kotlin
已经迫在眉睫。
Kotlin的工作原理
语言分为解释型和编译型两种
语言类型
编译型
编译器直接将源代码一次性编译成二进制文件,计算机可直接执行,例如C,C++
。
优点:一次编译,即可运行,运行期不需要编译,运行效率高。
缺点:不同操作系统需要不同的机器码,且修改代码需要真个模块重新编译
解释型
程序运行时,解释器会将源码一行一行实时解析成二进制再执行。例如JS,Python
。
优点:平台兼容性好,安装对应的虚拟机即可运行。
缺点:运行时需要解释执行,效率较低。
Java的语言类型
java
准确来说属于混合型语言,但更偏向于解释型。
编译:java
存在JIT
和AOT
,JIT
即时编译将可将热点代码直接编译成机器码,AOT
预先编译可再安装时把代码编译成机器码
解释:java
运行时需编译成class
文件,java
虚拟机再解释执行.class
。
Kotlin的运行原理
java
虚拟机只认class
文件,虚拟机不会关心class
时java
文件编译来的,还是其他文件编译来的。那此时我们创造一套自己的语法规则,再做一个对应的编译器,,则可让我们的语言跑在java
虚拟机上。Kotlin
则是此原理,运行前会先编译成class
,再供java
虚拟机运行。
创建Kotlin项目
打开android studio
,在选择语言时,选择Kotlin
在包下创建kotlin
文件
创建File
命名为HelloWorld
敲入下面代码则可运行打印Hello World!
package com.hbsd.demofun main() {println("Hello World!")}
运行结果如下:
下面进入语法学习
语法
变量
变量的声明
Kotlin
使用var,val
来声明变量,注意:Kotlin
不再需要;
来结尾
var
可变变量,对应java
的非final
变量
var b = 1
val
不可变变量,对应java
的final
变量
val a = 1
两种变量并未声明类型,这是因为Kotlin
存在类型推导机制,上述的a,b
会默认为Int
。假设想声明具体类型,则需下面的方式
var c: Int = 1
基本类型
Kotlin
不再存在基本类型,将全部使用对象类型
var和val的本质区别
打开Kotlin
对应的Java
文件
再点击下方按钮
则可查看对应的Java
文件
public final class HelloWorldKt {private static final int a = 1;private static int b = 2;private static int c = 10;...}
发现val a
对应的为final
,var b
和var c
对应的为非final
Kotlin
此设计的原因则是防止非final的滥用,若一个变量永远不被修改则有必要给其加上final
,使其他人看代码时更好理解。
后期我们写代码时则可先使用val,若真的需要修改再改为var
函数
函数的声明
无参无返回值
fun test() {}
有参有返回值
参数的类型需要写在形参名后面中间使用:连接多个参数使用,分割",“返回值使用”:"拼接
fun add(a: Int, b: Int): Int {return a + b}
声明技巧
当函数体只有一行代码时可直接使用下面方式声明方法
fun add (a: Int, b: Int): Int = a + b
Kotlin
存在类型推导,返回值类型也可省略
fun add (a: Int, b: Int) = a + b
函数的调用
fun main() {test()println(add(1, 2))}//运行结果//test//3
if语句
Kotlin
中的选择控制有两种方式。if
和when
if
与Java
的if
区别不大,实现一个返回最大值的函数
fun max(a: Int, b: Int): Int {if (a > b) return aelse return b}
Kotli
n的if
可以包含返回值,if
语句的最后一行会作为返回值返回
fun max(a: Int, b: Int): Int {return if (a > b) a else b}
上述我们说过一行代码可省略返回值
fun max(a: Int, b: Int) = if (a > b) a else b
查看对应的Java
文件,其上述实现都与下面代码等价
public static final int max(int a, int b) {return a > b ? a : b;}
when
实现一个查询成绩的函数,用户传入名字,返回成绩级别
if实现
Kotlin
的if
语句必须要有else
,不然会报错
fun getScore(name: String) = if (name == "Tom") "不及格"else if (name == "Jim") "及格"else if (name == "Pony") "良好"else if (name == "Tony") "优秀"else "名字非法"
Kotlin
中==
等价于Java
的equals
比较的时是对象里的内容,===
等价于Java
的==
,比较的为对象的引用。
when实现
也必须实现else
,否则报错
fun getScore(name: String) = when(name) {"Tom" -> "不及格""Jim" -> "及格""Pony" -> "良好""Tony" -> "优秀"else -> "名字非法"}
when
支持参数检查
fun checkNumber(num: Number) {when (num) {is Int -> println("Int")is Double -> println("Double")else -> println("others")}}
when
也可不传递形参
使用Boolean使when更加灵活
fun getScore(name: String) = when {name == "Tom" -> "不及格"name == "Jim" -> "及格"name == "Pony" -> "良好"name == "Tony" -> "优秀"else -> "名字非法"}
-> 后不仅可以只执行一行代码,可以多行,看一个比较复杂的例子:
fun getScore(name: String) = when {//若name以Tom开头则命中此分支name.startsWith("Tom") -> {//处理println("你好,我是Tom开头的同学")"不及格"}name == "Jim" -> "及格"name == "Pony" -> "良好"name == "Tony" -> "优秀"else -> "名字非法"}
循环语句
Kotlin
有两种循环方式,while和for-in,while
与java
中的while
没有区别,for-in是对Java for-each
的加强,Kotlin
舍弃了for-i
的写法
while
不再赘述,在学习for-in
之前需要明确一个概念-区间
val range = 0..10 //区间代表[0,10]
for-in
需借助区间来使用
fun main() {val range = 0..10for (i in range) { //也可直接for (i in 0..10)println(i)}//输出结果为 从0打印到10}
0..10
代表双闭区间,如果想使用左闭右开呢,需要借助until
关键字
fun main() {for (i in 0 until 10) {println(i)}//输出结果为 从0打印到9}
上述实现是逐步进行相当于i++
,Kotlin
也支持跳步
fun main() {for (i in 0 until 10 step 2) {println(i)}//输出结果为0,2,4,6,8}
上述实现都是升序,Kotlin
也可降序循环
fun main() {for (i in 10 downTo 1) {println(i)}//输出结果为10 - 1}
for-in
不仅可对区间进行遍历,还可对集合进行遍历,后续在集合处进行展示。
类和对象
类的创建和对象的初始化
在创建页面选择Class
创建
创建Person
类,并声明name
,age
,创建printInfo
方法
class Person {var name = ""var age = 0fun printInfo() {println(name +"'s age is " + age)}}
在main
方法中声明一个Person
对象并调用printInfo
方法
fun main() {val person = Person()person.name = "zjm"person.age = 20person.printInfo()}//结果如下zjm's age is 20
继承
声明Student
类继承Person
,Kotlin
中继承使用**:**,后接父类的构造,为什么需要构造后续讲解
class Student : Person(){ //此时Person报错var number = ""var grade = 0fun study() {println(name + "is studying")}}
Person
类当前不可继承,查看Person
对应的java
文件
public final class Person {...}
Person
类为final
不可被继承,因此需借助open关键字
只需在Person
类前加上open
open class Person {...}
此时Person
的java
文件变为
public class Person {...}
此时Student
将不再报错
构造
构造分为主构造和此构造
主构造
主构造直接写在类后面
修改Student
类
class Student(val number: String, val grade: Int) : Person(){...}
在创建Student
对象时,如下创建
val student = Student("1234", 90)
因之前Person
还有name
和age
,下面修改Person
类的主构造
open class Person(val name: String, val age: Int) {...}
此时Student
报错,因为继承Person
时,后边使用的是Person()
无参构造,上面我们修改了Person
的构造,则不存在无参构造了。
再修改Student
class Student(name: String, age: Int, val number: String, val grade: Int) : Person(name, age){...}
此时不在报错,声明方式如下
val student = Student("zjm", 20, "1234", 90)
在构造时需要进行特殊处理怎么办,Kotlin提供了init结构体,主构造的逻辑可在init
中处理
open class Person(val name: String, val age: Int) {init {println("name is" + name)println("age is" + age)}}
上述修改都为主构造,那如果类想有多个构造怎么办,此时需借助次构造
次构造
此时实现Student
的另外两个构造
三个参数的构造,name
,age
,number
,grade
不传参默认为``0
无参构造,字符串默认为"",int默认为0
class Student(name: String, age: Int, val number: String, val grade: Int) : Person(name, age){constructor(name: String, age: Int, number: String) : this(name, age, number, 0) {}constructor() : this("", 0, "", 0) {}...}
创建如下:
fun main() {val student1 = Student("zjm", 20, "123", 90)val student2 = Student("zjm", 20, "123")val student3 = Student()}
无主构造
若类不使用主构造,则后续继承类也不需要使用构造即可去掉继承类的()
,次构造可以调用父类构造super
进行初始化,但是次构造的参数在其他地方无法引用
class Student : Person {constructor(name: String, age: Int, number: String) : super(name, age) {}fun study() {//name,age可使用println(name + "is studying")//使用number则会报错,若number是主构造的参数则可引用//println(number) 报红}}
接口
接口的定义
和Java
中的接口定义类似
interface Study {fun study()fun readBooks()fun doHomework()}
接口的继承
继承接口只需在后用","
拼接,需实现Study
声明的全部函数
class Student(name: String, age: Int, val number: String, val grade: Int) : Person(name, age), Study{...override fun study() {TODO("Not yet implemented")}override fun readBooks() {TODO("Not yet implemented")}override fun doHomework() {TODO("Not yet implemented")}}
Kotlin
支持接口方法的默认实现,JDK1.8
以后也支持此功能,方法有默认实现则继承类无需必须实现此方法
interface Study {fun study() {println("study")}fun readBooks()fun doHomework()}
权限修饰符
Java
和Kotlin
的不同如下表所示:
Kotlin
引入internal
,摒弃了default
使用:
类上
public open class Person(val name: String, val age: Int){...}
变量上
private val value = 1
方法上
private fun test() {}
数据类和单例类
数据类
数据类则只处理数据相关,与Java Bean
类似,通常需要实现其get
,set
,hashCode
,equals
,toString
等方法
下面实现UserBean
,包含id
,name
,pwd
属性
Java
编写入如下:
public class UserBean {private String id;private String name;private String pwd;public UserBean() {}public UserBean(String id, String name, String pwd) {this.id = id;this.name = name;this.pwd = pwd;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;UserBean userBean = (UserBean) o;return Objects.equals(id, userBean.id) && Objects.equals(name, userBean.name) && Objects.equals(pwd, userBean.pwd);}@Overridepublic int hashCode() {return Objects.hash(id, name, pwd);}@Overridepublic String toString() {return "UserBean{" +"id='" + id + '\'' +", name='" + name + '\'' +", pwd='" + pwd + '\'' +'}';}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPwd() {return pwd;}public void setPwd(String pwd) {this.pwd = pwd;}}
Kotlin
编写此类将变得非常简单,新建一个kt
文件,选择如下:
一行代码即可搞定,Kotlin会自动实现上述方法。
data class UserBean(val id: String, val name: String, val pwd: String)
若无data
关键字,上述方法(hashCode
,equals
,toString
)无法正常运行,去掉data
查看Kotlin
对应的java
文件:
public final class UserBean {@NotNullprivate final String id;@NotNullprivate final String name;@NotNullprivate final String pwd;@NotNullpublic final String getId() {return this.id;}@NotNullpublic final String getName() {return this.name;}@NotNullpublic final String getPwd() {return this.pwd;}public UserBean(@NotNull String id, @NotNull String name, @NotNull String pwd) {Intrinsics.checkNotNullParameter(id, "id");Intrinsics.checkNotNullParameter(name, "name");Intrinsics.checkNotNullParameter(pwd, "pwd");super();this.id = id;this.name = name;this.pwd = pwd;}}
发现上面代码既无hashCode
,equals
,toString
也无set
加上data
且把变量改为var
,对应的java
文件如下:
public final class UserBean {@NotNullprivate String id;@NotNullprivate String name;@NotNullprivate String pwd;@NotNullpublic final String getId() {return this.id;}public final void setId(@NotNull String var1) {Intrinsics.checkNotNullParameter(var1, "<set-?>");this.id = var1;}@NotNullpublic final String getName() {return this.name;}public final void setName(@NotNull String var1) {Intrinsics.checkNotNullParameter(var1, "<set-?>");this.name = var1;}@NotNullpublic final String getPwd() {return this.pwd;}public final void setPwd(@NotNull String var1) {Intrinsics.checkNotNullParameter(var1, "<set-?>");this.pwd = var1;}public UserBean(@NotNull String id, @NotNull String name, @NotNull String pwd) {Intrinsics.checkNotNullParameter(id, "id");Intrinsics.checkNotNullParameter(name, "name");Intrinsics.checkNotNullParameter(pwd, "pwd");super();this.id = id;this.name = name;this.pwd = pwd;}@NotNullpublic final String component1() {return this.id;}@NotNullpublic final String component2() {return this.name;}@NotNullpublic final String component3() {return this.pwd;}@NotNullpublic final UserBean copy(@NotNull String id, @NotNull String name, @NotNull String pwd) {Intrinsics.checkNotNullParameter(id, "id");Intrinsics.checkNotNullParameter(name, "name");Intrinsics.checkNotNullParameter(pwd, "pwd");return new UserBean(id, name, pwd);}// $FF: synthetic methodpublic static UserBean copy$default(UserBean var0, String var1, String var2, String var3, int var4, Object var5) {if ((var4 & 1) != 0) {var1 = var0.id;}if ((var4 & 2) != 0) {var2 = var0.name;}if ((var4 & 4) != 0) {var3 = var0.pwd;}return var0.copy(var1, var2, var3);}@NotNullpublic String toString() {return "UserBean(id=" + this.id + ", name=" + this.name + ", pwd=" + this.pwd + ")";}public int hashCode() {String var10000 = this.id;int var1 = (var10000 != null ? var10000.hashCode() : 0) * 31;String var10001 = this.name;var1 = (var1 + (var10001 != null ? var10001.hashCode() : 0)) * 31;var10001 = this.pwd;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.id, var2.id) && Intrinsics.areEqual(this.name, var2.name) && Intrinsics.areEqual(this.pwd, var2.pwd)) {return true;}}return false;} else {return true;}}}
此时则和手动编写的java bean
功能一样了,所有方法都可正常运行
单例类
目前Java
使用最广的单例模式的实现如下:
public class Singleton {private Singleton() {}private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return SingletonHolder.INSTANCE;}public void test() {...}}
在Kotlin
中创建单例类需选择Object
生成代码如下:
object Singleton {fun test() {...}}
其对应的java
文件如下,和上述使用最多的java
单例实现类似
public final class Singleton {@NotNullpublic static final Singleton INSTANCE;public final void test() {}private Singleton() {}static {Singleton var0 = new Singleton();INSTANCE = var0;}}
使用如下:
fun main() {Singleton.test() //对应的java代码为Singleton.INSTANCE.test();}
Lambda
许多高级语言都支持Lambda
,java
在jdk1.8
以后才支持Lamda
语法,Lamda
是Kotlin
的灵魂所在,此小节对Lambda
的基础进行学习,并借助集合练习。
集合的创建和遍历
List
fun main() {//常规创建val list = ArrayList<Int>()list.add(1)list.add(2)list.add(3)//listOf不可变,后续不可添加删除,只能查val list1 = listOf<Int>(1, 2, 3 ,4 ,5)list1.add(6)//报错//mutableListOf,后续可添加删除val list2 = mutableListOf<Int>(1, 2, 3 ,4 ,5)list2.add(6)//循环for (value in list2) {println(value)}}
Set
set
用法与List
类似,只是把listOf
替换为mapOf
Map
fun main() {val map = HashMap<String, String>()map.put("1", "zjm")map.put("2", "ljn")//Kotlin中map支持类似下标的赋值和访问map["3"] = "lsb"map["4"] = "lyx"println(map["2"])println(map.get("1"))//不可变val map1 = mapOf<String, String>("1" to "zjm", "2" to "ljn")map1["3"] = "lsb" //报错//可变val map2 = mutableMapOf<String, String>("1" to "zjm", "2" to "ljn")map2["3"] = "lsb"for ((key, value) in map) {println(key + " " + value)}}
Lambda的使用
方法在传递参数时都是普通变量,而Lambda
可以传递一段代码
Lambda
表达式的语法结构
{参数名1: 参数类型, 参数名2:参数类型 -> 函数体}
Kotlin
的list
提供了maxByOrNull
函数,返回当前list
中xx最大的元素,XX是我们定义的条件,可能为长度,可能是别的,我们拿长度举例。
若不使用maxBy
,实现如下
fun main() {val list = listOf<String>("a", "aba", "aabb", "a")var maxStr = ""for (str in list) {if (str.length > maxStr.length) {maxStr = str;}}println(maxStr)}
maxByOrNull
是一个普通方法,需要一个Lambda
参数,下面结合Lambda
使用maxByOrNull
fun main() {val list = listOf<String>("a", "aba", "aabb", "a")var lambda = {str: String -> str.length}var maxStr = list.maxByOrNull(lambda)println(maxStr)}
直接当成参数也可传递
var maxStr = list.maxByOrNull({str: String -> str.length})
若Lambda
为方法的最后一个参数,则可将{}
提到外面
var maxStr = list.maxByOrNull() {str: String -> str.length}
若有且仅有一个参数且是Lambda
,则可去掉()
var maxStr = list.maxByOrNull {str: String -> str.length}
Kotlin
拥有出色的类型推导机制,Lambda
参数过多时可省略参数类型
var maxStr = list.maxByOrNull {str -> str.length}
若Lambda
只有一个参数,则可用it
替代参数名
var maxStr = list.maxByOrNull {it.length}
集合还有许多此类函数
创建list,后续操作都由此list
转换
val list = listOf<String>("a", "aba", "aabb", "a")
map
映射,返回新集合,将集合中的元素映射成另一个值
val newList = list.map { it.toUpperCase() }//将集合中的元素都准换成大写
filter
过滤,返回新集合,将集合中的元素进行筛选
val newList = list.filter { it.length > 3 }//筛选出长度大于3的元素
any
返回Boolean
,集合中是否存在元素满足Lambda
的条件,有则返回true
,无则false
val isAny = list.any {it.length > 10} //返回false
all
返回Boolean
,集合中元素是否全部满足满足Lambda
的条件,有则返回true
,无则false
val isAll = list.all {it.length > 0} //返回true
Lambda
的简单使用到这就结束了
Java函数式API的使用
Kotlin
调用Java
方法,若该方法接收一个Java
单抽象方法接口参数,则可使用函数式API
。Java
单抽象方法接口指的是接口只声明一个方法,若有多个方法则无法使用函数式API
。
Java
单抽象方法接口例如Runnable
public interface Runnable {void run();}
在Java
中启动一个线程如下:
new Thread(new Runnable() {@Overridepublic void run() {System.out.println("test");}}).start();
Kotlin
启动线程如下:
Kotlin
摒弃了new
,若想声明匿名内部类必须使用object
Thread(object : Runnable {override fun run() {println("test")}}).start()
因Runnable
是Java
单抽象方法接口,可对代码进行简化
Thread(Runnable {println("test")}).start()
Runnable
接口只用一个方法,使用Lambda
也不会有歧义,Kotlin
知道此Lambda
一定实现的为run
函数,借用Lambda
进一步简化:
Thread({println("test")}).start()
又因Thread
只需一个参数Runnable
参数,则可省略()
Thread {println("test")}.start()
与上类似的,click
也使用上述方法
button.setOnClickListener { println("test") }
这种方式可极大缩减代码量
空指针检查机制
国外统计程序出现最多的异常为空指针异常,Kotlin
存在编译时检查系统帮助我们发现空指针异常。
查看下面Java
代码
public void doStudy(Study study) {study.doHomework();study.readBooks();}
上述代码时存在空指针风险的,传入null,则程序崩溃,对其进行改进
public void doStudy(Study study) {if (study != null) {study.doHomework();study.readBooks();}}
对于Kotlin
来讲任何参数和变量不能为空
fun study(study: Study) {study.doHomework()study.readBooks()}fun main() {study(null) //报错study(Student()) //正确}
Kotlin
把空指针异常的检查提前到了编译期,若空指针则编译期就会崩溃,避免在运行期出现问题
若我们有特殊的需求可能需要传递null参数,参数则按照下面声明
fun study(study: Study?) {study.doHomework() //报错study.readBooks()//报错}
?
的意思则是当前参数可为空,如果可为空的话,则此对象调用的方法必须要保证对象不为空,上面代码没有保证,则报错,修改如下
fun study(study: Study?) {if (study != null) {study.doHomework()study.readBooks()}}
也可借助判空辅助工具
判空辅助工具
?.
其含义是?
前面对象不为空才执行.
后面的方法
fun study(study: Study?) {study?.doHomework()study?.readBooks()}
?:
其含义是?
前不为空则返回问号前的值,为空则返回:
后的值
比如
val c = if (a !=null ) {a} else {b}
借助?:
则可简化为
val c = a ?: b
再比如
fun getTextLength(text: String?): Int {if (text != null) {return text.length}return 0}
借助?:
则可简化为
fun getTextLength(text: String?) = text?.length ?: 0
!!
有些时候我们想要强行通过编译,就需要依靠!!,这时就是程序员来保证安全
fun study(study: Study?) {//假设此时为空抛出异常,则和java一样study!!.doHomework()study!!.readBooks()}
let函数
let
不是关键字,而是一个函数,提供了函数式API
的编程接口,会将调用者作为参数传递到Lambda
表达式,调用之后会立马执行Lambda
表达式的逻辑
obj.let { it -> //it就是obj//编写操作}
比如上面函数
fun study(study: Study?) {study.doHomework() //报错study.readBooks()//报错}
借助let
则可改为
fun study(study: Study?) {//此时靠?.则保证了study肯定不为空,才会执行let函数study?.let {//it为studyit.doHomework()it.readBooks()}}
全局判空注意事项
//全局变量var study: Study? = nullfun study() {//报错if (study != null) {study.readBooks()study.doHomework()}}
因全局变量随时有可能被其他线程修改,即使判空处理也不能保证其没有空指针风险,而let
则可规避上述问题
var study: Study? = nullfun study() {study?.let {it.doHomework()it.readBooks()}}
内嵌表达式
之前我们拼接字符串都是下面这样
var name = "zjm"var age = 20println("My name is " + name + ". I am " + age + ".")//打印结果//My name is zjm. I am 20.
现在靠着Kotlin
提供的内嵌表达式则不需要拼接,只需要下面这样则可实现
var name = "zjm"var age = 20println("My name is $name. I am $age." )//打印结果//My name is zjm. I am 20.
内嵌表达式还支持复杂的操作
${程序员想要的操作}
var name = "zjm"var age = 20println("My name is ${if (1 < 2) "zjm" else "ljn"}. I am $age." )//打印结果//My name is zjm. I am 20.
函数的参数默认值
Kotlin
支持函数存在默认值,使用如下
fun main() {myPrint(1)myPrint(1, "lalala")}fun myPrint(value: Int, str: String = "hello") {println("num is $value, str is $str")}//结果如下//num is 1, str is hello//num is 1, str is lalala
若value
想为默认值,则会报错,因为在使用时传入的第一个参数他认为是int
的,传入字符串会类型不匹配
fun main() {myPrint("zjm")//报错}fun myPrint(value: Int = 100, str: String) {println("num is $value, str is $str")}
Kotlin
提供了一种键值对传参来解决上述问题
fun main() {myPrint(str = "zjm") //正确调用}fun myPrint(value: Int = 100, str: String) {println("num is $value, str is $str")}
回顾之前的主次构造,Student
如下
class Student(name: String, age: Int, val number: String, val grade: Int) : Person(name, age){constructor(name: String, age: Int, number: String) : this(name, age, number, 0) {}...}
上述的此构造借助参数默认值技巧是可以不写的,将第四个参数默认值为0 即可
class Student(name: String, age: Int, val number: String, val grade: Int = 0) : Person(name, age){...}
上述关于Kotlin
的使用,已经够日常开发需要,后续笔者会更新一些进阶使用
黑客&网络安全如何学习
今天只要你给我的文章点赞,我私藏的网安学习资料一样免费共享给你们,来看看有哪些东西。
1.学习路线图
攻击和防守要学的东西也不少,具体要学的东西我都写在了上面的路线图,如果你能学完它们,你去就业和接私活完全没有问题。
2.视频教程
网上虽然也有很多的学习资源,但基本上都残缺不全的,这是我自己录的网安视频教程,上面路线图的每一个知识点,我都有配套的视频讲解。
内容涵盖了网络安全法学习、网络安全运营等保测评、渗透测试基础、漏洞详解、计算机基础知识等,都是网络安全入门必知必会的学习内容。
(都打包成一块的了,不能一一展开,总共300多集)
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享
3.技术文档和电子书
技术文档也是我自己整理的,包括我参加大型网安行动、CTF和挖SRC漏洞的经验和技术要点,电子书也有200多本,由于内容的敏感性,我就不一一展示了。
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享
4.工具包、面试题和源码
“工欲善其事必先利其器”我为大家总结出了最受欢迎的几十款款黑客工具。涉及范围主要集中在 信息收集、Android黑客工具、自动化工具、网络钓鱼等,感兴趣的同学不容错过。
还有我视频里讲的案例源码和对应的工具包,需要的话也可以拿走。
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享
最后就是我这几年整理的网安方面的面试题,如果你是要找网安方面的工作,它们绝对能帮你大忙。
这些题目都是大家在面试深信服、奇安信、腾讯或者其它大厂面试时经常遇到的,如果大家有好的题目或者好的见解欢迎分享。
参考解析:深信服官网、奇安信官网、Freebuf、csdn等
内容特点:条理清晰,含图像化表示更加易懂。
内容概要:包括 内网、操作系统、协议、渗透测试、安服、漏洞、注入、XSS、CSRF、SSRF、文件上传、文件下载、文件包含、XXE、逻辑漏洞、工具、SQLmap、NMAP、BP、MSF…
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享