Note: As of Kotlin beta 4, this problem is fixed.
fun test(a: List<String>) { }
The above Kotlin code generates byte code:
public static final void test(#NotNull List<? extends String> a)
{
Intrinsics.checkParameterIsNotNull(a, "a");
}
I have submitted an issue, but I need to circumvent this bug temporarily. Is there a way to mark a as invariant?
The problem has been fixed in out dev-branch and will be available within next public release.
Also there will be JvmSuppressWildcards/JvmWildcard annotations allowing to control generic signature.
As a temporary workaround you can use MutableList<String> in Kotlin declaration
Related
I tried to make abstract class for testing because I found weird problem for using generics
abstract class Test<T> {
open fun hello(vararg data: T) {
print("Default function")
}
}
This very simple abstract class has one opened method with vararg keyword. Problem can be reproduced by making another class which extends Test class.
class Hello : Test<Int>() {
//Problem 1
override fun hello(vararg data: Int) {
super.hello(*data) //Problem 2
println("Override function")
}
}
About first problem, Kotlin says method doesn't override anything even though this method surely overrides something. Weirdly, this error happens randomly, so I can't tell exact way to reproduce this bug
This error got removed when I add some codes (like really simple code such as println(), etc), but when you compile, it causes same error again.
About second problem, super.hello(*data) causes problem because this requires Array<out Int>, but found parameter is IntArray. I think Kotlin is considering IntArray and Array<*> as different class, but it shouldn't act like this...
I'm using Kotlin 1.4.10 which seems the latest version according to this site.
I'm posting this to check if these 2 problems are bug or if I did something incorrectly because when I change generic to String, all problems get removed.
Are there any mistakes I made in these sample codes above?
Known issue: https://youtrack.jetbrains.com/issue/KT-9495
As a workaround, you can use the boxed java.lang.Integer.
class Hello : Test<Integer>() {
override fun hello(vararg data: Integer) {
super.hello(*data)
println("Override function")
}
}
I am trying to switch to Kotlin from Java. But I have a lot of legacy code and third-party libraries. And I see that pretty often there are public fields without getters and setters in Java classes that must be accessed from other classes.
How can I access a public field of a Java class without getter from Kotlin code?
you can access directly to the property
can you add min code example ?
for this example i cant seem to understand what is the problem
Test.java
public class Test {
public int myPublicValue = 7;
}
Runner.kt
fun main(args: Array<String>) {
val t = Test()
t.myPublicValue
}
Kotlin allows me to create two main() functions. But does not allow two myfun() functions.
What is special about main()? Are there other special functions?
Can I create two static myfun() functions in same package? I want them to have file scope like main.
Test1.kt:
package start
fun main(args: Array<String>) {
}
fun myfun(args: Array<String>) {
}
Test2.kt:
package start
// OK!
fun main(args: Array<String>) {
}
// Error! Conflicting overloads
fun myfun(args: Array<String>) {
}
Kotlin allows to have multiple top-level main functions in the same package due to practical reasons — so that one could have an entry point in an each file without moving these files to different packages.
It is possible because each .kt file with top-level members is compiled to the corresponding class file, so these main functions do not clash, because they are located in separate class files.
Why is it allowed for main functions and not for other top-level functions? Having multiple functions with the same name and signature in the same package would make it impossible to distinguish them when calling from Kotlin. This is not a problem for main function, because when it is used as an entry point for a program, it's required to specify the class name where it is located.
What is special about main()? Are there other special functions?
To start a Java program you need
a class file,
static void main(String[]) method in that class file.
So from outside of the package you'd be able to start any of these main methods.
However if you try to call the main method from another Kotlin file inside of the package, you'd get an error, because Kotlin can't disambiguate one method from the other.
You can call any of them from Java as you please because they're compiled in different class files (see further).
Can I create two static myfun() functions in same package?
You can't define two top-level methods with the same name in the same package in Kotlin (with the above exception).
This is what your code compiles to:
public final class Test1Kt {
public static final void main(#NotNull String[] args) { /* ... */ }
public static final void myFun(#NotNull String[] args) { /* ... */ }
}
public final class Test2Kt {
public static final void main(#NotNull String[] args) { /* ... */ }
public static final void myFun(#NotNull String[] args) { /* ... */ }
}
As far as JVM is concerned all of these methods could coexist in peace. But this is an implementation detail of Kotlin.
Let's forget for a second that Kotlin apps run on JVM. Pretend your only tool is Kotlin, and you can't use Java, perhaps you're writing a Kotlin cross-platform module. How could you have two top-level functions with the same name? How would you pick which one to call? Again, you'd get an error, because Kotlin couldn't disambiguate one method from the other.
Edit: As noted by #Todd this behavior has been even more strict in the past: Why does Kotlin lang allow only single main function in project?
Regarding the question about how to have file-scoped functions, by default top-level functions (those not declared within a class) are public, which means their signatures must be unique, including the package name. You can make functions local to the file, rather than the package, by prefixing them with the private modifier, e.g., in each file:
private fun myfun(args: Array<String>) {
// method body here
}
Is it possible to add a new static method to the java.lang.Math class in Kotlin? Usually, such things are possible in Kotlin thanks to Kotlin Extensions.
I already tried doing the following in a file I made called Extensions.kt:
fun Math.Companion.clamp(value:Double,minValue:Double,maxValue:Double):Double
{
return Math.max(Math.min(value,maxValue),minValue)
}
but Math.Companion could not be resolved...
As of Kotlin 1.3, this is not possible. However, it's being considered for a future release!
To help this feature get implemented, go vote on this issue: https://youtrack.jetbrains.com/issue/KT-11968
Because all proposals are basically in limbo right now, I wouldn't hold my breath that this will get in any time soon
I think this is not possible. Documentation says the following:
If a class has a companion object defined, you can also define extension functions and properties for the companion object.
The Math class is a Java class, not a Kotlin one and does not have a companion object in it. You can add a clamp method to the Double class instead.
As of Kotlin 1.2 it is still not possible.
As a workaround, to statically "extend" Environment class I am currently using:
Class EnvironmentExtensions {
companion object {
#JvmStatic
fun getSomething(): File {
...
return Environment.something()
}
}
}
It is not an ideal solution but IntelliJ/Android Studio code completion helps with the usage:
val something = EnvironmentExtensions.getSomething()
Java:
public class JavaClass implements ModelController.Callback {
#Override
public void onModelsLoaded(#NonNull List<? extends Model> models) {
doSomething(models);
}
private void doSomething(List<Model> models) { }
}
Kotlin:
class ModelController {
var callback = WeakReference<Callback>(null)
interface Callback {
fun onModelsLoaded(models: List<Model>)
}
fun someFunction() {
callback.get().onModelsLoaded(ArrayList<Model>())
}
}
interface Model {
}
Without the ? extends Model in the Java onModelsLoaded method, the override doesn’t match the interface made in Kotlin. With it, I get the following error:
doSomething(<java.util.List<com.yada.Model>) cannot be applied to (java.util.List<capture<? extends com.yada.Model>>)
Why is the wildcard capture required and why doesn't it allow it to be used against the non-wildcard method?
The issue stems from Kotlin collections being variant, and Java only having use-site variance which is implemented though wildcards (capture is something connected to wildcards but not exactly the ? extends ... syntax itself).
When in Kotlin we say List<Model> it means "read-only list of Model or subtypes of Model", when we say the same in Java it means "mutable list of exactly Model and nothing else". To mean roughly what Kotlin's List<Model> means, in Java we have to say List<? extends Model>, this is why for the override to work you have to add the wildcard into the Java code.
Now, your doSomething is written in Java and says that it wants "a list of exactly Model", and when you are giving it "a list of Model or its subtypes", the Java compiler complains, because it can be dangerous: doSomething might try to do something that is not legitimate for a list of, say, ModelImpl, because it thinks it's working on a list of Model.
As of now (Kotlin Beat 2), you have two options:
use MutableList<Model> in your Kotlin code - this mean exactly what Java's List<Model> means, or
define doSomething so that it takes List<? extends Model>, which is what your current Kotlin code means.
In the next update of Kotlin we'll add an annotation on types to facilitate a somewhat cleaner workaround for this problem.
To solve the problem with capture<? extends Model>
You may do something like this:
void doSomething(List<Model> models) {
new ArrayList(models)
}