kotlin怎么配置和使用
这篇"kotlin怎么配置和使用"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇"kotlin怎么配置和使用"文章吧。
kotlin是一种运行在java虚拟机上的静态编程语言,2011年,JetBrains推出了kotlin项目,2016年2月15日正式发布了第一个官方稳定版本V1.0,2017年在google I/O大会上,google正式宣布kotlin成为Android官方开发语言。
配置
在我们的AndroidStudio开发工具中,要想使用Kotlin这个优秀的开发语言,我们需要安装插件,直接在安装插件界面搜索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示例
首先我们还和以前一样,创建一个Android项目,自动创建一个Activity之后我们再创建一个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实现是什么样子呢。尽管现在我们还不能写出Kotlin代码,但是在安装插件后AS中提供了自动转换Kotlin代码的功能
转换后的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) { str = "Code4Android" println(str) }}
注意:AS提供的java代码自动转换功能,我们不要轻易使用,更不要转化我们成熟的项目,如果需要就需要我们自己去重构实现。否则会有意向不到的事情等着你,毕竟转换不是那么智能。上面的代码只是让你先简单熟悉下Kotlin代码时什么样子的,接下来我们先去学习一下Kotlin的基本语法。相信很容易上手。
Hello World!
我们由一个简单的"Hello World!"输出程序开始。与新建java文件类似,如下图,我们选择Kotlin File/Class.创建一个Kotlin文件。
package com.learnrecord/***Created by Code4Android on 2017/4/21.*/var str: String = ""fun main(args: Array) { str = "Hello World!" println(str)}
上述代码就是简单的输出一个字符串"Hello World",package 后面跟的是包名,我们看出了和java文件的区别,在包名后面没有以分号";"结尾。在Kotlin语法中,语句结尾都不在有分号";"。
在Kotlin中变量声明有两种类型,val修饰变量是只读变量即只能赋值一次,再次赋值时就会编译错误,如果我们需要多次修改值就需要使用var。在上面的 var str: String = ""中,str是变量名,:String,表明该变量是String类型变量,后面就是赋值语句。我们也可以这样写var str= ""省略了生命变量类型,它可以根据赋的值而自动推断出类型。如果我们使用下面赋值语句str=null,发现null是不能赋值的,这就是Kotlin的特性,如果我们想赋值null,可以修改为 var str:String?=""。 fun就是函数生命,而这个main函数就和我们java中的main方法一样,是程序执行的入口。println就是一个打印输出。
Kotlin声明类型
在Kotlin中有如下几种Number类型,他们都是继承自Number抽象类。
Float(32位),Double(64),Int(32),Byte(8),Short(16),Long(64,类型用大写L,如12L),Any(任意类型),数组类型Array 根据传入的泛型数据自动匹配类型,Kotlin还提供了指定类型的Array,如ByteArray,CharArray,ShortArray,IntArray,LongArray,FloatArray,DoubleArray,BooleanArray。在数组类型中都提供了get(index),set(index,value)及iterator()方法供我们使用。
val iArray: IntArray = intArrayOf(1, 2, 3) val sArray: Array = Array(3, { i -> i.toString() }) val anyArray: Array = arrayOf(1, "2", 3.0, 4.1f) // 可将类型进行混排放入同一个数组中 val lArray: LongArray = longArrayOf(1L, 2L, 3L)
函数
我们先来实现一个简单的数值求和的函数,通用实现方法如下
fun sum(a: Int, b: Int): Int { return a + b }
传入两个Int型数值,sum是函数名,括号后面的:Int表示该函数返回Int的值,函数体中对两个数字相加并返回。在Kotlin中表达式也可以作为函数体,编译器可以推断出返回类型,可以简化为
fun sum(a: Int, b: Int) = a + b
为了更好理解表达式可以作为函数体,我们可以创建一个函数获取两个数的最大值,如下:
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) }
对于函数体,方法或者类等和java一样也有一些修饰符,如下
abstract //抽象类标示 final //标示类不可继承,默认属性 enum //标示类为枚举 open //类可继承,类默认是final的 annotation //注解类 private //仅在同一个文件中可见 protected //同一个文件中或子类可见,不可修饰类 public //所有调用的地方都可见 internal //同一个模块中可见,若类不加修饰符,则默认为该修饰符,作用域为同一个应用的所有模块,起保护作用,防止模块外被调用。
操作符
直接上代码如下
//操作符 shl 下面对Int和Long var a: Int = 4 var shl: Int = a shl (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 ) print( "/nand:" + and + "/nor:" + or + "/nxor:" + xor)
输出信息为
shl:8shr:2ushr:0and:0or:6xor:4
在上面的部分操作符可达到逻辑操作符, 当我们使用Boolean时,or() 相当于 ||,and() 相当于 &&, xor() 当操作符两边相反时为true,否则为false ,not()时取反。
数组遍历及控制语句
遍历数组
fun forLoop(array: Array) { //第一种方式直接输出字符(类似java foreach) for (str in array) { println(str) } //Array提供了forEach函数 array.forEach { println(it) } //array.indices是数组索引 for (i in array.indices) { println(array[i]) } //(类似javafor(int i=0;iwhile (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,一般用在内层循环中跳到外层循环:i in 0..2等价于java中 for(int i=0;ifor (i in 0..2) { for (j in 0..3) { println("i:" + i + " j:" + j) if (j == 2) //continue@loop//跳到外层循环,继续往下执行 break@loop //跳到外层循环label处,跳出改层循环 } }
倒序输出是downTo
//倒序输出5 4 3 2 1 0 for (i in 5 downTo 0) { println(i) } //设置输出数据步长 for (i in 1..5 step 3) print(i) // 输出 14 //step和downTo混合使用 for (i in 5 downTo 1 step 3) print(i) //输出52
类与枚举
/*** constructor:构造函数* constructor无修饰符(如:private)时,constructor可以省略:* 当是无参构造函数时,整个构造函数部分也可以省略,省略的构造函数默认是public的* 由于primary constructor不能包含任何代码,因此使用 init 代码块对其初始化,* 同时可以在初始化代码块中使用构造函数的参数*/open class People private constructor(var id: String, var name: String) { //可以类中初始化属性: var customName = name.toUpperCase() //初始化属性 //次构造函数,使用constructor前缀声明,且必须调用primary constructor,使用this关键字 constructor( id: String, name: String, age: Int) : this(id, name) { println("constructor") } init { println("初始化操作,可使用constructor参数") } //需要open修饰,子类才可以 open fun study() { print("study") } //People前的冒号":"是继承的意思,实现类接口的时候也是冒号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() }}}
数据类用来保存数据,类似于POJO类,使用data关键词进行定义,编译器默认会为数据类生成以下四个方法
equals() hashCode() toString() copy() 通过数据类你会看到Kotlin的简洁性,我们创建一个Staff类,有String类型的name,position和泛型T(使用泛型仅仅是为了在Kotlin中接触以下泛型) java实现代码:
public class StaffJ { 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数据类:
data class Staff(var name: String, val position: String,var age:T)
通过对比我们就看出了优点了,一行代码就实现了,具体使用
var staff = Staff("code4Android","Android工程师","22") //实例化对象
要获取某个属性如获取名字staff.name,赋值就是staff.name="code4Android2″,既然说了这样可以赋值,但是动手的小伙伴说为什么我敲的报错啊,如下
staff.position="前端"
编译报错了,在前面我们说过val修饰的属性只能赋值一次,那在这里val修饰的属性我们是不能再次赋值的。
fun main(arg:Array){ 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()} ") println("anotherStaff toString(): ${anotherStaff.toString()}") println("staff hashCode(): ${staff.hashCode()} ") println("anotherStaff hashCode(): ${anotherStaff.hashCode()}") println("staff is equals another staff ? ${staff.equals(anotherStaff)}")}
上面使用了字符模板,在Kotlin中有两种字符模板形式,/变量、{}
var name:String="Code4Android" println("我的名字叫$name") println("我的名字叫${name}")/*** java允许使用匿名内部类;kotlin也有类似的概念,称为对象表达式-object expressions*/open class KeyBord{ open fun onKeyEvent(code:Int):Unit = Unit}/**匿名内部类**/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 // 转换指定name为枚举值,若未匹配成功,会抛出IllegalArgumentException Color.valueOf("BLACK") Color.values() //已数组的形式,返回枚举值 println(color.name)////获取枚举名称 println(color.ordinal)//获取枚举值在所有枚举数组中定义的顺序,0开始}
在Kotlin中枚举还支持方法。
扩展
/*** fun receiverType.functionName(params){*body*}* receiverType : 待扩展的类名* . :修饰符为扩展符* functionName :为自定义的扩展函数名,* params :为自定义的扩展函数参数,可为空* 扩展函数作用域,受函数的visibility modifiers影响* 扩展函数并没有对原类做修改,而是为被扩展类的对象添加新的函数。* 有一条规则,若扩展函数和类原有函数一致,则使用该函数时,会优先使用类本身的函数。*/class Employee(var name: String) { fun print() { println("Employee") }}//扩展函数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) { 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) { 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,函数引用 fun isOdd(x: Int) = x % 2 != 0 val numbers = listOf(1, 2, 3) println(numbers.filter(::isOdd)) //3,属性引用(在此引用main函数主体外声明的变量) println(::x.get()) ::x.set(2) println(x) //4,::x 表达式评估为 KProperty 类型的属性 //它允许我们使用 get() 读它的值或者使用名字取回它的属性 val prop = A::p println(prop.get(A(1))) //5,对于扩展属性 println(String::lastChar.get("abc")) //6,与 java 反射调用 println(A::p.javaClass), var f: Array = A::p.javaClass.declaredFields
伴生对象
伴生对象(companion object )类似于java中的静态关键字static。在Kotlin没有这个关键字,而是伴生对象,具体用法
open class People constructor(var id: String, var name: String){ //可以类中初始化属性: var customName = name.toUpperCase() //初始化属性 //使用constructor前缀声明,且必须调用primary constructor,使用this关键字 constructor( id: String, name: String, age: Int) : this(id, name) { println("constructor") } init { println("初始化操作,可使用constructor参数") } //,Kotlin的class并不支持static变量,所以需要使用companion object来声明static变量, // 其实这个platformStatic变量也不是真正的static变量,而是一个伴生对象, companion object { val ID = 1 }}
使用的话直接People.ID。
单例模式
在Kotlin中使用object修饰类的时候,。该类是单例对象。
/*** 使用object定义类,该类的实例即为单例,访问单例直接使用类名,* 不能通过构造函数进行访问,不允许有构造函数* Place.doSomething() // 访问单例对象*/object Singleton { fun doSomething() { println("doSomething") }}/*** 实例化的时候,单例是懒加载,当使用的时候才去加载;而对象表达式是在初始化的地方去加载。** 当在类内部使用 object 关键词定义对象时,允许直接通过外部类的类名访问*内部对象进*而访问其相关属性和方法,相当于静态变量* 可以使用companion修饰单例,则访问其属性或方法时,允许省略单例名* MyClass.doSomething() // 访问内部单例对象方法*/class MyClass { companion object Singleton { fun doSomething() { println("doSomething") } }}
以上就是关于"kotlin怎么配置和使用"这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注行业资讯频道。