AndroidKotlin開發(fā)實例(HelloWorld!)及語法詳解

Android Kotlin開發(fā)實例及語法詳解

我們提供的服務有:成都網(wǎng)站設計、成都網(wǎng)站制作、外貿(mào)網(wǎng)站建設、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認證、留壩ssl等。為上千家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務,是有科學管理、有技術(shù)的留壩網(wǎng)站制作公司

前言

Kotlin是一種在 Java虛擬機上執(zhí)行的靜態(tài)型別編程語言,它主要是由俄羅斯圣彼得堡的JetBrains開發(fā)團隊所發(fā)展出來的編程語言。該語言有幾個優(yōu)勢

1. 簡潔
它大大減少你需要寫的樣板代碼的數(shù)量。
2. 安全
避免空指針異常等整個類的錯誤。
3. 通用
構(gòu)建服務器端程序、Android 應用程序或者在瀏覽器中運行的前端程序。
4. 互操作性
通過 100% Java 互操作性,利用 JVM 既有框架和庫。

配置

在我們的AndroidStudio開發(fā)工具中,要想使用Kotlin這個優(yōu)秀的開發(fā)語言,我們需要安裝插件,直接在安裝插件界面搜索Kotlin然后安裝。之后再gradle文件增加如下配置

apply plugin:'kotlin-android'
apply plugin:'kotlin-android-extensions'

dependencies {
 compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}

項目gradle文件

buildscript {
 ext.kotlin_version = '1.1.1'
 repositories {
  jcenter()
 }
 dependencies {
  classpath 'com.android.tools.build:gradle:2.3.1'
  classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

  // NOTE: Do not place your application dependencies here; they belong
  // in the individual module build.gradle files
 }
}

完成上面的配置后,我們就可以愉快的玩耍了。

Kotlin示例

首先我們還和以前一樣,創(chuàng)建一個Android項目,自動創(chuàng)建一個Activity之后我們再創(chuàng)建一個java類

public class MainActivity extends AppCompatActivity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
  setSupportActionBar(toolbar);

  FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
  fab.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View view) {
    Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
      .setAction("Action", null).show();
   }
  });
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.menu_main, menu);
  return true;
 }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
  // Handle action bar item clicks here. The action bar will
  // automatically handle clicks on the Home/Up button, so long
  // as you specify a parent activity in AndroidManifest.xml.
  int id = item.getItemId();

  //noinspection SimplifiableIfStatement
  if (id == R.id.action_settings) {
   return true;
  }

  return super.onOptionsItemSelected(item);
 }
}
public class Test {
 private static String str = null;

 public static void main(String[] args) {
  str = "Code4Android";
  System.out.println(str);
 }
}

那上面的代碼如果用kotlin實現(xiàn)是什么樣子呢。盡管現(xiàn)在我們還不能寫出Kotlin代碼,但是在安裝插件后AS中提供了自動轉(zhuǎn)換Kotlin代碼的功能

Android Kotlin開發(fā)實例(Hello World!)及語法詳解

轉(zhuǎn)換后的Kotlin代碼

class MainActivity : AppCompatActivity() {

 override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  setContentView(R.layout.activity_main)
  val toolbar = findViewById(R.id.toolbar) as Toolbar
  setSupportActionBar(toolbar)

  val fab = findViewById(R.id.fab) as FloatingActionButton
  fab.setOnClickListener { view ->
   Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
     .setAction("Action", null).show()
  }
 }

 override fun onCreateOptionsMenu(menu: Menu): Boolean {
  // Inflate the menu; this adds items to the action bar if it is present.
  menuInflater.inflate(R.menu.menu_main, menu)
  return true
 }

 override fun onOptionsItemSelected(item: MenuItem): Boolean {
  val id = item.itemId
  if (id == R.id.action_settings) {
   return true
  }
  return super.onOptionsItemSelected(item)
 }
}


object Test {
 private var str: String? = null

 @JvmStatic fun main(args: Array<String>) {
  str = "Code4Android"
  println(str)
 }
}

注意:AS提供的java代碼自動轉(zhuǎn)換功能,我們不要輕易使用,更不要轉(zhuǎn)化我們成熟的項目,如果需要就需要我們自己去重構(gòu)實現(xiàn)。否則會有意向不到的事情等著你,畢竟轉(zhuǎn)換不是那么智能。上面的代碼只是讓你先簡單熟悉下Kotlin代碼時什么樣子的,接下來我們先去學習一下Kotlin的基本語法。相信很容易上手。

Hello World!

我們由一個簡單的”Hello World!”輸出程序開始。與新建java文件類似,如下圖,我們選擇Kotlin File/Class.創(chuàng)建一個Kotlin文件。

