Kotlin基础(二):类型

前言

本文主要讲解类型,主要包括类和接口、扩展方法、空类型安全、智能类型转换、案例:使用Retrofit发送网络请求


Kotlin文章列表

Kotlin文章列表: 点击此处跳转查看


目录

在这里插入图片描述


(一)类和接口

(1)kotlin与java类定义,使用(实例化)

java:

public class SimpleClass {
    public int x;
    public SimpleClass(int x) {
        this.x = x;
    }
}

使用:

SimpleClass simpleClass = new SimpleClass(9);
System.out.println(simpleClass.x);

kotlin:

class SimpleClass(var x: Int, val y: String) {

}

使用:

val simpleClass = SimpleClass(9, "Hello")
println(simpleClass.x)

(2)kotlin与java接口的定义,实现

java:

public interface SimpleInf {
    void simpleMethod();
}

实现:

public class SimpleClass implements SimpleInf {

    @Override
    public void simpleMethod() {

    }

}

kotlin:

interface SimpleInf {
    val simpleProperty: Int // 定义一个变量
    fun simpleMethod()
}

实现:

class SimpleClass(var x: Int, val y: String) : SimpleInf {

    override val simpleProperty: Int
        get() {
            return 2 // 每次调用都会返回2
    }
    
    override fun simpleMethod() {

    }
   
}

调用:

fun main() {
    val simpleClass = SimpleClass(9, "Hello")
    println(simpleClass.simpleProperty) // 输出的就是2
}

(3)kotlin与java抽象类的定义,实现

java:

public abstract class AbsClass {
    public abstract void absMethod();
    protected void overridable(){ }
    public final void nonOverridable(){ }
}

使用:

public class SimpleClass extends AbsClass {

    public int x;

    public SimpleClass(int x) {
        this.x = x;
    }

    @Override
    public void absMethod() {

    }
}

kotlin:

abstract class AbsClass {
    abstract fun absMethod()
    open fun overridable(){}
    fun nonOverridable(){}
}

使用:

class SimpleClass(var x: Int, val y: String) : AbsClass() {

    override fun absMethod() {}

    final override fun overridable() {

    }
}

补充:
SimpleClass加上open后,SimpleClass2也能继承SimpleClass
overridable()前面加上了final,SimpleClass2就不能重写overridable()

open class SimpleClass(var x: Int, val y: String) : AbsClass() {

    override fun absMethod() {}

    final override fun overridable() {

    }
}

class SimpleClass2(x: Int, y: String): SimpleClass(x, y) {

}

(4)kotlin与java属性的定义,使用

java:

public class Person {

    private int age; //field
    private String name;

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        System.out.println("setAge: " + age);
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

kotlin:

class Person(age: Int, name: String) {
    var age: Int = age //property
        get() {
            return field
        }
        set(value) {
            println("setAge: $value")
            field = value
        }

