Kotlin method overloading - java

This following declaration is legal in Kotlin.
fun foo(): String = "foo_1"
fun <T> foo(): T = "foo_2" as T
As bytecode we are getting:
public final static foo()Ljava/lang/String;
// signature <T:Ljava/lang/Object;>()TT;
// declaration: T foo<T>()
public final static foo()Ljava/lang/Object;
It's also possible to call both of these methods from Kotlin.
The problem comes when I'm trying to call any of them from Java:
ClassKt.foo()
Ambiguous call. Both methods match ...
How to avoid such a problem? How to deal with such methods? What if 3-rd party kt library has same issue?
The example above is a synthetic one.

Why does it work with Kotlin to begin with... In Java having two methods like:
private static String test() {
return "";
}
private static <T> T test() {
return null;
}
would result in a compile time error. And for java devs this is sort of obvious, these methods would have the same type erasure. But this is rule imposed by javac, not by the JVM where this code runs. So javac does not treat two methods as having only a different return type as overloads. Well, kotlin is a different language and since it runs on the JVM (that expects valid byte-code) it allows treating methods with only the return type being different as overloads. I am yet to look at the byte code and understand how that happens; it also seems that this will work only for generic code, so may be type erasure is slightly different in case of kotlin.
Now, things should be obvious why calling such a method from java fails. Kotlin offers a neat solution for this: #JvmName("someDistinctName"). I am not entirely sure how this works under the hood either... yet, though I assume this will create a bridge method.
EDIT
#JvmName will rename the method at the byte-code level.

You can use #JvmName to differentiate the code when it's called from java:
#JvmName("fooString")
fun foo(): String = "foo_1"
fun <T> foo(): T = "foo_2" as T
This will allow calling the String method in Java with ClassKt.fooString(), which resolves the clash.

An easy solution would be writing a helper method in Kotlin and just calling that.
Another way using only Java would be getting a MethodHandle for both methods and using them:
MethodHandle MH_fooString = lookup().findStatic(ClassKt.class, "foo", methodType(String.class));
MethodHandle MH_fooT = lookup().findStatic(ClassKt.class, "foo", methodType(Object.class));
String foo = (String) MH_fooString.invokeExact();
It's not nearly as simple and requires handling exceptions though.

Related

Implementing a Kotlin property from a Java interface

Consider the following Java interface
interface Foo {
String getValue();
}
In Kotlin, get/set functions are converted to properties, so I would expect the implementation to look like this
class FooImpl : Foo {
val value: String get() = "Hello, World!"
}
But I actually have to implement the method as it is in the interface
class FooImpl {
override fun getValue(): String {
return "Hello, World!";
}
}
Why?
Kotlin makes an explicit difference between methods and properties. They are not considered the same thing; it just so happens that both are compiled down to methods in the end since the JVM doesn't natively support properties. As such, a method cannot implement a property since they're fundamentally different.
The reason why you can't implement a Java getter with a property is the same reason as why you can't implement a Kotlin-defined fun getX(): String with an override val x: String; they're just not compatible.
The confusion here seems to stem from how Kotlin allows you to access Java getters with a property-like syntax, i.e. val foo = obj.x is equivalent to val foo = obj.getX() if the class is defined in Java.
This is strictly a one-way relationship to make Kotlin code that interoperates with Java code slightly more compact and "Kotlin-like"; this syntactical shortcut doesn't extend to implementing the method as if it were a property.
Additionally, if you were to implement a method as a property, that would probably lead to strange effects. Arguably, it would be both a method and a property at the same time, which would not only be weird, but would likely lead to a lot of other unexpected behaviors and edge cases in the language. (For instance, how would it be treated when using reflection?)

Can you explain why the first unwrapped method reference does not compile?

