This is from an article from oracle about anonymous classes I was reading:
Anonymous classes are ideal if you have to implement an interface
that contains two or more methods
I though that is ideal if you have to implement fewer than two methods, cause you don't need to make more concrete named classes, but if you have to implement more than two will be more unreadable.
My question is:
Why should implementing anonymous classes with 2 or more methods be ideal?
You took that sentence out of context. Look at the sentence immediately before that one:
Because the EventHandler<ActionEvent> interface contains only one
method, you can use a lambda expression instead of an anonymous class
expression. See the section Lambda Expressions for more information.
(emphasis by me)
You'll be able to use lambda expression instead of anonymous classes with only a single method in the future, so using an anonymous class only makes sense if your interface has more than one method.
Readability might suffer if it has many methods, but there is no other language construct that enforces that a specific implementation may only be used at one point in the code.
The article is including information from JDK 8, in which case Lambda expressions can be used to implement single function interfaces instead of having to use an anonymous class.
So the 2+ method suggestion is strictly for JDK 8, for 7 and below anonymous classes are the only way (well, outside of full classes) for single method and multiple method interface implementations.
This is probably taking into account the new concise syntax available in Java 8 (fingers crossed) for single-method interfaces (i.e. Lambda Expressions). That would provide a better option than anonymous classes if the interface does indeed only have a single method.
Related
Java 8 has included a new feature called Defender methods which allows creation of default method implementation in interface.
Now first of all this is a huge paradigm shift for all condensed programmers in Java. I viewed a JavaOne 13 presentation given by Brian Goetz where he was discussing about the new stream() and parallelStream() implementations in Collections library.
For adding new methods in Collection interface, they could not have just added a new method without breaking the previous versions. So he told that for catering this a new feature of Default methods was added.
public interface SimpleInterface {
public void doSomeWork();
//A default method in the interface created using "default" keyword
default public void doSomeOtherWork(){
System.out.println("DoSomeOtherWork implementation in the interface");
}
}
Now my question is basically that are default methods just helpful when needed to add new methods to interface without breaking client code? Or are there some other uses to it too?
Besides having the possibility of adding methods to the interface in future versions, there is the important point of allowing an interface to stay a functional interface even if it has more than one method.
A functional interface has only one non-default abstract method which can be implemented via a lambda expression. One example is the Predicate interface which has only one abstract method (test) while providing default methods for negating a Predicate or combining it with another Predicate. Without default methods these methods had to be provided in another utility class like the pre-Java 8 Collections class (as you don’t want to give up the possibility of lambda implementations for such an interface).
As you said, the main motivation was allowing the evolution of existing interfaces.
However there are reasons why you'd want to use them in brand new interfaces as well:
One such reason is methods that can easily be implemented using the other (non-default) methods of the interface. Using default methods for this reduces the need for Foo-interface/AbstractFoo-base-implementation combinations (see AbstractList for example).
While this does not create an entirely new field, it means that you can have end-user-friendly interfaces (with lots of useful methods), still keeping it simple to implement.
There was a problem with interfaces that they were not open to extension, which means if there was a need to add new method to an interface it would have broken the existing implementation of these interfaces. Thus it was imperative that all the classes implementing that interface had to provide implementation for the newly added method, even if the method was not needed. Thus interfaces were not easy to evolve.
One example that comes to mind is Java MapReduce API for Hadoop, which was changed in 0.20.0 release to favour abstract classes over interfaces, since they are easier to evolve. Which means, a new method can be added to abstract class (with default implementation), with out breaking old implementations of the class.
With the release of Java 8, it is now possible to add default method in interfaces also, thus making them easier to evolve too. With the addition of default method to an interface, addition of new method, to even an interface will not break the pre-existing code.
For adding new methods in Collection interface, they could not have
just added a new method without breaking the previous versions.
Yes they could have done this but Let's think from API designer perspective for e.g. Collection Library is used by some libraries like apache-commons, guava etc and which instead are used by many java projects. Now imagine just by adding one new method in Collection interface will break entire chain of projects.
Now my question is basically that are default methods just helpful
when needed to add new methods to interface without breaking client
code? Or are there some other uses to it too?
Motivation/Need for Default Methods
API Evolution in compatible way
The initial purpose of introducing default methods was to make collections library backward compatible. This library was modelled as a deep hierarchy of interfaces, including prominent members such as Collection, List, Map, and Set. They needed to be enriched to make lambdas truly useful for everyday programming.
To make Collections library lambda rich, java architects could have
refactored them to support lambda but it was a far from a good
solution as it will break all the all existing Java deployments and
countless 3rd party libraries extending the Collections hierarchy
Instead java architects thought to introduce default methods capabilities for backward compatibility.
Use cases of Default Methods
One important use case is to aid functional thinking in java. A functional interface with default methods is a pure behaviour-only construct. It cannot hold state. This aligns your thinking with functional programming and allows you to take advantage of what the programming model has to offer
Optional Methods : There are classes in java that implement an interface but leave empty method implementations for e.g. Iterator interface. It defines hasNext and next but also the remove method. Prior to Java8 remove was ignored because the user didn't want to use that capablity. Therefore many classes implementing Iterator interface would have empty implementation of for remove which is unnecessary boiler plate code. With default methods we can provide a default implementation for such methods, so concrete classes don't need to explicitly provide an empty implementation.
Default methods helps in resolving Multiple inheritance of behaviour in java. Before Java8, there was support for Multiple inheritance of Type only and now with the help of default methods we can have multiple inheritance of behaviour.
For e.g.
Java 8 has three rules for resolving conflicts brought upon by
multiple inheritance when ambiguous:
First, an explicit method declaration in the class or a superclass takes priority over any default method declaration.
Otherwise, the method with the same signature in the most specific default providing interface is selected.
Finally, if there is still conflict, you have to explicitly override the default methods and choose which one your class should choose.
In Conclusion Default methods offer a brand new way to design objects.
References :
Java8 In Action
Functional Java: A Guide to Lambdas and Functional Programming in Java 8
default methods made possible the functional programming concept. For functional programming type code we need only one abstract method .
Also adding an method in interface will not made it compulsory for all the classes implementing an interface. Simplified the coding practise
Is groovy's extension module feature a hybrid form of java's inheritance feature? Why are the extension-module needs to be declared as static?
Short answer is I think yes. It is a bit difficult to answer clearly, since the inheritance for the extension methods is done completely by the runtime (and the static compiler). As such it has nothing to do with how Java does inheritance.
To answer the second question... They are static, because for situations in which you need state you usually use the meta class. Extension methods are initially thought of as convenience methods or to make the API more Groovy. As such, they are a special form of methods added to the meta class. You can see them as simplified version. But that also means they don't have all the abilities. Implementing extension methods, that can keep local state on a per "self"-object basis (basically what fields/properties would do) is actually difficult to do efficient... but you could always use per instance meta classes for this.
For all extensive purposes they are syntactic sugar so that a static method appears to be more OOP like. There is no inheritance because static methods in Java and Groovy do not participate in inheritance (that is classes do not inherit static methods).
The methods need to be static because the compiler does not know how to instantiate the surrounding class of the extension method.
However I believe there are languages that do allow for methods to be defined outside of the enclosing class and do some sort inheritance but not many do not (I believe CLOS and Dylan do). Also they are many languages that appear to allow methods to be added but the type of "object" is actually changed/hidden to some other type. This is called adhoc polymorphism (e.g. Clojure, Haskell, sort of Golang and sort of Scala) but again has nothing to do with inclusional polymorphism (Java inheritance).
Unfortunately the reference documentation and other docs don't define the semantics of extension methods:
Q. Can they override instance methods?
I tested extension methods via use Category methods and metaClass expando methods. Neither approach overrides instance methods. I didn't test extension modules installed via module descriptor.
Q. Can they be overridden by extension methods on subclasses?
I tested that, too. use methods and metaClass extension methods don't get overridden by extension methods on subclasses.
Q. Can they call inherited super methods?
No, since they're implemented via static methods.
Q. Can they call private methods?
Experiments showed that they can, surprisingly.
Q. Can they access private instance variables?
No, since they're implemented via static methods.
Q. Are they callable from Java methods?
Maybe, if the extension module is on the classpath when compiling the calling code. I didn't test it.
Conclusion: Extension methods are not a form of inheritance. They seem to be a dynamic form of Universal Function Call Syntax (UFCS), that is, when the language can't find a method variable.foo(arguments) it looks for a static extension function foo(variable, arguments) to call. [Please correct my hypothesis if wrong!]
You asked why they're defined as static. That seems to match the semantics: A static function that's not involved in inheritance, although its calling syntax makes it look like a convenient method call.
You can write an extension method like an instance method using the #groovy.lang.Category annotation. That does AST transformations at compile time to turn it into a suitable static method.
Also see Groovy traits. That is a form of (mixin) inheritance.
Java 8 has included a new feature called Defender methods which allows creation of default method implementation in interface.
Now first of all this is a huge paradigm shift for all condensed programmers in Java. I viewed a JavaOne 13 presentation given by Brian Goetz where he was discussing about the new stream() and parallelStream() implementations in Collections library.
For adding new methods in Collection interface, they could not have just added a new method without breaking the previous versions. So he told that for catering this a new feature of Default methods was added.
public interface SimpleInterface {
public void doSomeWork();
//A default method in the interface created using "default" keyword
default public void doSomeOtherWork(){
System.out.println("DoSomeOtherWork implementation in the interface");
}
}
Now my question is basically that are default methods just helpful when needed to add new methods to interface without breaking client code? Or are there some other uses to it too?
Besides having the possibility of adding methods to the interface in future versions, there is the important point of allowing an interface to stay a functional interface even if it has more than one method.
A functional interface has only one non-default abstract method which can be implemented via a lambda expression. One example is the Predicate interface which has only one abstract method (test) while providing default methods for negating a Predicate or combining it with another Predicate. Without default methods these methods had to be provided in another utility class like the pre-Java 8 Collections class (as you don’t want to give up the possibility of lambda implementations for such an interface).
As you said, the main motivation was allowing the evolution of existing interfaces.
However there are reasons why you'd want to use them in brand new interfaces as well:
One such reason is methods that can easily be implemented using the other (non-default) methods of the interface. Using default methods for this reduces the need for Foo-interface/AbstractFoo-base-implementation combinations (see AbstractList for example).
While this does not create an entirely new field, it means that you can have end-user-friendly interfaces (with lots of useful methods), still keeping it simple to implement.
There was a problem with interfaces that they were not open to extension, which means if there was a need to add new method to an interface it would have broken the existing implementation of these interfaces. Thus it was imperative that all the classes implementing that interface had to provide implementation for the newly added method, even if the method was not needed. Thus interfaces were not easy to evolve.
One example that comes to mind is Java MapReduce API for Hadoop, which was changed in 0.20.0 release to favour abstract classes over interfaces, since they are easier to evolve. Which means, a new method can be added to abstract class (with default implementation), with out breaking old implementations of the class.
With the release of Java 8, it is now possible to add default method in interfaces also, thus making them easier to evolve too. With the addition of default method to an interface, addition of new method, to even an interface will not break the pre-existing code.
For adding new methods in Collection interface, they could not have
just added a new method without breaking the previous versions.
Yes they could have done this but Let's think from API designer perspective for e.g. Collection Library is used by some libraries like apache-commons, guava etc and which instead are used by many java projects. Now imagine just by adding one new method in Collection interface will break entire chain of projects.
Now my question is basically that are default methods just helpful
when needed to add new methods to interface without breaking client
code? Or are there some other uses to it too?
Motivation/Need for Default Methods
API Evolution in compatible way
The initial purpose of introducing default methods was to make collections library backward compatible. This library was modelled as a deep hierarchy of interfaces, including prominent members such as Collection, List, Map, and Set. They needed to be enriched to make lambdas truly useful for everyday programming.
To make Collections library lambda rich, java architects could have
refactored them to support lambda but it was a far from a good
solution as it will break all the all existing Java deployments and
countless 3rd party libraries extending the Collections hierarchy
Instead java architects thought to introduce default methods capabilities for backward compatibility.
Use cases of Default Methods
One important use case is to aid functional thinking in java. A functional interface with default methods is a pure behaviour-only construct. It cannot hold state. This aligns your thinking with functional programming and allows you to take advantage of what the programming model has to offer
Optional Methods : There are classes in java that implement an interface but leave empty method implementations for e.g. Iterator interface. It defines hasNext and next but also the remove method. Prior to Java8 remove was ignored because the user didn't want to use that capablity. Therefore many classes implementing Iterator interface would have empty implementation of for remove which is unnecessary boiler plate code. With default methods we can provide a default implementation for such methods, so concrete classes don't need to explicitly provide an empty implementation.
Default methods helps in resolving Multiple inheritance of behaviour in java. Before Java8, there was support for Multiple inheritance of Type only and now with the help of default methods we can have multiple inheritance of behaviour.
For e.g.
Java 8 has three rules for resolving conflicts brought upon by
multiple inheritance when ambiguous:
First, an explicit method declaration in the class or a superclass takes priority over any default method declaration.
Otherwise, the method with the same signature in the most specific default providing interface is selected.
Finally, if there is still conflict, you have to explicitly override the default methods and choose which one your class should choose.
In Conclusion Default methods offer a brand new way to design objects.
References :
Java8 In Action
Functional Java: A Guide to Lambdas and Functional Programming in Java 8
default methods made possible the functional programming concept. For functional programming type code we need only one abstract method .
Also adding an method in interface will not made it compulsory for all the classes implementing an interface. Simplified the coding practise
Java 8 gave us many fun ways to use functional interfaces and with them a new annotation: #FunctionalInterface. Its job is to tell the compiler to yell at us if we fail to stick to the rules of a functional interface (only one abstract method that needs overriding please).
There are 43 interfaces in the java.util.function package with this annotation. A search of jdk.1.8.0/src for #FunctionalInterface only turns up 57 hits. Why are the other interfaces (such as AutoCloseable) that could have added #FunctionalInterface still missing it?
There is a bit of a vague hint in the annotations documentation:
"An informative annotation type used to indicate that an interface type declaration is intended to be a functional interface"
Is there any good reason NOT to intend that an interface I've designed (that may simply happen to be a functional interface) not be used as one? Is leaving it off an indication of anything besides not realizing it could have been added?
Isn't adding abstract methods to any published interface going to screw anyone implementing it, functional or not? I feel cynical assuming they just didn't bother to hunt them all down but what other explanation is there?
Update: After looking over "Should 'Comparable' be a 'Functional interface'?" I find I still have nagging questions. When a Single Method Interface and a Functional Interface are structurally identical what's left to be different? Is the difference simply the names? Comparable and Comparator are close enough to the same semantically. Turns out they are different structurally though so still not the best example...
Is there a case when an SMI is structurally fine to use as a Functional Interface but still discouraged over the semantic meaning of the name of the interface and the method? Or perhaps the contract implied by the Javadocs?
Well, an annotation documenting an intention would be useless if you assume that there is always that intention given.
You named the example AutoCloseable which is obviously not intended to be implemented as a function as there’s Runnable which is much more convenient for a function with a ()->void signature. It’s intended that a class implementing AutoCloseable manages an external resource which anonymous classes implemented via lambda expression don’t do.
A clearer example is Comparable, an interface not only not intended to be implemented as a lambda expression, it’s impossible to implement it correctly using a lambda expression.
Possible reasons for not marking an interface with #FunctionalInterface by example:
The interface has programming language semantics, e.g. AutoClosable or Iterable (that’s unlikely to happen for your own interfaces)
It’s not expected that the interface has arbitrary implementations and/or is more an identifier than the actual implementation, e.g. java.net.ProtocolFamily, or java.lang.reflect.GenericArrayType (Note that the latter would also inherit a default implementation for getTypeName() being useless for lambda implementations as relying on toString())
The instances of this interface should have an identity, e.g. java.net.ProtocolFamily, java.nio.file.WatchEvent.Modifier, etc. Note that these are typically implemented by an enum
Another example is java.time.chrono.Era which happens to have only a single abstract method but its specification says “Instances of Era may be compared using the == operator.”
The interface is intended to alter the behavior of an operation for which an implementation of the interface without inheriting/implementing anything else makes no sense, e.g. java.rmi.server.Unreferenced
It’s an abstraction of common operations of classes which should have more than just these operations, e.g. java.io.Closeable, java.io.Flushable, java.lang.Readable
The expected inheritance is part of the contract and forbids lambda expression implementations, e.g. in java.awt: ActiveEvent should be implemented by an AWTEvent, PrinterGraphics by a Graphics, the same applies to java.awt.print.PrinterGraphics (hey, two interfaces for exactly the same thing…), wheras javax.print.FlavorException should be implemented by a javax.print.PrintException subclass
I don’t know whether the various event listener interfaces aren’t marked with #FunctionalInterface for symmetry with other multi-method event listener that can’t be functional interfaces, but actually event listeners are good candidates for lambda expressions. If you want remove a listener at a later time, you have to store the instance but that’s not different to, e.g. inner class listener implementations.
The library maintainer has a large codebase with more than 200 candidate types and not the resources to discuss for every interface whether it should be annotated and hence focuses on the primary candidates for being used in a functional context. I’m sure, that, e.g. java.io.ObjectInputValidation, java.lang.reflect.InvocationHandler, juc RejectedExecutionHandler & ThreadFactory wouldn’t be bad as #FunctionalInterface but I have no idea whether, e.g. java.security.spec.ECField makes a good candidate. The more general the library is, the more likely users of the library will be able to answer that question for a particular interface they are interested in but it would be unfair to insist on the library maintainer to answer it for all interfaces.
In this context it makes more sense to see the presence of a #FunctionalInterface as a message that an interface is definitely intended to be usable together with lambda expressions than to treat the absence of the annotation as an indicator for it’s being not intended to be used this way. This is exactly like the compiler handles it, you can implement every single abstract method interface using a lambda expression, but when the annotation is present it will ensure that you can use this interface in this way.
Planned expansion. Just because an interface matches the requirements of an SMI now doesn't mean that expansion isn't needed later.
In java 8, functional interface is an interface having exactly one abstract method called functional method to which the lambda expression’s parameter and return types are matched.
The java.util.function contains general purpose functional interfaces used by JDK and also available for end users. While they are not the complete set of funtional interfaces to which lambda expressions might be applicable, but they provide enough to cover common requirements. You are free to create your own functional interfaces whenever existing set are not enough.
There are many such interfaces available which deserves to be designated as functional interface but java.util.function package already provides functional interfaces for our almost all purposes.
For example look into following code.
public interface Comparable<T> {
public int compareTo(T o);
}
#FunctionalInterface
public interface ToIntFunction<T> {
int applyAsInt(T value);
}
public static void main(String[] args){
ToIntFunction<String> f = str -> Integer.parseInt(str);
Comparable<String> c = str -> Integer.parseInt(str);
}
Comparable can also take an object and derive some int type value but there is a more general dedicated interface ToIntFunction is provided to perform this task. There is no such hard rule that all the deserving interfaces should be annotated with #FunctionalInterface but to gain the advantage of lambda feature, the interface should fulfill all criterias defined by FunctionalInterface.
How is it helpful to use anonymous class if every time we have to define a class while invoking a constructor of an interface.Wouldn't it be more better to simple use a generic type instead?
Anonymous classes is frequently used in GUI applications. When you only need to declare and create object of a class at the same time, it can make the code more precise.
Here is an example:
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println("Hello World!");
}
});
Anonymous classes are not defined every time they are instantiated. They get compiled into bytecode just like other classes, with a name e.g. MyEnclosingClass$1. See this post for more information: How are anonymous classes compiled in Java?
Tangentially, reflection can be used to identify them at runtime using Class.isAnonymousClass().
It depends on the situation; in some cases it will be better to use an anonymous class, and in others, it will be better to use a concrete class that implements the required interface.
If you believe that you'll need to provide the same anonymous class definition repeatedly, it will likely save you time to pass an instance of a concrete class that implements the required interface.
The Java language provides anonymous class syntax as a convenience.
To give you just a taste, here's a quick example from my own experience: Having lists backed by functions.
In general, anonymous classes have (among others) the following uses:
Suppose you want to have an object (an instance, not a class) whose behavior depends on some value available at runtime. Without anonymous classes, you can do this by setting fields (or calling state-changing methods) - but you can't have different code executing. Now, true, you could have bunch of switch() statements in your class' method code - but that completely decouples the definition of the behavior from its context. Another way you could go is to use a named subclass, but that's a lot of code, and it creates a noun you don't really want to exist.
Functional Programming! Until Java 8 comes along, anonymous functions are just about the only way you can pass around functions, which are not first-class citizens in Java. With those, you can perform many neat and elegant tricks like my example above.