Android Kotlin開發(fā)實例(Hello World!)及語法詳解

package com.learnrecord

/**
 *Created by Code4Android on 2017/4/21.
 */

var str: String = ""

fun main(args: Array<String>) {
 str = "Hello World!"
 println(str)
}

上述代碼就是簡單的輸出一個字符串“Hello World”,package 后面跟的是包名,我們看出了和java文件的區(qū)別,在包名后面沒有以分號“;”結(jié)尾。在Kotlin語法中,語句結(jié)尾都不在有分號“;”。

在Kotlin中變量聲明有兩種類型,val修飾變量是只讀變量即只能賦值一次,再次賦值時就會編譯錯誤
,如果我們需要多次修改值就需要使用var。在上面的 var str: String = “”中,str是變量名,:String,表明該變量是String類型變量,后面就是賦值語句。我們也可以這樣寫var str= “”省略了生命變量類型,它可以根據(jù)賦的值而自動推斷出類型。如果我們使用下面賦值語句str=null,發(fā)現(xiàn)null是不能賦值的,這就是Kotlin的特性,如果我們想賦值null,可以修改為 var str:String?=”“。
fun就是函數(shù)生命,而這個main函數(shù)就和我們java中的main方法一樣,是程序執(zhí)行的入口。println就是一個打印輸出。

Kotlin聲明類型

在Kotlin中有如下幾種Number類型,他們都是繼承自Number抽象類。

Float(32位),Double(64),Int(32),Byte(8),Short(16),Long(64,類型用大寫L,如12L),Any(任意類型),數(shù)組類型Array 根據(jù)傳入的泛型數(shù)據(jù)自動匹配類型,Kotlin還提供了指定類型的Array,如ByteArray,CharArray,ShortArray,IntArray,LongArray,F(xiàn)loatArray,DoubleArray,BooleanArray。在數(shù)組類型中都提供了get(index),set(index,value)及iterator()方法供我們使用。

 val iArray: IntArray = intArrayOf(1, 2, 3)
 val sArray: Array<String> = Array<String>(3, { i -> i.toString() })
 val anyArray: Array<Any> = arrayOf(1, "2", 3.0, 4.1f) // 可將類型進行混排放入同一個數(shù)組中
 val lArray: LongArray = longArrayOf(1L, 2L, 3L)

函數(shù)

我們先來實現(xiàn)一個簡單的數(shù)值求和的函數(shù),通用實現(xiàn)方法如下

 fun sum(a: Int, b: Int): Int {
  return a + b
 }

傳入兩個Int型數(shù)值,sum是函數(shù)名,括號后面的:Int表示該函數(shù)返回Int的值,函數(shù)體中對兩個數(shù)字相加并返回。在Kotlin中表達式也可以作為函數(shù)體,編譯器可以推斷出返回類型,可以簡化為

 fun sum(a: Int, b: Int) = a + b

為了更好理解表達式可以作為函數(shù)體,我們可以創(chuàng)建一個函數(shù)獲取兩個數(shù)的最大值,如下:

 fun max1(a:Int,b:Int)=if (a>b) a else b

需要注意的是若if后有多個表達式,如下

 fun max1(a:Int,b:Int)= if (a > b) {
  println(a)
  a
 } else {
  println(b)
  //如果我們將println(b)放到b的下面,運行會返回kotlin.Unit為無類型,返回值總是最后一個表達式的返回值或值
  b
 }
 println(max1(1,3))

括號中的表達式順序決定了返回的值及其類型。

如果我們的方法體僅僅是打印字符串,并不返回值則

 fun printInt(a: Int): Unit {
  println(a)
 }

Unit就類似我們java中的void,即沒有返回值,此時我們可以省略

 fun printInt(a: Int) {
  println(a)
 }

對于函數(shù)體,方法或者類等和java一樣也有一些修飾符,如下

  • abstract //抽象類標示
  • final //標示類不可繼承,默認屬性
  • enum //標示類為枚舉
  • open //類可繼承,類默認是final的
  • annotation //注解類
  • private //僅在同一個文件中可見
  • protected //同一個文件中或子類可見,不可修飾類
  • public //所有調(diào)用的地方都可見
  • internal //同一個模塊中可見,若類不加修飾符,則默認為該修飾符,作用域為同一個應用的所有模塊,起保護作用,防止模塊外被調(diào)用。

操作符

