Below example runs without any errors, can any one explain me how this works?, as interface doesn't contain any toString()/hashcode/equals method declaration how compiler will resolve method call?,as per my understanding toString()/hashcode/equals or Object class methods will be declared by default inside interface? please correct me if am wrong
interface int1
{
public void show();
}
class inttest implements int1
{
public void show()
{
System.out.println("inttest.show()");
}
#Override
public String toString()
{
return "tostring called";
}
}
public class MainClass1
{
public static void main(String[] args) {
int1 i=new inttest();
System.out.println(i.toString());
}
}
Any interface has all the public methods of the Object class (it either inherits them from a super-interface or declares them implicitly if it doesn't already declare them explicitly).
This makes sense, since any implementing class of any interface must be a (direct or in-direct) sub-class of the Object class, and therefore will inherit an implementation of all the Object methods.
9.2. Interface Members
If an interface has no direct superinterfaces, 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 an abstract method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface.
As all objects extend Object and Object has a toString() you are calling that method.
Related
Interface Implicitly inherit the Object class. Because interface SubInterface default Method call the Objectclass hashCode Method. It's possible then How & Why..?
package com.oca.test.exam;
interface SuperInterface {
default void printStuff() { System.out.println("Default Method"); }
}
interface SubInterface extends SuperInterface {
default void doStuff() {
this.printStuff();
System.out.println(this.hashCode());
}
}
public class InterfaceAbstractCombination implements SubInterface{
public static void main(String[] args) {
SubInterface sub = new InterfaceAbstractCombination();
sub.doStuff();
}
}
The interface is not inheriting the Object clas. The class which implements the interface SubInterface is inheriting the Object class.
Just think about it, will you be able to call doStuff() of SubInterface directly? You need to implement that interface in another class, create an instance of that class then you can call doStuff().
So InterfaceAbstractCombination class implements the SubInterface and when you call doStuff() you calling it on the instance of InterfaceAbstractCombination which is supplying the this.hashCode() inherited from the Object class, so this will refer to the instance of the class implementing the interface.
One thing to note, If you check the JLS spec
If an interface has no direct superinterfaces, 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.
So this is why you are able to call SuperInterface.super.hashCode();.
The hashCode of InterfaceAbstractCombination class is provided in your inheritance hierarchy. this does not belong to interface, even if it has default method.
Consider running below code you'll see same hashCode getting printed:
package com.oca.test.exam;
public class InterfaceAbstractCombination implements SubInterface {
public static void main(String[] args) {
SubInterface sub = new InterfaceAbstractCombination();
sub.doStuff();
System.out.println(sub.hashCode());
}
}
interface SuperInterface {
default void printStuff() {
System.out.println("Default Method");
}
}
interface SubInterface extends SuperInterface {
default void doStuff() {
this.printStuff();
System.out.println(this.hashCode());
}
}
interface TestInterface{
public void sayHello();
}
class A implements TestInterface{
public void sayHello(){
System.out.println("Hello");
}
public void sayBye(){
System.out.println("Hello");
}
public String toString(){
return "Hello";
}
public static void main(String args[]){
TestInterface ti=new A();
ti.sayHello();
ti.sayBye();//error
ti.toString();//How toString method can be called as it is not the part of the interface contract.
}
}
From this section in the Java Language Specification:
If an interface has no direct superinterfaces, 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 an abstract method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface.
So Object's public methods like toString are implicitly declared in all interfaces.
toString can be called because any implementation of any interface must be a sub-class of Object, which contains the toString method.
In order to call any other method that doesn't appear in the interface or in any super-interface your interface extends (and is not defined in Object class), you must cast the interface to the type of the class that contains that method.
Every object is an Object :) It would make sense to call Object methods on objects.
That's the heart of the matter - all reference types are subtypes of Object. Reference types include
class type
interface type
array type
type variable (T)
null type (for null)
intersection type ( A&B )
A subtype inherits methods from the supertype. Therefore all reference types inherit Object methods.
This is the nature of OO Languages. Interfaces only define a set of method signatures that a concrete class needs to implements. They don't restrict the nature of the class (abstract v concrete).
So when you declare TestInterface ti, in your example A implements TestInterface, so it is an instance of TestInterface. Likewise class B implements TestInterface {...} is also valid.
TestInterface ti = new A(); // Valid
ti = new B(); // Also valid (given the above definition)
We know that each class extends from Object which means that we can use all Object's methods
in any class. My problem is the following:
interface B{
}
public class A implements B{
public static void main(String[] args){
B i = new A();
i.display();//we can't do this : because the interface B doesn't define such a method
System.out.println(i.toString());// we can do this although the interface doesn't extend from Object
}
public void display(){
}
}
so I think the problem is clear , why I could invoke the toString method although the interface B can't extend from Object?
This is spelled out in the JLS ยง9.2. Interface Members:
If an interface has no direct superinterfaces, 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 an abstract method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface.
This ensures that it is possible to call Object methods via any interface.
I am having problems trying to figure out how to call the clone method from a object which its reference is of an interface type.
Basically this is what I need to do.
for(Interface obj: objs)
array.add(obj.clone());
I do not know what is the obj type, I just know it implements Interface, and when I try this code I get
"The method clone() is undefined for the type Interface".
And when I try to put clone() on my Interface I get:
"The method clone() of type Interface must override or implement a supertype method", because I am using #Override tag.
My intention is to use Object.clone() in the end. But I just cant figure this out.
Any thoughts?
The real code:
public interface Caracteristica {
#Override <---problem
public Object clone() throws CloneNotSupportedException;
#Override <---fine
public boolean equals(Object obj);
}
private final void setCaracteristicas(ArrayList<Caracteristica> caracteristicas) {
this.caracteristicas = new ArrayList<>();
for(Caracteristica caracteristica: caracteristicas)
this.caracteristicas.add((Caracteristica)caracteristica.clone());
}
Basically, clone() and the Cloneable interface is broken in a number of ways and even according to Josh Bloch it should be avoided. (See: http://www.artima.com/intv/bloch13.html)
Add a new method to your interface that returns the interface type and implement that in your class to make copies.
Edit to Add: Ignoring the above statement, the reason it is telling you that the #Override annotation in your interface is incorrect is because ... it is. You're not extending an interface that defines clone().
Interfaces don't extend Object; Section 9.2 of the JLS tells us:
If an interface has no direct superinterfaces, 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.
clone() is protected in Object so it is not implicitly included. If your IDE said to add the #Override tag, report that as a bug, because it's wrong.
equals(), on the other hand, is public in Object, therefore it is included in the implicit superinterface unless you override it.
If you are bound and determined, this will work though it's really ugly due to the confusion created by clone() being defined both in Object and MyInterface and having it return the interface type (which is allowed because it's a covariant type):
public interface MyInterface {
MyInterface clone();
void doSomething();
}
public class MyClass implements MyInterface {
#Override
public void doSomething() {
System.out.println("Hi");
}
#Override
public MyInterface clone() {
return new MyClass();
}
public static void main(String[] args) {
MyInterface mi = new MyClass();
MyInterface mi2 = mi.clone();
mi2.doSomething();
}
}
Object.clone() is protected, you can't call it from outside the class or its subclasses unless they explicitly change the access modifier to public thus there is no guarantee an object has a visible clone() method.
You have to define this in an interface or override it in a baseclass instead.
interface A {
void hi();
}
class AImpl implements A {
public void hi() {
System.out.println("hi");
}
public void to() {
System.out.println("Test");
}
}
public class InterfaceTest {
public static void main(String[] args) {
A a = new AImpl();
a.hi();
System.out.println(a.hashCode());
//a.to();
}
}
here interface A has no inheritance relationship with Object class but all the mehods of Object class can be access through the interface.
why?
From the Java Language Specification section 9.2:
The members of an interface are:
Those members declared in the interface.
Those members inherited from direct superinterfaces.
If an interface has no direct superinterfaces, 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. It is a compile-time error
if the interface explicitly declares
such a method m in the case where m is
declared to be final in Object.
The third bullet is the important one - basically interfaces which don't extend any other interfaces automatically inherit hashCode etc.