Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Is there some syntax (other than a series of if statements) that allows for the use of a switch statement in Java to check if an object is an instanceof a class? I.e., something like this:

switch (object) {
     case instanceof SecondObject:
        break;
     case instanceof ThirdObject:
        break;
}

Sidenote: I recognize that as a design pattern, checking against instanceof and making decisions based on it is not as preferable as using inheritance. To give some context why this would be useful to me, here's my situation:

I'm working on a project that involves a kryonet client/server. For communication over KryoNet, you pass objects that it serializes using kryo. Anything added to the object increases the size of these packets,1 so to minimize the network traffic, you keep these objects as light weight as possible. When you receive a packet, you need to know what to do with it, so I'm making this determination based on what type of packet object the passed object is an instanceof. This approach is the same undertaken in the examples included with Kryonet's distribution. I'd love to clean up the hideous class that translates these packets into action, and figure a switch statement would at least make it look moderately more organized.


1As I wrote the statement above, I had doubts about whether what I was saying was accurate. The answer below seems to disagree:

Methods don't add anything to the runtime size of an object. The method code is not transmitted, and nothing about the methods requires any representation in an object's state. This is not a sound reason for instanceof testing, etc.

I guess the real issue is I don't know what happens under the hood for Kryo to serialize an object and I was nervous to do anything that increased the bandwidth. Your answers have inspired me to do it with inheritance and add the appropriate methods to the objects. So thank you!

share|improve this question
    
Whatever you intend to do before each break violates the LSP. –  user61852 Feb 20 '13 at 20:26

3 Answers 3

up vote 13 down vote accepted

The answer is no.

But using Java 7 you could do this:

switch (object.getClass().getName()) {
  case "some.pkg.SecondObject":
    break;
  case "some.pkg.ThirdObject":
    break;
}

... which is not exactly the same, but may be close enough.

The problem is that this is "code smell", whether you do it using if ... instanceof tests or the switch hackery above.

Why?

Because any time you add a new class, you need to revisit all of the places where you do this class testing!! And there is the added problem that the code breaks if you rename the classes.

The recommended OO approach is to use polymorphism.

Anything added to the object increases the size of these packets, so to minimize the network traffic, you keep these objects as light weight as possible.

Methods don't add anything to the runtime size of an object. The method code is not transmitted, and nothing about the methods requires any representation in an object's state. This is not a sound reason for instanceof testing, etc.

share|improve this answer
2  
+1 for mentioning tests and pointing towards polymorphism. –  mri Feb 20 '13 at 9:43
1  
I would just like to point out that it might be a better solution to compare not against a concrete string, but against SampleType.class.getName(), as the second would survive an automatic refactoring. Not that I approve this practice... –  K.Steff Feb 21 '13 at 2:13
1  
@K.Steff - That would not work. The strings in a Java 7 string switch need to be compile time constants ... in the sense defined by the JLS. –  Stephen C Feb 21 '13 at 13:29
    
@StephenC Sorry, my bad. This makes it one more argument against this practice. –  K.Steff Feb 21 '13 at 16:34

No, and it's very unlikely that such a thing will be added.

You see, checking for the type of an Object and then doing different things for different types is considered terribly inelegant, because there already is a much better pattern for doing that: using inheritance and overridden methods. (Granted, that's only of use when the "do something" can be formulated as a method call on the checked Object, but usually it can.)

share|improve this answer
    
revised my question to add some additional background on why I'd be doing it this way in the first place. –  Cameron Fredman Feb 20 '13 at 9:05

In Java, it's only possible to switch on primitives. But you could do something similar.
I think it's some kind of design pattern though I could not find it...

You could hide the if-then-else stuff (which is needed in this case) and wrap it in a kind of switch-class:

public abstract MySwitch{
    public MySwitch(MyObject obj){

        if (obj instanceof SecondObject)
            secondObject((SecondObject)obj);
        else if (obj instanceof ThirdObject)
            thirdObject((ThirdObject)obj);
        else
            onDefault(obj);
    }

    protected abstract void secondObject(SecondObject obj);
    protected abstract void thirdObject(ThirdObject obj);
    protected abstract void onDefault(MyObject obj);
}

You could use it then like this in your code:

new MySwitch(obj){

    @Override protected void secondObject(SecondObject obj){

    }
    @Override protected void thirdObject(ThirdObject obj){

    }
    @Override protected void onDefault(MyObject obj){

    }
};

Just be aware that normally, calling abstract methods from constructor is a bad idea... I think, in this case, it could be OK, because this is and always will be a stateless class. If you don't like it, add an additional method to do the stuff.

This also has the advantage that if you add new classes to your inheritance tree and add a new case, you are forced to update all occurrences and don't forget a switch somewhere.

share|improve this answer
    
Very cool solution. –  Cameron Fredman Feb 20 '13 at 10:14

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.