How can I declare null array in Kotlin? - android

I have the following code in PHP public static $bitValueTable = null; and I want to convert it into Kotlin. My variable is a null array in the first step but I add some value after the program runs.
how can I convert?

By default any variable in kotlin can't hold null values but still you can create nullable object using ? operator, for better understanding check below url https://kotlinlang.org/docs/reference/null-safety.html.
So to create nullable array use below syntax
var myTypeArray: Array<type>? = null // check below example
var myStrArray: Array<String>? = null
Kotlin Arrays Documentation
Thanks

In kotlin you can use nullable objects with the secure call operator "?".
Now, you have a static variable in PHP, in kotlin there is no "static" as such, however the companion object {} fulfills the same function.
In this way the equivalent of public static $bitValueTable = null;
in kotlin is:
companion object {
var bitValueTable : Array<Type>? = null
}
Obs:
The default value of the variables in kotlin is public

Related

kotlin error at * - None of the following functions can be called with the arguments supplied

while building a simple currency converter app in android kotlin I got the following error at * operator ? what could be reason for the error.
You cannot use round() function with nullable Any and Float variables. Also you need to convert Any to Float.
Try to convert them with this example:
var rate : Any? = 5
var fromAmount : Float? = 3.5f
val result = round(rate!!.toString().toFloat() * fromAmount!!)
Seems that rate variable is nullable (float? I suppose), while multiplying operation work with non null values only.
Also smart cast wasn't used here, so rate variable seems to be changeable. So I recommend to make it unchangeable (val variable), or use buffer variable like following:
val bufferRate = rate
if(bufferRate == null) {
...
} else {
val convertedCurrency = fromAmount * bufferRate //here `bufferRate` should be smart casted to non nullable type
}

Not able to reassign value to function parameter,while its not declared as val, val cannot be reassigned

I am trying to write a function in kotlin but I am not able reassign value to function parameters ,its saying val cannot be reassigned .
class WebView{
var homepage = "https://example.com"
fun webViewLoad(url: String, preferredOrientation: String) {
if (url.equals("homepage")){
url = homepage
}
}
}
when I am trying to assign a value to url = homepage .it is giving me error val cannot be reassigned , I am new to kotlin ,I do not understand what is the issue , little help will be appreciated.
Function parameters works like val variables that couldn't be reassigned. Here you need to add variable with conditional initialization:
fun webViewLoad(url: String, preferredOrientation: String) {
val urlValue = if (url.equals("homepage")){
homepage
} else {
url
}
... //use here "urlValue" variable
}
By the way, in kotlin you don't need to use equals function to compare string: common operator == will be automatically replaced with equals in byte code.
Kotlin parameters are immutable since Kotlin M5.1
(Reference)
The main reason is that this was confusing: people tend to think that this means passing a parameter by reference, which we do not support (it is costly at runtime). Another source of confusion is primary constructors: “val” or “var” in a constructor declaration means something different from the same thing if a function declarations (namely, it creates a property). Also, we all know that mutating parameters is no good style, so writing “val” or “var” infront of a parameter in a function, catch block of for-loop is no longer allowed.
It is giving you error "val cannot be reassigned" because Kotlin function parameters are immutable i.e "val" by default. You don't need to mention the "val" keyword for it.
Quick Solution would be:
class WebView{
var homepage = "https://example.com"
fun webViewLoad(url: String, preferredOrientation: String) {
val finalUrl = if (url.equals("homepage")) homepage else url
}
}
Kotlin function parameters are final. There is no val or final keyword because that's the default (and can't be changed). Have a look at this.
By default parameters passed in the function are final what you can do is to add var. Hope it helps.
fun webViewLoad(var url: String, preferredOrientation: String) {
if (url.equals("homepage")){
url = homepage
}
}

Clone a object in kotlin

