• Post Reply Bookmark Topic Watch Topic
  • New Topic

final String tv = "abc"; As a class variable or a method variable ?  RSS feed

 
justin smythhe
Ranch Hand
Posts: 107
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
My method concatenates two strings, one never changes and the other can change.

eg. Some pseudo code

final String qMark ="?" which is used by:

method conc(String body)-
{
String ask = body + qMark;
}

Do I make qMark a private static final class variable or put it inside conc and make it a final variable ?
Which is better and why ?

 
James Boswell
Bartender
Posts: 1051
5
Chrome Eclipse IDE Hibernate
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Justin

If you have the following:



I would immediately ask why is qMark a constant? Given it's name, if you change it's value, you are going to have to change it's name as well (thus defeating the purpose of using the constant in the first place).

I see no reason why the conc method above shouldn't be defined as:

 
Praveen Kumar M K
Ranch Hand
Posts: 256
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
justin smythhe wrote:Do I make qMark a private static final class variable or put it inside conc and make it a final variable ?
Which is better and why ?


private, static and final have three varied meanings and usages. I doubt you can make any generalizations as such.
 
Stevens Miller
Bartender
Posts: 1444
30
C++ Java Netbeans IDE Windows
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@James Boswell: You make a good point about qMark and "?" being nearly transliteral, but if we were, say, discussing currency symbols and "qMark" were "cSymbol," there would be an advantage to centralizing its definition so, if it had to be changed, you could make the change to one place and see the effect everywhere cSymbol was used.

@justin smythhe: Where you define your constants is somtimes governed by the scope you want them to have. If you don't need qMark outside conc, define it in conc. If you don't need it outside Test, define it as you have. If you need it outside Test, make it public and you can refer to it as Test.qmark.

For a given application, I tend to use a very heavy-handed approch, which is to put all my constants into one class, making them all public. That may not be the most portable thing in the world, but I always know exactly where to go to change one, and exactly which class to use to get one. YMMV.
 
James Boswell
Bartender
Posts: 1051
5
Chrome Eclipse IDE Hibernate
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@ Stevens Miller
Totally agree with you about currency symbol. I'm always careful about how such constants are named to avoid the "we need to change the value, oh no, the name must change too" scenario.


The above snippet was produced by an offshore team we once worked with
 
Jesper de Jong
Java Cowboy
Sheriff
Posts: 16028
87
Android IntelliJ IDE Java Scala Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Some people think it's better to not have constants (in the form of strings or numbers) in the code directly, and use static final member variables instead for those constants. For example:

This would make code easier to read and easier to maintain; if, for some reason you'd ever want to change the value of the constant, you'd only have to do that in one place.

However, I think this only makes sense if the constant has a meaningful name that describes its purpose, which isn't the case in your example. It's obvious that QUESTION_MARK is "?" and it's never, ever going to change - if you do, you'd also want to rename the constant, otherwise it would look silly. So, making a constant for "?" only because you don't want to use literals is going too far, in my opinion.

I remember once, long ago, pulling an April Fool's prank with some of my colleagues. I was programming in C then, where you can define constants with the #define directive of the C preprocessor. We made a small program to auto-generate a file with constants, which looked like this:

Then we announced to one of the team leads that we were using this to avoid having numeric constants in the code, and that we've already replaced every numeric constant with these names. That freaked her out
 
James Boswell
Bartender
Posts: 1051
5
Chrome Eclipse IDE Hibernate
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Like it Jesper!
 
Stevens Miller
Bartender
Posts: 1444
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
James Boswell wrote:@ Stevens Miller
Totally agree with you about currency symbol. I'm always careful about how such constants are named to avoid the "we need to change the value, oh no, the name must change too" scenario.


The above snippet was produced by an offshore team we once worked with


Great example of a constant that, in effect, speaks for itself. Back in my Pascal days, I became so taken by the idea of avoiding hard-coded constants that I often said the only constants that should ever appear in a routine were 1, 0, and maybe -1. Maybe. I still tend to feel that way, more or less, but the real test is exactly what you've pointed to, James: does the constant value have an intrinsic relationship to the function it serves? If it does, it probably isn't going to change, and may well call for a name that is actually reflective of that value. If the function it serves changes, its value may change, but its name is likely to change, too, so using a named constant wouldn't do you much good. (Well, if you are using an IDE like NetBeans, which can rename all appearances of a variable for you, you might find it easier to rename a named constant than to find and change all appearances of a literal value, I suppose.)