In this example, passing a method reference to Stream.of does not work but once it's wrapped it works. I can't quite get my head around why this is. Isn't the method reference equivalent to the functional interface?
public class A {
String a() {
return "";
}
void b() {
Stream.of(this::a); // won't compile
Stream.of(wrap(this::a)); // will compile
}
static <T> Supplier<T> wrap(Supplier<T> f) {
return f;
}
}
Stream.of has the following signature:
public static<T> Stream<T> of(T t)
The following example will compile because you explicitly providing a type information for T.
Stream<Supplier<String>> a = Stream.of(this::a);
The first example Stream.of(this::a); equivalent to:
Object a = this::a;
where Object is not a functional interface and will not compile.
Providing with a functional interface this example compiles:
Runnable a = this::a;
Stream.of(a);
In the second example, wrap provides a functional interface Supplier
Stream.of(T) expects an Object and you pass to it a method reference in the first statement. But an Object parameter is not a functional interface, so it cannot accept a method reference or a lambda that is not specifically typed.
With lambda, it would produce also an error : Stream.of(()->this.a()).
A simpler example could be Stream.of(()-> "foo") that will just not compile.
But if you type the method reference or the lambda it works :
Stream.of((Supplier<String>) this::a)
or
Stream.of((Supplier<String>) () -> this.a())
In the working statement you pass to Stream.of(T) a parameter that is a Supplier<String>. That refers to a functional interface but that is typed as in the previous working examples, so it is valid as parameter that expects an Object.
this::a is contextless and could mean different things. You need to provide some context to help the compiler to figure out what you actually meant by this::a.
Stream.<Supplier<String>>of(this::a);
Though, that Stream<Supplier<String>> doesn't seem to be what you wanted. If you need a Stream<String>, use Stream.generate: no extra type information needed since the method takes a Supplier<T> (no ambiguity here).
Stream.generate(this::a);
On a side note, both statements expect you to save their results into variables. Defining variables of the right type often facilitates resolving such issues.
Stream<Supplier<String>> s1 = Stream.of(this::a);
Stream<String> s2 = Stream.generate(this::a);
All credit to #J-Alex and #Holger for their precious comments.

Java Reflection in Scala

I am trying to get a simple java reflection program working in Scala, and seem to be missing something ...
scala> val cl = new URLClassLoader(Array(new File("Hi.jar").toURI.toURL), getClass.getClassLoader)
cl: java.net.URLClassLoader = java.net.URLClassLoader#3c7b137a
scala> val c = cl.loadClass("Hi")
c: Class[_] = class Hi
scala> val m = c.getMethod("run")
m: java.lang.reflect.Method = public void Hi.run()
scala> m.invoke()
<console>:21: error: not enough arguments for method invoke: (x$1: Any, x$2: Object*)Object.
Unspecified value parameters x$1, x$2.
m.invoke()
^
What am I missing, as the prior line has indicated -
public void Hi.run()
What exactly is it expecting for the two arguments?
Scala is telling you exactly what your problem is: invoke needs 1+ parameters!
See the java doc:
invoke(Object obj, Object... args)
Invokes the underlying method represented by this Method object, on the specified object with the specified parameters.
So, you have to provide at least one argument - a reference to the object (or class) you want to call that method on! As Hi.run() seems to be static, you would want to use your c as only argument to your call.
The following arguments would be the actual parameters that your "reflected" method expects. In your case, no further arguments.
Long story short: you better keep the excellent tutorials from Oracle on reflection close to your scala console while experimenting. If you try to learn "reflection" by trial&error; I guarantee you: a lot of frustrating trials with many strange errors. Really: the reflection API is not very forgiving when you don't know what you are doing; even the slightest mistakes can lead to very unexpected results.
There is nothing specific to Scala there. Method.invoke requires the at least one argument being the instance on which it's applied (or null for a static method).
In Scala, you can use structural typing for such simple case.

Calling private Java methods in Scala