I have migrated my application from Java to Kotlin. In Java, the copying was working just fine. However, when migrated to Kotline it was not working. After that, I came to know about copy method in Kotlin
I have tied this, but it seems I am doing something wrong.
Here is my function :
fun updateSwitchState(deviceName: String, switchNumber: Int): AuraSwitch? {
val singleDevice = Switch()
for (c in FourNodeDevice) {
if (deviceName == c.name) {
val copyDevice : SwitchClone = SwitchClone(c.state, c.name)
val state = copyDevice.copy(state = copyDevice.state)
state.updateState(switchNumber)
singleDevice.state = state.state
return singleDevice
}
}
return null
}
Whenever I change data in object state in updateState Method the value in object c also gets changed. Any help will be useful
You never create a copy of a state object.
This call creates another SwitchClone with values identical to copyDevice itself.
val state = copyDevice.copy(state = copyDevice.state)
copy() only creates a shallow copy, which means all of your objects, in that case c, copyDevice and state point to the same c.state.
You need to explicitly create a deep copy (depending on what properties are mutable) of state object and assign it to copyDevice.state field.
For Kotlin when using the Kotlin Data Class data class you get a function called copy() for you. But If your Class is not a Data Class and your project has Gson and you want to copy the whole object ( probably edit after getting it ), Then if all those conditions are true then this is a solution. This is also a DeepCopy. ( For a data Class you can use the function copy()).
Then if you are using Gson in your project. Add the function copy():
class YourClass () {
// Your class other stuffs here
fun copy(): YourClass { //Get another instance of YourClass with the values like this!
val json = Gson().toJson(this)
return Gson().fromJson(json, YourClass::class.java)
}
}
If you want to install Gson then get the latest version here.
The copy() did not solve my purpose. However clone() did. I added the following line in my code and it worked as I desired.
val state = c.states.clone()

Kotlin - How to decide between "lateinit" and "nullable variable"?

I am confuse for lateinit and nullable variable, which one to use for variable.
lateinit var c: String
var d: String? = null
c = "UserDefinedTarget"
// if not added initialisation for c than throws UninitializedPropertyAccessException
if (c == "UserDefinedTarget") {
//do some stuff.
}
//not throws any exception whether d is initialise or not.
if(d == "UserDefinedTarget") {
//do some stuff
}
A type that is nullable is just that, a thing that has a valid state that is null.
A non-nullable late init var represents something where null is an invalid state, but for some reason you can't populate it in the constructor.
Android Activities are a good example of a use of lateinit. Activities must have a no args constructor and their lifecycle only really starts with onCreate().
These are two completely different concepts.
You can use lateinit to avoid null checks when referencing the property. It's very convenient in case your properties are initialized through dependency injection, or, for example, in the setup method of a unit test.
However, you should keep in mind that accessing a lateinit property before it has been initialized throws an exception. That means you should use them only if you are absolutely sure, they will be initialized.
Nullable types, on the other hand, are used when a variable can hold null.
class A {
lateinit var a: String
fun cat() {
print(a.length) // UninitializedPropertyAccessException is thrown
a = "cat"
print(a.length) // >>> 3
}
}
class B {
var b: String? = null
fun dog() {
print(b.length) // won't compile, null check is obligatory here
print(b?.length) // >>> null
b = "dog"
print(b?.length) // >>> 3
}
}
For more information:
Late-initialized properties
Nullable types
It depends.
Nullable variable means that variable can hold value or null. lateinit means that variable must be initialised later. It should be initialized before accessing it. If you attempt accessing uninitialized lateinit variable UninitializedPropertyAccessException will be thrown.
It's always better to avoid using nulls in your app. Nulls are evil. So if you can initialize variable in onCreate then it's better to use lateinit. Also if you use dependency injection in your app and fields should be injected it's also a valid case to use lateinit instead of handling nulls.
If for some reason you can't initialize variable, initializing code can result to null, or null can be assigned to this variable later than you should use nullable variable. Generally speaking if null is a valid value for the variable.
Use lateinit for properties that cannot be initialized in a constructor.

Kotlin data classes and nullable types

I'm new to Kotlin and I don't know why compiler complains about this code:
data class Test(var data : String = "data")
fun test(){
var test: Test? = Test("")
var size = test?.data.length
}
Compiler complains with test?.data.length, it says that I should do: test?.data?.length. But data variable is String, not String?, so I don't understand why I have to put the ? when I want to check the length.
The expression test?.data.length is equivalent to (test?.data).length, and the test?.data part is nullable: it is either test.data or null. Therefore it is not null-safe to get its length, but instead you should use the safe call operator again: test?.data?.length.
The nullability is propagated through the whole calls chain: you have to write these chains as a?.b?.c?.d?.e (which is, again, equivalent to (((a?.b)?.c)?.d)?.e), because, if one of the left parts is null, the rest of the calls cannot be performed as if the value is not-null.
If you don't want to use safe call before each non-nullable component of the call chain, you can get the result of the first safe call into a new variable with the standard extension functions run or let:
// `this` is non-nullable `Test` inside lambda
val size = test?.run { data.length }
// or: `it` is non-nullable `Test` inside lambda
val size = test?.let { it.data.length }
Note that size is still nullable Int? here.

Categories

Resources