aspose file tools*
The moose likes Beginning Java and the fly likes Defining a Constant Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "Defining a Constant" Watch "Defining a Constant" New topic
Author

Defining a Constant

Roger F. Gay
Ranch Hand

Joined: Feb 16, 2007
Posts: 399
As a JavaScript guy, I was a bit taken aback that I can't use strings in Java as switch-case argments and case elements. So I'm trying to do it anyway (sort of); by converting strings to hashCode() and using the resulting integer value. Let's say for example that I want to do something if I encounter a String.

OK. So that works. My question, as the title suggests, is about defining constants. So far, the only way I can make this work is by defining STRING with the integer constant value as above. What I worry about - without knowing how likely it is - is that some day the Java gurus will decide to change their algorithm for determining hash code values. I realize that I could create my own hashCode() method, but feel like it's bad practice to go around re-writing methods that are built into the language already.

What I would rather do is initialize STRING in the same way that I calculate the value of the argument. For example;

Doing it this particular way produces an error that the case descriptor STRING must be a constant rather than a variable.

So, my question is about creating a constant. Is there a way to set it's value within my method from the result of calling hashCode()?


Correlation does not prove causality.
marc weber
Sheriff

Joined: Aug 31, 2004
Posts: 11343

I think you should consider using enums, which work in switch/case statements.


"We're kind of on the level of crossword puzzle writers... And no one ever goes to them and gives them an award." ~Joe Strummer
sscce.org
Roger F. Gay
Ranch Hand

Joined: Feb 16, 2007
Posts: 399
That doesn't really seem to solve my problem. If I understand ENUM well enough, it simply gives me incremental integer values starting with 1. But the value of "String" for example, is not equal to 1 or 2 or ....

I know that I can come up with another way to relate strings to integers. But it would be nice to use one built in function to do that for me. I just get tired of too many extra fuctions doing little loops or lists of ifs etc. (such as if (theType.equals("String")) tval = 1; ...)

Perhaps I just don't understand the power of enums well enough. Is there a way to apply them that makes this more automatic?
[ August 03, 2007: Message edited by: Roger F. Gay ]
Roger F. Gay
Ranch Hand

Joined: Feb 16, 2007
Posts: 399
OK, wait a sec.

I'm not sure the declaration is right; but do you mean that I can do something like this (doing it right eventually), and STRING and INT can be used as case ids?


[ August 03, 2007: Message edited by: Roger F. Gay ]
[ August 03, 2007: Message edited by: Roger F. Gay ]
marc weber
Sheriff

Joined: Aug 31, 2004
Posts: 11343

Originally posted by Roger F. Gay:
... But the value of "String" for example, is not equal to 1 or 2 or...

Maybe I'm not understanding your requirements. I didn't think that your int values mattered, as long as they worked as tags for identification and for use in a switch/case statement. So my thought was to use enums instead of hashcodes. But if you need to assign particular values, one option might be adding that to your enum definition...

[ August 03, 2007: Message edited by: marc weber ]
Roger F. Gay
Ranch Hand

Joined: Feb 16, 2007
Posts: 399
�'m not following you. Your example seems to return to the use of explicit use of integer values in the declaration of the enum - exactly what I was trying to avoid. See example in first post using static final ...
marc weber
Sheriff

Joined: Aug 31, 2004
Posts: 11343

Originally posted by Roger F. Gay:
OK, wait a sec.

I'm not sure the declaration is right; but do you mean that I can do something like this (doing it right eventually), and STRING and INT can be used as case ids? ...

That might be one approach. This looks like it's patterned after the Card example in the enums page I linked to above.

Another approach might like the one I posted above, which is based on the Planet example from the same enums page.

The fundamental difference is that a Card HAS-AN enum Rank and HAS-AN an enum Suit. But a Planet IS-AN Enum that HAS its own members.
Remko Strating
Ranch Hand

Joined: Dec 28, 2006
Posts: 893
I don't know exactly what you're trying the solve but don't forget that different strings can have the same hashcode. So your solution can have some unexpected behavior.

Reading your code i would propose to use enums which the other members already said to you. I thought the enums where created to solve the kind of problem you have.


Remko (My website)
SCJP 1.5, SCWCD 1.4, SCDJWS 1.4, SCBCD 1.5, ITIL(Manager), Prince2(Practitioner), Reading/ gaining experience for SCEA,
marc weber
Sheriff

