Selecting overriding method java with multiple options - java

To clarify- To my understanding, the methods below are all override of Object.equals. Are they overloading instead and I am not understanding this correctly?
I'm running this code:
public class AA
{
private int _val=0;
public AA()
{
_val=5;
}
}
public class BB extends AA
{
public BB()
{
....
}
public boolean equals(BB ob)
{
return false;
}
public boolean equals(Object ob)
{
return true;
}
public boolean equals(AA ob)
{
return true;
}
public static void main(String args[])
{
AA a2=new BB();
BB b1=new BB();
if((a2.equals(b1)))
System.out.println("hi");
}
}
Class AA does not have an equalsmethod
I'm trying to figure out with the second method is triggered and not the first one. My understanding is:
Since class AA does not have an equals method, I suppose that at
compile-time the compiler wants to run the equals from Object
class.
At run time the compiler finds out that a2 is actually a BB object
and therefore has equals methods that override the method from
Object.
However, what is not clear to me is why the second method (Object ob) is chosen instead of the first (BB ob), if the sent object is defined and actually is a BB object.
Would appreciate your feedback!

When you call a.equals(b), the compiler looks at the equals methods in AA. If it found an appropriate one there, it would use it. In this case, AA has no methods called 'equals'. So it steps up the inheritance chain, and looks again. This time, it is looking at Object, and it finds Object.equals(Object). At runtime, it finds the most overridden version and calls it.
So if it's still just looking for a method called 'equals', why doesn't it find the more specific version equals(BB) at runtime?
BB.equals(BB) is not considered an override of Object.equals(Object). It has a more specific parameter, and can't handle a plain Object. Imagine the types are part of the name:
equals_Object
equals_BB
The compiler picked the equals_Object method, so at runtime the JVM will not find the equals_BB method, because it isn't looking for it.

Overloads are not chosen at runtime, they're chosen at compile time, when the compiler only knows that the object is an AA. Only overrides are chosen at runtime, based on the actual runtime type of the object, but the overload selected at compile time is still used.

Related

Why does it seem to call the wrong method?

Lets say I have two classes A and B . B inherits from A and B has the following methods:
public boolean equals(Object other) {
System.out.print("Object");
return true;
}
public boolean equals(A other){
System.out.print("A object");
return true;
}
public boolean equals(B other) {
System.out.print("B object");
return true;
}
A a1 = new A();
A ab = new B();
B b1 = new B();
what is unclear to me is why
ab.equals(a1)
ab.equals(b1)
Returns Object
ab is an instance of B with pointer of A. a1 is clearly both instance and pointer of A. So Why does it use the Object other instead of A other method?? same goes for b1 which is an instance of B with pointe B yet the compiler chose to apply the equals method like I inserted regular object?? AM i that stupid or is this language incoherent?
BTW A doesn't have any equals methods at all.
Explanation
BTW A doesn't have any equals methods at all.
But you do
ab.equals(a1)
ab.equals(b1)
And ab is:
A ab = new B();
So while it is actually a B, the variable is of type A.
Javas rules for choosing methods in such situations will start looking for an equals method in the A class. And it actually has one, the default implementation inherited from Object. It has the signature
public boolean equals(Object other)
So it decides for this signature. Now it asks the actual instance behind ab, which is of type B, for a method with that signature. It chooses the overriden implementation in B:
public boolean equals(Object other) {
System.out.print("Object");
}
And consequentially prints Object in both cases.
Details
The details for this are defined in JLS§15.12. Method Invocation Expressions. It talks about finding the most specific match. The rules can get quite complex if you dive deep into it.
Some excerpts:
The first step in processing a method invocation at compile time is to figure out the name of the method to be invoked and which class or interface to search for definitions of methods of that name.
The second step searches the type determined in the previous step for member methods. This step uses the name of the method and the argument expressions to locate methods that are both accessible and applicable, that is, declarations that can be correctly invoked on the given arguments.
There may be more than one such method, in which case the most specific one is chosen. The descriptor (signature plus return type) of the most specific method is the one used at run time to perform the method dispatch.
The class or interface determined by compile-time step 1 (§15.12.1) is searched for all member methods that are potentially applicable to this method invocation; members inherited from superclasses and superinterfaces are included in this search.
If more than one member method is both accessible and applicable to a method invocation, it is necessary to choose one to provide the descriptor for the run-time method dispatch. The Java programming language uses the rule that the most specific method is chosen.
The setup
Given a class A and a class B extends A, overriding and overloading equals(...) with different parameter types as follows:
class A {}
class B extends A {
public boolean equals(Object other) {
System.out.println("Object");
return true;
}
public boolean equals(A other) {
System.out.println("A object");
return true;
}
public boolean equals(B other) {
System.out.println("B object");
return true;
}
}
The question
Given the following code
A a1 = new A();
A ab = new B();
B b1 = new B();
ab.equals(a1);
ab.equals(b1);
Why is "Object" printed out for both calls?
The explanation
The signature of method called is determined through the static type of the receiver and the static type of the parameters (as described in JLS, §15.12.3). Furthermore, through dynamic dispatch, a child-class override of a method may be executed.
If we analyze the type of ab (the receiver of the call), we find it to be A. There is only one method called equals(...) wihtin A, which is equals(Object) (inherites from Object). the parameters (a1 and b1 respectively) are assignable to Object, so this method is called.
Through dynamic dispatch, equals(Object) in B is actually executed and "Object" is printed out for both calls.
A full example is available on Ideone

