I am new to Java. I want to know whether there is a way to re-initialize a declared global variable as a constant later after using it as a variable ... That is because after doing some work with a declared variable I want to use it in a Switch case statement...
class A {
int x;
int y;
public static void main(String args[]) {
A a = new A();
System.out.println(a.x);
a.y = 3;
a.x = 5;
switch (a.y) {
case a.x:// Something
}
}
}
this is an example for What I need... print statement mentions, that I need to do something with variable x. later I want to use it in a Switch case statement. I don't want to use x after switch case statement... Please help me...
I want to know whether there is a way to re-initialize a declared global variable as a constant later after using it as a variable...
No, there isn't. (Java also doesn't have global variables; looking at your code, x and y are instance data members. The closest thing Java has to global variables are public static [aka "class"] data members in public classes.)
That is because after doing some work with a declared variable I want to use it in a Switch case statement...
You can't if the case values (a.x, in your case) aren't constants. Instead, you have to use if/else if/else:
class A {
int x;
int y;
public static void main(String args[]) {
A a = new A();
System.out.println(a.x);
a.y = 3;
if (a.y == a.x) {
// ...
}
else if (a.y == something_else) {
// ...
}
else {
// ...
}
}
}
No, the answer is you cannot do this in Java.
The "things" after case need to be constants.
In Java 7 or later, you can also use strings as case labels.
Switch statement Java
That is not possible. To use something as a case in a switch, it must be a constant known at compile time. If you want to set it based on a variable (i.e. at run time), there is no way it could be known at compile time.
You can only switch on compile time constants. I think what you're trying to achieve could be done with a simple if statement.
if (a.y == a.x) {
// do stuff.
}
Since constants in Java are compile time, "re-initializing" does not make sense as a concept.
In Java, when you write a switch statement, the compiler must be able to tell at compile time what the values of the case choices will be. If you want to set up a switch where one of the case choices will be a value determined at runtime--sorry, you can't. Use if statements instead.
Traditionally, switch statements (and CASE statements in other languages) were used to set up jump tables. That is, in a C program:
switch (n) {
case 1:
...code
case 2:
...code
case 14:
...code
}
The compiler would set up a table with at least 14 entries. The #1, #2, and #14 entries in the table would contain code addresses of places that it would jump to. (The others would have the address of a "default" location.) Then, the code generated by the compiler wouldn't be a series of "compare-to-1, if equal-then else compare-to-2, if equal-then else ..." kinds of instructions; instead, after making sure n was in the range of the table, it would index into the table, find the address, and jump directly there. Very efficient. Java does the same thing if you give it an integer (for Strings, it can create a jump table based on the hash code, but it still has to compare the strings for equality--thanks to #ErwinBolwidt for providing more information on this).
The point behind all this, though, is that in order to generate the table, the compiler has to know the values ahead of time. So what you're asking for isn't supported, at least in C or Java. (I think some languages do relax this and allow variable values in case, but they may all or mostly be interpreted languages.)
Related
What role do literals play in switch statements? Would it be better to use variables instead? Or how about using constants?
Usually you switch on a variable, never a literal. You use case on a literal, like this:
public void doSomething(int x) {
switch(x) {
case 1: System.out.println("It's 1."); break;
default: System.out.println("It's something else."); break;
}
}
Using "switch" on a literal wouldn't really make much sense - a literal can only have one value (whose value is known at the time you write the code). The switch block lets you do different things depending on what that value is. But since you know what the value is (it's a literal) it wouldn't make sense to switch on a literal.
Constants often make an appearance in the case statement, but again not in switch for the same reasons literals aren't used there.
For example:
3 methods exist
"map1method,
map2method,
map3mehtod"
and I want to call the right one depending on what the integer 'activemap' has currently stored in it.
I could do an If statement
"If (activemap == 1)
map1method;
elseif (activemap ==2)
..."
But is there a possible way of using the integer more efficiently?
Like a "map(activemap)method"
Also could I also call a specific array in a batch of them in the same fashion.
This is all in java by the way.
It is possible via reflection but I would urge you to stay away from that approach. Why not have all three methods built into one? One option would be to use a switch statement to handle the various cases:
void mapMethod(int activemap) {
switch (activemap) {
case 1:
// map1method
break;
case 2:
// map2method
break;
case 3:
// map3method
break;
default:
break;
}
}
Now, you can call
mapMethod(activemap)
If you want to take the reflection approach instead (which as I said I don't think you should), you can do something along the lines of
String methodName = "map" + activemap + "method";
MyClass.class.getDeclaredMethod(methodName).invoke(null);
A switch statement would be slightly easier to read:
switch(activemap) {
case 1: map1method(); break;
case 2: map2method(); break;
}
You could use reflection to build the method name up at runtime, but that wouldn't be simpler. Reflection is a lot of code.
The most effective way to do this is to either create an enum to represent the different calls and use the int as a lookup for the enum value, or if that's not possible, to use a switch statement. You can use reflection to accomplish what you're talking about (look up a method at runtime based on its name), but it's less efficient and more cumbersome than either of those options.
You can do it using Reflection, It will be something like this:
java.lang.reflect.Method method;
method = myObject.getClass().getMethod("map+"activemap"+method", param1.class, param2.class, ..);
method.invoke(object, arg1, arg2,...);
Why doesn't this Java code compile?
class A {
public static void main(String[] args) {
boolean b;
switch(1) {
case 1:
b = true;
}
System.out.println("b: " + b);
}
}
It's complaining that b might not have been initialized, even though it is in all cases as far as I can tell. How could b not be initialized?
$ javac A.java
A.java:8: variable b might not have been initialized
System.out.println("b: " + b);
^
1 error
You need to initialize it beforehand, or add a default clause:
switch (1) {
case 1:
b = true;
default:
b = false;
}
It's just not feasible for the JVM to analyze all possible cases, not even for a literal. At least, as #assylias points out, the language specification doesn't demand that it should.
Therefore, from a code analysis standpoint, it has to handle a literal the same way as it would handle a variable, and it can't know that a specific path is always chosen, even here where we can easily see that the first case will always match.
So, it needs to see that the variable b gets initialized no matter what the value is, and therefore demands a default clause.
You can refer to JLS #16.2.9. In particular, without a default statement, the compiler can't decide that b is definitely assigned after the switch statement, even if it is obvious in your example that it is.
In some of our companys projects code I often read something like this:
boolean foo = Boolean.FALSE;
Besides the fact that AFAIK I only have to initialize local variables in Java at all (no random values like in Pascal) and besides the fact that especially for booleans I often WANT to have an initialization, what do I miss here? Why not:
boolean foo = false;
I don't get it. And code analyzation tools like PMD and Findbugs mark it, too. But why?
Edit:
Without really knowing much about the bytecode except that it is there I created an example class and decompiled it. The Boolean.FALSE went to:
0: getstatic #15 // Field java/lang/Boolean.FALSE:Ljava/lang/Boolean;
3: invokevirtual #21 // Method java/lang/Boolean.booleanValue:()Z
6: istore_1
The 'false' variant went to:
0: iconst_1
1: istore_1
So without knowing too much about this, I'd guess that more statements means more time to execute so it's not only wrong but also slower in the long run.
boolean foo = Boolean.FALSE;
This is strange and unnecessarily complicated code, written by someone who likely didn't know Java very well. You shouldn't write code like this, and PMD and FindBugs are right to mark this.
Boolean.FALSE is a java.lang.Boolean object that gets auto-unboxed; the compiler essentially translates this to:
boolean foo = Boolean.FALSE.booleanValue();
I don't have to initialize variables in Java at all...
Member variables do not need to be initialized explicitly; if you don't, they'll be initialized with a default value (which is false in the case of boolean). Local variables do need to be explicitly initialized; if you try to use a local variable without initializing it, the compiler will give you an error.
Both are same. but boolean foo = false; is enough.
There is no good reason to do this, it was probably just a novice Java programmer. I wouldn't worry too much, just replace it with false.
At the same time, you can usually if not always arrange your code such that you never declare a variable you don't have the final value for, i.e., making your objects immutable, which makes them easier to think about. What's the value of x? compared to What's the value of x between the calls to foo() and bar()? The first is generally easier to answer. This requires you to split up your classes along lines you might not be used to doing but I recommend at least trying it out.
The style to use an auto-unboxed Boolean constant in fact meshes well with the overall oververbosity endemic to many Java projects. For example:
public boolean isItOrIsItNotTheValueWeExpect(String aStringParameterThatCouldBeNull) {
boolean booleanReturnValue = Boolean.FALSE;
if (aStringParameterThatCouldBeNull != null) {
if (aStringParameterThatCouldBeNull.length() > 3) {
booleanReturnValue = Boolean.TRUE;
}
else {
booleanReturnValue = Boolean.FALSE;
}
}
else if (aStringParameterThatCouldBeNull == null) {
booleanReturnValue = Boolean.TRUE.booleanValue();
}
return booleanReturnValue;
}
Obviously, the code above would be much preferred to this unreadable mess:
public boolean validate(String s) {
return s == null? true : s.length() > 3;
}
The very occurrence of a ternary operator is considered a transgression and some projects even have it flagged by CheckStyle.
If your projects conform to such stylistic guidelines as these, that could justify your suspicious line of code.
There is no difference really although the 1st method won't work on a 1.4 or earlier JVM. The first is more convoluted since it is fetching the static value from the Boolean object and then relying on autoboxing (introduced in 1.5) to change it from a Boolean object to a boolean primitive) although I can't imagine it would ever make any speed difference.
Generally though if you are assuming a particular initial value for a variable then I would recommend initialising it rather than just declaring it as it makes the code more readable.
I didn't know methods could have floating blocks like this:
class X {
public static void main( String [] args ) {
{ //<--- start
int i;
} //<-- ends
}
}
I was aware of floating blocks outside methods, but never tried them inside.
This could probably be used to define local scope or something.
Is there a use for floating blocks inside methods in Java?
Is there a use?
Yes - to limit the scope of local variables.
Is it a good idea?
Probably debatable (and likely will be).
The "pro" camp will say it never hurts to narrow the scope of variable. The "con" camp will say that, if you use it in a method and your method is long enough to warrant narrowing the scope of variables to specific sections, then it is probably an indication that you should make separate methods out of the different sections.
Personally, I use them, e.g.:
public void doGet(
final HttpServletRequest request,
final HttpServletResponse response)
throws IOException {
final PersistenceManager pm = PMF.get().getPersistenceManager();
final List<ToDoListGaejdo> toDoLists;
{
final Query query = pm.newQuery(ToDoListGaejdo.class);
query.setOrdering("listName asc");
toDoLists = (List<ToDoListGaejdo>) query.execute();
}
final List<ToDoItemGaejdo> entries;
{
final Query query = pm.newQuery(ToDoItemGaejdo.class);
query.setOrdering("listName asc, priority asc");
entries = (List<ToDoItemGaejdo>) query.execute();
}
final ServletOutputStream out = response.getOutputStream();
out.println("<head>");
out.println(" <title>Debug View</title>");
....
Yes, they are useful for two purposes.
First, you can limit the scope of variables using such blocks. This can help with the readability of code, because you have a smaller area to consider when determining how a variable is used. Additionally, this can minimize the required number of "slots" for the method frame, conserving stack space. I'd be very surprised to find a case where this optimization was necessary.
Second, when you attach a label to the block, a targeted break can be used inside the block to jump to the end of the block. This is not quite as evil as an unadulterated goto statement, but a sighting still triggers red flags and warning bells.
You've just given an example yourself. You can make the declaration of i 'more local' than method scope. When it goes out of scope, the rest of the method can't see it.
Syntactically, a block can appear anywhere a statement can appear. This is the fundamental principle of block-structured languages.
One further case where blocks are useful is in switch statements; e.g. the following is invalid
switch (i) {
case 1:
float j = ...;
break;
case 2:
float j = ...; // compilation error
break;
...
}
but it is OK with added blocks:
switch (i) {
case 1:
{
float j = ...;
break;
}
case 2:
{
float j = ...; // just fine
break;
}
...
}
This kind of use-case arises when you implement things like state machines and interpreters using (big) switch statements. You could argue that the local variables should all have different names, but:
using the same name for the same concept (though in a different scope) in gnarly code like this is good for large-scale readability, and
using the blocks makes it easier for the compilers to recognize that the variables declared within may share stack frame slots. This is potentially significant if the enclosing method is also recursive.
(OK, this is all either micro-optimization, or a consequence of micro-optimization. But let's assume we've determined that it is justified.)