Checking “instanceof” rather than value using a switch statement

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!

4

I fully realize that I am 2 years late to the party 🙂 but probably few clarifications will help other devs.

What the other answers missed to address was the mentioning of the “Kryonet” which adds additional twist to the problem: usually when kryonet is used it means that

a) the client is an android app and

b) the client is some game

If both conditions are met IMHO using the instanceof if-else sequence is the way to go.

The usual way of structuring client/server app in our case android game + “pure” java server is to use (at least) 3 projects:

  • “common” – which contains code common for the server and the client, most importantly all the message classes (which usually implement some tag/marker interface as GameMessage).
  • server – contains the server and includes the common project. Usually all messages are simply registered in Kryonet, i.e. no pooling is used (because on server GC is not considered a problem)
  • android client – contains the android app (game) and includes the common project. Because in java games creating objects during the game may trigger the GC it is considered the biggest mortal sin (which leads straight to the hell of missed frames) it is considered good practice1 to use object pooling for the game messages (this requires little customization on the Kryonet/kryo in order to use object pools). All messages are (must be) registered in kryonet in the same order as on the server in order things to work.

First, lets look at the alternatives and see why they are not fit for the structure/implementation described above:

1. They say ‘Use polymorphism and method overriding’

Take a look here for an example of the proposed solution (accepted answer by jmg). It looks very elegant but there there are at least 2 big problems:

  1. You can’t just use parameterless overrided method like do() because in real implementation you will some need external data to act upon. For example when receiving PlayerAbandonedGame message on the server you will need at least the particular game object as parameter in order to call removePlayer(Player pl) method. NewGameState message will require reference to the particular GameState variable that will be updated and so on. One very ugly solution is overrided method to have single parameter like TheWholeThing which contains all the objects that may be needed. It is needless to say that this not only violates the principle of encapsulation but also “spreads” the game logic across multiple message classes.

  2. Remember that we have the common project and all the messages are defined there. Even if server-to-client messages are completely distinct set to client-to-server messages it will be simply stupid to put server or client logic in the common project.

Game message objects are just data containers. It is up to the server or the client to handle that data in a particular way (or even ignore it as often happens with out of order UDP messages).

2. They say ‘Use reflection’

Our context is ‘a) the client is an android app’. The reaction of every android developer hearing Use reflection should be to stand up, clear his/hers throat and with his/hers best british accent to say: ‘Are you completely mAd?!’ 🙂

Reflection is very slow on older Android versions, it is slow even now (5.0). Also IMO using reflection is the ugliest possible solution not just for this particular problem. It should be avoided up in the stack, i.e. in app dev.

Way to go

Back to the original question: if one really insist on using switch the solution is to have base class like:

public abstract class GameMessage {
    byte mCode; // not private because of kryo

    public GameMessage(byte code) {
        super();
        mCode = code;
    }

    public byte getCode() {
        return mCode;
    }
}

concrete message will look like:

public class PlayerAbandonedGame extends GameMessage {
    // some fields

    public PlayerAbandonedGame() {
        super((byte) 42);
    }
}

and then message handler will look like:

public synchronized void onMessageReceived(GameMessage msg) {
    switch(msg.getCode()) {
        case 42:
            // do something
            break;
        default:
            mLogger.error("Unknown message code {}", msg.getCode());
            // may be even throw an exception?
            break;
    }

    // ...
}

Of course it is advisable to use enum values instead of hardcoded numbers…

Potential drawback is (as mentioned in other answers) if you create new message class and forget to add it to some of the switch statements. The compiler cannot catch this problem and you will hit it only runtime (in the default case).

Real (small) drawback is that code field is send each time and adds to the traffic. In reality this adds about 1-10% to the size of the messages (if you use byte for the code field).

How I do it

I personally use if-else sequence with instanceof test like:

public synchronized void onMessageReceived(GameMessage msg) {
    if (msg instanceof MyLetterAttemptResult) {
        handleMyLetterAttemptResult((MyLetterAttemptResult) msg);
        mPools.release(msg);
    } else if (msg instanceof InAutoMatchQueue) {
        handleInAutoMatchQueue((InAutoMatchQueue) msg);
    } else if (msg instanceof AutoMatchRetry) {
        handleAutomatchRetry();
    // more else-ifs
    } else {
        mLogger.error("Unknown message {}", msg.getClass().getSimpleName());
        // throw exception may be?
    }
}

Isn’t that “code smell”? You bet it is, but after trying all other alternatives it seems to me that it is best. To reduce the smelliness it is better to try to keep code in the ifs short like above. Just call handle* method and release message back to the pool (if it is pooled).

Isn’t that slow? It is a bit slower than the switch(msg.getCode()) but not that much. Here is some benchmarking (answer by Dan Mihai Ile). Advantage is that you don’t have the code field send each time over the network. Keep the most frequently used messages at the top so they are found first.

Isn’t that error prone? There is a risk if you create new message class and forget to add corresponding else if. The thing is that you have just two separate message handling methods – one on the server and one on the client. Both are the single most important code pieces repectively on the server and the client. You will simply have to not mess it up. Just add the new message class immediately to the unit test that tests onMessageReceived().

This is not OOP! I have a better solution! I will be very happy to discuss it and use it :-). btw, I wonder if @Cameron (the author of this question) found better solution. After all this question is 2 years old…


1 For me avoiding the GC is more like “utter crap” than “best practice”. As Eonil commented in 1: I regard avoiding GC on GC based language is a kind of insane trial.

2

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.

4

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.)

1

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.

0

I think we can do in this way too:

public enum Switch {
  BED_ROOM, BATH_ROOM, LIVING_ROOM 
}

then create an interface Switchable:

public interface Switchable {
  public Switch getSwitch();
}

Then implement switches that take switch type as constrictor param:

public BedRoom implements Switchable {

  private Switch switch;

  public BedRoom(Switch switch) {
    this.switch = switch;
  }  

  public Switch getSwitch() {
    return switch;
  }

  public int getBedCapacity() {
    return 2; // implement the way your wish
  }
}

Then use like below:

Switchable switch = new BedRoom(Switch.BED_ROOM)
switch(switch.getSwitch()) {
  case BED_ROOM:
    BedRoom br = (BedRoom) switch;

    br.getBedCapacity(); // do anything with bedroom methods.
    break;
}

5

If there is a common base class, then you can add a method there returning some enum value, and override it in each subclass. So you can switch on “object.type” for example without any problems. You can add an assert at the end of the switch statement, and in some languages the compiler will warn you if you added a new type to the enum and don’t take it into account,

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật