Why don't implement all method in interface Comparator? - java

Today, I'm trying to learn some features in Java 8, specific about Lambda Expressions. I create a new Comaparator like this :
Comparator<String> strCom = new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
return 0;
}
};
When I read code inside Comparator interface, I have got confused. Althrough interface Comparator have two method compare() and equals(), we don't need implement all of them. I had found some reason why we don't need implement method equals() here. But i also read in javadocs
If your class claims to implement an interface, all methods defined by that interface must appear in its source code before the class will successfully compile. What Is an Interface?
So, can someone help me understand this ? Do not override equals() is still legal ?

equal is not needed to implement because it is inherited from the Object class, as everything in Java is an Object
As you can see in the documentation the equal Method is already defined in the Object class:
https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html
You only need to implement the equals method if you want to check if two Comparators have the same data and therefore are "equal", but this is probably not what are you looking for, as Comparators normally do not hold any instance variables

The tutorial is trying to introduce the concept of interfaces through a simple example, but it ends up being misleading.
Take this code for example:
public interface MyInterface {
public void foo();
public void bar();
}
public class Super {
public void foo() { System.out.println("foo"); }
}
public class Sub extends Super implements MyInterface {
public void bar() { System.out.println("bar"); }
}
This is perfectly valid code, despite the fact that Sub only explicitly implements one of MyInterfaces methods. It's easy to see why this is valid: foo() is already implemented by Super, and that implementation is inherited by Sub.
The exact rule goes like this:
Unless the class being declared is abstract, all the abstract member
methods of each direct superinterface must be implemented (§8.4.8.1)
either by a declaration in this class or by an existing method
declaration inherited from the direct superclass or a direct
superinterface, because a class that is not abstract is not permitted
to have abstract methods (§8.1.1.1).
While the rule only talks about direct superclasses, it is technically also true for indirect superclasses, as method inheritance bubbles down through the hierarchy.
Given that equals() is implemented by Object and Object is the direct or indirect superclass of every class, you don't have to provide an implementation for equals().

Related

Strange behavior observed in inheritence

I have an interface, IfcBase which is implemented by another class Base. This class is further extended by a second class SubBase. Further SubBase class implements another interface IfcNew. Both these interfaces have a method declared that has the same signature. Now SubBase does not define the method from IfcNew. I now create an instance of SubBase and assign it to the reference type IfcNew. I then invoke the lone method and get an output. The method from IfcBase was executed in this case. I believe this should not be allowed at some stage, either during compilation or execution. I fail to understand the behavior and solicit help. The source is below. Thanks a lot!
public interface IfcBase
{
public void printString();
}
public class Base implements IfcBase
{
public void printString()
{
System.out.println("Base Class");
}
}
public interface IfcNew
{
public void printString();
}
public class SubBase extends Base implements IfcNew
{
//
}
public class Test
{
public static void main(String[] args)
{
IfcNew i = new SubBase();
i.printString(); //Output:Base Class
}
}
This is how inheritance works in Java.
You have a method called public void printString() implemented in Base, from which you extend SubBase. As a result this implementation will be implicitly available in this class.
For the implements IfcNew part in the SubBase declaration, compiler will only check to see if SubBase has a method implemented which has the same signature as public void printString(). Since it implicitly inherits this implementation from Base, it has nothing to complain about.
This behavior can be easily understood if you look at it from OO design point of view. Please take a look at this article which I wrote few years ago. Look under the section called Method signature, Object Interface, Types, Subtypes and Supertypes. By the definition of subtype that is provided there, SubBase is already a subtype of IfcNew, so compiler has no problem with it.
This is the correct behavior of inheritance in Java.
There is no warning when implementing multiple interfaces with same-signature methods, because resolution takes place at runtime.
In this case, your SubBase class does not need to implement printString as its parent does, even if it isn't the "same" printString: the identical signature allows resolution at runtime.
This is obvious and not strange. This is because the method with same signature is already implemented in the base class and when you extend the base class it is automatically inherited. Now when you try to assign the object to IfcNew reference the method implemented is called which is not overriden in subclass, meaning that the base class method is called which actually is the implementation of IfcBase.

Interface Method Usage(Java)?