Joined: Aug 31, 2004
Posts: 11343

Originally posted by Roger F. Gay:
�'m not following you. Your example seems to return to the use of explicit use of integer values in the declaration of the enum - exactly what I was trying to avoid. See example in first post using static final ...

Hmmm... Then I'm not following.

What exactly are your int values for?
Roger F. Gay
Ranch Hand

Joined: Feb 16, 2007
Posts: 399
I built a socket server that receives objects of various kinds. The first thing the handler does is check to see what type of object it is. The class name (could be String for example) goes into the switch.

Nothing to it in JavaScript (which is more my native language). Could have just :


Of course I could;

But I prefer switch-case and decided to see if I could learn something about defining constants instead of avoiding the problem I've gotten myself into.
[ August 03, 2007: Message edited by: Roger F. Gay ]
marc weber
Sheriff

Joined: Aug 31, 2004
Posts: 11343

Originally posted by Remko Strating:
I don't know exactly what you're trying the solve but don't forget that different strings can have the same hashcode. So your solution can have some unexpected behavior...

That's a good point. Objects that are equal should return the same hashCode, but objects that are unequal are not required to return different hashCodes.

So if enums aren't the answer, an alternative to hashCode needs to be found as well.
Roger F. Gay
Ranch Hand

Joined: Feb 16, 2007
Posts: 399
I've looked at the algorithm currently used in java's hashCode() method. I'm pretty sure it will do for the relatively small number of types I'll be processing. I suppose it could grow to 20 - that would be a rather large number of classes to define for this application. But that's a very small number in relation to the big numbers generated by the algorithm.

Besides ... it's not too much to check all 20 or so to make sure that no conflicts are produced by the current algorithm.
marc weber
Sheriff

Joined: Aug 31, 2004
Posts: 11343

Originally posted by Roger F. Gay:
I built a socket server that receives objects of various kinds. The first thing the handler does is check to see what type of object it is. The class name (could be String for example) goes into the switch...

Okay. In that case, I think using a series of if/else statements is the best approach.
Garrett Rowe
Ranch Hand

Joined: Jan 17, 2006
Posts: 1296
Or maybe you could use a Map<String, Strategy> where a Strategy is just an interface with a doSomething() like method that may or may not return a value:



or



Some problems are so complex that you have to be highly intelligent and well informed just to be undecided about them. - Laurence J. Peter
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
Garrett's solution is one I use often ... perhaps even when I shouldn't, but let's ignore that for now. Your method would look something like:

This is nice if you have a lot of types or you might add, change and remove them often. You can load the map from configuration and never touch this method again. Code that is closed for modification but open to extension is A Good Thing.


A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
Roger F. Gay
Ranch Hand

Joined: Feb 16, 2007
Posts: 399
Fantastic. If I use mapping, I'll probably end up better understanding its mysteries. I first ran across it in an RMI tutorial; where the following is in the "compute engine"

and asked a friend of mine - What the heck is an html-tag-looking thing doing in the Java code? Nice approach. I'm definitely going to try this one. Very nice to understand that Java can handle processing an arbitrary type. Cool!

Back to defining constants for a moment. I thought defining a variable as final means that its value becomes final once it's set. So, I didn't think that there would be a difference between:

But the first VAL1 works in switch-case ( i.e. case VAL1: ) but the second does not. Apparently, Java keeps track of how the final value was born; and accepts 10 as a constant, but not the result of myFunc, even though VAL1 is final.
[ August 04, 2007: Message edited by: Roger F. Gay ]
Roger F. Gay
Ranch Hand

Joined: Feb 16, 2007
Posts: 399
And - back to mapping. This is pretty cool, so I might learn to over-use it as well. While I'm boot-strapping (learning and building a real application at the same time), I end up with a bunch of things that would be very interesting to dive into and learn more about. In the interest of prioritizing for efficiency, I'd like to see if this approach is going to work in my application.

Stan's example and the RMI tutorial example both execute the object. (And in the RMI example, there must be an exact duplicate of the object already on the machine.) I may very well pass self-executing objects in a later phase of the project - giving actual new instructions and coding to the recipient application. But at the moment, the objects being passed just contain data. (One possible form is an xml document. Another is a String. But it can be useful to pass Java objects defined in classes either with simple data lists or even with their own get and set methods.)