To me, though, that tends to argue more in favor of names that describe function apart from the value those names are hiding. If you can do that, you probably should. For example, we agree about the currency symbol: makes sense to call it just that, "CURRENCY_SYMBOL," since that describes its function without committing us to what the symbol is. "QUESTION_MARK" pretty much does commit us to what the symbol is. We could force-fit a different name into the same context, like "INTERROGATORY_GLYPH," but that's only worth doing if the nature of the symbol matters more in terms of what it does than in terms of what it is. For example, in Spanish, I believe questions not only end with the "?" symbol, but they also start with a companion symbol that is the "?" rotated 180 degrees. (We don't have that symbol in English, so if my keyboard can produce it, I'd appreciate it if someone told me how. Also, I don't speak Spanish, so if I've got this wrong, let me know.) If you needed a program that could be internationalized, you might want to define "LEADING_INTERROGATORY_GLYPH" and "TRAILING_INTERROGATORY_GLYPH," even if the value of "TRAILING_INTERROGATORY_GLYPH" never changed, partly to avoid confusing anyone who had to cope with your code, and partly because, well, you never know... it might change for reasons you will learn down the road. Either way, it makes more sense to name it according to its function than according to what it is, for precisely the reason you (and others here) have identified: naming a constant after its value is, effectively, the same as using the constant itself.

Now, I could still get behind that, for a completely different reason. Consider this bit of C pre-processor code:

That certainly fails our test, since it is clearly named after the value it represents. Why would I use it? Two reasons: first, typing "PI" is a lot easier and less error-prone than typing ((double)3.14159) over and over (btw, if I were to do this in practice, I'd extend my literal value to as many decimal places as my target platforms could hold, of course), and, second, it is somewhat more self-documenting in code that is likely to need the value of pi.

My point, in the end, is that it is usually best practice to use constants in place of literals, and that our OP has actually asked his question by using an example that illustrates the exception, more than the rule. I'd hate for him or anyone reading this thread to come away thinking we were arguing in favor of hard-coded constants. When in doubt, except for 1, 0, and maybe -1, don't use them. Maybe -1. Maybe.
 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens Miller wrote:I became so taken by the idea of avoiding hard-coded constants that I often said the only constants that should ever appear in a routine were 1, 0, and maybe -1. Maybe. I still tend to feel that way, more or less, but the real test is exactly what you've pointed to

Actually, there are a few other considerations. For example:
public static final int TWO = 2;
is IMO quite different from
public static final BigInteger TWO = BigInteger.valueOf(2);
which, in addition to MINUS_ONE, is sadly lacking from the current API. I'd actually say that TEN is far less important (though not for BigDecimal).

Why? Because TWO is a constant that has very specific implications for optimization, which is quite important for a BigInteger.
Why MINUS_ONE? Because it completes the set required for any "signum"-style method or result.

With an int TWO constant, what are you gaining? There's the literal '2', which is pretty much every way identical. The only possible reason I could see for it would be in a very involved calculation where the type might be revised at some future date.

As to CURRENCY_SYMBOL, I'm not even sure that it would qualify as a constant for anything other than a class like Locale.

Winston
 
Campbell Ritchie
Marshal
Posts: 55761
163
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
For ¿ try ¿
 
Stevens Miller
Bartender
Posts: 1444
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:
As to CURRENCY_SYMBOL, I'm not even sure that it would qualify as a constant for anything other than a class like Locale.

Winston


Yeah, if you could, you'd want that kind of localization to be done at run time, not compile time, which would implicate a variable, not a constant. (Help me out, here, Winston, as I can't test this right now: can a static final be assigned once at run time?)