Can Someone Explain how the methods of interface used in classes?
Note: My Doubt is "Methods are already defined in Class then why we should implement it ? "
For Example :
interface printable{
void print();
}
class A implements printable{
public void print(){System.out.println("Hello");}
public static void main(String args[]){
A obj = new A();
obj.print();
}
}
why print() is declared in interface??
You define a method by giving its implementation. They are the same thing, so you are right that once you define a method, you don't also need to implement it.
An interface declares that anything implementing this interface will defined those methods. This is part of the contract for interfaces. This allows you to call any method of an interface knowing than any concrete implementation will have such a method.
BTW In Java 8, it will support virtual extensions which means an interface can give a default implementation. This has to be defined in terms of other methods provided by the interface.
An Interface is a contract that all classes that implement it, should have a definition for the methods specified in the interface. An interface does not define the method body as such.
An interface defines a set of method which must be implemented. It says nothing on how they are implemented. This is where the class definition comes in, since it defines how these methods are implemented.
Thus, when you call a class which implements a particular interface, then you know, for sure, that you will find whatever set of methods the interface defines.
Interfaces are usually handy when you need to expose some endpoints to your application, without the need to expose the logic.
EDIT: As per your example, the printable interface defines what behaviour should a class which implements it expose, in this case print.
This will allow you to do something along the lines of printable p = new A(); p.print();.
Assuming you have something which yields an object which implements the printable interface, then, whoever is calling that method will not need to bother what is the actual implementation of the print method. The interface makes sure that whatever you are returning, will contain an implementation of that method.
#NarutoUzumaki
Welcome to Stack overflow!
I agree with Chris. You can replace the doSomething method with eat() method to get a better understanding. A dog may eat something different than a cat and to a giraffe.
Its up to you how you implement the eat method, and when using it create a reference of the interface Animal and point it to the instance of Dog, Cat or Giraffe which ever eat method you want to use. This makes your class design very extensible.
Hope you get a clear idea now.
Generally Interface based Programming is recommended, Because of the following reasons
1)Interface means rule , you should follow those rules while implementing those methods in Implemented class.
2) Dependency is less between classes while instancing your implemented class then call your methods from another class or some where.
3) You can publish your interface details only no need to disclose the implemented details of your methods to out side the world.
Defining an interface is the difference between:
public void doSomething(Dog d)
{
d.doSomething();
}
public void doSomething(Cat c)
{
c.doSomething();
}
public void doSomething(Giraffe g)
{
g.doSomething();
}
and
public void doSomething(Animal a)
{
a.doSomething();
}
Why?
Well, if all the classes just implement their own methods, there's no common reference between them. However, if they all implement the method from a common interface, they can be referred to by the same reference type; in this case Animal.

Precise definition of "functional interface" in Java 8

