kotlin码上开学练习题
这个系列是扔物线码上开学系列课程的课后练习题,记录的也主要是一个java程序员在转kotlin 时重点关注的一些用法的比较。《Kotlin 的变量、函数和类型》子类重写父类的override函数,能否修改它的可见性;以下的写法有什么区别?可空变量的声明、初始化和传参《Kotlin 里那些「不是那么写的」》单例练习、数组和集合的练习;《Kotlin 里那些「更方便的」》主构造器和字符串模板$的练习
这个系列是扔物线 码上开学系列课程 的课后练习题,记录的也主要是一个java程序员在转kotlin 时重点关注的一些用法的比较。
本节内容目录
Q1:子类重写父类的 override 函数,能否修改它的可见性
-
《Kotlin 的变量、函数和类型》
Q1:子类重写父类的 override 函数,能否修改它的可见性
父类是 internal 可以修改为public,但是父类为public时无法修改为private/internal。
分析:只要记住子类不能降低父类的可见性即可。至于为什么不讨论protect,是因为Kotlin 里的 override 函数的可见性是继承自父类的,父类public子类就public,父类private方法子类就无法复写。也就是说,对于kotlin来说,写不写protect都是继承自父类。
延申1:如果不是继承自父类的话,Kotlin 函数默认可见性都是 public (和变量一样)。
延申2:关于能不能继承,Kotlin 里的类和方法默认是 final ,不能继承的(而 Java 里只有加了 final 才是无法继承 的)。如果想创建一个类的子类,需要使用open 关键字来修饰这个类(方法)。
Q2:以下的写法有什么区别?
- 1. activity as? NewActivity
- 2. activity as NewActivity?
- 3. activity as? NewActivity?
1. 如果 activity 是 NewActivity,转换成功,否则返回空,当 activity 为空的时候,返回也是为 null。
2. 如果 activity 是NewActivity 类型,就转换成功,否则抛出 java.lang.ClassCastException 异常。问号的作用是当 activity 为 null 的时候,不会抛出异常,返回 null。
3. 如果 activity 是 NewActivity 类型,就转换成功,否则返回空。
分析:as 是强转关键字,强转成一个错误的类型的时候抛异常, as? 就是来解决强转失败的问题的。推荐写法应该是:3或者
(activity as? NewActivity)?
这里 第一个? 确保强转能成功才往下执行,第二个? 表示成功且强转结果不为null的话,才会继续往下执行。
Q3:可空变量的声明、初始化和传参
使用 Android Studio 创建一个基于 Kotlin 的新项目(Empty Activity),添加一个新的属性(类型是非空的 View),在 onCreate 函数中初始化它。声明一个参数为 View? 类型的方法,传入刚才的 View 类型属性,并在该方法中打印出该 View? 的 id。
class MainActivity : AppCompatActivity() {
//因为没办法再声明的时候给一个非null的初始值,所以用lateinit
lateinit var view: View;
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
view = findViewById(R.id.my_view);
print(view);
}
// 参数view是可空的
protected open fun print(view: View?) {
//可空变量调用要加 ?,或者 !!
Log.d("tag", "id = " + view?.id);
}
}
-
《Kotlin 里那些「不是那么写的」》
Q1:单例练习
创建一个 Kotlin 类,这个类需要禁止外部通过构造器创建实例,并提供至少一种实例化方式。
package com.example.demo1.testkotlin
import android.view.View
import java.time.LocalDateTime
import java.util.*
class Sample private constructor() {
companion object {
fun getInstance(): Sample {
return Sample()
}
}
}
Q2:数组和集合的练习
分别用 Array、IntArray、List 实现 「保存 1-100_000 的数字,并求出这些数字的平均值」,打印出这三种数据结构的执行时间
package com.example.demo1.testkotlin
import android.view.View
import java.util.*
class Sample private constructor() {
public fun compare() {
println("ArrayCal : " + getTimeLin { ArrayCal() } + " ms,")
println("IntArrayCal : " + getTimeLin { IntArrayCal() } + " ms,")
println("ListCal : " + getTimeLin { ListCal() } + " ms,")
}
private fun getTimeLin(cal: () -> Unit): Long {
val startTime = System.nanoTime()
print(cal().toString() + "")
return System.nanoTime() - startTime;
}
private fun ArrayCal(): Int {
var result = 0
var array: Array<Int> = Array(100000) { it -> it + 1 }
for (item in array) {
result += item
}
return result / 100000
}
private fun IntArrayCal(): Int {
var result = 0
var arrays: IntArray = IntArray(100000) { it -> it + 1 }
for (item in arrays) {
result += item
}
return result / 100000
}
private fun ListCal(): Int {
var result = 0
var list = mutableListOf(0)
for (i in 1..100000) {
list.add(i - 1)
}
return result / 100000
}
}
返回结果:
Array<Int>: 75657200 ms,
IntArray : 13486500 ms // ①
List<Int> : 44496400 ms
知识点:
① Kotlin 中要用专门的基本类型数组类 (IntArray FloatArray LongArray) 才可以免于装箱,因此IntArray 在这里运行效率比Array<Int>高。
补充: 原先在 Java 里的基本类型,类比到 Kotlin 里面,条件满足如下之一就不装箱:
-
不可空类型。
-
使用 IntArray、FloatArray 等。
-
《Kotlin 里那些「更方便的」》
Q1: 主构造器和字符串模板$的练习
请按照以下要求实现一个 Student 类:
写出三个构造器,其中一个必须是主构造器
主构造器中的参数作为属性
写一个普通函数 show,要求通过字符串模板输出类中的属性
fun print(view: View?) {
var stu: Student = Student("cy", 1)
stu.show()
}
//主构造器 primary constructor,写在类名之后。主构造函数不是必须要写的
class Student(name:String){
// 主构造器中的值可以直接赋值给成员变量
var name = name;
var id = 0;
//如果写了主构造,次构造函数就必须 this(),调用主构造
constructor(name:String ,id:Int):this(name){
this.id = id;
}
fun show(){
// 注意 $的用法。
Log.d("tag","id = $id ,name = $name");
}
}
Q2 : 循环的用法
编写程序,找出集合 {21, 40, 11, 33, 78} 中能够被 3 整除的所有元素,并输出。
fun show() {
val intArray = intArrayOf(21, 40, 11, 33, 78);
// 写法一:最接近java 的写法,Kotlin 的 in 后面的变量可以是任何实现 Iterable 接口的对象。
for (i in intArray) {
if (i % 3 == 0) {
Log.d("tag", "$i");
}
}
//写法二:IntArray的操作函数forEach
intArray.forEach { i ->
// i-> 是lambda 表达式,i 表示数组的每个元素
if (i % 3 == 0) {
Log.d("tag", "$i");
}
}
}
Q3:为什么数组的 filter 之后变成 List
val newList: List = intArray.filter { i ->
i != 1 // 👈 过滤掉数组中等于 1 的元素
}
过滤之后,intArray这个数组类型的对象,变成了一个List。原因可能是Kotlin中数组的元素个数不能变,再filter之前并不知道结果数组大小,所以用的是一个List。
更多推荐



所有评论(0)