Go Back   Velocity Reviews > Newsgroups > Java
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read


Reply

Java - instanceof NOT (always) bad? The instanceof myth.

 
Thread Tools Search this Thread
Old 06-20-2006, 06:03 PM   #1
dmx_dawg@hotmail.com
 
Posts: n/a
Default instanceof NOT (always) bad? The instanceof myth.

Hi all.

I just decided to write a message regarding the myth that the use of
the instanceof keyword is categorically bad. Not all java programmers
have fallen prey to the myth, but after years on the newsgroups it has
almost gotten to the point where if it was discovered that you used
instanceof anywhere in your app, it *must* be because you have a poorly
designed system.

Is this a situation of 'bad-practice-phobia', where the fear of being
thought of as a newbie programmer (or worse, a 'hack' who still
'doesn't get' OO) makes people create the most elaborately complex and
unmaintainable designs to avoid using a specific 'bad practice'?

I think what's very often forgotten is that a bad practice can never be
reduced to something as simplistic as 'never ever use keyword X'. All
bad practices have there 'scope of ill-use'--which may be very big--but
are almost never (if ever) absolute.

Specifics:



Alex Blewitt's Javaworld article
================================
It has been said that, in most cases, instanceof should not be used to
test for object equality (see [BLEWITT1]) as it can break the symmetric
property of the equals method's equivalence relation. In this case,
using the getClass method of Object is the appropriate choice. This
makes a lot of sense.

But notice that Mr. Blewitt's article never simply says 'always use
getClass over instanceof'. He explicitly states a specific situation
in which using instanceof is not appropriate. So next time someone
cites Mr. Blewitt's article to prove your use of instanceof is bad
without even seeing your code, you can be fairly certain they've
probably never actually read the article. They are simply deep in the
'instanceof is always, always bad' myth.

Yoe see, getClass will always return the runtime class of an object and
is useless if what you want to determine is whether an object falls
within a specific inheritance hierarchy. In the example below, we want
to determine if an object's class implements a specific interface.
Here getClass does not help us.

class A implements IShared
{
}

A a = new A();

a instanceof A; // true
a instanceof IShared; // true

a.getClass() == A.class // true
a.getClass() == IShared.class // false

Now, of course, this is a contrived example with no context, but the
need to check whether an object can be polymorphically treated as a
specific type--wherever that type may exist in its inheritance
hierarchy--can often be useful in practice (see the references section
for some specific examples of this, such as those uses found in the
Ecplipse framework).



Avoiding instanceof
===================
Another thing you may find on the net are people who will try their
darndest to provide you with an example of how you can get around using
instanceof. They will explain that you need their complex, difficult
to maintain, cyclic-dependency-creating solutions because your design
is bad (you used instanceof right?... so it *must* be bad), and that
your solution will certainly be a nightmare to maintain in the future.
Let's take a brief look at some of the common 'solutions'.



Use method overloading instead
==============================
Some may say that you simply need to overload a number of methods with
different class parameters. Why use instanceof to determine if an
object's class implements a specific interface? Let the overloading
functionality of the language do this for you!

The problem is that

interface Animal
{
public void move();
}

class Fish implements Animal
{
public void move()
{
System.out.println("swim!");
}

public void eatAlgae(){}
}

class Mouse implements Animal
{
public void move()
{
System.out.println("scurry!");
}

public void makeHoleInWall(){}
}


So now we can create methods such as

class Test
{

public void scare(Mouse m)
{
m.move();
m.makeHoleInWall();
}

public void scare(Fish fish)
{
f.move();
f.eatAlgae();
}

public Test()
{
Animal fish = new Fish();

scare(fish); // does not compile
}

}


So what happened? Why doesn't this even compile? Because the fish
object's compile-time type is Animal, *not Fish*. Of course, we could
get around this by creating a new scare(Animal a) method, but then
we're right back where we started.



Visitor (and Proxy Visitor)
===========================
Another option that is often brought up is the use of the Visitor
pattern. The problem with this is that it creates a huge maintenance
issue. Visitor requires updating all of the 'visitable' classes every
time we add new visitable class into the pattern.

Why not use adapter classes then? The problem is that in Java, its not
always simple for 'visitable' classes to extend a 'VistableAdapter' (to
avoid implementing an accept method for every possible visitable class)
due Java's single inheritance (e.g.: if your class is already extending
a class, you're out of luck unless you want to get into some messy
code). This turns the Visitor pattern into a maintenance nightmare.

