Kotlinノート(一)基礎知識点--java対比

10543 ワード

オブジェクトの作成
Java
Kotlin
A a = new A()
var a = A()
タイプ宣言
Java
Kotlin
String s
var s : String
final String s
val s : String
class A extends B
class A : B
class A implements B
class A : B
文字列テンプレート
Java
Kotlin
String.format("%s今年%d歳",name,age);
「${name}今年は${age}歳」
方法
Java
Kotlin
String text(int para1,String para2) { ... }
fun test(para1: Int, para2: String): String { ... }
Kotlinプロパティ:関数パラメータのデフォルト値と可変パラメータ
Kotlin関数のパラメータには「=」でデフォルト値を指定し、関数メソッドを呼び出すときにこのパラメータを渡さなくてもよいが、他のパラメータには「=」で指定する必要がある.次の例ではパラメータpara 2は渡されず、実際の値はデフォルト値「para 2」である
fun test(para1: Int, para2: String = "para2", para3: String): String { ... }

test(22, para3 = "hello")

可変パラメータ値は、キーワードvarargで定義する必要があります.ここで注意しなければならないのは、1つの関数に1つの可変パラメータしか持たないことです.この可変パラメータは必ずしも最後のパラメータである必要はないが、この場合、このメソッドを呼び出すには、特定の値を指定していない他のパラメータに値を渡す必要がある.
fun test(vararg para1: String, para2: String): String { ... }

test("para1", "para4", "para5", para2 = "hello")

コンストラクタ
Kotlin
クラスのコンストラクション関数は==primary constructor==と==secondary constructor==に分けられ、前者は1つしかありませんが、後者は複数あります.両方が指定されていない場合、デフォルトはパラメータなしprimary constructorです.primary constructorはクラスヘッダの一部であり、constructorキーワードで定義され、可視性フィールド定義がない場合は省略できる.初期化コードはinitコードブロックに単独で書く必要があります.==primary constructorのパラメータはinitコードブロックと変数の初期化時にのみ使用できます.==secondary constructorもconstructorキーワードで定義されており、primary constructorを直接または間接的にエージェントする必要があります.
class Student(name: String) { // primary constructor
    var mName: String = name
    init {
        println("Student is called " + name)
    }

    constructor(age: Int, name: String):this(name) {
        println("Student is ${age} years old")
    }
}

継承
Java
Kotlin
Javaではクラスのデフォルトが継承され、finalキーワードで修飾されたクラスのみが継承されません.
Openで修飾されたクラスのみが継承できます
単一の例
Java
Kotlin
コードによる単一例の実装
キーワードobjectで単例クラスを定義する
object Shop { //     primary constructor     ,
    fun buySomething() {
        println("Bought it")
    }
}

Shop.buysomething() //   

静的IDと呼び出し
Java
Kotlin
staticクラス内の静的プロパティまたはメソッドを識別
単一クラスobjectをcompanionで修飾し、静的属性またはメソッド機能を実現する
class Mall(name: String) {

    // companion            [  ] 
    companion object Shop { //   java   ,Kotlin                   
        val SHOP_NAME: String = "McDonald" //    Java  public static String
        fun buySomething() { //    Java  public static void
            println("Bought it")
        }
    }
    
}


Mall.buySomething() //      ,

if-else文
Kotlin
Kotlinのif-else文はJavaと一致し、構造的にif(条件A){条件Aは本当に実行する操作}else{条件Aは偽の実行する操作}ここでは主にKotlinの特徴、すなわちif-else文が論理式として使用できることを紹介する.それだけでなく、論理式は、コードブロックの最後の式をブロックの値とするコードブロックの形式で現れることもできる.
//         
fun maxNum(x: Int, y: Int): Int {
    var max = if (x > y) x else y
    return max
}
//            
fun maxNumPlus(x: Int, y: Int): Int {
    var max = if (x > y) {
        println("Max number is x")
        x
    } else {
        println("Max number is y")
        y
    }
    return max
}

when文
Java
Kotlin
switch-case文
いろいろな形式の条件表現があります.if-elseと同様にKotlinのwhenも論理式として使用できる
//         
fun judge(obj: Any) { // Any     java  Object 
    when (obj) {
        1 -> println("   1")
        -1, 0 -> println("   0 -1")
        in 1..10 -> println("    10    ")
        "abc" -> println("    abc")
        is Double -> println("         ")
        else -> println("    ")
    }
}