Recently I started exploring Java 8 and I can't quite understand the concept of "functional interface" that is essential to Java's implementation of lambda expressions. There is a pretty comprehensive guide to lambda functions in Java, but I got stuck on the chapter that gives definition to the concept of functional interfaces. The definition reads:
More precisely, a functional interface is defined as any interface that has exactly one abstract method.
An then he proceeds to examples, one of which is Comparator interface:
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
}
I was able to test that I can use a lambda function in place of Comparator argument and it works(i.e. Collections.sort(list, (a, b) -> a-b)).
But in the Comparator interface both compare and equals methods are abstract, which means it has two abstract methods. So how can this be working, if the definition requires an interface to have exactly one abstract method? What am I missing here?
From the same page you linked to:
The interface Comparator is functional because although it declares two abstract methods, one of these—equals— has a signature corresponding to a public method in Object. Interfaces always declare abstract methods corresponding to the public methods of Object, but they usually do so implicitly. Whether implicitly or explicitly declared, such methods are excluded from the count.
I can't really say it better.
Another explanation is given in the #FunctionalInterface page:
Conceptually, a functional interface has exactly one abstract method. Since default methods have an implementation, they are not abstract. If an interface declares an abstract method overriding one of the public methods of java.lang.Object, that also does not count toward the interface's abstract method count since any implementation of the interface will have an implementation from java.lang.Object or elsewhere.
You can test which interface is a correct functional interface using #FunctionalInterface.
E.g.:
this works
#FunctionalInterface
public interface FunctionalInterf {
void m();
boolean equals(Object o);
}
this generates an error:
#FunctionalInterface
public interface FunctionalInterf {
void m();
boolean equals();
}
Multiple non-overriding abstract methods found in interface FunctionalInterf
Q. But in the Comparator interface both compare() and equals() methods are abstract, which means it has two abstract methods. So how can this be working, if the definition requires an interface to have exactly one abstract method? What am I missing here?
A.
A functional interface may specify any public method defined by Object, such as equals( ),
without affecting its “functional interface” status. The public Object methods are considered implicit
members of a functional interface because they are automatically implemented by an instance of a
functional interface.
An interface cannot extend Object class, because Interface has to have public and abstract methods.
For every public method in the Object class, there is an implicit public and abstract method in an interface.
This is the standard Java Language Specification which states like this,
“If an interface has no direct super interfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless a method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface.”
That's how Object class' methods are declared in an interface. And according to JLS, this does not count as interface' abstract method. Hence, Comparator interface is a functional interface.
A functional interface has only one abstract method but it can have multiple default and static methods.
Since default methods are not abstract you’re free to add default methods to your functional interface as many as you like.
#FunctionalInterface
public interface MyFuctionalInterface
{
public void perform();
default void perform1(){
//Method body
}
default void perform2(){
//Method body
}
}
If an interface declares an abstract method overriding one of the public methods of java.lang.Object, that also does not count toward the interface’s abstract method count since any implementation of the interface will have an implementation from java.lang.Object or elsewhere.
Comparator is a functional interface even though it declared two abstract methods. Because one of these abstract methods “equals()” which has signature equal to public method in Object class.
e.g. Below interface is a valid functional interface.
#FunctionalInterface
public interface MyFuctionalInterface
{
public void perform();
#Override
public String toString(); //Overridden from Object class
#Override
public boolean equals(Object obj); //Overridden from Object class
}
Here is a "show me the code" approach to understanding the definition:
we shall look into OpenJDK javac for how it checks validity of classes annotated with #FunctionalInterface.
The most recent (as of July, 2022) implementation lies here:
com/sun/tools/javac/code/Types.java#L735-L791:
/**
* Compute the function descriptor associated with a given functional interface
*/
public FunctionDescriptor findDescriptorInternal(TypeSymbol origin,
CompoundScope membersCache) throws FunctionDescriptorLookupError {
// ...
}
Class Restriction
if (!origin.isInterface() || (origin.flags() & ANNOTATION) != 0 || origin.isSealed()) {
//t must be an interface
throw failure("not.a.functional.intf", origin);
}
Pretty simple: the class must be an interface and must not be a sealed one.
Member Restriction
for (Symbol sym : membersCache.getSymbols(new DescriptorFilter(origin))) { /* ... */ }
In this loop, javac goes through the members of the origin class, using a DescriptorFilter to retrieve:
Method members (of course)
&& that are abstract but not default,
&& and do not overwrite methods from Object,
&& with their top level declaration not a default one.
If there is only one method matching all the above conditions, then surely it is a valid functional interface, and any lambda will overwrite that very method.
However, if there are multiple, javac tries to merge them:
If those methods all share the same name, related by override equivalence:
then we filter them into a abstracts collection:
if (!abstracts.stream().filter(msym -> msym.owner.isSubClass(sym.enclClass(), Types.this))
.map(msym -> memberType(origin.type, msym))
.anyMatch(abstractMType -> isSubSignature(abstractMType, mtype))) {
abstracts.append(sym);
}
Methods are filtered out if:
their enclosing class is super class of that of another previously matched method,
and the signature of that previously matched method is subsignature of that of this method.
Otherwise, the functional interface is not valid.
Having collected abstracts, javac then goes to mergeDescriptors, which uses mergeAbstracts, which I will just quote from its comments:
/**
* Merge multiple abstract methods. The preferred method is a method that is a subsignature
* of all the other signatures and whose return type is more specific {#see MostSpecificReturnCheck}.
* The resulting preferred method has a thrown clause that is the intersection of the merged
* methods' clauses.
*/
public Optional<Symbol> mergeAbstracts(List<Symbol> ambiguousInOrder, Type site, boolean sigCheck) {
// ...
}
Conclusion
Functional interfaces must be interfaces :P , and must not be sealed or annotations.
Methods are searched in the whole inheritance tree.
Methods overlapping with those from Object are ignored.
default methods are ignored, unless they are later overridden by sub-interfaces as non-default.
Matching methods must all share the same name, related by override equivalence.
Either there is only one method matching the above conditions, or matching methods can get "merged" by their class hierarchy, subsignature relations, return types and thrown clauses.
The Java docs say:
Note that it is always safe not to override Object.equals(Object).
However, overriding this method may, in some cases, improve
performance by allowing programs to determine that two distinct
comparators impose the same order.
Maybe Comparator is special? Maybe, even though it's an interface, there is somehow a default implementation of equals() that calls compare()? Algorithmically, it's trivial.
I thought all methods that were declared in interfaces were abstract (i. e. no default implementation). But maybe I'm missing something.
Definition:
If an interface contains only one abstract method, then such type of interface is called functional interface.
Usage:
Once we write Lambda expression "->" to invoke its functionality ,
then in this context we require Functional Interface.
We can use the Functional Interface reference to refer Lambda
expression.
Inside functional interface we can have one abstract method and n
number of default/static methods.
Functional interface with respect to inheritance:
If an interface extends Functional interface and the child interface does not contain any abstract method , then the child interface is also considered to be Functional Interface.
Functional interface is not new to java, its already used in following interface API's:
Runnable : contains run() method only.
Callable : contains call() method only.
Comparable : contains compareTo() method only.
Before Java 8, an interface could only declare one or more methods also known as Abstract Method (method with no implementation, just the signature). Starting with Java 8 an interface can also have implementation of one or more methods (knows as Interface Default Method) and static methods along with abstract methods. Interface Default Methods are marked default keyword.
So the question is, what is Functional Interface?
An interface with Single Abstract Method (SAM) is called Functional Interface.
Which means -
An interface with Single Abstract Method is a Functional Interface
An interface with Single Abstract Method and zero or more default
methods and zero or more static method is also a valid Functional
Interface.
More detail with example code https://readtorakesh.com/functional-interface-java8/

