cast byte to enum

15,196

Solution 1

Your most effective solution would be to pass messages back and forth with an ObjectOutputStream. This is good for a number of reasons.

  1. Built in enum serialization
  2. Extendability to more complex message passing is smoother
  3. The ability to pass in callbacks and parameters is baked in as well!

Solution 2

You're probably thinking of enum as something like we have in c/C++ or C#, which is basically a syntax sugar for declaring constants.

Java's enum is a completely different beast though... It is a built-in implementation of the Typesafe Enum pattern. Since it is strongly typed, it is not possible to directly cast a enum from a byte, or even from an integer.

But all enums are complete classes in Java, so nothing stops you from implementing an additional method that does that conversion for you.

Hope it helps.

Edit: Again, I'm not a Java programmer, but I guess something like this would work:

public enum PortableTypes {
    Boolean,
    Type2,
    Type3;

    public static PortableTypes convert(byte value) {
        return PortableTypes.values()[value];
    }        
};

public void testConversion() {
    byte b = 5;
    PortableTypes type = PortableTypes.convert(b);
}

Let me know if it works.

Solution 3

Java enums have ordinals to help you out.

To get from a constant to a number, call WHATEVER.ordinal(). It returns the index of the constant in the declaration order. So, for:

enum Underwear { BRIEFS, BOXERS };

Underwear.BRIEFS.ordinal() is 0, and Underwear.BOXERS.ordinal() is 1.

To get from a number to the enum object, call values() and index the returned array.

The horse's mouth here is: http://download.oracle.com/javase/6/docs/api/java/lang/Enum.html

Solution 4

Or write a static getter method:

PortableTypes.get(b);

public static PortableTypes get(byte b) {
  return PortableTypes.values()[b];
}

Solution 5

An enum is designated a type (though it defaults to a value of int usually in persistence etc...) it actually has a type. The bigger question is why you want to cast it as I would file it under "Bad practice" generally. Strong typing is a major advantage of modern languages.

If you just need a byte value read up on enum design patterns in Java.

If you need the value you can do something like:

enum SomeEnum
{
    a((byte)0x01),
    b((byte)0x02),
    c((byte)0x03),
    d((byte)0x04);

    byte byteVal;

    SomeEnum(byte b)
    {
      byteVal = b;
    }

    //Continued long winded example
    public MyNum replacementValueOf(byte b)
    {
      for(MyNum num : MyNum.values())
        if(b == num.getByte())
          return num;
      throw new RuntimeException("Your byte " + b + " was not a backing value for MyNum.");
    }
}

I was giving an in-depth answer, but I agree with the posts above, rethink the design pattern.

Share:
15,196
Darkhydro
Author by

Darkhydro

My favorite language is C#, especially in conjunction with XNA, which I use to create games in my free time. I use Java as well on a fairly regular basis, and have a good amount of experience in C/C++. My areas of interest are networking, engine creation, AI, and gameplay. I am currently working on my M.S. in Computer Science.

Updated on June 04, 2022

