From: Vikram on 14 Jun 2010 12:20 Hi, If we have two methods in a class as below: public void test(String s){ ....... ...... } public void test(Object o){ ........ ..... } And we invoke the method as : test(null) : from another class, the method with the String parameter is executed. Any particular reason for this?
From: Lew on 14 Jun 2010 13:05 Vikram wrote: > If we have two methods in a class as below: > > public void test(String s){ > ...... > ..... > > } > > public void test(Object o){ > ....... > .... > > } > > And we invoke the method as : test(null) : from another class, the > method with the String parameter is executed. Any particular reason > for this? Yes. See the JLS: <http://java.sun.com/docs/books/jls/third_edition/html/ expressions.html#292575> Nutshell version: most specific argument-type matching wins. In general if you have a question about Java syntax and semantics like this one, the answer is in the JLS. Your method overload question is quite important, actually. It's a common mistake to overload 'equals()' when the intent is to override, e.g., public class Foo { ... public boolean equals( Foo other ) { ... } } This method will appear to work if passed a 'Foo' argument because the 'Foo' argument matches more specifically than the 'Object' argument to the other 'equals()' method in the class, but it will fail in general when clients pass an 'Object' argument and bypass the specific overload, getting the parent-class version instead. -- Lew
From: Simon Brooke on 14 Jun 2010 13:46 On Mon, 14 Jun 2010 10:05:08 -0700, Lew wrote: > Your method overload question is quite important, actually. It's a > common mistake to overload 'equals()' when the intent is to override, > e.g., > > public class Foo > { > ... > public boolean equals( Foo other ) > { > ... > } > } > > This method will appear to work if passed a 'Foo' argument because the > 'Foo' argument matches more specifically than the 'Object' argument to > the other 'equals()' method in the class, but it will fail in general > when clients pass an 'Object' argument and bypass the specific overload, > getting the parent-class version instead. Sorry, why is this a mistake? If a 'Bar' argument is passed, equals must return false anyway. Does it matter which implementation of equals is invoked? I can see how this might matter for other methods with different semantics, but why equals, particularly? -- ;; Semper in faecibus sumus, sole profundam variat
From: Lew on 14 Jun 2010 14:24 Lew wrote: >> Your method overload question is quite important, actually. It's a >> common mistake to overload 'equals()' when the intent is to override, >> e.g., >> >> public class Foo >> { >> ... >> public boolean equals( Foo other ) >> { >> ... >> } >> } >> >> This method will appear to work if passed a 'Foo' argument because the >> 'Foo' argument matches more specifically than the 'Object' argument to >> the other 'equals()' method in the class, but it will fail in general >> when clients pass an 'Object' argument and bypass the specific overload, >> getting the parent-class version instead. > Simon Brooke wrote: > Sorry, why is this a mistake? If a 'Bar' argument is passed, equals must > return false anyway. Does it matter which implementation of equals is > invoked? > Yes. As I already stated in my post, it will fail in the general case when clients invoke it with an 'Object' argument. You will then get the non-overridden 'equals(Object)' method from the parent class, which typically provides object identity comparison rather than value comparison, or else value comparison on the wrong fields. > I can see how this might matter for other methods with different > semantics, but why equals, particularly? > The parent 'equals()' method typically is one of those "other methods with different semantics". The semantics of 'equals(Object)' will differ from that of 'equals(Foo)' without special care, i.e., an override of the former that invokes the latter. 'equals()' is typically called with an 'Object' argument, and therefore the overload will not be invoked. Things like collections depend on the method to have an override. No override yields undesired behavior. -- Lew
From: Eric Sosman on 14 Jun 2010 14:25
On 6/14/2010 1:46 PM, Simon Brooke wrote: > On Mon, 14 Jun 2010 10:05:08 -0700, Lew wrote: > >> Your method overload question is quite important, actually. It's a >> common mistake to overload 'equals()' when the intent is to override, >> e.g., >> >> public class Foo >> { >> ... >> public boolean equals( Foo other ) >> { >> ... >> } >> } >> >> This method will appear to work if passed a 'Foo' argument because the >> 'Foo' argument matches more specifically than the 'Object' argument to >> the other 'equals()' method in the class, but it will fail in general >> when clients pass an 'Object' argument and bypass the specific overload, >> getting the parent-class version instead. > > Sorry, why is this a mistake? If a 'Bar' argument is passed, equals must > return false anyway. Does it matter which implementation of equals is > invoked? The second sentence is often true, even "usually" true, but not universally true. It sometimes makes sense for the equals() of one class to return true when handed an instance of a different class. For example, consider the equals() contract of Set: Set<String> hs = new HashSet<String>(); hs.add("hello"); hs.add("world"); Set<String> ts = new TreeSet<String>(); ts.addAll(hs); assert hs.getClass() != ts.getClass(); assert hs.equals(ts); -- Eric Sosman esosman(a)ieee-dot-org.invalid |