Overridden and Overloaded Methods

What does it mean by "Casting affects the selection of overloaded methods at compile time but not overridden methods"?
I read the following passage on "Overridden methods and dynamic binding" (https://www.oreilly.com/library/view/learning-java-4th/9781449372477/ch06s01.html) and I couldn't understand the last paragraph
"In a previous section, we mentioned that overloaded methods are selected by the compiler at compile time. Overridden methods, on the other hand, are selected dynamically at runtime. Even if we create an instance of a subclass our code has never seen before (perhaps a new class loaded over the network), any overriding methods that it contains are located and used at runtime, replacing those that existed when we last compiled our code.
In contrast, if we created a new class that implements an additional, more specific, overloaded method, and replace the compiled class in our classpath with it, our code would continue to use the implementation it discovered originally. This situation would persist until we recompiled our code along with the new class. Another effect of this is that casting (i.e., explicitly telling the compiler to treat an object as one of its assignable types) affects the selection of overloaded methods at compile time but not overridden methods."
I couldnt understand the "Casting" line: "Another effect of this is that casting (i.e., explicitly telling the compiler to treat an object as one of its assignable types) affects the selection of overloaded methods at compile time but not overridden methods."
That line is referring to the fact that
overloaded versions of a method are chosen at compile time, based on the compile-time types of the arguments that you are passing; whereas
overridden methods are chosen at run time, based on the classes of the objects on which you call each method.
To understand this distinction, consider a situation where you have both overrides and overloads, like this.
public class Person {
}
---------------------------------------------------------
public class Postman extends Person {
}
---------------------------------------------------------
public class Dog {
public void barkAt(Person p) {
System.out.println("Woof woof");
}
public void barkAt(Postman p) {
System.out.println("Grrrr");
}
}
---------------------------------------------------------
public class Rottweiler extends Dog {
#Override
public void barkAt(Person p) {
System.out.println("I'm going to eat you.");
}
#Override
public void barkAt(Postman p) {
System.out.println("I'm going to rip you apart.");
}
}
In this situation, we call one of these barkAt methods, like this.
Dog cujo = new Rottweiler();
Person pat = new Postman();
cujo.barkAt(pat);
Now in this particular case, it's the compiler that chooses whether cujo.barkAt(pat); calls a method like public void barkAt(Person p) or public void barkAt(Postman p). These methods are overloads of one another.
To do this, the compiler looks at the type of the expression being passed to the method - that is, the variable pat. The variable pat is of type Person, so the compiler chooses the method public void barkAt(Person p).
What the compiler doesn't do is choose whether it's the method from the Rottweiler class or the Dog class that gets called. That happens at run time, based on the class of the object on which the method gets called, NOT on the type of the variable that you call the method on.
So in this case, what matters is the class of the object called cujo. And in this example, cujo is a Rottweiler, so we get the overridden version of the method - the one defined in the Rottweiler class.
This example will print out I'm going to eat you.
To summarise:
The overload is chosen at compile time based on the parameter type.
The override is chosen at run time based on the object class.
Now, it's possible to use casting to change the compiler's choice of overload. It's not possible to use casting to change the run time choice of override. So, we could write
cujo.barkAt((Postman) pat);
This time, the parameter passed to the method is an expression of type Postman. The compiler chooses an overload accordingly, and this will print I'm going to rip you apart..
Casting affects the selection of overloaded methods at compile time but not overridden methods
Overloaded methods are visible at compile time. But overridden methods becomes visible at runtime.
Thumb Rule:
Java calls the overridden methods based on contents of reference variable and not type of reference variables.
Below example is self explainatory. Hope it helps.
class Animal {
public void speak() {
System.out.print("Animal sounds/roars.");
}
}
class Human extends Animal {
#Override // Method is overridden
public void speak() {
System.out.print("Humans talking english.");
}
public void speak(String words) { // Method is overloaded.
System.out.print("We have brain. We are intelligent."+words);
}
}
class Earth {
public static void main(String a[]) {
Animal a = new Animal();
a.speak(); // Prints Animal sounds/roars.
Human h = new Human();
h.speak(); // Prints "Humans talking english."
Animal a = h; // Cast to superclass reference variable. However, underlying object is of Human.
a.speak(); // Prints "Humans talking english." because speak() is known by Animal at compile time. During runtime,
// the object contains the human object and hence java calls human overridden method.
a.speak("I want to be human."); // Compile time error as speak(..) is not known by Animal at compile time.
}
}

what does Object do in java? [duplicate]

This question already has answers here:
When overriding equals in Java, why does it not work to use a parameter other than Object?
(7 answers)
Overloaded method selection based on the parameter's real type
(7 answers)
Closed 6 years ago.
I have this code in java and I do not understand the meaning of the Object in the following code ...
Here is the code
public class Tester {
public static void main(String[] args) {
Foo foo1 = new Foo(1);
Foo foo2 = new Foo(2);
System.out.print(foo1.equals(foo2));
}
}
class Foo {
Integer code;
Foo(Integer c) {
code = c;
}
public boolean equals(Foo f) {
return false;
}
public boolean equals(Object f) {
return true;
}
}
When I run the code I get false
but when I remove
public boolean equals(Foo f) {
return false;
}
and run the code I get true...
Why is that and what is happening ?
Thanks
This is method overloading resolution. There are two method candidates, one that takes an Object and the other takes Foo, when you pass a Foo, the most specific method (the one that takes Foo) will be called.
When you remove the method that takes Foo, you won't have an overload any longer and because Foo is an Object (as any class in Java) the method will accept it.
Method Overloading. Most specific method gets chosen at run time.
As per Language specification most specific method chooses at run time.
If more than one member method is both accessible and applicable to a method invocation, it is necessary to choose one to provide the descriptor for the run-time method dispatch. The Java programming language uses the rule that the most specific method is chosen.
You are getting false because most specific method got choosen. That is the reason
public boolean equals(Foo f) {
return false;
}
This method called and returning false. When you remove this method,
public boolean equals(Object f) {
return true;
}
This gets called because every Foo is Object.
Because the compiler is going to invoke the most-specific method matching the parameters. When you have equals(Foo) that is more specific than equals(Object). When you remove equals(Foo) the equals(Object) is the only method that is still valid. It is also worth noting that Foo has an implicit parent class, java.lang.Object.
i think you don,t really understand object oriented programming, you should get a book on OOP to understand the consepts. check it-ebboks.com for some helpfull books
An objact is an instance of a class, take for instance a classroom of student offering the same subjects , if john doe is a memebr of that class that is he offers the courses in that class he is an instance of that class
public boolean equals(Foo f) {
return false;
}
is returning false no mattter what parameter you pass into it

Java overloading and inheritance rules

I've been studying because I have an exam and I don't have many problems with most of Java but I stumbled upon a rule I can't explain. Here's a code fragment:
public class A {
public int method(Object o) {
return 1;
}
public int method(A a) {
return 2;
}
}
public class AX extends A {
public int method(A a) {
return 3;
}
public int method(AX ax) {
return 4;
}
}
public static void main(String[] args) {
Object o = new A();
A a1 = new A();
A a2 = new AX();
AX ax = new AX();
System.out.println(a1.method(o));
System.out.println(a2.method(a1));
System.out.println(a2.method(o));
System.out.println(a2.method(ax));
}
This returns:
1
3
1
3
While I would expect it to return:
1
3
1
4
Why is it that the type of a2 determines which method is called in AX?
I've been reading on overloading rules and inheritance but this seems obscure enough that I haven't been able to find the exact rule. Any help would be greatly appreciated.
The behavior of these method calls is dictated and described by the Java Language Specification (reference section 8.4.9).
When a method is invoked (§15.12), the number of actual arguments (and
any explicit type arguments) and the compile-time types of the
arguments are used, at compile time, to determine the signature of the
method that will be invoked (§15.12.2). If the method that is to be
invoked is an instance method, the actual method to be invoked will be
determined at run time, using dynamic method lookup (§15.12.4).
In your example, the Java compiler determines the closest match on the compile type of the instance you are invoking your method on. In this case:
A.method(AX)
The closest method is from type A, with signature A.method(A). At runtime, dynamic dispatch is performed on the actual type of A (which is an instance of AX), and hence this is the method that is actually called:
AX.method(A)
I will clarified it in more simple way. See when you making sub class object with super class reference like here you did.
Always one thing keep in your mind that when you call with super class reference, no matters object is of sub class it will go to the super class, check method with this name along with proper signature is there or not.
now if it will find it, than it will check whether it is overridden?? if yes than it will go to the sub class method like here it went. another wise it will execute the same super class method.
I can give you the example of it...just hide
public int method(A a) {
return 3;
}
method & check your answer you will get 1 2 1 2, why because it gives first priority to reference. because you overridden it & than calling it, so its giving 3..!! hope its big but easy to understand. Happy Learning
a2 referenced as an A and the JVM using the reference first (not the acutal object as you expected).

Overriding or overloading?

Guys I know this question is silly but just to make sure:
Having in my class method:
boolean equals(Document d)
{
//do something
}
I'm overloading this method nor overriding right? I know that this or similiar question will be on upcoming egzam and would be stupid to not get points for such a simple mistake;
Based on the code provided, we can't tell for sure whether you're overloading or overriding it.
You are most likely overloading the equals(Object o) method.
class A {
void method() {..}
}
class B extends A {
// this is overriding
void method() {..}
}
And
// this is overloading
class A {
void method(boolean b) {..}
void method(String arg) {..}
void method(int arg) {..}
}
P.S. you are using a bracket convention that is not widely accepted on the java world. In Java it is more common to place opening the curly bracket on the same.
You are not even overloading, since the other method is called equals. But if you add that s, you will be overloading equals. Although, to be precise, we talk about overloading if two (or more) methods with the same name but different signature are defined in the same class. In your case, it is trickier, since your equals with its different signature partly hides the original equals. Which is usually a bad thing, because this almost always leads to hard to understand behaviour, thus subtle bugs. Whenever someone calls equals on an instance of your class, depending on the parameter type the call may go to a different implementation of the method.
class Document {
public boolean equals(Document d)
{
//do something
}
}
Document doc1 = new Document();
Document doc2 = new Document();
String string = new String();
doc1.equals(doc2); // calls Document.equals
doc1.equals(string); // calls Object.equals!
You would be overriding Object.equals if you defined your method with the exact same signature as the original, i.e.
public boolean equals(Object obj) ...
In this case, both of the above calls to equals correctly execute Document.equals.
From the code you posted it could be either. If equal is defined in a superclass with the same parameter declarations then you are overriding it. If there is already a method called equal, but with different parameter types, you are overloading it.
On a related note, if you are using Java 5 and above and your intent is to override then it is highly recommended to use the #Override annotation before the method definition to indicate your intention. The wrong usage of this annotation (i.e. when you want to override and are not doing so) would flag a compile error.
As of Java 6 you can use the #Override annotation while defining methods that are
declared in an interface the class in implementing.
Overloading: same method name, same parameter list, different classes
Overriding: same method name, different parameter list, same or different classes.
Class A {
bool Equals(Document d) {...}
bool Equals(A a) {...} // overloaded method
}
Class B extends A {
bool Equals(Document d) {...} // overridden method
bool Equals(B b) {...} // overloaded method
}
One thing to note, the return type does not matter, it's the name of the method and the parameter list that make all the difference.

Categories

Resources