タブ
Kotlinでは、abc@,xyz@の形式で任意の式にラベルを付けることができます.これらのラベルは、return、break、continueなどのジャンプ動作と組み合わせて使用できます.
fun labelTest() {
    la@ for (i in 1..10) {
        println("outer index " + i)
        for (j in 1..10) {
            println("inner index " + j )
            if ( inner % 2 == 0) {
                break@la
            }
        }
    }
}

記号「?」
Kotlinでは、変数を定義すると、デフォルトは空ではないタイプです.彼にnullを直接付与しようとすると、コンパイラは直接エラーを報告します.Kotlin中将記号「?」セキュアコールオペレータとして定義します.変数タイプの後に?番号定義は、空のタイプであることを示します.同様に、サブプロパティとメソッドを呼び出すときにも文字を使用できますか?を選択して設定できます.Kotlinのコンパイラは、コードを書くときに空でないことをチェックするので、以下の例では、s 2が空でないと判断した場合、それ自体が空可能なタイプであっても、サブ属性やメソッドを安全に呼び出すことができる.ifelse構造の論理については、Kotlinは「?:」オペレータを提供し、コード量を大幅に簡素化し、可読性を失わない.Kotlinは「!!」も提供しています.ダブル感嘆符オペレータは、オブジェクトのプロパティとメソッドを強制的に呼び出し、空ではないかどうかを無視します.これは危険なオペレータで、特別なニーズがない限り、NPEから離れるためには、あまり使わないほうがいいです.
var s1: String = "abc"
s1 = null //         
var s2: String? = "abc"
s2 = null //        

var l1 = s1.length //      
var l2 = s2.length //        ,       

if (s2 != null) s2.length // Java      
s2?.length // Kotlin        ?。 s2 null ,s2?.length  null
if (s2 != null) s2.length else -1 // Java    ifelse  
s2?.length ?: -1 // Kotlin elvis   
s2!!.length //      NPE