So in this phase, the objects themselves are not executable. They just contain data, and it's up to the handler rather than the data object to do the processing. (Although as an aside, I'm starting to think that at least the self-created Java objects could instantiate their own handlers when executed - maybe later.)

Given this explanation, do you still think mapping is a useful approach? If so, would you provide a short orienting example. How do I use mapping to say (as a simple example) - IF this is a String: System.out.println(theString);
[ August 04, 2007: Message edited by: Roger F. Gay ]
Roger F. Gay
Ranch Hand

Joined: Feb 16, 2007
Posts: 399
Wildly, but perhaps logically - can you use overloading with mapping? Something in the neighborhood of:

Oh - meeoh myooh! Is overloading the answer I seek?


Perhaps you can see why I'm posting to the Java beginner's discussion thread.
[ August 04, 2007: Message edited by: Roger F. Gay ]
Roger F. Gay
Ranch Hand

Joined: Feb 16, 2007
Posts: 399
No. The simple overloading approach doesn't work. The objects are passed in as Object types, and don't know what specific type they are until properly cast to a specific type. So, that brings me back to where I started. I think I found this out through trial and error some time ago, when I first approached this - which led to a variety of attempts to solve it.

For the moment, unless there's something nicer to do with mapping, I think I'll just:

I guess I'd rather - if possible - have some way to do this through declarations. It just seems easier to maintain.

I could then define constants for STRING, DOCUMENT using enum.

But here's the question (from ** see question below ** in the code). Is there a way that I can cast directly to the right object type at that point in the code? This is a beginner's question. At my level of knowledge, what I'm asking for seems like a dream rather than something I've ever seen in the Java language. But what I'd like to do is something like:


where "(processType[0][i])" casts "theType" to it's type. I'm just looking for a generic way to cast to the proper type so that overloading works. For example, can I (evol(processType[0][1]))? (evol - evaluate - is intentionally misspelled so that that post is accepted.)

Searching and thinking and editing post ---

Maybe the Java cast command is a candidate?
http://tcl.tk/man/java1.2.6/TclJava/JavaCastCmd.html
[ August 04, 2007: Message edited by: Roger F. Gay ]
Roger F. Gay
Ranch Hand

Joined: Feb 16, 2007
Posts: 399
just a side note


is more compact / direct than what I wrote above.
Roger F. Gay
Ranch Hand

Joined: Feb 16, 2007
Posts: 399
And back to mapping I guess:

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#cast(java.lang.Object)

I can't see how to use it though. The output of the cast method is presumably an object of the type object that's been sent. But that means I would have to know that already.



Oh but wait. Why do I constantly want to do something other than overloading? If I understand the cast method, I could:



I'll try that, but I don't really know the cast method. Trial and error approach.
[ August 04, 2007: Message edited by: Roger F. Gay ]
Roger F. Gay
Ranch Hand

Joined: Feb 16, 2007
Posts: 399
It seems like the following should work:

rtm.getClass().getName() properly returns the name of the class (not Object, which is how it is transported; but the original type)

In other words, if the original object was a String, rtm.getClass().getName() returns the String "String"

But when I use rtm.getClass().cast(rtm) - I just get into an infinite loop. I can see that it doesn't quite make sense. I'm asking for the current class of rtm, in order to cast rtm to something. I was just encouraged because rtm.getClass.getName() works.

So now I'm starting to think about a for loop comparing the name and fetching an object of the corresponding type in order to use the cast method. I don't know. But it just seems like there should be a simple approach to this. Maybe I'm closing in (and maybe I'm not).
[ August 04, 2007: Message edited by: Roger F. Gay ]
Roger F. Gay
Ranch Hand

Joined: Feb 16, 2007
Posts: 399
If I have to have a for loop, then I have to have one. Wish I could do without. But the following produces a null pointer exception; apparently for processClass[i].getClass().getName()



edit: (I love to explain things to others. So many things suddenly become clear to me.)
Perhaps it's because:

[ August 04, 2007: Message edited by: Roger F. Gay ]
Roger F. Gay
Ranch Hand

Joined: Feb 16, 2007
Posts: 399
OK. It works so long as rtd, cm, and str are not null objects.

