How to refer to a Kotlin delegating singleton object from Java? - java

I have a Kotlin object that delegates it's implementation, in my case to MutableSet<String> like so:
object MySet : MutableSet<String> by TreeSet<String>() {
init {...}
}
In Java I'd like to say something like MySet.contains. How can I do that?

object declares a singleton. Unlike Kotlin, you cannot use a type name to refer to its instance in Java. Therefore, the Kotlin compiler translates the singleton instance to a field called INSTANCE instead, so you can do:
MySet.INSTANCE.contains(foo);
in Java.
While you can probably find INSTANCE by chance, just by using the auto-complete in IntelliJ, the only place where I could find this officially documented is in the Calling Kotlin from Java page at the bottom of this section, which talks about calling static methods.
object Obj {
#JvmStatic fun callStatic() {}
fun callNonStatic() {}
}
In Java:
Obj.callStatic(); // works fine
Obj.callNonStatic(); // error
Obj.INSTANCE.callNonStatic(); // works, a call through the singleton instance
Obj.INSTANCE.callStatic(); // works too

Related

Instantiating interfaces in Java/Kotlin

I read that in Java "interfaces cannot be instantiated - they can only be implemented by classes or extended by other interfaces".
However I can perfectly write:
val set = setOf<String>("one", "two")
in Kotlin, with set being of type Set<String>.
Doesn't this contradict my first statement as I'm instantiating the Set?
I read that in Java "interfaces cannot be instantiated - they can only be implemented by classes or extended by other interfaces"
What this means is just that you can't write
Set<String> set = new Set<String>(...);
(don't confuse with new Set<String> { ... } which creates an anonymous class implementing Set and instantiates that class). You can write Set.of("one", "two") though this method was only added in Java 9. It is a factory method, just like Kotlin setOf, not "instantiating an interface".
The Kotlin equivalent to the illegal new Set would be
val set = Set<String>(...)
which is also not allowed.
Though Kotlin intentionally blurs the line between constructors and methods; it would be perfectly in line with other types in the standard library to define a factory method called Set which would be called in the same way, or an operator fun invoke in the companion object. See the List method for an example.

Two observables point to the same reference

I wrote the following example and checked the value of the observerA variable for objects a and b.
Example
class Test {
val observerA = Observer<String>{}
}
Check
val a = Test()
val b = Test()
AppLogger.LOGE("[A]ObserverA: ${a.observerA} [B]ObserverA: ${b.observerA}")
Result
[A]ObserverA: com.test.Test$observerA$1#e3d8a1b
[B]ObserverA: com.test.Test$observerA$1#e3d8a1b
My guess is that a.observerA and a.observerA should be different, but they refer to the same object.
When I wrote observerA as below, I saw that different objects were created. I do not know why this difference appears.
val observerA = object : Observer<String>{
override fun onChanged(t: String?) {
}
}
When you use this syntax, you're defining a lambda with an empty body:
Observer<String>{}
This lambda will be compiled down to an anonymous class. If the lambda doesn't capture any variables, as an optimization step, there'll only be one instance of it (since you can't tell the difference in behaviour anyway).
As you've discovered already, you can force the compiler to create new instances of this Observer by using the full object expression syntax, which guarantees a new instance every time.
Source for the statements above, from the Kotlin in Action book:
As of Kotlin 1.0, every lambda expression is compiled into an anonymous class (...). If a lambda captures variables, the anonymous class will have a field for each captured variable, and a new instance of that class will be created for every invocation. Otherwise, a single instance will be created. The name of the class is derived by adding a suffix from the name of the function in which the lambda is declared (...).
If class Test is a singleton which is used in dagger for example (dependency injection) it will only be initialized once and the second time it will take point to the same object.
https://en.wikipedia.org/wiki/Singleton_pattern

Passing parameter information with { }

So you can do generic types with <> and you can pass objects with (). But what is it called when you pass information with {}, as in this example?
new Filter<CLDevice>() {
public boolean accept(CLDevice device) {
CLDeviceCapabilities caps = CLCapabilities.getDeviceCapabilities(device);
return caps.CL_KHR_gl_sharing;
}
}
Also does this work only for constructors or can any method make use of {} to gather data?
Is there any caveats associated with such code, like is it not performant?
What you are showing is not actually passing information (like passing an argument to a method), it's passing behavior.
Because up until Java 7 no lambdas existed, in order to pass behavior you always needed a class (after all in the java world everything a class). The syntax you are showing, is the syntax for an anonymous inner class. This syntax is used as a shortcut when you don't need/want to create a new class file, but just need to pass some behavior.
Note that you could just as easily use the same syntax if you had to implement (behavior passing) more than one method - something you could not do with Java 8 lambdas.
In this case you are providing an implementation via an anonymous class for a Single Abstract Method (SAM) interface or functional interface.
In java { and } define scope. There are various type of scopes for example class, method, block.
In your example your are creating a anonymous class.
So you can do generic types with <>.
You can pass objects with ().
What is it called when you pass information with {}, as in this example
With {} you create a body of a method or an anonymous class/method/object.. here your code is defining an anonymous method.

Deferred initialization of immutable variables

I've been using scala's lazy val idiom a lot and I would like to achieve something similar in Java. My main problem is that to construct some value I need some other value which is not known at object construction time, but I do not want to be able to change it afterwards. The reason for that is, I'm using a GUI library which instanciates the object on my behalf and calls a different method when everything I need is created, which is when I know the values I need.
Here are the properties I try to achieve:
* Immutability of my variable.
* Initialization in some other method than the constructor.
I do not think this is possible in Java, for only final achieves immutability of the variable and final variables cannot be initialized outside of the constructor.
What would be the closest thing in Java to what I am trying to achieve ?
One way to do it would be to push the actual instantiation of the value in question into another class. This will be final, but won't be actually created until the class is loaded, which is deferred until it is needed. Something like the following:
public class MyClass
{
private static class Loader
{
public static final INSTANCE = new Foo();
}
Foo getInstance()
{
return Loader.INSTANCE;
}
}
This will lazily initialise the Foo as and when desired.
If you absolutely need the Foo to be an instance variable of your top-level class - I can't think of any way off-hand to do this. The variable must be populated in the constructor, as you noted.
In fact I'm not sure exactly how Scala gets around this, but my guess would be that it sets the lazy val variable to some kind of thunk which is replaced by the actual object when first evaluated. Scala can of course do this by subverting the normal access modifiers in this case, but I don't think you can transparently do this in Java. You could declare the field to be e.g. a Future<Foo> which creates the value on first invocation and caches it from that point on, but that's not referentially transparent, and by the definition of final I don't see a way around this.
Andrzej's answer is great, but there is also a way to do it without changing the source code. Use AspectJ to capture Constructor invocations and return non-initialized objects:
pointcut lazyInit() : execution(* com.mycompany.expensiveservices.*.init(*));
void around() : lazyInit() && within(#Slow *) {
new Thread(new Runnable(){
#Override
public void run(){
// initialize Object in separate thread
proceed();
}
}
}
Given this aspect, all constructors of objects marked with a #Slow annotations will be run in a separate thread.
I did not find much reference to link to, but please read AspectJ in Action by Ramnivas Laddad for more info.

How can I pass a Scala object reference around in Java?

I want to return from a Java method a reference to a Scala object. How can I do that?
My Scala objects are like this:
trait Environment
object LocalEnvironment extends Environment {...}
object ServerEnvironment extends Environment {...}
... and I want my Java method to be like this:
Environment getEnvironment() { return LocalEnvironment; } // DOES NOT COMPILE
Is there a way to do this?
While the $.MODULE$ method works, a slightly less jarring way to get Java-interop with Scala objects is to expose the object as a method on itself.
The Scala:
object LocalEnvironment extends Environment{
def instance = this
}
The Java:
Environment getEnvironment() { return LocalEnvironment.instance(); }
This works because under the covers, .instance() is implemented as a static method on class LocalEnvironment. There has been some discussion about Scala objects getting an "instance" method by default, for just this purpose.
{ return LocalEnvironment$.MODULE$; }
should work.
Edit: the reason why this works is that this is how Scala represents singleton objects. The class ObjectName$ has a field in it called MODULE$ that is populated with the single valid instance of that class. But there is also a class called ObjectName that copies all the methods as static methods. That way you can use it like Java (just call ObjectName.methodName) in most cases, and Scala gets to have a real class to pass around.
But when Java needs to pass the class around--not something normally done with a bunch of static methods, which is what object is designed to emulate in Java--you then have to know how Scala represents it internally.

Categories

Resources