    var name: String = name
        get() {
            return field // backing field
        }
        set(value) {

        }
}

fun main() {
    val ageRef = Person::age
    val person = Person(18, "Bennyhuo")
    val nameRef = person::name
    ageRef.set(person, 20) // ageRef未绑定Receiver
    nameRef.set("Andyhuo")// nameRef绑定Receiver
}

(二)扩展方法

扩展函数可以在已有类中添加新的方法,不会对原类做修改,扩展函数定义形式:

fun receiverType.functionName(params) {
    body
}

receiverType:表示函数的接收者,也就是函数扩展的对象
functionName:扩展函数的名称
params:扩展函数的参数,可以为NULL

fun String.padding(count: Int, char: Char = ' '): String {
    val padding = (1..count).joinToString("") { char.toString() }
    return "${padding}${this}${padding}"
}

fun String.isEmail(): Boolean {
    return matches(Regex("(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"))
}

fun String.times(count: Int): String {
    return (1..count).joinToString("") { this }
}


fun main() {
    "admin@bennyhuo.com".isEmail()
    println("Hello".padding(1))
    println("*".times(10))

    // 获取扩展方法的引用
    val stringTimes = String::times
    val stringTimesBound = "*"::times
}

(三)空类型安全

(1)空类型安全的概念

kotlin中,一个常规的String类型变量是不可以设置为 null的

var a: String = "abc"           
a = null    // Error: Null  can not be a value of a non-null type String

为了允许为null,我们可以将变量声明为可空String类型,写作:String?

var b:String? = "abc"
b = null // that's OK

对于Kotlin的其它类型而言,也是只需要在类型后面加上?,即可表示为该类型可空。(尽量不使用,除非必须)
现在我们看一下空引用的属性和方法,很显然,这是不安全,编译器会报错:

var nullObj:String? = null
length = nullObj.length  // error: 因为 nullObj 是一个null

补充:? ?. ?:的区别
?为可空操作符,声明可空类型,避免抛出NPE,例如var b:String? = “abc” b就可以为空
?.为安全调用操作符,为空返回null,避免抛出NPE,例如nullable?.length,如果为空,返回null,不为空,则返回nullable.length的值
?:为Elvis操作符, val t = b?.length ?: -1,如果 ?: 左侧表达式(b?.length)非空,elvis 操作符就返回其左侧表达式,否则返回右侧表达式(-1)


(2)强转为不可空类型

!!的使用

var nullable: String? = "Hello"
val length = nullable!!.length

(3)安全调用(?.)

我们可以通过使用安全调用操作符(?.)来实现

var nullable: String? ="Hello"  
nullable = null    
val length: Int = nullable ?. length ?: 0      

nullable == null, length =0  
nullable != null, length = nullable!!.length

(四)智能类型转换

(1)智能类型转换案例

public class Person implements Kotliner {
    public final String name;
    public final int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

java:

public class JavaCasts {
    public static void main(String... args) {
        Kotliner kotliner = new Person("benny", 20);
        if (kotliner instanceof Person) {
            System.out.println(((Person) kotliner).name);
        }
    }
}

kotlin:

val kotliner: Kotliner = Person("benny",20)    
if (kotliner is Person) {
    println(kotliner.name)  // 自动转换为person
}

(2)智能类型转换的作用范围

var value: String? = null    // value: String?
value ="benny    
if (value = null) {  // 通过智能转换把value从String?类型转换为String类型
     println(value.length)// value: String
}
// value: String?

(3)不支持智能转换的情况

var tag: String? = null
fun main() {
  if (tag != null) {  // 虽然判断不为空,但其他线程可能对它做修改
       println(tag.length)
  }
}

(4)类型的安全转换

val kotliner: Kotliner = Person("benny",20)    
if (kotliner is Person) {
    println((kotliner as? Person)?.name)  // 自动转换为person
}
as? 安全转换,失败返回null

(5)编码建议

尽可能使用val来声明不可变引用,让程序的含义更加清晰确定
尽可能减少函数对外部变量的访问,也为函数式编程提供基础
必要时创建局部变量指向外部变量,避免因它变化引起程序错误


(五)案例:使用Retrofit发送网络请求

(1)添加依赖

implementation "com.squareup.retrofit2:retrofit:2.6.2"
implementation "com.squareup.retrofit2:converter-gson:2.6.2"
implementation "com.google.code.gson:gson:2.8.1"

(2)Repository

data class Repository(
    var id: Int,
    var node_id: String,
    var name: String,
    var full_name: String,
    var private: Boolean,
    var owner: Owner,
    var html_url: String,
    var description: String,
    var fork: Boolean,
    var url: String,
    var forks_url: String,
    var keys_url: String,
    var collaborators_url: String,
    var teams_url: String,
    var hooks_url: String,
    var issue_events_url: String,
    var events_url: String,
    var assignees_url: String,
    var branches_url: String,
    var tags_url: String,
    var blobs_url: String,
    var git_tags_url: String,
    var git_refs_url: String,
    var trees_url: String,
    var statuses_url: String,
    var languages_url: String,
    var stargazers_url: String,
    var contributors_url: String,
    var subscribers_url: String,
    var subscription_url: String,
    var commits_url: String,
    var git_commits_url: String,
    var comments_url: String,
    var issue_comment_url: String,
    var contents_url: String,
    var compare_url: String,
    var merges_url: String,
    var archive_url: String,
    var downloads_url: String,
    var issues_url: String,
    var pulls_url: String,
    var milestones_url: String,
    var notifications_url: String,
    var labels_url: String,
    var releases_url: String,
    var deployments_url: String,
    var created_at: String,
    var updated_at: String,
    var pushed_at: String,
    var git_url: String,
    var ssh_url: String,
    var clone_url: String,
    var svn_url: String,
    var homepage: String,
    var size: Int,
    var stargazers_count: Int,
    var watchers_count: Int,
    var language: String,
    var has_issues: Boolean,
    var has_projects: Boolean,
    var has_downloads: Boolean,
    var has_wiki: Boolean,
    var has_pages: Boolean,
    var forks_count: Int,
    var mirror_url: Any,
    var archived: Boolean,
    var disabled: Boolean,
    var open_issues_count: Int,
    var license: Any,
    var forks: Int,
    var open_issues: Int,
    var watchers: Int,
    var default_branch: String,
    var organization: Organization,
    var network_count: Int,
    var subscribers_count: Int
) {
    data class Owner(
        var login: String,
        var id: Int,
        var node_id: String,
        var avatar_url: String,
        var gravatar_id: String,
        var url: String,
        var html_url: String,
        var followers_url: String,
        var following_url: String,
        var gists_url: String,
        var starred_url: String,
        var subscriptions_url: String,
        var organizations_url: String,
        var repos_url: String,
        var events_url: String,
        var received_events_url: String,
        var type: String,
        var site_admin: Boolean
    )

    data class Organization(
        var login: String,
        var id: Int,
        var node_id: String,
        var avatar_url: String,
        var gravatar_id: String,
        var url: String,
        var html_url: String,
        var followers_url: String,
        var following_url: String,
        var gists_url: String,
        var starred_url: String,
        var subscriptions_url: String,
        var organizations_url: String,
        var repos_url: String,
        var events_url: String,
        var received_events_url: String,
        var type: String,
        var site_admin: Boolean
    )
}

(3)kotlin

import com.google.gson.GsonBuilder
import retrofit2.Call
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
import retrofit2.http.Path
import java.io.File

interface GitHubApi {
    @GET("/repos/{owner}/{repo}")
    fun getRepository(@Path("owner") owner: String, @Path("repo") repo: String): Call<Repository>
}

fun main() {
    val gitHubApi = Retrofit.Builder().baseUrl("https://api.github.com")
        .addConverterFactory(GsonConverterFactory.create())
        .build()
        .create(GitHubApi::class.java)

    val response = gitHubApi.getRepository("JetBrains", "Kotlin").execute()

    val repository = response.body()

    if (repository == null) {
        println("Error! ${response.code()} - ${response.message()}")
    } else {
        println(repository.name)
        println(repository.owner.login)
        println(repository.stargazers_count)
        println(repository.forks_count)
        println(repository.html_url)

        File("Kotlin.html").writeText(
            """
            <!DOCTYPE html>
            <html>
            <head>
                <meta charset="UTF-8">
                <title>${repository.owner.login} - ${repository.name}</title>
            </head>
            <body>
                <h1><a href='${repository.html_url}'>${repository.owner.login} - ${repository.name}</a></h1>
                <p>${repository.description}</p>
                <p>Stars: ${repository.stargazers_count}</p>
                <p>Forks: ${repository.forks_count}</p>
            </body>
            </html>
        """.trimIndent()
        )
    }
}

(4)java

import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class GitHuber {
    public static void main(String... args) throws IOException {
        GitHubApi gitHubApi = new Retrofit.Builder().baseUrl("https://api.github.com")
                .addConverterFactory(GsonConverterFactory.create())
                .build().create(GitHubApi.class);

        Response<Repository> response = gitHubApi.getRepository("JetBrains", "Kotlin").execute();

        Repository repository = response.body();

        if (repository == null) {
            System.out.println("Error! " + response.code() + " " + response.message());
        } else {
            System.out.println(repository.getName());
            System.out.println(repository.getOwner().getLogin());
            System.out.println(repository.getStargazers_count());
            System.out.println(repository.getForks_count());
            System.out.println(repository.getHtml_url());

            File htmlFile = new File("Kotlin.html");
            BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(htmlFile));
            bufferedWriter.write("<!DOCTYPE html>\n" +
                    "<html lang=\"en\">\n" +
                    "<head>\n" +
                    "    <meta charset=\"UTF-8\">\n" +
                    "    <title>" + repository.getOwner().getLogin() + " - " + repository.getName() + "</title>\n" +
                    "</head>\n" +
                    "<body>\n" +
                    "<h1><a href='" + repository.getHtml_url() + "'>" + repository.getOwner().getLogin() + " - " + repository.getName() + "</a></h1>\n" +
                    "<p>" + repository.getDescription() + "</p>\n" +
                    "<p>Stars: " + repository.getStargazers_count() + "</p>\n" +
                    "<p>Forks: " + repository.getForks_count() + "</p>\n" +
                    "</body>\n" +
                    "</html>");

            bufferedWriter.close();
        }
    }
}

注意:
不要忘记加网络权限

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值