I regularly use the Scala REPL for rapid Java iteration and testing, but sometimes I want to trigger some private behavior of a class, and have to recompile the code in order to make the method visible. I'd like to be able to call private Java methods directly in the REPL, without needing to make code changes.
What I've got so far:
// Calls private Java methods
// We currently define an overload for every n-argument method
// there's probably a way to do this in one method?
def callPrivate(obj: AnyRef, methodName: String) = {
val method = obj.getClass().getDeclaredMethod(methodName)
val returnType = method.getReturnType
method.setAccessible(true)
println("Call .asInstanceOf[%s] to cast" format method.getReturnType.getName)
method.getReturnType.cast(method.invoke(obj))
}
def callPrivate(obj: AnyRef, methodName: String, arg: AnyRef) = {
val method = obj.getClass().getDeclaredMethod(methodName, arg.getClass())
method.setAccessible(true)
method.invoke(obj, arg)
}
Which can be used like:
scala> callPrivate(myObj, "privateMethod", arg).asInstanceOf[ReturnedClass]
But this requires defining a near duplicate method for every n-argument method type (and requires an external cast, but I suspect that's unavoidable). Is there any way to refactor this so that one function can handle any number of arguments?
Note: I'm using Scala 2.9.1, so I'm looking for solutions using Java Reflection. Answers using Scala Reflection are welcome, but don't address my problem directly.
DISCLAIMER: There has been a while since the last time I programmed in Scala and I don't have any kind of Scala environment around to test what I am showing you. So it might have small syntax errors here and there, bear with me. Hope the rest is useful
In theory you could provide our callPrivate method with an extra variable argument that specifies the method parameters:
def callPrivate(obj: AnyRef, methodName: String, parameters:AnyRef*) = {
val parameterTypes = parameters.map(_.getClass())
val method = obj.getClass.getDeclaredMethod(methodName, parameterTypes:_*)
method.setAccessible(true)
method.invoke(obj, parameters:_*)
}
There is a flaw however. This won't work if you have a method somewhere with a signature like this:
public X someMethod(A parameter);
and A is inherited (or implemented) by class B. If you try to invoke your Scala method this way callPrivate(someObject, "someMethod", new B()) it won't work mostly because the getDeclaredMethod lookup will search for someMethod(B) instead of someMethod(A) - even when new B() is of type A too!
So that's a naive implementation. You could potentially get all the valid types of all the method parameters and perform the getDeclaredMethodlookup with all the combinations for them, however there is one more caveat in that direction: You might bump with overloaded methods that accept different combinations of the same set of parameters and you will not know which one to call (i.e. you may have someMethod(A,B) and someMethod(B,A) and you won't be able to know which one should be invoked)
One way avoid that is to force the caller to provide you with tuples instead of raw instances, each tuple has the parameter value and the parameter type to be used. So it is up to the caller to specify which method he want to invoke.
def callPrivateTyped(obj: AnyRef, methodName: String, parameters:(AnyRef,Class[_])*) = {
val parameterValues = parameters.map(_._1)
val parameterTypes = parameters.map(_._2)
val method = obj.getClass.getDeclaredMethod(methodName, parameterTypes:_*)
method.setAccessible(true)
println("Call .asInstanceOf[%s] to cast" format method.getReturnType.getName)
method.invoke(obj, parameterValues:_*)
}
// for convenience
def callPrivate(obj: AnyRef, methodName: String, parameters:AnyRef*) = {
callPrivateTyped(obj, methodName, parameters.map(c => (c, c.getClass)):_*)
}
That should do the trick.
Also, one more thing: Keep in mind that the way you are using getDeclaredMethod will only return methods (with any scope) that are implemented in obj.getClass(), meaning that it won't return any inherited method. I don't know if that is by design, if not you will need to add a recursive lookup over the superclasses of your obj.

How to implement Scala apply method in Java