Now I have obviously skimmed over this one very quickly, but this is
because Robert C. Martin has already ready written on this better than
I could. Check out his web page on the subject [MARTIN1], as well (if
you have ACM Portal access) his published paper on it [MARTIN2].



Other people using instanceof
=============================
I encourage people to check out some of the other sources I've listed
here. Maybe if people found out that the Eclipse framework uses
instanceof [OTAKU], or if after they read an article by Bill Venners
with a section explicitly titles 'When to use instanceof' [VENNERS],
they will see that one should always beware of grand sweeping
generalizations in any situation. So go ahead and use instanceof when
it's appropriate, avoid it when it's not appropriate, and don't believe
the hype!

Cheers!


Michael N. Christoff



References
==========
BLEWITT
Object equality--Writing equals and hashCode methods for data objects
http://www.javaworld.com/javaworld/j...14-equals.html

MARTIN1
Visitor vs instanceof
http://butunclebob.com/ArticleS.Uncl...rsusInstanceOf

MARTIN2
Acyclic visitor
http://portal.acm.org/citation.cfm?i...CM&coll=portal

VENNERS
See section "When to use instanceof" at the following link:
http://www.artima.com/objectsandjava...terfaces1.html

OTAKU
See section "Extensibility the interface way"
http://www.beust.com/weblog/archives/2005_06.html

  Reply With Quote
Old 06-20-2006, 06:43 PM   #2
Oliver Wong
 
Posts: n/a
Default Re: instanceof NOT (always) bad? The instanceof myth.


<> wrote in message
news: oups.com...
>
> I think what's very often forgotten is that a bad practice can never be
> reduced to something as simplistic as 'never ever use keyword X'. All
> bad practices have there 'scope of ill-use'--which may be very big--but
> are almost never (if ever) absolute.


Never use keyword "goto" (unless your goal is to make your Java code not
compile).

>
> Specifics:
>
>
>
> Alex Blewitt's Javaworld article
> ================================
> It has been said that, in most cases, instanceof should not be used to
> test for object equality (see [BLEWITT1]) as it can break the symmetric
> property of the equals method's equivalence relation. In this case,
> using the getClass method of Object is the appropriate choice. This
> makes a lot of sense.
>
> But notice that Mr. Blewitt's article never simply says 'always use
> getClass over instanceof'. He explicitly states a specific situation
> in which using instanceof is not appropriate. So next time someone
> cites Mr. Blewitt's article to prove your use of instanceof is bad
> without even seeing your code, you can be fairly certain they've
> probably never actually read the article. They are simply deep in the
> 'instanceof is always, always bad' myth.


Actually, I think it's a good idea to use instanceof in the equals() method.
Here's how I usually implement it (written off the top of my head, might
contain some syntax errors, but hopefully the semantics is clear):

<code>
class Foo {
private int myField;

@Overrides public boolean equals(Object other) {
if (other == this) {
return true;
}
if (other instanceof Foo) {
return this.equals((Foo)other);
}
return false;
}

public boolean equals(Foo other) {
if (other == this) {
return true;
}
if (!this.getClass().equals(other.getClass())) {
/*this is explained below*/
return other.equals(this);
}
if (this.myField != other.myField) {
return false;
}
return true;
}
}
</code>

The .getClass() conditional is basically checking whether other's exact
class is Foo, or if it is a strict-subclass of Foo. In the case that it is
exactly a Foo, then we have all the information we need to determine
equality, and so the method proceeds as normal.

In the case that "other" is a subclass of Foo, then I invoke that subclasses
equals() method, because the subclass would knows more about Foo than Foo
knows about the subclass.

Note that with this pattern, all subclasses of Foo *MUST* override the
equals(Foo) method, or else you'll end up with an infinite recursion.

[...]
>
>
> Use method overloading instead
> ==============================
> Some may say that you simply need to overload a number of methods with
> different class parameters. Why use instanceof to determine if an
> object's class implements a specific interface? Let the overloading
> functionality of the language do this for you!
>
> The problem is that
>
> interface Animal
> {
> public void move();
> }
>
> class Fish implements Animal
> {
> public void move()
> {
> System.out.println("swim!");
> }
>
> public void eatAlgae(){}
> }
>
> class Mouse implements Animal
> {
> public void move()
> {
> System.out.println("scurry!");
> }
>
> public void makeHoleInWall(){}
> }
>
>
> So now we can create methods such as
>
> class Test
> {
>
> public void scare(Mouse m)
> {
> m.move();
> m.makeHoleInWall();
> }
>
> public void scare(Fish fish)
> {
> f.move();
> f.eatAlgae();
> }
>
> public Test()
> {
> Animal fish = new Fish();
>
> scare(fish); // does not compile
> }
>
> }
>
>
> So what happened? Why doesn't this even compile? Because the fish
> object's compile-time type is Animal, *not Fish*. Of course, we could
> get around this by creating a new scare(Animal a) method, but then
> we're right back where we started.
>


