IDEA Community 2017.1.2, JRE 1.8, Kotlin 1.1.2-2
I have Java methods, located in libGdx that don't have any annotations regarding their nullability, e.g.:
public void render (final RenderableProvider renderableProvider) {
renderableProvider.getRenderables(renderables, renderablesPool);
as we can see, argument can't be null. However, since nothing tells that it's not-null argument, Kotlin will happily pass null in RenderableProvider?. How do I tell Kotlin to check during compile-time that I should be passing RenderableProvider and not RenderableProvider??
I've read about external annotations, however there is no "Specify Custom Kotlin Signature" and if I annotate renderableProvider as #NotNull nothing changes - kotlin still allows null.
I even tried to replace org.jetbrains.annotations.NotNull with javax.annotation.Nonnull in XML manually, but it makes no difference - code compiles and crashes with NPE.
External annotations are no longer supported. You'll either have to fork libgdx and annotate the methods there or live with this issue, unfortunately.
You could wrap it in an extension function and then only use that for rendering:
fun RenderClass.renderSafe(renderProvider: RenderableProvider) =
this.render(renderProvider)
Now you can't pass null.
Related
I declared an inline class
#JvmInline
value class Creator<T>(val type: KClass<T>);
, and declared an interface
interface Itf {
fun <T> creator(type: KClass<T>): Creator<T>;
}
I want to implement this interface by generating the bytecode by asm(https://asm.ow2.io/ 1).
I found java method decompiled from bytecode is
public KClass<T> creator-9k1ZQyY();
The java method name is “creator-9k1ZQyY”. the suffix “-9k1ZQyY” is added by kotlin compiler and I know why kotlin compiler did it.
This suffix is very important for bytecode generator.
My question:
If the interface and inline class are stable, can kotlin compiler guarantee that suffix is stable too? Does that suffix have nothing to do with the version of kotlin-compiler?
The docs seem to suggest the mangling is stable:
functions using inline classes are mangled by adding some stable hashcode to the function name
As noted in the same doc, the mangling scheme has changed once with the version 1.4.30 of the Kotlin compiler, but I would consider it quite stable nonetheless. They even provided a flag to use the old scheme to generate binary compatible code, so I'm assuming it's not only unlikely to change again, but even if it does, it will surely be done with some way to keep compatibility.
For String.strip() I get warning 'strip(): String!' is deprecated. This member is not fully supported by Kotlin compiler, so it may be absent or have different signature in next major version"
Why is it? "strip" comes from Java String
What should I use?
First of all: String.strip() is a new function in Java 11. Kotlin targets JVM 6 by default, so I was unable to reproduce your issue at first, I got a compilation error. Using JVM 11 as target in Android Studio worked with your compiler warning.
Kotlin's string class (kotlin.String) is not the same as Java's string class (java.lang.String). The Kotlin type is however mapped to the Java type (quote):
Kotlin types such as List, MutableList, String, CharSequence etc. are all compiled to their java equivalents, and thus any runtime checks will not be able to distinguish between them. At compile-time, however, they are distinct types with different sets of members. In particular, the Kotlin types do not have all members that the corresponding Java types have. They have those listed in the Kotlin std lib reference, as well as a few extra JVM specific ones (such as Collection.stream())
kotlin.String does not have a .strip() function. You are just "incidentally" calling java.lang.String.strip() which happens to be there in some target JVMs but not defined in Kotlin. If you look at the kotlin.String source in your IDE you can see it is not defined there.
The reason it is not there is because it was explicitly graylisted by the Kotlin team:
Some methods in JDK classes are undesirable in Kotlin built-ins (e.g. a lot of String methods or List.sort(), because there are Kotlin analogues with better signatures already defined).
.strip() does the same thing as kotlin.String.trim(), so use that instead.
Extended Reading
Extended Reading 2
The commit which put .strip() on the graylist
I am very new to Kotlin development and I came across custom annotation classes in the documentation.
Is there a way for me to use an annotation on a function as a way to pre-populate some variables, or to run a decorator function before running the annotated function?
Something like:
class TestClass {
#Friendly("Hello World")
private fun testFun() {
greet()
//does something else
}
}
with an annotation class like
#Target(AnnotationTarget.FUNCTION)
#Retention(AnnotationRetention.BINARY)
annotation class Friendly(val message: String) {
fun greet() {
println(message)
}
}
I know this isn't valid Kotlin code, but I can't find any examples on how to actually use values from annotations without using reflection (if it's even possible)
Please let me know if I can do something like this, and more usefully, a better resource on annotation classes for Kotlin?
To make use of your custom annotations, you need to either create your own annotation processor (and use kapt Kotlin compiler plugin) to generate some new sources (but not modify existing!) at compile time, or use #Retention(AnnotationRetention.RUNTIME) meta-annotation (which is default in Kotlin), so that they could be accessed via reflection in runtime.
#Retention(AnnotationRetention.BINARY) meta-annotation you're using is equivalent of #Retention(RetentionPolicy.CLASS) in java, which is mostly useless (see https://stackoverflow.com/a/5971247/13968673).
What you're trying to do with annotations (call some additional code before/after method execution) reminds me aspect-oriented programming. Take a look at Spring AOP and AspectJ frameworks, following this paradigm, and their approach for annotations processing. TL;DR: Spring AOP is processing annotations in runtime, generating proxy-classes with respectful code, while AspectJ is using its own compiler (even not an annotation processor, cause it also introduces its own syntactic extension for java language), and can generate respectful bytecode at compile-time. They both are originally java-oriented, but with some configurational pain could be used with Kotlin too.
I am implementing an interface of a third party library(java). I am overriding a function with the following signature:
override fun onCallback(name: String?) {
}
I can change to the following without the compiler complaining:
override fun onCallback(name: String) {
}
What is the effect of this? What happens if the underlying library calls onCallback(null)?
Types coming from Java are platform types (in this case, this parameter has a type of String!. If the parameter is not annotated in Java, it's up to you to decide whether it can ever have a null value, and you have to mark the type of the parameter in Kotlin accordingly. If you mark it as non-nullable, but Java code passes null to it, you'll get an exception at runtime - Kotlin generates checks for parameters like this, which you can look at by decompiling the generated bytecode.
Also see the official docs about null safety and platform types for more detail.
In most Dart documentation pages, some variables and functions are crossed out. like in https://api.dartlang.org/1.14.2/dart-js/dart-js-library.html
What does this signify?
In Dart metadata can be added to classes, fields, library declaratoins, parameters, ... as annotation.
#Deprecated('some reason')
class SomeClass {
String someField;
int otherField;
SomeClass({
this.someField,
#Deprecated('don\'t use this anymore") this.otherField});
}
is such an annotation and some tools like the Dart analyzer and dartdoc use this information to produce warnings (Analyzer) or other visual cues that some API still exists but should be avoided because it's planned to be removed eventually.
It signifies that the class, function, property etc. is deprecated
In Dart, annotations are used to mark something as deprecated. Notice the documented annotation on this class.