拡張メソッド
拡張関数定義の形式
メソッド内でreceiverTypeを呼び出すことができるオブジェクトの元のメソッド
fun receiverType.functionName(params){
    body //  :         this ,   this   receiverType   (   )
}
  • receiverType:関数の受信者、すなわち関数拡張のオブジェクトを表す
  • functionName:拡張関数の名前
  • params:拡張関数のパラメータ、NULL
  • よくある例ですが、thisはcontextを表しています.
    fun Context.showLongToast(msg: String) {
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show()
    }
    

    拡張メソッドの場所
    簡単に言えば2つに分けることができます:classの中で、classの外
  • 拡張メソッドを1つのクラスに書き込む場合、他のクラスで直接呼び出すことは有効ではない.
  • class B {
    
        fun Student.doF(){
            doFly() // Student          
        }
    
        fun dow2(s:Student){
            s.doF()
        }
    
    }
    
    
    //   
    B().dow2(Student())
    

    他のクラスでstudentを呼び出す.doF()は有効ではありません.Bオブジェクト呼び出しdow 2(s)を作成するだけで、拡張メソッドが呼び出されます.
  • 単独でファイルを新規作成したり、クラスの外に書いたりして、すべて任意に呼び出すことができます.上記toastの例のように、拡張方法を個別のファイルに書いたりして、任意のactivityやContextを持つクラスで
  • を呼び出すことができます.
    /**
    *      
    */
    package ****
    
    import android.content.Context
    import android.widget.Toast
    import java.util.*
    
    //     
    fun Context.showLongToast(msg: String) {
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show()
    }
    
    
    /**
    *      ,class  
    */
    fun Context.showLongToast(msg: String) {
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show()
    }
    class Student(name: String) {
        ...
    }
    
    
    //   
    class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            showLongToast("111")
        }
    }
    
    

    オブジェクトの拡張を伴う
    付随オブジェクトは「クラス名.」を通過する.形式呼び出しに伴うオブジェクト.伴随オブジェクトに拡張関数を宣言した場合、どのように呼び出しますか?その呼び出し方式は,伴随オブジェクトと同様にクラス名限定子で呼び出される.もちろん、拡張プロパティもそうです.(オブジェクトcompanionの使用に伴い、上記を参照)
    fun Student.Shop.doW(){
        println("         ")
    }
    
    
    //  
    Student.doW()
    

    拡張関数名は元のクラスの関数名と同じです.
    同時に、呼び出し時に拡張関数の書き込み位置によって異なる場合があります.
  • 類外.setText()はTextViewのメソッドと同じ名前ですが、呼び出すとすべて
  • が提示されます.
    fun TextView.setText(msg: String) {
        this.setText("    "+msg)
    }
    

    しかし、ツンデレがヒントなしに呼び出され、同じ方法を生で書く場合、拡張ではなくメンバー関数を優先的に使用します.
    open class Person {
        fun doFly() {
            println("   ")
        }
    }
    
    fun Person.doFly() {
        println("   ")
    }
    
    fun main(args: Array) {
    
        val person: Person = Person()
        person.doFly()
    }
    
    // Log  
       
    
  • クラス内では、次の例により、doFly()が重複する場合、this(すなわちPerson)のメソッド
  • がデフォルトで呼び出されると結論する.
    open class Person {
    
        fun doFly() {
            println("Person do fly")
        }
    }
    
    class MyInfo {
    
        fun doRun() {
            println("MyInfo do run")
        }
    
        fun doFly() {
            println("MyInfo do fly")
        }
    
        fun Person.doSwim() {
            doFly() //     this(    Person)    
            doRun()
        }
    
        fun doSomething(person: Person) {
            person.doSwim()
        }
    }
    
    //     
    fun main(args: Array) {
    
        val myInfo: MyInfo = MyInfo()
        val person: Person = Person()
        myInfo.doSomething(person)
    }
    // Log  
    Person do fly
    MyInfo do run
    

    ただしMyInfoのdoFly()も呼び出す必要がある場合はdoFly()の前に「this@MyInfo.「いいですよ.
      fun Person.doSwim() {
            doFly()
            [email protected]()
            doRun()
    }
    
    // Log
    Person do fly
    MyInfo do fly
    MyInfo do run
    

    受信者はNULL
    呼び出し元オブジェクトが空の場合、呼び出すこともできます.
    fun Person.doFly() {
    
        if (null == this) {
            println("null")
        }
        println("doFly")
    }
    

    拡張プロパティ
    拡張プロパティ、すなわちExtension Property、すなわちいくつかの関数をデータとして追加し、「=」を使用して、直接設定または使用します.
    
    val List.lastIndex: Int 
    get() = size - 1
    

    注意:拡張属性は実際にクラスに新しいメンバーを追加しないため、拡張属性にバックエンドドメイン変数を持たせることはできません.したがって、拡張属性については初期化器の存在は許されない.拡張属性の動作は、指定された値取り方法と設定方法を明確にすることによってのみ定義できます.つまり、拡張属性はvalとしてのみ宣言でき、varとして宣言できないことを意味します.強制的にvarと宣言すると、初期化されても実行中に例外エラーが報告され、その属性にバックエンドドメイン変数がないことを示します.
    データクラス
    Javaのデータmodelは、通常、複数の属性と対応するgetter、setterから構成されています.多くのプロパティのデータクラスがある場合、これらのクラスは大量のgetterメソッドとsetterメソッドのために数爆発するだけでなく、エンジニアリングメソッド全体の数を急増させます.Kotlinでもこの層の特性最適化を行い,データクラスの簡単な実装を提供した.getやsetの方法を書く必要はありません.これらはコンパイラの背後で行われています.あなたが得たのはさわやかできれいなデータクラスです.具体的には以下の例を参照してください.
    data class Student (
        var name: String,
        var age: Int,
        var hobby: String?,
        var university: String = "NJU"
    )
    fun printInfo() {
        var s: Student = Student("Ricky", 25, "playing Gwent")
        println("${s.name} is from ${s.university}, ${s.age} years old, and likes ${s.hobby}")
    }
    

    生成コードの一貫性と有意義な方法を保証するために,データクラスオブジェクトは要求を満たさなければならない.
  • 構造関数には、少なくとも1つのパラメータ
  • が必要です.
  • すべての構造関数パラメータはvalまたはvarを表示する必要があります.
  • データクラスオブジェクトはabstract,open,sealed or innerではありません.
  • データクラスオブジェクトは他のクラスを継承することはできないが、インタフェース
  • を実現することができる.
  • Java仮想マシンでは、生成されたクラスにパラメータのない構造関数が必要な場合、すべての属性のデフォルト値には具体的な値が必要です.
  • componentN()
    クラスオブジェクトには、いくつかのプロパティがあります.このメソッドcomponentN()はいくつかあります.たとえば、上記の例では、呼び出しメソッドs.nameとs.component 1()の効果は同じです.
    コピー
    クラスオブジェクトをコピーする必要はありませんが、一部のプロパティを変更して、残りのプロパティ値を維持する必要はありません.これはcopy()関数で実現する必要がある.上記のUserクラスでは、次のようにレプリケーションを実行できます.
    fun copy(name: String = this.name, age: Int = this.age) = User(name, age)
    
    //   
    val jack = User(name = "Jack", age = 1)
    val olderJack = jack.copy(age = 2)
    
    

    関連ドキュメント
    Kotlin-拡張;Kotlin基礎学習+迅速な実践