在Kotlin中var和val的区别是什么?
我已经通过了这个链接:
属性和字段
如本连结所述:
只读属性声明的完整语法不同于
可变1有两种方式:它以val开头,而不是var
不允许设置。
但在此之前有一个使用setter的例子。
fun copyAddress(address: Address): Address {
val result = Address() // there's no 'new' keyword in Kotlin
result.name = address.name // accessors are called
result.street = address.street
// ...
return result
}
var和val的确切区别是什么?
为什么我们两者都需要?
这不是Kotlin中的变量的副本,与Java的区别:'var'和。“val”?因为我问的是与文档中的特定例子有关的疑问,而不仅仅是一般的疑问。
如果我们使用val声明变量,那么它将是只读变量。我们不能改变它的值。它就像Java的最终变量。它是不可变的。
但如果我们使用var声明变量,那么它将是一个我们可以读或写的变量。我们可以改变它的值。这是可变的。
data class Name(val firstName: String, var lastName: String)
fun printName(name: Name): Name {
val myName = Name("Avijit", "Karmakar") // myName variable is read only
// firstName variable is read-only.
//You will get a compile time error. Val cannot be reassigned.
myName.firstName = myName.firstName
// lastName variable can be read and write as it's a var.
myName.lastName = myName.lastName
return myName
}
Val不能最近通过关键字lateinit初始化,但非原始变量可以最近通过关键字lateinit初始化。
用var定义的变量是可变的(读和写)
用val定义的变量是不可变的(只读)
Kotlin可以在android studio中删除findViewById和减少setOnClickListener的代码。完整参考:Kotlin令人敬畏的特性
可变变量的值可以随时改变,而不可变变量的值不能改变。
哪里用var,哪里用val ?
在值经常变化的地方使用var。例如在获取android设备的位置时
var integerVariable : Int? = null
在整个类的值没有变化时使用val。例如,你想通过编程方式设置文本视图或按钮的文本。
val stringVariables : String = "Button's Constant or final Text"
val和var都可以用于声明变量(局部和类属性)。
局部变量:
Val声明只读变量,只能赋值一次,但不能重新赋值。
例子:
val readonlyString = “hello”
readonlyString = “c u” // Not allowed for `val`
var声明了你在Java中知道的可重赋变量(Java 10中将引入关键字“局部变量类型推断”)。
例子:
var reasignableString = “hello”
reasignableString = “c u” // OK
使用val总是更可取的。尽量避免使用var !
类的属性:
这两个关键字还用于在类中定义属性。作为一个例子,看看下面的数据类:
data class Person (val name: String, var age: Int)
Person包含两个字段,其中一个字段是只读(name)。另一方面,年龄可以在类实例化后通过提供的setter重新赋值。注意,name没有相应的setter方法。
在Kotlin中,我们使用var来声明变量。它是可变的。我们可以改变,重新分配变量。的例子,
fun main(args : Array<String>){
var x = 10
println(x)
x = 100 // vars can reassign.
println(x)
}
我们使用val来声明常量。它们是不可变的。无法更改,请重新分配值。Val类似于java中的final变量。的例子,
fun main(args : Array<String>){
val y = 10
println(y)
y = 100 // vals can't reassign (COMPILE ERROR!).
println(y)
}
通过将Kotlin反编译为Java,我得到了确切的答案。
如果你在Kotlin中这样做:
data class UsingVarAndNoInit(var name: String)
data class UsingValAndNoInit(val name: String)
你会得到UsingVarAndNoInit:
package classesiiiandiiiobjects.dataiiiclasses.p04variiiandiiival;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;
public final class UsingVarAndNoInit {
@NotNull private String name;
@NotNull
public final String getName() {
return this.name;
}
public final void setName(@NotNull String string) {
Intrinsics.checkParameterIsNotNull((Object) string, (String) "<set-?>");
this.name = string;
}
public UsingVarAndNoInit(@NotNull String name) {
Intrinsics.checkParameterIsNotNull((Object) name, (String) "name");
this.name = name;
}
@NotNull
public final String component1() {
return this.name;
}
@NotNull
public final UsingVarAndNoInit copy(@NotNull String name) {
Intrinsics.checkParameterIsNotNull((Object) name, (String) "name");
return new UsingVarAndNoInit(name);
}
@NotNull
public static /* bridge */ /* synthetic */ UsingVarAndNoInit copy$default(
UsingVarAndNoInit usingVarAndNoInit, String string, int n, Object object) {
if ((n & 1) != 0) {
string = usingVarAndNoInit.name;
}
return usingVarAndNoInit.copy(string);
}
public String toString() {
return "UsingVarAndNoInit(name=" + this.name + ")";
}
public int hashCode() {
String string = this.name;
return string != null ? string.hashCode() : 0;
}
public boolean equals(Object object) {
block3:
{
block2:
{
if (this == object) break block2;
if (!(object instanceof UsingVarAndNoInit)) break block3;
UsingVarAndNoInit usingVarAndNoInit = (UsingVarAndNoInit) object;
if (!Intrinsics.areEqual((Object) this.name, (Object) usingVarAndNoInit.name)) break block3;
}
return true;
}
return false;
}
}
你也会得到UsingValAndNoInit:
package classesiiiandiiiobjects.dataiiiclasses.p04variiiandiiival;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;
public final class UsingValAndNoInit {
@NotNull private final String name;
@NotNull
public final String getName() {
return this.name;
}
public UsingValAndNoInit(@NotNull String name) {
Intrinsics.checkParameterIsNotNull((Object) name, (String) "name");
this.name = name;
}
@NotNull
public final String component1() {
return this.name;
}
@NotNull
public final UsingValAndNoInit copy(@NotNull String name) {
Intrinsics.checkParameterIsNotNull((Object) name, (String) "name");
return new UsingValAndNoInit(name);
}
@NotNull
public static /* bridge */ /* synthetic */ UsingValAndNoInit copy$default(
UsingValAndNoInit usingValAndNoInit, String string, int n, Object object) {
if ((n & 1) != 0) {
string = usingValAndNoInit.name;
}
return usingValAndNoInit.copy(string);
}
public String toString() {
return "UsingValAndNoInit(name=" + this.name + ")";
}
public int hashCode() {
String string = this.name;
return string != null ? string.hashCode() : 0;
}
public boolean equals(Object object) {
block3:
{
block2:
{
if (this == object) break block2;
if (!(object instanceof UsingValAndNoInit)) break block3;
UsingValAndNoInit usingValAndNoInit = (UsingValAndNoInit) object;
if (!Intrinsics.areEqual((Object) this.name, (Object) usingValAndNoInit.name)) break block3;
}
return true;
}
return false;
}
}
这里有更多的例子:https://github.com/tomasbjerre/yet-another-kotlin-vs-java-comparison
简而言之,val variable是final(不可变)或将来不会改变的常量值
而且
Var变量(可变)可以在未来改变。
class DeliveryOrderEvent(val d : Delivery)
// Only getter
请参阅上面的代码。它是一个模型类,将用于数据传递。我在变量之前设置val,因为这个变量是用来获取数据的。
class DeliveryOrderEvent(var d : Delivery)
// setter and getter is fine here. No error
同样,如果你以后需要设置数据,你需要在变量之前使用var关键字,如果你只需要获得一次值,那么使用val关键字
val变量的值只能赋值一次。
val address = Address("Bangalore","India")
address = Address("Delhi","India") // Error, Reassigning is not possible with val
虽然你不能重新赋值,但你可以修改对象的属性。
//Given that city and country are not val
address.setCity("Delhi")
address.setCountry("India")
这意味着您不能更改变量所指向的对象引用,但可以更改该变量的底层属性。
可以根据需要多次重新分配var变量的值。
var address = Address("Bangalore","India")
address = Address("Delhi","India") // No Error , Reassigning possible.
显然,它的底层属性可以被改变,只要它们没有被声明为val。
//Given that city and country are not val
address.setCity("Delhi")
address.setCountry("India")
在Kotlin中val是一个只读属性,它只能被getter访问。Val是不可变的。
Val例子:
val piNumber: Double = 3.1415926
get() = field
然而,var是一个读写属性,因此它不仅可以由getter访问,还可以由setter访问。Var是可变的。
Var示例:
var gravity: Double = 9.8
get() = field
set(value) {
field = value
}
如果你试图改变一个不可变的val, IDE会显示错误:
fun main() {
piNumber = 3.14 // ERROR
println(piNumber)
}
// RESULT: Val cannot be reassigned
但是可变的var可以被改变:
fun main() {
gravity = 0.0
println(gravity)
}
// RESULT: 0.0
把val比作final是错误的!
var是可变的,val是只读的;是的,val不能像Java中的final变量一样被重新赋值,但它们可以随着时间的推移返回不同的值,所以说它们是不可变的是错误的;
考虑以下几点
var a = 10
a = 11 //Works as expected
val b = 10
b = 11 //Cannot Reassign, as expected
到目前为止很好!
现在考虑以下关于val的情况
val d
get() = System.currentTimeMillis()
println(d)
//Wait a millisecond
println(d) //Surprise!, the value of d will be different both times
因此,vars可以对应于Java中的非最终变量,但val也不是最终变量;
虽然kotlin中有类似final的const,因为它们是编译时常量,没有自定义getter,但它们只适用于原语
var就像一个通用变量,可以被多次赋值,在Kotlin中被称为可变变量。而val是一个常量变量,不能赋值多次,只能初始化一次,在Kotlin中被称为不可变变量。
瓦尔:
分配一次(只读)
Var:
Mutable
例子:
定义一个变量来存储userId值:
val userId = 1
如果我们试图改变变量userId,你会得到错误消息
userId = 2
error: val cannot be reassigned // Error message!
让我们创建一个新变量来存储用户名:
var userName = "Nav"
如果你想重新分配userName的值,你可以很容易地做到这一点,因为var是可变的
userName = "Van"
现在userName的值是“Van”。
欲了解更多信息,请访问:
https://medium.com/techmacademy/kotlin-101-val-vs-var-behind-the-scenes-65d96c6608bf