• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Constants and switch statement

 
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm new to Java and have encountered a "there's got to be a better way to do this" situation. I'm writing an app that deals with output from a device attached via serial cable. I have a small number of "commands" to deal with, all of which have a 4-letter acronym. My thought on processing these was to use a switch statement based on the hash code of the acronym. I created constants to hold the hash codes of the commands, like this:

static final int PRID="PRID".hashCode();

But Java won't let me use PRID as a case label; it says it needs a constant there. I could figure out the hash code values for the commands and hard code them in, but there's got to be a better way than that. I thought "final" told the compiler that this is a constant, no?
 
Ranch Hand
Posts: 1258
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well, unfortunately, it's not that the case can't take final variables, it's just that the case value must be what the language spec calls a "constant expression". In your case, PRID isn't a constant expression because it's a final variable whose value isn't a literal value. For example, final int PRID = 3 would work, but ... = "PRID".hashCode() won't. Sorry.

I would suggest the good ol' fashioned if ... else if ... else.

If you're interested ... constant expression.
 
author and iconoclast
Posts: 24207
46
Mac OS X Eclipse IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Jeff,

Welcome to JavaRanch!

They have to be compile-time constants, not simply variables whose values won't change. The compiler won't evaluate "hashCode()" at compile time.

If the list of commands is fairly short, use "if-else"



The more Java-like method, and the way that you'd do things the object-oriented way, would be to use polymorphism, with a Command interface and one implementation per command. You could use a Map data structure to relate the commands to the Command objects. If you're interested, I could certainly tell you more about it. In any case, for a handful of commands, the if-else is going to work just fine.
 
Jeff Allison
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for the quick reply. The if/else if/else if... is the obvious alternative, but I am loathe to go there because of the inefficiencies implied. Doing an indexOf() or startsWith() or any other string comparison method for every option seems brutal. You start doing things like putting the more likely commands early in the list. Just not elegant.

I'll probably just come up with a state machine that'll parse the incoming commands. I was trying to short-cut that process with the computed hash value, but that looks like a non-starter.

Thanks again.
 
Jeff Allison
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

The more Java-like method, and the way that you'd do things the object-oriented way, would be to use polymorphism, with a Command interface and one implementation per command. You could use a Map data structure to relate the commands to the Command objects. If you're interested, I could certainly tell you more about it. In any case, for a handful of commands, the if-else is going to work just fine.



Sure, I'm interested. There aren't many commands, but listing them all in an if-else violates my sensibilities. Plus it's always good to do things in the most natural way for the language you're using. After all, we can write FORTRAN in any language, right?

Thanks!
 
Ernest Friedman-Hill
author and iconoclast
Posts: 24207
46
Mac OS X Eclipse IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This is the basic idea. You probably will want your execute() method to take some arguments -- that's up to you. The Command object lookup will be cheap.

 
(instanceof Sidekick)
Posts: 8791
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
That's a very cool approach. When you get into large systems you'll find parts that you'd like to call done and never touch again. This core "get a request, execute a command" routine would be a nice one. If you have another class somewhere that reads a configuration file and loads the map with 4-letter-instruction and a command instance, you can add new commands without touching this class.

If this sounds interesting Google for "dependency injection" and "application assembler". If it sounds too advanced, just shove those terms way back in your brain for later reference.
 
Jeff Allison
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

This is the basic idea. You probably will want your execute() method to take some arguments -- that's up to you.



Fantastic! I have never receive such immediate and comprehensive assistance in a forum. This is exactly what I was after, only I wasn't sure how to get there.

I do get a warning from the compiler about unchedked or unsafe operations. I am guessing that is due to the cast from the generic object stored in the HashMap to the specific Commands object that I need. I'm ignoring that for now as the code works.

Thanks again, I very much appreciate the help.
 
Ranch Hand
Posts: 3061
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The ideas presented in Ernest's post above are an implementation of a Design Pattern. Design Patterns are basically outlines of solutions to commonly found problems. In particular, I think this is called the Command Pattern. There are many generic design patterns as well as some that are specific to certain domains of problems (such as database or web programming). If you are interested in learning more about this fascinating (and useful) topic, I hope this post gives you some keywords that you can google for.

Layne
 
Jeff Allison
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

In particular, I think this is called the Command Pattern.



And in C you'd just use an array of function pointers to implement it. My problem is getting away from C language thinking and into Java thinking. Looks like this forum will be helpful in that regard.
 
Ernest Friedman-Hill
author and iconoclast
Posts: 24207
46
Mac OS X Eclipse IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This is indeed a great place. I stopped in one day for a drink, and never left...

But yeah, this is just like a dispatch table in C, and yes, the Patterns folks call this the Command Pattern.

The message about unsafe operations leads me to believe you're using the new Java 5, which has generic types. In Java 5 (which I haven't used extensively myself, yet) you can say



with no cast, and no warning.
 
Jeff Allison
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

The message about unsafe operations leads me to believe you're using the new Java 5, which has generic types. In Java 5 (which I haven't used extensively myself, yet) you can say...



Bingo. That did it. The syntax is weird, but I get the gist. Thanks again.
reply
    Bookmark Topic Watch Topic
  • New Topic