If you need to find out the type of object then you aren't using
generics properly, or you should learn (as I did recently!) about the
Visitor pattern.
An example of not using generics properly:
E.g.: List<Object> objects=new ArrayList<Object>();
objects.add("blah");
System.out.println((String)objects.get(0)).length());
Of course, String and Object could be any subtype and supertype.
The reason this is bad is that I would be better off using List<String>
strings=new ArrayList<String>();, then I *know* it's a String.
An example where the Visitor pattern might be more useful:
interface Supertype
{
}
final class Subtype implements Supertype
{
}
final class Subtype2 implements Supertype
{
}
List<Supertype> objects=new List<Supertype>();
objects.add(new Subtype());
objects.add(new Subtype2());
Supertype object=objects.get((int)(Math.random()*2)); //pick an element
at random.
if (object instanceof Subtype)
System.out.println("Yo, dude, it's the first one!");
else
System.out.println("Must be the second.");
I would change this to use the Visitor pattern, which at first glance
is more verbose, but you get used to it. I'm still getting used to it.
final class Visitor
{
public void visit(Subtype subtype)
{
System.out.println("Must be the first.");
}
public void visit(Subtype2 subtype2)
{
System.out.println("Must be the second.");
}
}
interface Supertype
{
void accept(Visitor visitor);
}
final class Subtype implements Supertype
{
void accept(Visitor visitor)
{
visitor.visit(this); //calls the first method in Visitor.
}
}
final class Subtype2 implements Supertype
{
void accept(Visitor visitor)
{
visitor.visit(this); //calls the second method in Visitor.
}
}
Then:
List<Supertype> objects=new List<Supertype>();
objects.add(new Subtype());
objects.add(new Subtype2());
Supertype object=objects.get((int)(Math.random()*2)); //pick an element
at random.
object.accept(new Visitor());
Look, no casts! No instanceof either. Just polymorphic goodness.
I will readily admit that I am not completely comfortable with this,
I'm trying it out on some of my code, but I can see immediately that it
will stop me from writing an error-prone if..else tree (one error is
simply to miss out a subtype). If it prevents bugs, I'm happy.