I have the code
if (WORDLIST[language]==null) throw new Exception("Invalid Language");
List<String> wordlist = WORDLIST[language];
the compiler says
Error: A value of type 'List?' can't be assigned to a variable of type 'List' because 'List?' is nullable and 'List' isn't.
However its both not possible in my code for language to be set to a value that is not valid and just to be safe there is the exception thrown if it gets called somewhere without checking the language exists. How can I get the compiler to recognize this is valid?
Full Code is here(though the exception was added afterwards to try and handle new compiler):
https://github.com/mctrivia/bip39-multi/blob/mctrivia-patch-1/lib/src/bip39_multi_base.dart#L80
Map.operator [] returns a nullable type, period. The compiler doesn't know what WORDLIST[language] will return at runtime; it doesn't know that WORDLIST isn't some Map implementation that returns different values each time operator [] is called. This is the same reason why only local variables can be type promoted.
The typical ways to fix this are:
Use ! to force the result to be non-nullable:
if (WORDLIST[language]==null) throw new Exception("Invalid Language");
List<String> wordlist = WORDLIST[language]!;
Use a local variable:
var result = WORDLIST[language];
if (result == null) throw new Exception("Invalid Language");
List<String> wordlist = result;
Since wordlist is probably already a local variable, you also could just reorder your code:
List<String>? wordlist = result;
if (wordlist == null) throw new Exception("Invalid Language");
// wordlist is now type-promoted to be List<String>.
The compiler is not smart enough to promote general expressions, only local variable can be promoted.
When you write if (WORDLIST[language] == null) throw ..., that doesn't actually make the compiler any wiser wrt. the following WORDLIST[language] expression.
It takes specific knowledge about the implementation of the [] operator of WORDLIST to guarantee that it returns the same value every time it's called with the same argument. The compiler does not assume to have such knowledge.
What you should do is:
List<String>? wordlist = WORDLIST[language];
if (wordlist == null) {
throw ArgumentError.value(language, "language", "Invalid language");
}
// use `wordlist` as `List<String>` here.
By assigning the value to a local variable, you allow the test+throw to promote that variable to non-nullable in the following (implicit else-branch) code.
One way to hint to the compiler is to add an else clause, that way the compiler is sure the else branch will only execute when WORDLIST[language]!=null.
if (WORDLIST[language]==null) throw new Exception("Invalid Language");
else List<String> wordlist = WORDLIST[language];
Related
I am a beginner in kotlin and this is the code I tried to execute, but runtime error is being displayed. Please help me resolve this.
import java.util.*
fun main(args: Array<String>)
{
var inp = Scanner(System.`in`);
var t:Int = inp.nextInt();
repeat(t)
{
var n:Int = inp.nextInt();
var s:String = readLine()!!
for (i in s)
{
println(i);
}
println()
}
}
Exception in thread "main" kotlin.KotlinNullPointerException
at ProgKt.main(prog.kt:10) This is the error that is displayed.
Smeki's answer is right, but I just need to point something out since you're a beginner and it might get confusing.
Normally you'd do something like this:
val s = readLine()
Notice you're not specifying the type of s - it's being inferred by whatever you're assigning to it. Because readLine returns a nullable String?, which is a String that could be null (which is what the ? on the end means), then the compiler knows that s is a String?. It's the equivalent of doing this:
val s: String? = readLine()
And you can do that explicitly if you want! You usually don't need to though. And now you have your nullable s, you can do some null-checking to use it safely:
if (s != null) {
// we know it's not null, so now you can do stuff with it
} else {
// if you like, you can handle the null case separately, like breaking out of
// the loop (since null from readLine() means you've reached the end)
}
There's other ways to handle nulls and do null-checking - here's the documentation about it and I'd strongly recommend reading it and getting your head around it - it's a key part of the language! And it makes your life easier and code safer in the long run (avoids problems like this! !! gets around null-safety and it's usually a bad sign)
But remember when I said you can explicitly declare the type for s? Here's what I said it would be, and what you've written:
// correct
val s: String? = readLine()
// something's different!
val s: String = readLine()
See how you're missing the ? that says its a nullable type? Even if you're planning to null-check s after this, it's going to crash at this line because s is declared as a non-null type, and readLine() is gonna to be null at some point. When you assign null to a non-null variable, it'll crash with an error - because as far as the compiler's concerned, something's gone wrong.
(You should also get some warnings in your IDE if you're using one, trying to null-check a variable that you've declared as non-null will give you some "why are you trying to do this? It can't be null, right?" messages that hint that something's wrong somewhere. Also if you didn't add the !! after readLine(), you'd get a warning about that - probably why you added the !! in the first place! It doesn't make the problem go away, just stops the IDE from warning you about it)
Also you might have noticed, I made s a val instead of a var because it's a fixed value you're not going to change - always prefer vals unless you definitely need to change that variable, it's not such a big deal here but it makes some other things easier (you'll get warnings about that too)
Well, NPE is the most probably thrown from
var s:String = readLine()!!
where those !! are part of kotlin null-safety feature.
And from java doc of readLine() we can find out when is null returned.
/**
* Reads a line of input from the standard input stream.
*
* #return the line read or `null` if the input stream is redirected to a file and the end of file has been reached.
*/
fun readLine(): String? = LineReader.readLine(System.`in`, Charset.defaultCharset())
I am taking a JSON input and I want it to convert it to uppercase. Can someone please help me with my code
int synchronizeSingleUnit(ApiResultDTO apiResultDTO, def inputJSON, int totalUpdates) {
def sql = synchronizationApiSqlHelperService.getUnitsSql()
String unit = getEmptyIfValueNull(inputJSON.unit)
def session = sessionFactory_apiDb.openSession() as SessionImpl
def connection = session.connection()
def sqlConnection = new Sql(connection)
try {
sqlConnection.execute(sql, [unit:unit])
} catch (Exception ex) {
// Preload result with statement to be executed
apiResultDTO.setJsonFailingPart(inputJSON)
apiResultDTO.setFailedSql(sql, [unit:unit])
throw new ExceptionWrapper(apiResultDTO, ex)
} finally {
session.close()
connection.close()
}
You can use java String.toUpperCase() as in:
String unit = getEmptyIfValueNull(inputJSON.unit)
String uCaseUnit = unit.toUpperCase()
< -- edit -- >
As a comment and addition, I don't know the specifics of method getEmptyIfValueNull but judging from the name you just want to return an empty string when the expression inputJSON.unit returns null.
Groovy has two special operators which make expressions like these easier to write.
the safe navigation operator ?. and
the elvis operator ?: (see how that looks like an Elvis smiley?)
using these two you could rewrite your code somewhat more concisely as:
String unit = inputJSON.unit?.toUpperCase() ?: ''
explanation:
inputJSON.unit?.toUpperCase() - evaluate inputJSON.unit and if that expression returns null, just return null from the entire expression (never executing the toUpperCase method). If inputJSON.unit returns a non-null value, things work as they would just by using inputJSON.unit.toUpperCase().
... ?: '' - take an expression and if it is not empty string or null,return it, otherwise return the empty string.
Where the first operator .? is specifically for handling null values and the second operator ?: uses groovy truth which includes, but is more inclusive than just null values.
There are a few ways of writing the above, for example:
String unit = (inputJSON.unit ?: '').toUpperCase()
but to my mind the first version "flows" better. To each his own.
I am trying to get a class, which combines list, set and map in Kotlin. I wished to write isScalar function, which should return true if object contains only one element and wrote
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap
import it.unimi.dsi.fastutil.objects.ReferenceArrayList
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet
class Args {
var list : ReferenceArrayList<M>? = null
var set : ReferenceOpenHashSet<M>? = null
var map : Reference2ReferenceOpenHashMap<M, M>? = null
fun isEmpty() : Boolean {
return list === null && set === null && map === null
}
fun isScalar() : Boolean {
if(list !== null && list.size == 1) {
return true
}
}
}
Unfortunately it gave me error in comparison
list !== null && list.size == 1
saying
Smart cast to 'ReferenceArrayList<M>' is impossible, because 'list' is a mutable property that could have been changed by this time
As far as I understood, this is related with multithreaded assumption. In Java I would make function synchronized if would expect multithreding. Also, I would be able to disregard this at all, if I am not writing thread-safe.
How should I write in Kotlin?
I saw this solution https://stackoverflow.com/a/44596284/258483 but it expects MT, which I don't want to. How to avoid smart casting if it can't do it?
UPDATE
The question is how to do this in the same "procedural" form. How not to use smart casting?
UPDATE 2
Summarizing, as far as I understood, it is not possible/reasonable to explicitly compare variable with null in Kotlin at all. Because once you compare it, next time yous hould compare it with null again implicitly with such operations like .? and you can't avoid this.
If you take advantage of the fact that null cannot equal 1 (or anything else, really), you can make this check very concise:
fun isScalar() : Boolean =
list?.size == 1
When a null-safe call to list.size returns null, we get false because 1 != null. Otherwise, a comparison of whatever value size returns is made, and that works as you would expect.
By using the null safe operator (?.) you are avoiding a smart cast entirely. Kotlin gives us smart casts to make code cleaner, and this is one of the ways it protects us from misuses of that feature. Kotlin isn't going to protect us from everything (division by zero, the example you use in comments, for example). Your code is getting caught up in a legitimate case of where smart casting can go wrong, so Kotlin jumps in to help.
However, if you are absolutely sure there are no other threads working, then yes, this check is "wrong". You wouldn't need the warning in that case. Judging by this thread on kotlinlang.org, you aren't the only one!
You can perform the null check, and if it succeeds, access a read-only copy of your variable with let:
fun isScalar() : Boolean {
return list?.let { it.size == 1 } ?: false
}
If list is null, the entire let expression will evaluate to null, and the right side of the Elvis operator (false) will be returned.
If list is not null, then the let function is called, and result of the it.size == 1 expression is returned - it refers to the object that let was called on (list in this case). Since it's used with a safe call, this it will have a non-nullable type and size can be called on it.
I had the same problem in the given lines
sliderView.setSliderAdapter(adapter!!)
sliderView.setIndicatorAnimation(IndicatorAnimationType.WORM)
Finally, error resolved by adding !!
sliderView!!.setSliderAdapter(adapter!!)
sliderView!!.setIndicatorAnimation(IndicatorAnimationType.WORM)
First of all, I am aware of question 'Groovy String to int' and it's responses. I am a newbe to Groovy language and right now playing around some basics. The most straightforward ways to convert String to int seem to be:
int value = "99".toInteger()
or:
int value = Integer.parseInt("99")
These both work, but comments to these answers got me confused. The first methodString.toInteger() is deprecated, as stated in groovy documentation. I also assume that
Integer.parseInt() makes use of the core Java feature.
So my question is: is there any legal, pure groovy way to perform such a simple task as converting String to an int?
I might be wrong, but I think most Grooviest way would be using a safe cast "123" as int.
Really you have a lot of ways with slightly different behaviour, and all are correct.
"100" as Integer // can throw NumberFormatException
"100" as int // throws error when string is null. can throw NumberFormatException
"10".toInteger() // can throw NumberFormatException and NullPointerException
Integer.parseInt("10") // can throw NumberFormatException (for null too)
If you want to get null instead of exception, use recipe from answer you have linked.
def toIntOrNull = { it?.isInteger() ? it.toInteger() : null }
assert 100 == toIntOrNull("100")
assert null == toIntOrNull(null)
assert null == toIntOrNull("abcd")
If you want to convert a String which is a math expression, not just a single number, try groovy.lang.Script.evaluate(String expression):
print evaluate("1+1"); // note that evalute can throw CompilationFailedException
Does any common Java library provide a method to find an element in a finite collection and ensure that there was exactly one match?
The method could, for example, return null if nothing was found and throw an exception if multiple elements were found.
Currently I use my own Implementation (see below), but I'd rather not pollute business code with such utility methods (even if extracted in a separate utility package).
I also don't want the overhead of iterating over collection more than once, or an overhead of filtering collection and looking at the length of the result.
P.S. my current solution (which works, but is to be replaced with a library method):
public static <T> T getSingleMatch(Iterable<T> lookIn, com.google.common.base.Predicate<? super T> predicate) {
T foundItem = null;
for (T item : lookIn) {
if (predicate.apply(item)) {
if (foundItem != null)
throw new RuntimeException("multiple matches"); // alternatively: `return null;`
else
foundItem = item;
}
}
// alternatively: `if (foundItem == null) throw ...`
return foundItem;
}
One option is to separate out the two ideas into two methods, so that each method does one thing - then combine the calls
One method to lazily filter, returning a sequence of matching results
One method to return an item from a sequence, requiring it to be the only item
Guava has both of those:
Iterables.filter to filter lazily
Iterables.getOnlyElement to return the sole element of a sequence
So for example:
String match = Iterables.getOnlyElement(Iterables.filter(source, predicate));
int index = collection.indexOf(item);
if (index != -1 && index == collection.lastIndexOf(item)) {
// one and only one
}
If index != -1 it means no such item. If the next if statement doesn't evaluate to true it means that there are at least 2 items. You can restructure it to throw exceptions, return null or return the index or item. I trust you know how to do this based on your question.