I want to call some Java code from Scala code. I would like to use Scala's apply construct, so I can call it like this:
val led = OutPin(0)
instead of:
val led = new OutPin(0)
I naively implemented an additional apply method in my Java code like this:
public class OutPin {
public OutPin(int pinNumber) {
}
public OutPin apply(int pinNumber) {
return new OutPin(pinNumber);
}
}
This does not make my Scala code (first line above) compile, and instead gives me an error:
Object OutPin is not a value
What is the correct way to implement Scala's apply method in Java?
Your problem is not with the apply method per-se, but with trying to implement a Scala singleton object in Java.
I think (but am not certain) that this is very difficult, perhaps even impossible, by design.
Consider a very, very simple case:
object Obj;
This compiles to two JVM bytcode files, Obj$.class and Obj.class. In theory, it should be easy to just inspect the bytecode of those two classes, and reexpress the same thing in Java. The basic structure of Scala singleton objects is very, very simple:
For a singleton object Obj, a Obj.class and Obj$.class must be generated
The Obj$ class must have a public final static field of type Obj$ called MODULE$, which will be initialized on class initialization refer to the singleton object. In Scala, calls to Obj.foo() get mapped to Obj$.MODULE$.foo() [...if Obj had a method called foo(), that is!]
The Java compiler doesn't know anything about these Scala generated class pairs, so for Java interop, the Obj class contains static functions that just forward to a call of a method of the same name and signature on Obj$.MODULE$.
That sounds complicated, but it's really not so much. It's trivial to write a pair of Java classes that goes this far. But the Scala compiler (2.10.3) still won't recognize the pair as constituting a Scala singleton. Diving into the bytecode of a Scala-compiler generated singleton, you'll see that there are details that are hard to express in legal Java. [Hint: javap -c -p -s -v <fully-qualified-class-name>]
For example, the final static MODULE$ field is initialized indirectly by the static initializer. The static initializer just constructs an Obj$ object, without directly assigning it. The assignment occurs within the private constructor. That's illegal in Java: blank static finals must be certainly initialized in the static initializer, and cannot be assigned in code (like the private constructor) that might potentially be called from outside the initializer and multiple times. The Scala compiler generates bytecode that respects the blank final semantics (because the private constructor is only called once), but exceeds the Java compiler's ability to verify those semantics. So this code would be rejected if expressed in Java.
Also, the Obj class (the version without the terminal dollar sign) includes an annotation of type ScalaSig, which looks quite complicated and would be hard to reproduce by hand (in Java or in Scala), at least for those of us unsure exactly how this annotation works.
I don't know exactly what the Scala compiler looks for before deciding to treat a pair of classes as a "value", that is a valid Scala singleton object, but Scala's designers have chosen not to make it easy, despite the simplicity of the basic scheme. Probably they wish to preserve the ability to reorganize how scala singleton objects translate to bytecode. Letting Java programmers synthesize scala singleton objects would effectively render the current scheme a permanent part of Scala's public API.
Note that writing an ordinary, non-singleton class whose instances have an apply(...) method and so can be called like functions is easy from Java and works fine. Here's a Java cat:
public class Cat {
public String apply( int i ) {
return "Meow: " + i;
}
}
Here's a use of Scala's sugared apply:
Welcome to Scala version 2.10.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_45).
Type in expressions to have them evaluated.
Type :help for more information.
scala> val Morris = new Cat;
Morris: Cat = Cat#6b4feafa
scala> Morris(8)
res0: String = Meow: 8
If you want an apply method that is usable in Scala you should implement it on the scala an side using object to wrap your java class with the same name of the class which instantiate it
object OutPin {
def apply(pinNumber :Int) = new OutPin(pinNumber)
}
The problem is that the Scala compiler says you must define two companion objects in the same file, otherwise you get the error:
Companions 'class OutPin' and 'object OutPin' must be defined in same file
Here is another approach that might work for you. If you define your Scala OutPin in a separate package, then it will work. For example:
Java class:
package base;
public class OutPin {
private final int i;
public OutPin(int i) {
this.i = i;
}
public int getI() {
return this.i;
}
}
Scala class:
package base.scala
object OutPin {
def apply(i: Int): base.OutPin = new base.OutPin(i)
}
Sample Scala client:
import base.scala.OutPin
object Client extends App {
val op = OutPin(1)
println(op.getI)
}
Running Client prints 1
To get access to the sugared apply you would have to import base.scala instead of just base. If it's really important to get the apply syntax it might be worth it.

Categories

Resources