直接上代碼如下

 //操作符 shl 下面對Int和Long
 var a: Int = 4
 var shl: Int = a shl (1) //Java中的左移運算符 <<
 var shr: Int = a shr (1) //Java中的右移運算符 >>
 var ushr: Int = a ushr (3) //無符號右移,高位補0 >>>
 var and: Int = 2 and (4) //按位與操作 &
 var or: Int = 2 or (4) //按位或操作 |
 var xor: Int = 2 xor (6) //按位異或操作 ^
 print("\nshl:" + shl + "\nshr:" + shr + " \nushr:" + ushr + "\nand:" + and + "\nor:" + or + "\nxor:" + xor)

輸出信息為

shl:8
shr:2 
ushr:0
and:0
or:6
xor:4

在上面的部分操作符可達到邏輯操作符, 當我們使用Boolean時,or() 相當于 ||,and() 相當于 &&, xor() 當操作符兩邊相反時為true,否則為false ,not()時取反。

數(shù)組遍歷及控制語句

遍歷數(shù)組

 fun forLoop(array: Array<String>) {
  //第一種方式直接輸出字符(類似java foreach)
  for (str in array) {
   println(str)
  }
  //Array提供了forEach函數(shù)
  array.forEach {
   println(it)
   }
  //array.indices是數(shù)組索引
  for (i in array.indices) {
   println(array[i])
  }
  //(類似javafor(int i=0;i<arry.length;i++))
  var i = 0
  while (i < array.size) {
   println(array[i++])
  }
 }

使用when判斷類型

fun whenFun(obj: Any) {
  when (obj) {
   25 -> println("25")
   "Kotlin" -> println("Kotlin")
   !is String -> println("Not String")
   is Long -> println("Number is Long")
   else -> println("Nothing")
  }
 }

is 和java中instanceof是一個作用判斷是否為某個類型。!is即判斷不是某個類型。

//@定義label,一般用在內(nèi)層循環(huán)中跳到外層循環(huán):i in 0..2等價于java中 for(int i=0;i<=2;i++)效果
 loop@ for (i in 0..2) {
  for (j in 0..3) {
   println("i:" + i + " j:" + j)
   if (j == 2)
   //continue@loop//跳到外層循環(huán),繼續(xù)往下執(zhí)行
    break@loop //跳到外層循環(huán)label處,跳出改層循環(huán)
  }
 }

倒序輸出是downTo

 //倒序輸出5 4 3 2 1 0
 for (i in 5 downTo 0) {
  println(i)
 }
 //設置輸出數(shù)據(jù)步長
  for (i in 1..5 step 3) print(i) // 輸出 14
  //step和downTo混合使用
  for (i in 5 downTo 1 step 3) print(i) //輸出52

類與枚舉

/*** constructor:構(gòu)造函數(shù)
 * constructor無修飾符(如:private)時,constructor可以省略:
 * 當是無參構(gòu)造函數(shù)時,整個構(gòu)造函數(shù)部分也可以省略,省略的構(gòu)造函數(shù)默認是public的
 * 由于primary constructor不能包含任何代碼,因此使用 init 代碼塊對其初始化,
 * 同時可以在初始化代碼塊中使用構(gòu)造函數(shù)的參數(shù)
 */
open class People private constructor(var id: String, var name: String) {
 //可以類中初始化屬性:
 var customName = name.toUpperCase() //初始化屬性
 //次構(gòu)造函數(shù),使用constructor前綴聲明,且必須調(diào)用primary constructor,使用this關鍵字
 constructor( id: String, name: String, age: Int) : this(id, name) {
  println("constructor")
 }
 init {
  println("初始化操作,可使用constructor參數(shù)")
 }
 //需要open修飾,子類才可以
 open fun study() {
  print("study")
 }
 //People前的冒號":"是繼承的意思,實現(xiàn)類接口的時候也是冒號
class Student(id: String, name: String) : People(id, name) {
 var test: Number = 3
 private var name1: String?
  get() {
   return name1
  }
  set(value) {
   name1 = value
  }
 //override修飾的方法,默認是可以被繼承的。若希望不被繼承,可以使用 final 關鍵詞修飾
 override fun study() {
  super.study()
 }
}

}

數(shù)據(jù)類用來保存數(shù)據(jù),類似于POJO類,使用data關鍵詞進行定義,編譯器默認會為數(shù)據(jù)類生成以下四個方法

  • equals()
  • hashCode()
  • toString()
  • copy()

通過數(shù)據(jù)類你會看到Kotlin的簡潔性,我們創(chuàng)建一個Staff類,有String類型的name,position和泛型T(使用泛型僅僅是為了在Kotlin中接觸以下泛型)

java實現(xiàn)代碼:

public class StaffJ<T> {
 private String name;
 private String position;
 private T age;
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String getPosition() {
  return position;
 }