Still - would be nice to do this without a loop. It just seems so close at this point. But maybe this is the most compact, easily maintainable way to do it?

I'm especially irritated by this approach because it requires creating objects that are not used.
[ August 04, 2007: Message edited by: Roger F. Gay ]
Garrett Rowe
Ranch Hand

Joined: Jan 17, 2006
Posts: 1296
I'm not exactly sure what you are trying to do, but here's a small example of what I was suggesting:

Obviously you should replace the dummy implementations of StringStrategy.execute() and DocumentStrategy.execute() with more meaningful implementations.

Is this helpful or just more noise?
Roger F. Gay
Ranch Hand

Joined: Feb 16, 2007
Posts: 399
Garrett;

I guarantee that was extremely helpful. I didn't know how to implement a strategy before. I've posted to the beginner's forum because - despite many years programming experience - I'm fairly new to Java, and even got cheated out of OO experience for many years. I'm trying to catch up.

I'll look at it more carefully this evening. Right now I'm so hungry it's getting a bit hard to think.
Andrew Monkhouse
author and jackaroo
Marshal Commander

Joined: Mar 28, 2003
Posts: 11525
    
100

I agree that the strategy pattern is almost certainly better than using a case statement, but I thought I'd see how I could implement it based on my understanding of Roger's requirements:And the output:As a side note, one of the interview questions I frequently use can be easily solved using an if..else statement or a case statement - my challenge to candidates is to find some other way of handling it, and the strategy pattern is almost always where we end up.

Regards, Andrew


The Sun Certified Java Developer Exam with J2SE 5: paper version from Amazon, PDF from Apress, Online reference: Books 24x7 Personal blog
Roger F. Gay
Ranch Hand

Joined: Feb 16, 2007
Posts: 399
Thanks Andrew. That indeed solves my switch-case problem, with enums no less. Interesting comment about your interviews. I'm kind of hoping I'll never need to seek another job - but one never knows.
Roger F. Gay
Ranch Hand

Joined: Feb 16, 2007
Posts: 399
Garrett;

I've traced through the logic of your example. Everything is there. I've even been helped a little by the Wikipedia entry for Strategy pattern.

It still seems a bit strange to me. Do you have a suggestion for the best introductory tutorial on Maps / Strategy you've ever seen?
marc weber
Sheriff

Joined: Aug 31, 2004
Posts: 11343

Originally posted by Roger F. Gay:
Thanks Andrew. That indeed solves my switch-case problem, with enums no less...

Whew... At least I'm somewhat vindicated (although I should have asked for more background before going down that road).
Roger F. Gay
Ranch Hand

Joined: Feb 16, 2007
Posts: 399
Thanks marc. I know it can be a tricky business getting involved in a beginners discussion. Among the tricky bits are occassional delays between the demonstration of a solution and - "Oh - I get it!" I'm sure that seeing clearly the second time was predicated on looking and thinking about it once before.

I started out the weekend feeling a bit frustrated. The application concept I'm working on is quite interesting. But the problem I expressed in this thread (and one in intermediate) was making me wonder if could make sufficient progress in a reasonable amount of time. I've learned a lot through these discussions - broadened my knowledge and deepened my understanding of Java, and even have a new list in mind of other things I need to learn. The bit I felt stuck on is no longer a problem. "I get it!"

Much appreciated.
Roger F. Gay
Ranch Hand

Joined: Feb 16, 2007
Posts: 399
Garrett;

First order of business this morning, after email and forum check: I ran your example. I suppose I didn't yesterday, because sometimes forum postings are just rough sketches rather than working code. After looking at it a few times - I decided it looked like a real program and tried it.

Fantastic. It works! Seeing it work has a certain psychological effect - I get it. Thanks. I know something about Strategy now.
Roger F. Gay
Ranch Hand

Joined: Feb 16, 2007
Posts: 399
Hello World by String!
Hello World by Document!
Hello World by CommandMessage!

Last week I was thinking that I'd support only one message type through step 1 of this project and deal with different message types later. This weekend has been great. Thanks all!
Garrett Rowe
Ranch Hand

Joined: Jan 17, 2006
Posts: 1296
Seeing it work has a certain psychological effect - I get it. Thanks. I know something about Strategy now.

I'm glad to hear that you found what I wrote to be useful.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Defining a Constant