Comments

  • Darkhydro
    Darkhydro almost 2 years

    I have the following code:

    
    public enum PortableTypes { Boolean, etc...};
    
    public void testConversion() {
      byte b = 5;
      PortableTypes type = (PortableTypes)b;
    }
    

    When I compile, I am told that these are inconvertible types. I was unaware that something as simple as this would be left out of java. Am I missing something, or does Java just not support casting into an enum at all? I tested with an int as well, and it failed.

    If this is not supported, what is the easiest workaround?

    EDIT:

    Since everyone keeps complaining about "bad design", I'll explain a little further. I am using an enum to represent the types that you can send using my TcpServer. The packet is sent with this type, and on the receiving side I look at the type and use it to convert the bytes that are read from the packet into usable data. Obviously you can't send an enum using an OutputStream, so I need to convert the enum value into a numerical value to be sent. I disagree with the idea that this is "bad design", I think that Enums are indeed supposed to be used for exactly this purpose, but that this design does not work in Java because it is strongly typed.

  • Darkhydro
    Darkhydro about 13 years
    @Patrick seriously? I do this all the time in C#. Why would this be a problem? Enums are just like a collection of static final integers but with their own type. The reason I do this is I need to send the type as an int.
  • Darkhydro
    Darkhydro about 13 years
    is there a workaround for this then, or do i have to declare a bunch of static final integers...?
  • rsenna
    rsenna about 13 years
    @Darkhydro: see my answer - I'm a C# programmer too, but AFAIK the Java's enum is in fact much superior to the C# implementation.
  • Artem
    Artem about 13 years
    Kind of a long-winded replacement for ordinal().
  • Artem
    Artem about 13 years
    Kind of a long-winded replacement for PortableTypes.values()[b].
  • Artem
    Artem about 13 years
    What's wrong with values() and ordinal(). That's why there are there.
  • Darkhydro
    Darkhydro about 13 years
    @Daniel how would i rewrite the sample code in my question using this new Enum?
  • Beez
    Beez about 13 years
    Long-winded, maybe. But more object-oriented, no?
  • Artem
    Artem about 13 years
    Well, we could debate that all day. Point taken. He could do the same sort of OO wrapping in his native C# after all.
  • Darkhydro
    Darkhydro about 13 years
    @bmargulies what is ordinal() and what does it do?
  • Darkhydro
    Darkhydro about 13 years
    what is ordinal() and what does it do? and what is the type of WHATEVER? I didn't see this method in the enum or the constant
  • Jon Skeet
    Jon Skeet about 13 years
    @Darkhydro: "Enums are just like a collection of static final integers but with their own type." - In C#, yes. Not in Java.
  • corsiKa
    corsiKa about 13 years
    @bmargulies Ordinal is discouraged because the order of declaration breaks code (silently.)
  • Patrick
    Patrick about 13 years
    @Darkhydro "Enums are just like a collection of static final integers". Ultimately, all of this is just a collection of 0 and 1 in the memory. But data types were invented precisely to prevent this confusion.
  • Artem
    Artem about 13 years
    Just like in C and C++. If your purpose in life is to assign names to numbers starting with 0, it's perfectly fine.
  • Artem
    Artem about 13 years
    Java gives you a .ordinal() method on every one of the enum items. If you add more methods to your enum (as per other answers here) they also appear in the same place.
  • user unknown
    user unknown about 13 years
    PortableTypes.java:10: ordinal has private access in java.lang.Enum if(t.ordinal == (int)b) t.ordinal () will do it.
  • Chad La Guardia
    Chad La Guardia about 13 years
    Thanks, fixed. Although, i should mention don't use this as there are better solutions already posted haha.
  • Jesper
    Jesper about 13 years
    Your fromByte method should be static.
  • Darkhydro
    Darkhydro about 13 years
    @Daniel I tried this solution, but i still couldn't cast a byte value into my enum, and i couldn't use the constructor (it was private). otherwise this would be my favorite answer.
  • Darkhydro
    Darkhydro about 13 years
    thanks for posting this. Definitely the best solution. This class is really powerful glad you introduced me to it.
  • corsiKa
    corsiKa about 13 years
    @Darkhydro no problem. I ran into the same problem three weeks ago trying to pass Strings and bytes and all kinds of stuff over a socket. Each message type was different, I had all kinds of switch cases going on. Now I have an abstract Message class and I just go Message m = in.readObject(); m.performCallback(engine);` and it just works. It just works. Right out of the box. No fancy setup or nothin'.
  • corsiKa
    corsiKa about 13 years
    @Darkhydro Consider reading up on stackoverflow.com/questions/5453522/… It's a question I asked that handled some of the basics, and it was very informative for me.
  • Paŭlo Ebermann
    Paŭlo Ebermann about 13 years
    @Darkhydro: .ordinal() simply is its sequence number in the declaration order. The other direction goes with EnumType.values()[i].
  • Darkhydro
    Darkhydro about 13 years
    yeah that makes a lot of sense. its pretty cool that it works so easily. like 3 lines of code. Also it would work with polymorphism right? so i could just have the same method for all sub-classes of my base object and it'll choose the right method based on what class is actually read in
  • corsiKa
    corsiKa about 13 years
    @Darkhydro That's exactly right. My question was originally about "How do I determine the type?" and the answer is "As long as you know its parent type (the only type you send across) you don't need to know its real type." I was a happy dev that day. :)
  • Daniel B. Chapman
    Daniel B. Chapman about 13 years
    @Darkhydro you can't cast it (they are actually a type) if you want to use it you would need to add a method like "public static SomeEnum getValue(byte b);" which is why I suggested rethinking the design pattern, you can look above and see the example. For what you're doing the ordinal approach is really a better way to hand it. However, it is terrible for maintenance which is why I tend to do the above (glowcoder alludes to this).
  • Daniel B. Chapman
    Daniel B. Chapman about 13 years
    @Darkhyrdo after reading your comments above, yes what I'm doing above is probably the most maintainable design. You want to make sure that packet uses the same information on both sides and that it remains static. While valueOf(int i) will work via a & 0x000000FF to get your byte, if you have more than 0xFF states or you change the order it is a problem. Alternatively, if it is all runtime just (byte)(Enum.VALUE.ordinal() & 0xFF) -> to the server and Enum.valueOf((int)(packetByte & 0xFF) for the return.