 public void setPosition(String position) {
  this.position = position;
 }
 public T getAge() {
  return age;
 }
 public void setAge(T age) {
  this.age = age;
 }
}

Kotlin數(shù)據(jù)類:

data class Staff<T>(var name: String, val position: String,var age:T)

通過對比我們就看出了優(yōu)點了,一行代碼就實現(xiàn)了,具體使用

 var staff = Staff("code4Android","Android工程師","22") //實例化對象

要獲取某個屬性如獲取名字staff.name,賦值就是staff.name=”code4Android2”,既然說了這樣可以賦值,但是動手的小伙伴說為什么我敲的報錯啊,如下

 staff.position="前端"

編譯報錯了,在前面我們說過val修飾的屬性只能賦值一次,那在這里val修飾的屬性我們是不能再次賦值的。

fun main(arg:Array<String>){
 var staff = Staff("code4Android","Android工程師","22") //實例化對象
 staff.name="code4Android2"
 var staff1=staff.copy()
 //使用copy的時候可以指定默認值,可以指定任意個用逗號","隔開
 var staff2=staff.copy(name="ccc",position = "kotlin")
 println("name:${staff2.name} position:${staff2.position} age ${staff2.age}")
 //staff.position="Kotiln" //val不能再次賦值
 var anotherStaff= Staff("code4Android","Android工程師",22) //實例化對象

 println("staff toString(): ${staff.toString()} anotherStaff toString(): ${anotherStaff.toString()}")
 println("staff hashCode(): ${staff.hashCode()} anotherStaff hashCode(): ${anotherStaff.hashCode()}")
 println("staff is equals another staff ? ${staff.equals(anotherStaff)}")
}

上面使用了字符模板,在Kotlin中有兩種字符模板形式,$<變量>、${<變量>}

 var name:String="Code4Android"
 println("我的名字叫$name")
 println("我的名字叫${name}")

/**
 * java允許使用匿名內(nèi)部類;kotlin也有類似的概念,稱為對象表達式-object expressions
 */
open class KeyBord{
 open fun onKeyEvent(code:Int):Unit = Unit
}

 
/**匿名內(nèi)部類**/
var key=object :KeyBord(){
 override open fun onKeyEvent(code:Int):Unit = Unit
}

枚舉

enum class Color{
 RED,BLACK,BLUE,GREEN,WHITE
}
fun display(){
 var color:Color=Color.BLACK
 Color.valueOf("BLACK") // 轉(zhuǎn)換指定name為枚舉值,若未匹配成功,會拋出IllegalArgumentException
 Color.values() //已數(shù)組的形式,返回枚舉值
 println(color.name)////獲取枚舉名稱
 println(color.ordinal)//獲取枚舉值在所有枚舉數(shù)組中定義的順序,0開始
}

在Kotlin中枚舉還支持方法。

擴展

/**
 * fun receiverType.functionName(params){
 *body
 *}
 * receiverType : 待擴展的類名
 * .   :修飾符為擴展符
 * functionName :為自定義的擴展函數(shù)名,
 * params  :為自定義的擴展函數(shù)參數(shù),可為空
 * 擴展函數(shù)作用域,受函數(shù)的visibility modifiers影響
 * 擴展函數(shù)并沒有對原類做修改,而是為被擴展類的對象添加新的函數(shù)。
 * 有一條規(guī)則,若擴展函數(shù)和類原有函數(shù)一致,則使用該函數(shù)時,會優(yōu)先使用類本身的函數(shù)。
 */
class Employee(var name: String) {
 fun print() {
  println("Employee")
 }
}

//擴展函數(shù)
fun Employee.println() {
 print("println:Employee name is $name")
}


/**
 * 可以擴展一個空對象
 */
fun Any?.toString1(): String {
 if (this == null)
  return "toString1:null"
 else {
  return "toString1" + toString()
 }
}

/**
 * 擴展屬性
 * 由于擴展屬性實際上不會向類添加新的成員,
 * 因此無法讓一個擴展屬性擁有一個后端域變量. 所以,對于擴展屬性不允許存在初始化器.
 * 擴展屬性的行為只能通過明確給定的取值方法與設值方法來定義,也就意味著擴展屬性只
 * 能被聲明為val而不能被聲明為var.如果強制聲明為var,即使進行了初始化,
 * 在運行也會報異常錯誤,提示該屬性沒有后端域變量。
 */
val Employee.lastName: String
 get() {
  return "get:"+name
 }

使用

fun main(arg: Array<String>) {
 var employee = Employee("Code4Android")
 employee.print()
 employee.println()
 println(employee.toString1())
 println(employee.lastName)
}

代理

**
 * 被代理接口
 */
