My non-nullable ArrayList is returning a null upon calling it and throwing a Null Pointer Exception - kotlin

Running this on IntelliJ IDEA 2020.11 using JDK 14 and coding it in Kotlin.
I have a class with a variable menuComponents which is an ArrayList full of MenuComponents, but it's empty at initialization.
var menuComponents: ArrayList<MenuComponent> = ArrayList()
I want to edit the components so I wrote this.
for (component in menuComponents) {
//Do some stuff. The stuff doesn't matter, it throws an exception if I leave it blank
}
When I call on this method, I get a null pointer exception. Additionally, the for loop doesn't even matter.
class NPE() {
init {
refreshProperties()
}
var menuComponents: ArrayList<Double> = ArrayList()
fun refreshProperties() {
refreshJMenuComponents()
}
private fun refreshJMenuComponents() {
val i = menuComponents.size
println("$i is the length.")
for (index in 0 until menuComponents.size) {
val component = menuComponents[index]
println("Refreshed component: $component")
}
}
}
fun main() {
NPE()
}
This statement errors out too. I don't change menuComponents at all before I call these, so it should just be equal to a blank array list. I don't know why it's throwing a Null Pointer Exception.
menuComponents = arrayListOf(//component 1, component 2)
If I try running any of the previous statements on menuComponents now, it still throws a Null Pointer Exception. The value is not nullable, and I am explicitly setting it equal to something, so why is it erroring out at all? It should just not even compile if there is a null object somewhere? It compiles and then throws an exception.
Is this some sort of possible bug or am I just missing something?

I just needed to move the variable initialization above the init block.
class NPE() {
var menuComponents: ArrayList<Double> = ArrayList()
init {
refreshProperties()
}
fun refreshProperties() {
refreshJMenuComponents()
}
private fun refreshJMenuComponents() {
val i = menuComponents.size
println("$i is the length.")
for (index in 0 until menuComponents.size) {
val component = menuComponents[index]
println("Refreshed component: $component")
}
}
}
fun main() {
NPE()
}

Related

How to call constructor default lambda using Kotlin Refelction?

Trying to call lambda provided by MyClass constructor using Kotlin Reflection.
data class MyClass(
var magic:Int=2,
var lambdaValue: ()->String = { //trying to call this lambda from reflection
"Working"
},
)
fun main(args: Array<String>) {
val clazz=MyClass::class
val obj=clazz.createInstance()
val kProperty=clazz.memberProperties
clazz.constructors.forEach{cons-> // for each construtor
cons.parameters.forEach{ parameter-> // looping through constructor parameters
val property=kProperty.find { it.name==parameter.name } // finding the exact property
print(parameter.name+" : ")
if(parameter.type.arguments.isEmpty()) // if empty Int,Float
{
println(property?.get(obj))
}else{
println(property?.call(obj)) // unable to call lambda
}
}
}
}
property.call(obj) returns Any which is not invokable. Any solution?
Expected:
magic : 2
lambdaValue : Working
Frankly speaking, I'm not sure what was your idea behind parameter.type.arguments.isEmpty(). It seems unrelated to what you try to do.
If we have a value of the property already, we can simply check its type and if its is a function then invoke it:
val value = kProperty.find { it.name==parameter.name }!!.get(obj)
print(parameter.name+" : ")
when (value) {
is Function0<*> -> println(value())
else -> println(value)
}
I think usefulness of such a code in generic case isn't very high. This code doesn't know what is the function and if it is going to return a value or perform some action, etc. Maybe in your specific case it is more useful.

Undetected throw declaration (Kotlin)

Let's have a function which just computes something in try-catch and returns the result:
private fun compute(): String {
return try {
// do some computation
// ...
"result"
} catch(t: Throwable) {
throw RuntimeException("Uups") // <-- GOAL: extract this to a dedicated method
}
}
I would like to extract the throw declaration to a separate function (which contains the my boilerplate code).
However, I'm unable to compile such setup in Kotlin.
A simplistic (and still uncompilable) version of the described problem:
private fun compute(): String {
return try {
// do some computation
// ...
"result"
} catch(t: Throwable) {
justThrow() // <-- NOT COMPILABLE, STRING EXPECTED
}
}
#Throws(RuntimeException::class)
private fun justThrow() {
// some boilerplate code
// ...
throw RuntimeException("Uups")
}
How write justThrow() method in Kotlin so that the whole code is compilable?
In Java this case would be detected by a compiler (I suppose).
Kotlin version: 1.4.21
You can declare the return type of your method as Nothing. This type can be used for any method that does not return normally. That might be because it will always throw an exception, or simply never returns at all, for instance because it contains an infinite loop.
private fun justThrow(): Nothing {
// some boilerplate code
// ...
throw RuntimeException("Uups")
}

ArrayList field not correctly gathered

I'm actually new at Kotlin, and I encounter the following problematic:
I have a class holding an ArrayList of EnsembleVerifier class.
This other class is instantiated with an ArrayList of Square.
When I tried to get this ArrayList, I discovered that this one has no element inside.
Is there any absurdity/misconception in my code? Is it something else? Thank you in advance! :)
GridVerifiers.kt
class GridVerifiers(private val grid: Grid) {
private var verifiers: ArrayList<EnsembleVerifier> = ArrayList()
init {
generateVerifiers()
}
private fun generateVerifiers() {
generateLineVerifiers()
generateColumnVerifiers()
generateSubGridVerifiers()
}
private fun generateLineVerifiers() {
val line: ArrayList<Square> = ArrayList()
for (lineIndex in grid.gridState.indices) {
for (columnIndex in grid.gridState.indices)
line.add(grid.gridState[lineIndex][columnIndex])
println(line.size) // returns 9
verifiers.add(EnsembleVerifier(line))
line.clear()
}
}
...
EnsembleVerifier.kt
class EnsembleVerifier(private val squares: ArrayList<Square>) {
...
fun isValid(): Boolean {
val buffer: ArrayList<Int> = ArrayList()
println(squares.size) // returns 0!
for (square in squares) {
if (square.value in buffer) return false
buffer.add(square.value)
}
return true
}
In java most of the time you are working with references to objects. This means in your case, that your are always working with the same array line. Therefore, when you call line.clear you are cleaning the array that that reference is pointing at, and that's causing your issue with empty arrays.
You need to generate new objects every time instead of cleaning the list.
private fun generateLineVerifiers() {
for (lineIndex in grid.gridState.indices) {
val line: ArrayList<Square> = ArrayList()
for (columnIndex in grid.gridState.indices)
line.add(grid.gridState[lineIndex][columnIndex])
println(line.size) // returns 9
verifiers.add(EnsembleVerifier(line))
}
}

"Property must be initialized or be abstract" in init block when throwing an exception

Why does kotlin report Property must be initialized or be abstract. The object construction is never finished, so it should not matter whether a is initialized or not. Could a case be demonstrated where this would be a problem?
class Foo {
private val a: Int
init {
a = 42
throw Exception()
}
}
fun main() {
Foo()
}
kotlin playground
However these work just fine
fun bar() {
throw Exception()
}
class Foo {
private val a: Int
init {
a = 42
bar()
}
}
fun main() {
Foo()
}
kotlin playground
class Foo {
private val a: Int = throw Exception()
}
fun main() {
Foo()
}
kotlin playground
Similar java code works as expected:
public class Test {
private static class Foo {
private final int a;
public Foo() throws Exception {
a = 42;
throw new Exception();
}
}
public static void main(String []args) throws Exception {
new Foo();
}
}
The question is very well answered in the below link.
Kotlin: why do I need to initialize a var with custom getter?
Essentially it boils down to having a backing field for every "val" (property) . If you can provide a backing field, you need not initialize the field. Below is a small example of it.
class Foo {
private val a: Int
get() = getValue()
}
fun getValue():Int {
throw Exception()
}
fun main() {
Foo()
}
Similar java code works as expected:
Java initializes fields to 0 (or null/false depending on type) by default. You can see it e.g. by printing a's value before the a = 42 line.
Kotlin doesn't, because this implicit initialization makes it too easy to forget to initialize a property and doesn't provide much benefit. So it requires you to initialize all properties which have backing fields.
It seems to be a compiler bug as Alexey suggested
There is similar issue posted on Kotlin bug tracer.

Kotlin: Null check in if block

I started to learn Kotlin recently. One thing I can't get my head around is the null check blocks. The following statement is considered unsafe, and the compiler won't allow you to compile this.
var testVar: String? = null;
// if (testVar != null )
{
// Doing some work....
println(testVar.length)
}
But when you uncomment the if line, everything works. This seems great.
But what if // Doing some work.... is computationally expensive and another thread changes the value of testVar to null while this thread is in // Doing some work line? In this scenario:
Does the program throw a NullPointerException?
OR:
Does the bytecode cache the value of testVar and use the cached value inside the if block?
In your initial example, is your var local to a function? For example:
fun doStuff() {
var testVar: String? = null
if (testVar != null) {
println(testVar.length)
}
}
In this case, no other scope has reference to testVar so nothing else can change it. However, if the var is a class property, i.e.
class MyClass {
var testVar: String? = null
fun doStuff() {
if (testVar != null) {
println(testVar.length)
}
}
}
This will fail to compile as testVar could have been set to null by another thread in between the check and the usage.
Going further, if you try to be tricky:
fun doStuff() {
var testVar: String? = null
fun trickyFunction() {
testVar = null
}
if (testVar != null) {
trickyFunction()
println(testVar.length)
}
}
The compiler will fail as your variable is captured by a changing closure. So in general, if you are able to use the variable via a smart-cast to non-null, you should not have to worry about any potential for NPEs.
For the second scenario (var properties) it is preferable to rely on .let to capture an immutable reference to the current value, i.e.
testVar?.let { capturedTestVar ->
println(capturedTestVar.length)
}