In a much larger sense, I think the example of a currency symbol touches upon the challenges arising from imposing a computer-language philology on a natural-language philology. We'd love to be able to map the grammar and syntax of human languages all into a kind of grand formalism that, with a few specific settings, would allow our programs all to work equally well in any of those languages. The history of the BNF notation, however, teaches us that this is a fool's errand. Human languages are not susceptible of being fully formalized (short of doing so by exhaustion; that is, by recording the entirety of a language itself). Thus, it seems it would be impossible to write a computer program that is fully independent of all natural language choices. We get around that, of course, by writing programs that have no need for being able to express themselves in either every language, nor in every way allowed for by any one language. If we know our program must print out prices, and that it will do so only in one of, say, 25 languages, and we find out that all 25 languages use [$#Z][0-9]+ (or something of that sort) for their price strings, we can get our jobs done, and to heck with any other language that alternates "%" and "~" as its currency symbol on every other use (not that I know of one, but nothing prevents that, however inconvenient it might be for us as programmers).

Of course, human beings get along with their natural languages just fine, so, in principle, a computer could do it too. Just not with anything limited to what you can do with a public static final String .
 
Stevens Miller
Bartender
Posts: 1444
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:For ¿ try ¿

Hey, thanks!

¿Cómo te enteraste de eso?
 
Campbell Ritchie
Marshal
Posts: 55761
163
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens Miller wrote: . . . ¿Cómo te enteraste de eso?
Which Google translate says means, “How did you hear about that?”

You need to know about HTML characters and Unicode numbers. I use lots of Unicode numbers, for example for “”. There are lists of HTML characters for website use, the best I know being this one. I went onto that page, used ctrl‑F‑“question” and voilà. You do need to know that & is & to write the tag by hand.

… and you’re welcome
 
Stevens Miller
Bartender
Posts: 1444
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:
Stevens Miller wrote: . . . ¿Cómo te enteraste de eso?
Which Google translate says means, “How did you hear about that?”


Heh. Since I don't speak Spanish, I used Google to translate "How did you learn that?" for me. It's always amusing to trans-translate back into the original language with that thing, and see what you get.

If you ask Google to translate this:

"Programming with references instead of pointers is like doing surgery with a spoon instead of a scalpel."

into Japanese, then translate it back into English, you get this:

"Instead Instead, programming using a reference pointer is like performing surgery with a spoon of the female."

Which, if you ever used it to speak to someone in Japanese, might give you some understanding of that expression you've left on the other person's face.
 
Campbell Ritchie
Marshal
Posts: 55761
163
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens Miller wrote: . . . If you ask Google to translate this:

"Programming with references instead of pointers is like doing surgery with a spoon instead of a scalpel."

into Japanese, then translate it back into English, . . .
Well I got the female bit, but Google has been female and changed its mind:-
 
Campbell Ritchie
Marshal
Posts: 55761
163
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
shall we get back to the official point of the discussion.
 
justin smythhe
Ranch Hand
Posts: 107
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens Miller wrote:
@justin smythhe: Where you define your constants is somtimes governed by the scope you want them to have. If you don't need qMark outside conc, define it in conc. If you don't need it outside Test, define it as you have. If you need it outside Test, make it public and you can refer to it as Test.qmark.

For a given application, I tend to use a very heavy-handed approch, which is to put all my constants into one class, making them all public. That may not be the most portable thing in the world, but I always know exactly where to go to change one, and exactly which class to use to get one. YMMV.


Why is it not portable ?

What if the method is accessed by several threads ? Is a copy of the method variables created for each thread ?
If that is the case, then a several copies of a "final variable inside a method" will be created, vs one copy for a static final class variable.
 
justin smythhe
Ranch Hand
Posts: 107
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
justin smythhe wrote:
eg. Some pseudo code

final String pi ="3.14159" which is used by:

method conc(String toppings)-
{
String fullPie = toppings + pi;
}



What if I change my question as shown in the above quotes ? Does that change anything ?
 
Stevens Miller
Bartender
Posts: 1444
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
justin smythhe wrote:
Stevens Miller wrote:
For a given application, I tend to use a very heavy-handed approch, which is to put all my constants into one class, making them all public. That may not be the most portable thing in the world, but I always know exactly where to go to change one, and exactly which class to use to get one. YMMV.


Why is it not portable ?


I may have used the wrong word. Instead of "portable," I should probably have said "reusable." If you dump all your constants into one class, then you are going to have all of those constants again in another application if it reuses that class. So, if my application has some constants set for colors that are used in displaying certain words, and it also has some constants set for prices of inventory items, any other application that wants to use my same color constants is also going to get my inventory item prices as well. The person writing that other application is free to ignore my inventory item price constants (they can even set their own in a different class, as a class effectively defines a name space that allows for each space to use the same names as any other space, with no collisions), but I may not want anyone who uses my color definitions to be able to see my price definitions. It just makes a lot more sense from a modularity point of view to group your constants into classes that are based on what the constants are for. But I'm lazy SOB, so I just pile them all up in one place and that's that. Since I work entirely alone, it's not like I run much risk of other programmers seeing something I don't want them to see.

What if the method is accessed by several threads ?


No problem. A constant is a constant. If the method defining it is accessed by multiple threads, the constant is the same in every thread.

Is a copy of the method variables created for each thread ?
If that is the case, then a several copies of a "final variable inside a method" will be created, vs one copy for a static final class variable.


I don't know how the optimizer handles this, but I would be surprised if a final variable set at compile time were created anew for each thread. Since a final variable set at compile time cannot be changed, it would not be necessary to create a new one for each entry into the method (whether those were multi-threaded entries, or single-threaded recursive entries). However, I simply would not worry about it. Unless you are dealing with huge quantities of data you are setting this way (I'm talking about megabytes, at least), you're just not going to see any performance implications in most applications, even if the compiler is ignoring some obvious opportunities to optimize (and, really, I have grown to respect the optimizer; it's quite good at what it does).

