3. inline内联声明当一种函数内部不需要在传递参数给其他函数时,使用该关键字编译器可以直接将函数与我们的调用替换。
6. 伴生对象与匿名内部类
- Kotlin中并没有延用static这个关键字,而是使用伴生对象实现,在class内部声明一个companion object代码块,其内部的成员变量和方法都将被编译成为静态的。
- 针对那些获取抽象类或者接口对象而来的。最常见的匿名内部类点击事件。会用到
object。 - 区别:companion object代码块中的成员变量最终会被声明到外部类中,也这是为什么我们能通过外部类名直接访问,而object类则需要用外部类.内部类的方式调。
- 匿名内部类
- 伴生对象类似一个单例,其与JvmStatic静态方法不同,详细可以看这篇文章
5.1 kotlin 中 @JvmStatic 注解的作用。ps:binding方法也要用这个
7. 嵌套类与内部类
-
一个类内部声明在另一个类内部,默认情况下,称为嵌套类。Kotlin的嵌套类和Java的静态内部类相似,不能访问外层类的实例成员。
-
内部类持有外层类对象的引用,可以访问外层类的实例成员,使用inner标记
//嵌套类和内部类调用都是两层级嵌套,inner标记的好处是可以持有外部类的一个对象引用。
-
匿名内部类:采用对象表达式来创建接口对象,即匿名内部类的实例。
1)来自知乎,匿名内部类
2)首先有一个接口,接口内含一个待实现方法
3)创建一个方法,参数是哪个接口对象,利用这个对象实现接口方法
window.addMouseListener(object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) { …… }
override fun mouseEntered(e: MouseEvent) { …… }
})
- Map使用的好处
8.5泛型的使用
11. 函数类型通项式:(A, B) -> C
- (x: Int, y: Int) -> Point
- 通过A.方法指定接收者对象 A.(B) -> C
- Kotlin中的Unit,Any和Nothing
3.1 Unit相当于Void
3.2 Any相当于非空的Object,Any?为可空,其为Any的父类
12. Lambda表达式
- val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
- 利用自动推断模式:val sum = { x, y -> x + y }
- 其中只有一个参数,编译器可以自动识别签名,就可以不用声明唯一的参数并且省略 -> , 该参数会隐式声明为 it
fun isActivityOncreate(): Boolean //Ac中提供return
fun isTemplateIdleTop(): (Boolean) -> Unit //ac中提供方法
两种方法本质上都是adapter调用,Ac提供实现
adapter中写个接口 可供ac实现 ac给个return值 adapte中可以拿到
interface adapterListener {
fun isActivityOncreate(): Boolean
}
adapter想传给ac 写个lambda函数,外面传的是函数的实现{},adapter里面调方法名和参数
private var clickBlock: (Int, Int, TemplateItem) -> Unit
//如果是个Boolean ac需要传个boolean
// 这种写法相当于传一个表达式给adapter中,这个表达式可用括号里的参数,adapter提供参数,具体方法靠外界传,内部相应的invoke即可执行,但无法获取最后一行返回值 clickBlock: ((Int, Int, TemplateItem) -> Unit )这样就可以获取最后一行返回值
//两个的回调可以这么写
successBlock = { localList ->
},
failBlock = {
}
15.注解
- 定义:把元数据(Metadata)附加到代码上,然后可以在编译期或运行期访问这些元数据
- 举例 :比方是要调一个参数或方法,程序通过上下文没法指定,就用这个来(普通注解)
@Fancy class Foo {
@Fancy fun baz(@Fancy foo: Int): Int {
return (@Fancy 1)
}
}
- 元注解
Kotlin标准库中定义了以下元注解:
@Target 指定可以用该注解标注的元素的可能的类型(类、函数、属性、表达式等);
@Retention 指定该注解是否存储在编译后的 class 文件中,以及它在运行时能否通过反射可见 (默认都是 true);
@Repeatable 允许在单个元素上多次使用相同的该注解;
@MustBeDocumented 指定该注解是公有 API 的一部分,并且应该包含在生成的 API 文档中显示的类或方法的签名中。
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION,AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
@MustBeDocumented
annotation class Fancy
大部分相关的类位于包kotlin.annotation中
四:java式代码转Kotlin例子
例一:
- 这个例子java口味非常重【LocalMusicAdapter】kotlin的主构造方法传入两个参数,var一下之后 内部就可以直接用【就相当于构造方法初始化过了】
1)注释掉的那个构造方法,十分明确的java构造写法,kotlin特性直接在主构造方法传入两个参数,var一下之后 内部就可以直接用
2)ViewHolder初始化,接着使用init方法自动初始化就好了
package com.ywjh.localfaraway
class LocalMusicAdapter(): RecyclerView.Adapter<LocalMusicAdapter.LocalMusicViewHolder>() {
//传入数据源
var context: Context?=null
var mDatas: MutableList<LocalMusicBean>? = null
//创建构造方法
constructor(context: Context?, mDatas: MutableList<LocalMusicBean>?) : this() {
this.context = context
this.mDatas = mDatas
}
// fun LocalMusicAdapter(context: Context, mDatas: List<LocalMusicBean>) {
// this.context = context
// this.mDatas = mDatas
// }
//创建并返回 ViewHolder 生成与初始化
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LocalMusicViewHolder {
val view = LayoutInflater.from(context).inflate(R.layout.item_local_music, parent, false)
val holder = LocalMusicViewHolder(view)
return holder
}
//返回条目数量
override fun getItemCount(): Int {
return mDatas!!.size
}
//绑定Viewholder 拿到holser后对TextView进行设置
override fun onBindViewHolder(holder: LocalMusicViewHolder, position: Int) {
val musicBean = mDatas?.get(position)
holder.idTv?.setText(musicBean!!.getId())
holder.songTv?.setText(musicBean!!.getSong())
holder.singerTv?.setText(musicBean!!.getSinger())
holder.albumTv?.setText(musicBean!!.getAlbum())
holder.timeTv?.setText(musicBean!!.getDuration())
//holder.itemView.setOnClickListener { v -> onItemClickListener.OnItemClick(v, position) }
}
class LocalMusicViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
//继承recycleView和ViewHolder内部类
var idTv: TextView? = null
var songTv:TextView? = null
var singerTv:TextView? = null
var albumTv:TextView? = null
var timeTv:TextView? = null
public fun LocalMusicViewHolder(itemView: View) {//kotlin 当中没有这种构造方法,所有不会进行初始化
idTv = itemView.findViewById(R.id.item_local_music_num)
songTv = itemView.findViewById(R.id.item_local_music_song)
singerTv = itemView.findViewById(R.id.item_local_music_singer)
albumTv = itemView.findViewById(R.id.item_local_music_album)
timeTv = itemView.findViewById(R.id.item_local_music_durtion)
}
}
}
转kotlin
package com.ywjh.localfaraway
class LocalMusicAdapter(internal var context: Context, internal var mDatas: List<LocalMusicBean>) ://传入上下文和List
RecyclerView.Adapter<LocalMusicAdapter.LocalMusicViewHolder>() {//kotlin设置数据源可以直接放里面
//J1:写一个接口 含有一个方法获取 用于(获取)传入View以及位置
interface OnItemClickListenerM {
fun OnItemClick(view: View, position: Int)//点击位置的position传进去
}
//j2通过函数传递接口 创建接口对象实现
internal lateinit var onItemClickListenerm: OnItemClickListenerM
//j3 对象
fun setOnItemClickListenerM(onItemClickListenerm: OnItemClickListenerM) {//该接口对象初始化
this.onItemClickListenerm = onItemClickListenerm
}
//v1先定义Viewholde内部类 这里定义的itemView是可以直接用的
inner class LocalMusicViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {//直接构造方法拿到View
//var idTv: TextView 核心是拿到View
var albumIg:ImageView?=null
var songTv: TextView
var singerTv: TextView
var albumTv: TextView
var timeTv: TextView
//v2.用于显示到View界面上
init {
//idTv = itemView.findViewById(R.id.item_local_music_num)
albumIg= itemView.findViewById(R.id.item_local_music_albumpic)
songTv = itemView.findViewById(R.id.item_local_music_song)
songTv = itemView.findViewById(R.id.item_local_music_song)
singerTv = itemView.findViewById(R.id.item_local_music_singer)
albumTv = itemView.findViewById(R.id.item_local_music_album)
timeTv = itemView.findViewById(R.id.item_local_music_durtion)
}
}
//1获取context上下文 创建holder对象 通过View创建holder
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LocalMusicViewHolder {
val view = LayoutInflater.from(context).inflate(R.layout.item_local_music, parent, false)
val holder = LocalMusicViewHolder(view)//内部类holder
return holder//拿到holder也行
}
//绑定界面1.创建ViewHolder方法进行赋值 2.kotlin惰性加载
//2.点击事件:java 监听外层view 找每条holder的记录
//kotlin 定义
//recycleView和listview不一样 未封装成型的点击事件类
//在onbind中可以获取每项的itemview 设定一个接口 自己封装,调用onitemlistener
//2为子项赋值 每次回滚时执行实时富裕项目
override fun onBindViewHolder(holder: LocalMusicViewHolder, position: Int) {
var musicBean:LocalMusicBean ?=null
musicBean = mDatas[position]
// holder.idTv.setText(musicBean.getId())
holder.songTv.setText(musicBean.getSong())
holder.singerTv.setText(musicBean.getSinger())
holder.albumTv.setText(musicBean.getAlbum())
holder.timeTv.setText(musicBean.getDuration())
if (musicBean.getthumb()!=null)
holder.albumIg?.setImageBitmap(musicBean.getthumb())
holder.itemView.setOnClickListener { //每项被点击时实现接口回调 回调的数据是v和position
//监听父view 设置点击该view的 onItemClickListenerm赋予view和position
v -> onItemClickListenerm?.OnItemClick(v, position)
}
}
//3计数
override fun getItemCount(): Int {
return mDatas.size
}
}
例二
1.
import java.util.TreeMap
fun main(args: Array<String>) {
var a="zero"
val b:Long=1231
//类型转换
var l=12
var m="12"
l=m.toInt()
m=l.toString()
println(a)
println(b)
sayHello()
println(diary("panada"))
println(getmess(null))
var nums=1..10//声明数组区间
for(num in nums)
print(num)
//list 的引用
var lists= listOf("1","2",3)
// for(list in lists)
// print(list)
//有序列
for((i,e)in lists.withIndex()) {
println("$i $e")
}
//map运用 类似词典 且有索引
var map=TreeMap<String,String>()
map["好"]="good"
map["学"]="study"
map["向上"]="up"
println(map["好"])
print(z(3,5))
//ps调用float单精度area(3.0f,3.0f)
}
//函数
fun sayHello(){
println("Hello")
}
//无参数无返回类型
//fun sum(a: Int, b: Int): Int=x+y
fun sum(a: Int, b: Int): Int { // Int 参数,返回值 Int
return a + b
}
var z={x:Int,y:Int -> x+y}
var y:(Int,Int)->Int={x,y ->x+y}
//print包裹dollar参数取值
fun diary(place:String):String{
var message="你好${place}"
return message
}
//排除空指针异常+?表示传入可为“null”
fun getmess(mess:String?):String{
return "得到"+mess
}
//switch与when语句
fun grade(score:Int){
when(score){
10-> print("考了满分")
8-> print("考的不错")
else-> print("继续加油")
}
}
2.输入输出
fun main(args: Array<String>){
while (true){
println("请输入第一个数字")
var num1= readLine()
println("请输入第二个数字")
var num2= readLine()
//35字符串连接
/* var num3=num1?.toInt()
var num4=num1?.toInt()
println("${num3}+${num4}=${num3+num4}")*/
//?输入为空则空,但空和空无法相加会报错 !!抛出空指针异常
//更新输入a抛出异常,结合while就可以一直运行,不报运行代码错误
try {
var num3:Int=num1!!.toInt()
var num4:Int=num2!!.toInt()
println("${num3}+${num4}=${num3+num4}")
}catch (e:Exception){
println("大哥,你输入的有问题吧 ")
}
}
}
例三:读写流BufferedReader和BufferedWritersubstring() 方法 区间取值
import java.io.BufferedReader
import java.io.FileReader
import java.io.IOException
//导入java.io包下的BufferedReader类
//导入java.io包下的FileReader类
//导入java.io包下的IOException类
object SameAndDifferent {
//类名
@JvmStatic
fun main(args: Array<String>) { //程序主入口函数,带命令行参数
val Al1= ArrayList<String>()
try { //try代码块,当发生异常时会转到catch代码块中
//读取指定的文件
val inFile =
BufferedReader(FileReader("E:\\sametest\\sequence.txt"))
var str1: String? //定义一个字符串类型变量str
//var string1= arrayOfNulls<String>(1000)
var i = 0 //定义一个整型变量
while (inFile.readLine().also { str1 = it } != null) { //readLine()方法, 用于读取一行,只要读取内容不为空就一直执行
if(str1!!.indexOf("<h4>")!=-1&&str1!!.indexOf("</h4>")!=-1){
str1 = str1!!.substring(str1!!.indexOf(".html")+7, str1!!.indexOf("</a>"))
//第2799行:<h4><a href="../to-sorted-set.html">toSortedSet 测试
//str1 = str1!!.substring(str1!!.indexOf(".html'>")+1, str1!!.length)
//第2763行:<h4><a href="../to-mutable-list.html">toMutableList</a></h4>
// var str2=str1!!.substring(str1!!.indexOf(".html'>")+1, str1!!.indexOf("</a>"))
val bytes = str1!!.toByteArray() //获得字节数
val getname:String=str1!!.trim()
Al1.add(getname)
for (j in Al1) {
println(j)
}
//println(getname) //输出从每一行读取的内容
//println("第" + i + "行有" + bytes.size + "个字节" + str1!!.length + "个字符") //输出每一行的字符和字节个数
}
i++
}
} catch (e: IOException) { //当try代码块有异常时转到catch代码块
e.printStackTrace() //printStackTrace()方法是打印异常信息在程序中出错的位置及原因
}
例四:set集合的运用
import java.util.Collections.addAll
import java.util.ArrayList
import java.util.HashSet
fun main(args: Array<String>) {
val result = HashSet<Int>()
val set1 = object : HashSet<Int>() {
init {//伴生初始化方法
add(1)
add(3)
add(5)
}
}
val set2 = object : HashSet<Int>() {
init {
add(1)
add(2)
add(3)
}
}
result.clear()//result一个结果集 首先清除0
result.addAll(set1)//将set1结果集存入
println("去重复交集前1:$set1")
println("去重复交集前2:$set2")
result.retainAll(set2)//retatinAll(保留所有相同的结果集)
println("set1与set2的交集是:$result")
result.clear()
result.addAll(set2)
println("差集前的1:$set1")
println("差集前的2:$set2")
result.removeAll(set1)//移除即可
println("set2与set1的差集是:$result")
result.clear()
result.addAll(set1)
result.addAll(set2)
print("set1和set2的并集:$result")
System.err.print("set1集合并集:是去重复" + "\n")
val list = ArrayList<Int>()
val list1 = object : ArrayList<Int>() {
init {
add(1)
add(3)
add(5)
}
}
val list2 = object : ArrayList<Int>() {
init {
add(1)
add(2)
add(3)
}
}
list.clear()
list.addAll(list1)
println("去重复交集前1:$list1")
println("去重复交集前2:$list2")
list.retainAll(list2)
println("list1与list2的交集是:$list")
list.clear()
list.addAll(list2)
println("差集前的1:$list1")
println("差集前的2:$list2")
list.removeAll(list1)
println("list2与list1的差集是:$list")
list.clear()
list.addAll(list1)
list.addAll(list2)
print("list1和set2的并集:$list")
System.err.print("List集合并集:是不会去重复")
}
例五:数据类的运用
1:老师讲的
data class Complex(val re: Double=0.0, val im: Double=0.0) { //主构造器初始化
constructor( re:Int, im:Int):this(re.toDouble(),im.toDouble())
//传入其他类型的参数 通过this转换后委托主构造器
constructor( re:Double, im:Int):this(re,im.toDouble())
constructor( re:Int, im:Double):this(re.toDouble(),im)
//加减乘除方法简化 operator操作符的重载
operator fun plus(other:Complex) = Complex(re+other.re,im+other.im)
operator fun minus(other:Complex) = Complex(re-other.re,im-other.im)
operator fun times(other:Complex) = Complex(re*other.re - im*other.im,re*other.im + other.re*im)
operator fun div(other:Complex) = with( other.re*other.re + other.im*other.im ) {
Complex( (re*other.re + im*other.im)/this,(other.re*im - re*other.im)/this)
}
fun modulus() = Math.sqrt(re*re + im*im)
override fun toString():String {
if ( re == 0.0 ) return if ( im == 0.0 ) "0" else "${im}i"
return if ( im == 0.0 ) "$re" else
if ( im > 0.0 ) "${re} + ${im}i" else "${re} - ${-im}i"
}
//重写equals方法 因为浮点有-0 +0的区别 所以用equals
override fun equals(other: Any?) = when (other) {
!is Complex -> false
else -> this === other ||
re == other.re && im == other.im
}
//因为Double有-0.0 < +0.0 问题,按照一般原则,两个对象相等, 它们的hashcode也要相等
override fun hashCode()= 31*( if (re.equals(-0.0)) 0.0 else re ).hashCode() + ( if (im.equals(-0.0)) 0.0 else im ).hashCode()
}
fun main() {
val d1=-0.0
val d2=0.0
println("d1=d2:${d1==d2}")
println("d2==-0.0:${d2.equals(-0.0)}")
println("d1==-0.0:${d1.equals(-0.0)}")
println("d1=d2:${d1.compareTo(d2)}")
println(d1.hashCode())
println(d2.hashCode())
val c1 = Complex(1.0, 1.0)
val c2 = Complex(1.0, 2.0)
val c3=Complex(3,-2)
val c4=Complex(0.0,0.0)
val c5=Complex(0,2.0)
val c6=Complex(3.0,0)
println(c1)
println(c2)
println(c3)
println(c4)
println(c5)
println(c6)
println("-----------")
val c7=Complex(+0.0,+0.0)
val c8=Complex(-0.0,-0.0)
println(c7)
println(c8)
val c9=Complex(3,0)
val c10=Complex(3.0,-0.0)
val c11=Complex(3.0,+0.0)
println("c1==c2: ${c1 == c2}")
println("c7==c8: ${c7 == c8}")
println("c9==c10: ${c9 == c10}")
println("c11==c10: ${c11 == c10}")
println("c1.hashcode=${c1.hashCode()}")
println("c7.hashcode=${c7.hashCode()}")
println("c8.hashcode=${c8.hashCode()}")
println("c9.hashcode=${c9.hashCode()}")
println("c10.hashcode=${c10.hashCode()}")
println("c11.hashcode=${c11.hashCode()}")
println("c2+c1=${c2+c1}")
println("c1-c2=${c1-c2}")
println("c1*c2=${c1*c2}")
println("c2/c1=${c2/c1}")
val c12=Complex()
println("c1/c12=${c1/c12}")
println(c1.modulus())
// copy() function
println(c1.copy())
println(c1.copy(re=0.0))
println(c1.copy(im = 2.1))
println("re = ${c1.component1()}")
println("im = ${c1.component2()}")
}
运行结果:
d1=d2:true
d2==-0.0:false
d1==-0.0:true
d1=d2:-1
-2147483648
0
1.0 + 1.0i
1.0 + 2.0i
3.0 - 2.0i
0
2.0i
3.0
-----------
0
0
c1==c2: false
c7==c8: true
c9==c10: true
c11==c10: true
c1.hashcode=-33554432
c7.hashcode=0
c8.hashcode=0
c9.hashcode=-1057488896
c10.hashcode=-1057488896
c11.hashcode=-1057488896
c2+c1=2.0 + 3.0i
c1-c2=-1.0i
c1*c2=-1.0 + 3.0i
c2/c1=1.5 + 0.5i
c1/c12=NaN - NaNi
1.4142135623730951
1.0 + 1.0i
1.0i
1.0 + 2.1i
re = 1.0
im = 1.0
2:未改进的,偏java写法
data class datacomplex(val real: Double,val image: Double) { //数据型data 复数类
//fun copy(real:Double = this.real, image:Double = image) = datacomplex(real, image)
internal fun add(a: datacomplex):datacomplex { // 1复数相加
val real2 = a.real
val image2 = a.image
val newReal = real + real2
val newImage = image + image2
var result:datacomplex=datacomplex(newReal,newImage)
return result
}
internal fun sub(a: datacomplex): datacomplex { //2 复数相减
val real2 = a.real
val image2 = a.image
val newReal = real - real2
val newImage = image - image2
var result:datacomplex=datacomplex(newReal,newImage)
return result
}
internal fun mul(a: datacomplex): datacomplex { //3 复数相乘
val real2 = a.real
val image2 = a.image
val newReal = real * real2 - image * image2
val newImage = image * real2 + real * image2
var result:datacomplex=datacomplex(newReal,newImage)
return result
}
internal operator fun div(a: datacomplex):datacomplex { //4 复数相除
val real2 = a.real
val image2 = a.image
val newReal = (real * real2 + image * image2) / (real2 * real2 + image2 * image2)
val newImage = (image * real2 - real * image2) / (real2 * real2 + image2 * image2)
var result:datacomplex=datacomplex(newReal,newImage)
return result
}
internal fun mod(a: datacomplex):datacomplex { //5 复数模运算
val real2 = a.real
val image2 = a.image
val newReal = (real * real2 + image * image2) +(real2 * real2 + image2 * image2)
val newImage = (image * real2 - real * image2) + (real2 * real2 + image2 * image2)
var result:datacomplex=datacomplex(newReal,newImage)
return result
}
//6toString打印方法
override fun toString(): String {
return "当前运算(实部=$real, 虚部=$image)"
}
}
//主函数入口
fun main(args: Array<String>){
println("请用户输入第一个复数的实部和虚部:2.0 4.0")
val data1 = datacomplex(2.0,4.0)
println("请用户输入第二个复数的实部和虚部:3.0 5.0")
val data2 = datacomplex(3.0,5.0)
// 以下分别为加减乘除
val result_add: datacomplex = data1.add(data2)
val result_sub = data1.sub(data2)
val result_mul = data1.mul(data2)
val result_div = data1.div(data2)
val result_mod = data1.mod(data2)
println("data类复数相加"+result_add.toString())
println("data类复数相减"+result_sub.toString())
println("data类复数相乘"+result_mul.toString())
println("data类复数相除"+result_div.toString())
println("data类复数相除"+result_mod.toString())
val resultcopy: datacomplex = data1.copy(real = 2.0)//data类copy函数调用
println("copy函数测试"+resultcopy.toString())
if (resultcopy.equals(data1))
println("两个对象相等,copy成功" )
println("解析函数componentN()用于数据类解析声明")//Component函数在解构声明中使用
val testcomponentN = datacomplex(real=3.5, image=2.4)
val (realtc, imagetc) = testcomponentN///编译器处理:val name=jane.Component1() val age=jane.Component2()
println("realtc = $realtc,imagetc=$imagetc")//real=3.5, image=2.4
}
运行结果
请用户输入第一个复数的实部和虚部:2.0 4.0
请用户输入第二个复数的实部和虚部:3.0 5.0
data类复数相加当前运算(实部=5.0, 虚部=9.0)
data类复数相减当前运算(实部=-1.0, 虚部=-1.0)
data类复数相乘当前运算(实部=-14.0, 虚部=22.0)
data类复数相除当前运算(实部=0.7647058823529411, 虚部=0.058823529411764705)
data类复数相除当前运算(实部=60.0, 虚部=36.0)
copy函数测试当前运算(实部=2.0, 虚部=4.0)
两个对象相等,copy成功
解析函数componentN()用于数据类解析声明
realtc = 3.5,imagetc=2.4
859个字