Java method that accepts references to interface objects

I'm kinda unsure about the following question:
If Launchable is a Java interface, what objects can be passed into the following method? What methods could be invoked on item inside this method?
public void prepareForLaunch (Launchable item) {
// some code
}
My current answer is:
From the above information, the only objects that can be passed into the method are objects that where instantiated as subclass types of the interface Launchable.(?) The methods that could be invoked on item inside the method would have to be public methods or protected methods within the same package. These methods would also have to be to be intended for a subclass of Launchable object since it is only in abstract and actual(concrete) classes where a method body’s definition can exist.
I was wondering if someone here can check my answer and add any suggestions. Thanks!
You can only pass in instances of classes that implement Launchable (either directly, or by inheritance from a superclass). You can also pass in null.
Inside of the method, you can call all the methods defined in Launchable (and in Object).
These methods would be defined in the Launchable interface, but implemented in the actual class (a fact that is guaranteed by the Java type system, which won't let you have classes with incomplete interface implementations, those would need to be declared abstract and cannot be instantiated).
If you need to call any other methods you need to know that the object in question also implements some other interface (or is of a given class), and do a typecast to that first.
Since you stated that Launchable is an interface, an instance of any class that implements Launchable could be passed to prepareForLaunch. Any class implementing Launchable would have to implement the methods defined in the interface and thus any method of Launchablecould be invoked to objects given to prepareForLaunch.
You are right about the first part. About the methods you can invoke: If you are not using casting then you can only invoke public\protected within the same package of Launchable. If you will use casting you can extend the range of the methods you can invoke to the methods in the casted-to class.
Consider this code:
public interface Launchable
{
public void aMethod();
}
public class SomeClass implements Launchable
{
public void aMethod()
{
}
public void bMethod(){}
}
Without casting youll be able to call
item.aMethod();
With Casting youll be able to call:
((SomeClass)item).bMethod();
you should use implements statement ,
public void prepareForLaunch() implements Launchbla {
}

How can an interface include a method that references the concrete implementation type of the interface in its signature or return type?

Suppose I am designing something like the following interface:
public interface MyInterface{
public MyInterface method1();
public void method2(MyInterface mi);
}
However, there is the caveat that the return type for method1 and the parameter for method2 match the concrete implementation and not just MyInterface. That is, if I have MyInterfaceImpl that implements MyInterface, it needs to have the following:
public class MyInterfaceImpl implements MyInterface{
#Override
public MyInterfaceImpl method1(){...}
#Override
public void method2(MyInterfaceImpl mi){...}
}
As written above, method1 won't cause any compile errors, but there is nothing guaranteeing that the return type matches in all implementations. Of course method2 won't even compile because the signature does not match the interface.
One candidate solution is to use self-referential or recursive bounds in generics:
public interface MyInterface<T extends MyInterface<T>>{
public T method1();
public void method2(T mi);
}
public class MyInterfaceImpl implements MyInterface<MyInterfaceImpl>{
#Override
public MyInterfaceImpl method1();
#Override
public void method2(MyInterfaceImpl mi);
}
This would get me what I want with one exception: other implementations might pass the wrong generic type (nothing forces T to match the concrete type). So potentially someone else could implement the following:
public class NotMyInterfaceImpl implements MyInterface<MyInterfaceImpl>{
#Override
public MyInterfaceImpl method1();
#Override
public void method2(MyInterfaceImpl mi);
}
That would compile just fine even though NotMyInterfaceImpl should implement MyInterface<NotMyInterfaceImpl>.* That makes me think I need something else.
*Note that I don't think I'm trying to violate LSP; I'm OK with the return type/parameter being subclasses of NotMyInterfaceImpl.
So I don't know of a clean way to do this. That leads me to believe that I might be focusing too much on implementation details in the interface, but it doesn't seem that way to me. Is there any way to do the type of thing I described, or is this some kind of smell that I'm putting something in an interface that doesn't belong there?
This is the exact situation faced by the Comparable interface (its compareTo method wants to take an argument the same type as the object it is called on). So what does it do? It's simply defined as Comparable<T>. The idea is that an implementing class "should" implement Comparable with itself as the parameter (allowing it to "compare to" itself); but this is not enforced (since there is no way to do it).
Yes, as you noted, this will allow any class to implement Comparable with a parameter of any other class: class Foo implements Comparable<Bar> where Foo and Bar have no relation to each other. However, this is not really a problem.
All the methods and classes (sorting, maximum, etc.) that require Comparable objects have the following generic type constraint <T extends Comparable<? super T>>. This ensures that objects of type T are comparable with themselves. That way, it is completely type-safe. So the enforcement is not made in the declaration of the Comparable interface, but in the places that use it.
(I notice that you use <T extends MyInterface<T>> while Comparable uses simply <T>. Although <T extends MyInterface<T>> will exclude cases where the type parameter does not implement MyInterface, it will not exclude cases where the type parameter does implement MyInterface, but is different than the class. So what's the point of half-excluding some cases? If you adopt Comparable's way of restricting it where they are used, it's type-safe anyway, so there is no point in adding more restrictions.)
I believe that this cannot be done. There is simply no way to refer to an object's implementation class in the framework of generics, nor, as far as i know, any way to construct a cage out of pure generics which is capable of constraining the implementation class to match a type parameter.
The most useful thing i can suggest is using a self-referential parameter, and then always acquiring instances of implementations from factory methods which look like:
public <T extends MyInterface<T>> T newInstance();
It is easier for a camel to pass through the eye of a needle than for an instance of NotMyInterfaceImpl to pass through that return type. So, although troublemakers could write classes which do not conform to your masterplan, they couldn't return them from factories. Unless NotMyInterfaceImpl extended MyInterfaceImpl; but then, in a sense, it would also be a MyInterfaceImpl, so perhaps that would be kosher?
EDIT: A slightly more useful version of that idea is to always pass instances of implementations of the interface around in a suitably restrictive holder, like:
class Holder<T extends MyInterface<T>> {
public final T value;
}
If someone gives you a Holder<Q>, then you know that Q must be a version of MyInterface bound to itself, which is what you're after.
The point of returning the interface is such that the method does not care the actual implementation of the returned object. In your case you actually want to mandate the type to be a particular sub-implementation of that interface.
To apply the constraints that you described above, IMHO the design should probably be a base class instead of an interface. This allows you to control the implementation, for example a top-level flow, and leave low-level strategy to sub-classes to implement:
class MyBaseImpl {
public final void fixedFlow() {
MyBaseImpl obj = method1();
obj.method2(this);
}
protected abstract MyBaseImpl method1();
....
}
There has to be other methods to make it interesting...; perhaps you have good reasons to want to do this...
Hope this helps!
What you are trying to do is not legal because you are trying to narrow the parameter of the implemented type, and this "does not make sense". You are tryint to use "covariant" parameters, and only covariant return types are allowed (and even logic, and only supported from Java 5).
I mean, if it was possible to use covariant parameter types, you could do things like:
MyInterface instance = new MyInterfaceImpl();
And then, invoke on "instance" the method with another implementation supported by the interface but not supported by the MyInterfaceImpl class this way:
instance.method2(new MyInterfaceImpl_2());
Java cannot convert MyInterfaceImpl_2 to MyInterfaceImpl, so it prevents you from doing so at compilation time.
What you could do is to widen the parameter, using "contravariant" parameter, which would be logic. For more detail on this, check this anser:
Demonstrate covariance and contravariance in Java?
The only workaround that I can think of, is to solve the problem at runtime, I mean, doing something like this:
public class MyInterfaceImpl implements MyInterface{
#Override
public void method2(MyInterface mi){
realMethod((MyInterfaceImpl) mi);
}
public void realMethod(MyInterfaceImpl) {...}
}
But you could get ClassCast exception, of course.
Is this what you are looking for?
public interface MyInterface {
static abstract class MyInterfaceImpl implements MyInterface {
#Override
public abstract MyInterfaceImpl method1();
#Override
public abstract void method2(MyInterfaceImpl mi);
}
MyInterfaceImpl method1();
void method2(MyInterfaceImpl mi);
}
And you could even implement method 1 or 2 instead of making them abstract.

Categories