I'm not sure that this example is an argument for/against using
instanceof. At best, it's an argument against Java's choice of resolving
method calls based on the declared type of a reference, rather than the
runtime type. A cleaner design that doesn't involve instanceof or its lack
thereof might be:

<code>
public interface Animal {
public void actScared();
}

public class Test {
public Test() {
Animal fish = new Fish();
fish.actScared();
}
}
</code>

>
>
> Visitor (and Proxy Visitor)
> ===========================
> Another option that is often brought up is the use of the Visitor
> pattern. The problem with this is that it creates a huge maintenance
> issue. Visitor requires updating all of the 'visitable' classes every
> time we add new visitable class into the pattern.
>
> Why not use adapter classes then? The problem is that in Java, its not
> always simple for 'visitable' classes to extend a 'VistableAdapter' (to
> avoid implementing an accept method for every possible visitable class)
> due Java's single inheritance (e.g.: if your class is already extending
> a class, you're out of luck unless you want to get into some messy
> code). This turns the Visitor pattern into a maintenance nightmare.
>
> Now I have obviously skimmed over this one very quickly, but this is
> because Robert C. Martin has already ready written on this better than
> I could. Check out his web page on the subject [MARTIN1], as well (if
> you have ACM Portal access) his published paper on it [MARTIN2].


I only read [MARTIN1], and it seems the main argument is to "avoid
recompiling", which IMHO isn't a significant gain.

- Oliver

  Reply With Quote
Old 06-20-2006, 09:37 PM   #3
Daniel Dyer
 
Posts: n/a
Default Re: instanceof NOT (always) bad? The instanceof myth.

On Tue, 20 Jun 2006 19:03:54 +0100, <> wrote:
> Yoe see, getClass will always return the runtime class of an object and
> is useless if what you want to determine is whether an object falls
> within a specific inheritance hierarchy. In the example below, we want
> to determine if an object's class implements a specific interface.
> Here getClass does not help us.


This isn't an argument for or against instanceof, but you can achieve what
you describe by using the Class object returned by getClass:

http://java.sun.com/j2se/1.5.0/docs/...ava.lang.Class)

Dan.

--
Daniel Dyer
http://www.dandyer.co.uk
  Reply With Quote
Old 06-20-2006, 09:39 PM   #4
Chris Smith
 
Posts: n/a
Default Re: instanceof NOT (always) bad? The instanceof myth.

<> wrote:
> I just decided to write a message regarding the myth that the use of
> the instanceof keyword is categorically bad. Not all java programmers
> have fallen prey to the myth, but after years on the newsgroups it has
> almost gotten to the point where if it was discovered that you used
> instanceof anywhere in your app, it *must* be because you have a poorly
> designed system.


