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
Related
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
Would appreciate any help on understanding below two concepts in Java 8.
What I know
A lambda is an object without an identity and should not be used as a regular object.
A lambda expression should not be calling methods from Object class like toString, equals, hashCode etc.
What I'd like know more about
What difference does lambda expression have to be called as an object without identity?
Why exactly should methods from Objectclass not be used while using lambda expression?
1) A lambda is an object without an identify and should not be used as a regular object.
This is not true. A lambda is a Java object, and it does have an identity1. The problem is that the lifecycle is deliberately left specified to allow Java compilers freedom to optimize the code that evaluates them. Therefore, you cannot know when new lambda objects are going to be created, or existing ones are going to be reused.
JLS 15.27.4 says:
"At run time, evaluation of a lambda expression is similar to evaluation of a class instance creation expression, insofar as normal completion produces a reference to an object. Evaluation of a lambda expression is distinct from execution of the lambda body.
Either a new instance of a class with the properties below is allocated and initialized, or an existing instance of a class with the properties below is referenced. ... "
2) A lambda expression should not be calling methods from Object class like toString, equals, hashCode etc.
As written, that is also not true. A lambda expression may call those methods. However, it is not advisable to rely on those methods to have any specific behavior when you call them on a lambda object
The JLS states:
"The class ... may override methods of the Object class."
In other words, it may ... or may not ... override them. If you rely a particular behavior of these methods, your application is (in theory) non-portable.
Furthermore, since the instantiation semantics are also unspecified, the behavior of Object::equals and Object::hashCode are uncertain.
Finally, it is unspecified whether lambdas are clonable.
1 - Sure, a lambda doesn't have a name: it is anonymous. But name and identity are different concepts.
Basically, a lambda is a convenience of doing this:
#FunctionalInterface
interface A {
void b();
}
void c(A a) {
...
}
void main() {
c(new A() {
void b() {
...
}
});
}
I apologize for the less than stellar variable names, but as you can see, A is an interface with one method. c is a method that takes in an A interface. However, instead of creating your own class that implements A, you can create it on the spot. This is what you call an anonymous class, since it doesn't have a name. This is where the quote you have:
A lambda is an object without an identify
comes from. The class doesn't have an identity. The reason it relates to lambdas is because if an interface has only one method, you can use lamdas to simplify it.
void main() {
c(
() -> {
...
}
);
}
This is the exact same as before.
The second part, why lambdas shouldn't use Object's methods, I didn't know before. You should probably have someone else answer this, however my guess is that lambda classes don't look like it extends Object directly, so you can't use it's methods.
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.
I have a class with an implicit parameter defined as:
class Test(implicit one: String)
And I want to instantiate that object like so:
val grr = new Test("aha")
I get the following exception.
error: too many arguments for constructor Test: ()(implicit one: String)Test
val grr = new Test("aha")
But if I call it like so
val grr = new Test()("haha")
grr: Test = Test#3bd40a57
I get a Test object.
Why does Scala instantiate of implicit methods require you to call the object with blank parameters in this instance? Why is there an implicit blank parameter list presented for such object instances?
First, Test is not an implicit class. See this for a discussion of implicit classes.
Instead, Test is a class that has no explicit constructor arguments but one implicit String argument. This means the only way you can instantiate Test is to either provide the implicit argument explicitly as you did, which is awkward and defeats the purpose, or to provide one and only one String in implicit scope at instantiation time and have the compiler "pick it up."
In other words, if you have something like this in scope:
implicit val s: String = "haha"
Then all you will have to do to instantiate Test is this:
val grr = new Test
And if you don't have one in scope, the compiler will let you know it. That's a good thing.
The main thing though is to make sure you get the distinction between implicit parameters and implicit classes.
The implicit blank parameter list is there just for constructors, not all methods. I think this is probably because the parser needs to distinguish between a reference to the type Test (or the companion object) and a reference to the constructor. If it allowed a constructor with no arguments, then Test by itself would be ambiguous.
Normally in scala when you refer to an "implicit class" you do it like this:
object Container {
implicit class Test(val one: string)
}
Then you can do:
import Container._
and it will implicitly convert Strings into Test objects.
In Java, the standard way to create an object is using
MyClass name = new MyClass();
I also often see the construct
new MyClass() { /*stuff goes in here*/ };
I've been looking online for a while and can't find a good explanation of what the second construct style does or how it does it.
Can someone please explain how and why you would use the second construct?
This construct makes actually two things: 1) It declares an anonymous class which extends the class you use in the constructor and 2) creates an instance of this anonymous class.
Edit: When using such a construct you can observe the anonymous class by looking at the generated .class files. There is the normal MyClass.class file and another one for each anonymous subclass: MyClass$1.class for the first and so on.
You would use the second construct in the case that you want to make an anonymous class. if you have a method that takes a callback as an argument, you might want to specify the implementation of the callback inline as opposed to giving it a name and putting it in a separate file or declaring it elsewhere in the same file.
There's also a trick called double brace initialization where you can get around not having syntax for literal maps and lists by using anonymous classes, like this:
Map map = new HashMap() {{put("foo", 1); put("bar", 2);}};
Here the nested braces create an instance initializer. The object bound to map is not a HashMap, its class is an anonymous class extending HashMap. (That means if you have a PMD rule about classes needing to declare serial uids then it will complain about this.)
Double-brace initialization is a fun trick to know but don't use it in real code. It's not safe to pass around the map created like this, because the inner object keeps a reference to the outer instance so if anything in the program holds onto a reference to the map it keeps the outer object from getting garbage-collected. There are also problems with serialization.
As others have already said, it creates an instance of an anonymous class, subclassing Class. Here's an example how it is commonly used:
panel.addMouseListener(
new MouseAdapter () {
#Override
public void mouseEntered(MouseEvent e) {
System.out.println(e.toString());
}
}
);
The above code creates an instance of an anonymous class which extends MouseAdapter. In the anonymous class the method mouseEntered has been overridden to demonstrate that the anonymous class works basically as any other class. This is very convenient and common way to create (usually simple) listeners.
Second construction creates an instance of anonymous class which is a subclass of Class.
If you want to new a object by a protect constructor from another package, you can use:
new Foo() {};
otherwise you will get an access error. It equals anonymous subclass inherited from Foo class.
From jdk8 onwards you may have seen different syntax seems like creating an objects while using lambda expressions.
NOTE: Lambda expressions don't get translated into anonymous inner classes, they use invoke dynamic that was introduced in Java 7 to execute functional methods.
For Example:
public class LambdaSample {
public static void main(String[] args) {
//If implementation is only one statement then {} braces are optional
Runnable oneLineImplRunnable = ()->System.out.println("This is one line lambda expression");
//Multiple statements in the implementation then {} braces are mandatory
Comparator<StudentTest> stdComparator = (StudentTest s1,StudentTest s2)->{
if(s1.getFirstName().equals(s2.getFirstName())) {
return s1.getLastName().compareTo(s2.getLastName());
}else {
return s1.getFirstName().compareTo(s2.getFirstName());
}
};
}
}