interface Base {
 fun display()
}

/**
 * 被代理類
 */
open class BaseImpl : Base {
 override fun display() = print("just display me.")
}

/**
 * 代理類,使用:以及關鍵詞by進行聲明
 * 許代理屬性和其他繼承屬性共用
 * class Drived(base: Base) : Base by base,BaseImpl()
 */
class Drived(base: Base) : Base by base

//使用
fun show() {
 var b = BaseImpl()
 var drived = Drived(b)
 drived.display()

}

**
 * 代理類型:
 * 懶加載:Lazy
 * 觀察者:Delegates.observable()
 * 非空屬性:Delegates.notNull<>()
 */
class Water {

 public var weight:Int by Delegates.notNull()
 /**
  * 代理屬性
  */
 public val name: String by lazy {
  println("Lazy.......")
  "Code4Android"
 }
 public var value: String by Delegates.observable("init value") {
  d, old, new ->
  println("$d-->$old->$new")
 }
}

fun main(arg: Array<String>) {
 show()
 var water = Water()
 println(water.name)
 println(water.name)
 water.value = "11111"
 water.value = "22222"
 water.value = "33333"
 println(water.value)
 println(water.value)
 //必須先賦值否則IllegalStateException: Property weight should be initialized before get.
 water.weight=2
 print(water.weight)
}

操作符::

val String.lastChar: Char
 get() = this[this.length - 1]

class A(val p: Int)

 //1,反射得到運行時的類引用:
 val c = Student::class
 //2,函數(shù)引用
 fun isOdd(x: Int) = x % 2 != 0
 val numbers = listOf(1, 2, 3)
 println(numbers.filter(::isOdd)) 

 //3,屬性引用(在此引用main函數(shù)主體外聲明的變量)
 println(::x.get())
 ::x.set(2)
 println(x)
 //4,::x 表達式評估為 KProperty<Int> 類型的屬性,它允許我們使用 get() 讀它的值或者使用名字取回它的屬性
 val prop = A::p
 println(prop.get(A(1))) 

 //5,對于擴展屬性
 println(String::lastChar.get("abc")) 

 //6,與 java 反射調(diào)用
 println(A::p.javaClass),
 var f: Array<Field> = A::p.javaClass.declaredFields

伴生對象

伴生對象(companion object )類似于java中的靜態(tài)關鍵字static。在Kotlin沒有這個關鍵字,而是伴生對象,具體用法

open class People constructor(var id: String, var name: String){
 //可以類中初始化屬性:
 var customName = name.toUpperCase() //初始化屬性

 //使用constructor前綴聲明,且必須調(diào)用primary constructor,使用this關鍵字
 constructor( id: String, name: String, age: Int) : this(id, name) {
  println("constructor")
 }

 init {
  println("初始化操作,可使用constructor參數(shù)")
 }
 //,Kotlin的class并不支持static變量,所以需要使用companion object來聲明static變量,
 // 其實這個platformStatic變量也不是真正的static變量,而是一個伴生對象,
 companion object {
  val ID = 1
 }
}

使用的話直接People.ID。

單例模式

在Kotlin中使用object修飾類的時候,。該類是單例對象。

/**
 * 使用object定義類,該類的實例即為單例,訪問單例直接使用類名,不能通過構(gòu)造函數(shù)進行訪問,不允許有構(gòu)造函數(shù)
 * Place.doSomething() // 訪問單例對象
 */
object Singleton {
 fun doSomething() {
  println("doSomething")
 }
}


/**
 * 實例化的時候,單例是懶加載,當使用的時候才去加載;而對象表達式是在初始化的地方去加載。
 *
 * 當在類內(nèi)部使用 object 關鍵詞定義對象時,允許直接通過外部類的類名訪問內(nèi)部對象進而訪問其相關屬性和方法,相當于靜態(tài)變量
 * 可以使用companion修飾單例,則訪問其屬性或方法時,允許省略單例名
 * MyClass.doSomething() // 訪問內(nèi)部單例對象方法
 */
class MyClass {
 companion object Singleton {
  fun doSomething() {
   println("doSomething")
  }
 }
}

 感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

源碼下載:http://xiazai.jb51.net/201705/yuanma/KotlinForAndroid(jb51.net).rar

網(wǎng)頁標題:AndroidKotlin開發(fā)實例(HelloWorld!)及語法詳解
轉(zhuǎn)載注明:http://muchs.cn/article42/gceohc.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供全網(wǎng)營銷推廣、品牌網(wǎng)站建設、外貿(mào)網(wǎng)站建設、響應式網(wǎng)站、ChatGPT、電子商務

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站建設網(wǎng)站維護公司