In Java 7, for the given code:
final Integer i=9;
final int x=5;
switch(x){
case 1:
case i://compilation error is thrown here
}
What is the reason behind this?
Integer i = 9;
With this i is now a reference to Integer object and it's not a valid type to switch on in Java.
Following are the valid variable types, you can Switch on
Convertible ints - int, byte,short,char
Enums
String constants - support added in Java 7
Other than these valid values, you cannot just switch on any other Object
This is the reason I was looking for:
Wrapper objects such as Integer cannot be used in a case statement as they are not compile time constants(because the boxing and un boxing happens at runtime). hence you can only use primitives that are compile time constants which
must also be final.
In many languages switch statements represent a constant time lookup over a set of compile time constants.
The javac compiler will transform the switch statement into a very efficient bytecode representation and for that optimization the compile time constant is necessary.
1) switch case doesnt support any Object type as case, more over it supports primitive variables as constants and literals.
2) From Java 7 it supports Strings.
ex:-
final int num1=10;
int x=0;
int num2=5;
final Integer y=20;
switch (num2) {
case num1: //logic
case x ://logic ----> Compile time Error since it is not final/constant.
case y ://logic ----> Compile time Error,since it is of object type.
default:
//logic
}
Related
I'm doing some Java homework and I am on a problem that has a code relating to converting test scores to letter grades where errors must be found:
switch(score)
{
case (score > 90):
grade = 'A';
break;
etc...
Everywhere I've read, and everything I've tried in netbeans says boolean functions aren't allowed. Is the error that it should just be an if statement?
The content associated to the case has to compatible with the type of the expression used in the switch.
You use an int (probably) in the switch, so the cases have to be int values (or another type convertible to an int such as a char for example). The problem is that you provide a boolean that is not convertible to an int and whatever it is not what you are looking for.
The JLS.14.11. The switch Statement states indeed :
Given a switch statement, all of the following must be true or a
compile-time error occurs:
Every case constant associated with the switch statement must be
assignment compatible with the type of the switch statement's
Expression (ยง5.2).
If the two types don't match, you don't want to use a switch but a series of conditional statements (if-else-if) instead of.
According to the JLS, the parameters of the case statements can only be int, short, byte, char, String or Enum literals or constants.
So to answer your question, the given code will not compile and yes, it should be an if statement.
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.)
int i = 10;
i++; // it ok primitive value can use ++.
Integer integer = 10;
integer++; // how it can use ++
MyClass myClass = new MyClass();
myClass++; // then why myclass can't use ++.
C++ has the ability to overload operators. The Java language considers this to be open to too much abuse (overloaded operators can be obfuscating) so it was never incorporated into Java.
Therefore, you can't write myClass++ as the syntax is not available to specify that operation.
But ++ does work on a selection of non-primitives. The mechanism exploited is called autoboxing. (Essentially the underlying plain-old-data type is extracted from the boxed type, incremented then re-boxed to the original reference type).
Somewhat related to this is the ability to apply += and + to java.lang.String instances. Simply put, this is a special case. Although fully aware of the risk of downvotes I regard this as one of the worst kludges in Java, particularly += which will create a new instance of a string (as strings themselves are immutable), and many Java programmers will be unaware of the effect this has on memory.
It is because of Java's autoboxing feature which is added in Java 1.5
The compiler will convert the statment as follow
Integer integer = 10;
integer.iniValue++;
You can try to add the compiler flag "javac -source 1.4" and it will return an error
From the Link provided in a comment by Konstantin V. Salikhov,
Integer has a defined method to return an int, which then has the ++ operator defined.
MyClass has no ++ operator, hence myClass++; is invalid
The method in question goes like:
Integer myInteger = 10;
myInteger.intValue++;
Autoboxing is the automatic conversion that the Java compiler makes between the primitive types and their corresponding object wrapper classes.
Operator overloading in Java has a description (as to it being not allowed) at Operator overloading in Java
I have the following code:
Variable var;
//var is initialized to an unknown class type, stored as a public variable named type.
//var = new Variable<Integer>(Integer.class, <some integer value>);
//var.type is equal to Integer.class
switch (var.type)
{
case Integer.class:
//do some class specific stuff
break;
case Float.class:
//do some class specific stuff
break;
etc...
}
When I type the code out I get an error saying "Integer.class constant expression expected". I would like to use a switch block because it is cleaner that typing out:
if (var.type == Integer.class) {}
I am confused as to why the if block will compile without error while the switch block will not. I'm not entirely against using if blocks but its more a matter of my curiosity at this point. Thanks.
The Java Language Specification states that, for a switch statement's Expression:
The type of the Expression must be char, byte, short, int, Character, Byte,
Short, Integer, String, or an enum type, or a compile-time error occurs.
You cannot use a switch statement for this. Only integer values, strings or enums can be used with switch case labels.
You cannot use a switch statement to compare class type of an object. You would have to live with if-else statements.
What is the difference between final variables and compile time constants?
Consider the following code
final int a = 5;
final int b;
b=6;
int x=0;
switch(x)
{
case a: //no error
case b: //compiler error
}
What does this mean? When and how are final variables assigned a value? What happens at run time and what happens at compile time? Why should we give switch a compile time constant? What other structures of java demands a compile time constant?
The problem is, that all case: statements must be ultimate at compile time.
Your first statement is ultimate. a will for 100% be no other value than 5.
final int a = 5;
However, this is not guaranteed for b. What if there would be an if-statement around b?
final int b;
if(something())
b=6;
else
b=5;
What does this mean?
It means that 'b' isn't a compile time constant expression, and the JLS requires it to be.
When and how are final variables assigned a value?
Formally, when the assignment statement or initializer is executed.
But in practice, if the final declares a compile time constant the expression is evaluated at compile time and its value is hard-wired into the code.
What happens at run time and what happens at compile time?
See above.
Why should we give switch a compile time constant?
Because the JLS requires it.
It is necessary for the bytecode compiler to check that the switch statement is well formed; i.e. that the values of the switch constants don't collide. It also allows the JIT compiler to generate code that is optimized for the actual values of the switch constants.
What other structures of java demands a compile time constant?
None that I can think of, off the top of my head.
From compiler point of view you are trying to use a variable b that might not be initialized. The switch statement are compiled into JVM bytecode tableswitch or lookupswitch which requires that values used in case statement are both compile time constant and unique.
final int a = 4; // compiler is sure a is initialized
final int b;// variable b is not guranted to be assigned
e.g.
Although this statement will ultimately initialize b , but compiler can't detect it.
if (a < 4) b= 10;
if (a >= 4) b = 8
final int b; can be assigned once and value is not sure, that will be decided on runtime depending on conditions. that is the reason, even if being a final variable, it is not COMPILE TIME constant although it will be a RUN TIME constant and case needs compile time constants.
The switch statement needs a constant. As final variables can be delayed initialized and the compiler cannot determine for b that it has a value in the case branch.