I think I should also say that writing a routine that can be called at the same time by multiple threads is often a tricky business. It's certainly possible, particularly if the routine makes no access to any state outside its own scope. But, even though you are asking a pretty sophisticated question, I suggest you avoid this issue in practice for now.
 
Stevens Miller
Bartender
Posts: 1444
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
justin smythhe wrote:
justin smythhe wrote:
eg. Some pseudo code

final String pi ="3.14159" which is used by:

method conc(String toppings)-
{
String fullPie = toppings + pi;
}



What if I change my question as shown in the above quotes ? Does that change anything ?


I think it does not change anything. The same answers and suggestions you've received here are still applicable. If pi might be used outside of conc, you've defined it in a good place. If not, defining it inside conc might be slightly better from a design point of view. From a performance point of view, I think it will make no difference where you define it.

By the way, I'd be neglectful if I didn't mention that the java.lang.Math class already provides a public static final double PI value.
 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens Miller wrote:
justin smythhe wrote:What if I change my question as shown in the above quotes ? Does that change anything ?
I think it does not change anything. The same answers and suggestions you've received here are still applicable. If pi might be used outside of conc, you've defined it in a good place.

If it might be used outside of conc he's probably defined it wrong, because it should be public (or have a public getter).
But:
@justin: The real mistake in your code is that 'pi' is NOT a String, it's a number. In fact, I'd argue that a "topping" isn't a String either, it's a Topping.
It's a really bad habit to use Strings as substitutes for other types, so I'd get out of it as soon as you can. Generally, the ONLY time you want to use Strings is when you:
(a) Display (and that's where most people use toString()).
(b) For input - in which case they should be converted immediately and discarded.

Stevens Miller wrote:but I may not want anyone who uses my color definitions to be able to see my price definitions. It just makes a lot more sense from a modularity point of view to group your constants into classes that are based on what the constants are for. But I'm lazy SOB, so I just pile them all up in one place

One problem with that approach (and of public constants in general) is that of "API leak". For example, if justin (or you) defines the constant:
public static final double PI = 3.14159;
you've just propagated an error that other people now have to live with. At least Math.PI guarantees that it's "the double value that is closer than any other to pi".

It's one of the reasons that static imports were created: so you don't have to make constants public.

Winston
 
Stevens Miller
Bartender
Posts: 1444
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:
Stevens Miller wrote:
justin smythhe wrote:What if I change my question as shown in the above quotes ? Does that change anything ?
I think it does not change anything. The same answers and suggestions you've received here are still applicable. If pi might be used outside of conc, you've defined it in a good place.

If it might be used outside of conc he's probably defined it wrong, because it should be public (or have a public getter).


But that would make it available outside the class, wouldn't? I'm thinking of the case where other methods in the same class, besides conc, might need it, but no other class's methods need it.
 
Stevens Miller
Bartender
Posts: 1444
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:
It's one of the reasons that static imports were created: so you don't have to make constants public.


Winston, would say more about that, please? I hadn't heard of static imports until your comment, so I looked them up (here's a tidy page about them). Very useful thing to know, so thanks. But I am confused by your last comment, regarding not having to make constants public. Aren't they public in the statically imported package?
 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens Miller wrote:Aren't they public in the statically imported package?

Is an imported class public? Only if it's defined as such. I suspect they can't be private; but pretty much anything else.

The argument about public constants came about as the result of designers using interfaces to define them. Basically, it was a way of avoiding typing, because all interface fields are, by default, public, static and final. The problem is that interfaces are for defining types, not constants, and usurping them simply to avoid typing a few extra characters is bad. Why?
1. It's a wolf in sheep's clothing - or vice-versa - either way, it's not what it says it is.
2. Any class can implement it as a marker interface. Why you would is questionable, but it is possible.

But the argument that really convinces me is API leakage. The definition of a public constant exposes not only its type, but also
(a) the value.
(b) something of the implementation (even if only by induction); otherwise, why did you define it?

Winston
 
Campbell Ritchie
Marshal
Posts: 55761
163
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens Miller wrote: . . . I hadn't heard of static imports until your comment, so I looked them up (here's a tidy page about them). . . .
Try this page, too, which I preferred.
 
Stevens Miller
Bartender
Posts: 1444
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:
Stevens Miller wrote: . . . I hadn't heard of static imports until your comment, so I looked them up (here's a tidy page about them). . . .
Try this page, too, which I preferred.

Good one. Great warning about that antipattern, too.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!