On these newsgroups? I've followed these newsgroups for many years
(since about 199 and haven't gotten that impression. Nevertheless, if
the impression has been given, then it is incorrect.

What has often been said is that avoiding runtime type dependencies in
general is a good idea whenever possible. Typically, though, this
advice is applied to reflection instead of use of the instanceof
keyword. I can also see that there are a lot of places where someone
unfamiliar with OO programming may wish to use instanceof, but which
should be replaced with polymorphism. Again, though, I see no
justification for an absolute rule forbidding instanceof. Indeed,
inheritance is often poorly applied to situations where it breaks proper
separation of concerns.

> It has been said that, in most cases, instanceof should not be used to
> test for object equality (see [BLEWITT1]) as it can break the symmetric
> property of the equals method's equivalence relation. In this case,
> using the getClass method of Object is the appropriate choice. This
> makes a lot of sense.


I am completely with you on this one. I have noticed a tendency (not so
much on this newsgroup, but in other places, at least, such as
introductory textbooks of fly-by-night tutorial web sites that are
sometimes posted here) to do the following:

1. Assume that the programmer intends to write a certain kind of very
mechanical implementation of the equals or hashCode methods.

2. Draw conclusions about how to uphold their contracts, on the basis of
these mechanical implementations.

3. Forget that less mechanical implementations are possible.

This tendency is exaggerated by the section (which is a good one, by the
way) in Josh Bloch's Effective Java that gives a mechanical way to
handle hashCode (but that *also* notes that it only applies to
information that is relevant to object identity... a qualification that
is often lost in translation), and by the kinds of silly introductory
examples to overriding hashCode and equals that are frequently in intro
textbooks or tutorials.

An excellent example of where this does NOT apply is java.util.List.
The contract for java.util.List.equals contains a requirement that any
List should compare equal to any other List with the same contents. I
think this is a very poor requirement, but it is nevertheless a
requirement. Beginning an implementation of MyList.equals by comparing
this.getClass() to other.getClass() is a sure-fire guarantee of breaking
the contract.

What is true, though, is that in the absence of some specification for
how to declare dissimilar classes, the task shoulod be considered
impossible... i.e., they should always be considered unequal. That
specification logically ought to occur in the documentation of some
supertype. Hence, it may be valid to say that instanceof should never
be used to check equals UNLESS there is some specification in some
supertype that defines equality for some containing inheritance sub-
hierarchy.

> Another thing you may find on the net are people who will try their
> darndest to provide you with an example of how you can get around using
> instanceof. They will explain that you need their complex, difficult
> to maintain, cyclic-dependency-creating solutions because your design
> is bad (you used instanceof right?... so it *must* be bad), and that
> your solution will certainly be a nightmare to maintain in the future.


Hopefully, you don't mean to include here situations in which someone
provides not only general advice on how to avoid using instanceof, but
also specific negative consequences of the use of instanceof, and how
their proposed solutions avoids those drawbacks. For example, one
common problem with instanceof is that it introduces a single point that
must be extended in order to completely integrate a new subtype into the
system. If the solution can avoid this by moving certain type-specific
code into the subclass itself, this is nearly always a good thing.
Therefore, there is reason to be cautious with this keyword when working
in a situation where the list of possible subtypes is not theoretically
limited, such as when working with a hierarchy of objects representing
different accounting policies for various legal jurisdictions.

> Use method overloading instead
> ==============================


> Visitor (and Proxy Visitor)
> ===========================


You missed the obvious one. If possible, take the type-specific
behavior, and move it into a polymorphic method of the class. Doing so
can require some creativity in design... but that's because you're
really doing design rather than following someone's furmulaic answer.
Design is a creative process. It involves finding and using the
abstractions that are inherent to the system.

My suspicion is that when most advice is given to avoid instanceof, this
is what is meant. Don't use instanceof, but rather identify and
describe the inherent abstractions that allow you to write something
that applies to all relevant types. If the advice is taken to mean
something else, such as that a specific trick should be employed to
remove the keyword in an automatable way, then someone has profoundly
missed the point.

> Other people using instanceof
> =============================


Note that most of the really good examples of using instanceof come from
writing code that is inherently somewhat dynamic systems. The only
exception I can think of comes from so-called "marker" interfaces, which
are problematic from a design standpoint anyway; or from backward-
compatibility limitations that prevent making appropriate changes to a
common supertype.

--
Chris Smith - Lead Software Developer / Technical Trainer
MindIQ Corporation
  Reply With Quote
Old 06-21-2006, 07:04 AM   #5
Twisted
 
Posts: n/a
Default Re: instanceof NOT (always) bad? The instanceof myth.

Daniel Dyer wrote:
> This isn't an argument for or against instanceof, but you can achieve what
> you describe by using the Class object returned by getClass:
> http://java.sun.com/j2se/1.5.0/docs/...ava.lang.Class)


"Foo.class.isAssignableFrom(object.getClass()) " is just a very
roundabout and awkward version of "object instanceof Foo" is it not?

  Reply With Quote
Old 06-21-2006, 08:33 AM   #6
Daniel Dyer
 
Posts: n/a
Default Re: instanceof NOT (always) bad? The instanceof myth.

On Wed, 21 Jun 2006 08:04:49 +0100, Twisted <> wrote:

> Daniel Dyer wrote:
>> This isn't an argument for or against instanceof, but you can achieve
>> what
>> you describe by using the Class object returned by getClass:
>> http://java.sun.com/j2se/1.5.0/docs/...ava.lang.Class)

>
> "Foo.class.isAssignableFrom(object.getClass()) " is just a very
> roundabout and awkward version of "object instanceof Foo" is it not?


Yes, but the point is that the OP claimed it was not possible. instanceof
would be preferable in most situations, but isAssignable from can be
useful in a situation where you don't know at compile-time exactly which
class that you are using.

Dan.

--
Daniel Dyer
http://www.dandyer.co.uk
  Reply With Quote
Old 06-21-2006, 11:33 AM   #7
Chris Uppal
 
Posts: n/a
Default Re: instanceof NOT (always) bad? The instanceof myth.

Chris Smith wrote:

> An excellent example of where this does NOT apply is java.util.List.
> The contract for java.util.List.equals contains a requirement that any
> List should compare equal to any other List with the same contents. I
> think this is a very poor requirement, but it is nevertheless a
> requirement.


I hadn't realised that. Live and learn...

I like the idea that a List<java.awt.Point> can be equal to a List<byte[]>


> My suspicion is that when most advice is given to avoid instanceof, this
> is what is meant. Don't use instanceof, but rather identify and
> describe the inherent abstractions that allow you to write something
> that applies to all relevant types. If the advice is taken to mean
> something else, such as that a specific trick should be employed to
> remove the keyword in an automatable way, then someone has profoundly
> missed the point.


+1 (and in spades).


> Note that most of the really good examples of using instanceof come from
> writing code that is inherently somewhat dynamic systems. The only
> exception I can think of comes from so-called "marker" interfaces, which
> are problematic from a design standpoint anyway; or from backward-
> compatibility limitations that prevent making appropriate changes to a
> common supertype.


And +1 again.

-- chris




  Reply With Quote
Old 06-21-2006, 08:03 PM   #8
Twisted
 
Posts: n/a
Default Re: instanceof NOT (always) bad? The instanceof myth.

Chris Uppal wrote:
> I like the idea that a List<java.awt.Point> can be equal to a List<byte[]>


I think it's more that a LinkedList<Foo> may be equal to an
ArrayList<Foo>. I expect sets are even more flexible, comparing equal
no matter what order the objects are in too.

> +1 (and in spades).
>
> And +1 again.


What's this -- an obscure way of saying "I agree" or "Seconded"? You do
realize it is possible to take conciseness *too* far?

  Reply With Quote
Old 06-21-2006, 09:40 PM   #9
Chris Smith
 
Posts: n/a
Default Re: instanceof NOT (always) bad? The instanceof myth.

Twisted <> wrote:
> Chris Uppal wrote:
> > +1 (and in spades).
> >
> > And +1 again.

>
> What's this -- an obscure way of saying "I agree" or "Seconded"? You do
> realize it is possible to take conciseness *too* far?


It is a means of expressing agreement.

I believe it originated (at least I first saw it) in open-source
software project practices. In that setting, it's an official voting
mechanism: someone makes a suggestion about a course of action on the
project mailing list, and any active developers (often, committers) for
the project may post +1 or -1 or 0, and the votes are all tallied at the
end to see whether the vote passed or failed.

I doubt it is used merely for conciseness; it's a sort of cultural
heritage thing, as well.

--
Chris Smith - Lead Software Developer / Technical Trainer
MindIQ Corporation
  Reply With Quote
Old 06-21-2006, 10:06 PM   #10
Timo Stamm
 
Posts: n/a
Default Re: instanceof NOT (always) bad? The instanceof myth.

Chris Smith schrieb:
> Twisted <> wrote:
>> Chris Uppal wrote:
>>> +1 (and in spades).
>>>
>>> And +1 again.

>> What's this -- an obscure way of saying "I agree" or "Seconded"? You do
>> realize it is possible to take conciseness *too* far?

>
> It is a means of expressing agreement.
>
> I believe it originated (at least I first saw it) in open-source
> software project practices. In that setting, it's an official voting
> mechanism: someone makes a suggestion about a course of action on the
> project mailing list, and any active developers (often, committers) for
> the project may post +1 or -1 or 0, and the votes are all tallied at the
> end to see whether the vote passed or failed.
>
> I doubt it is used merely for conciseness;


If you call for votes on a topic and receive hundreds of replies, the
conciseness of +1/-1 is very useful. It is much easier to count
occurrences of "+1" instead of having to consider dozens of variants of
the expression of agreement. It also helps to keep a voting thread from
trailing off.


Timo
  Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off

Similar Threads
Thread Thread Starter Forum Replies Last Post
Debunking the myth of DVD rot Smaug69 DVD Video 15 08-22-2004 01:16 PM
Walt Disney: The Man Behind the Myth DVD - any good online prices? Mark DVD Video 0 04-13-2004 05:09 AM
Walt: The Man Behind the Myth DVD - over $20 everywhere? John DVD Video 0 04-08-2004 02:52 PM




SEO by vBSEO 3.3.2 ©2009, Crawlability, Inc.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47