I know that there is a question like this on Stack Overflow but I want to know why we can't declare variables inside if statements so that we can save space by just utilizing the if scope.
For example, if I write:
if (int i) {
...
}
then I could use i only within the if scope, but if I write it outside of the if statement, then i variable should be in memory for the whole block.
if ( int i ) => int i is not a boolean expression, so this won't work.
if ( booleanExpr ){
int a = 5;
...
}
here a is a local variable within the if block. At the end of the if-block, it is removed from the stack and becomes unusable.
int a = 5;
if ( booleanExpr){
...
}
Here a is not local to the if block, but to the containing method. So, it will be on the stack during the entire execution of the method (starting from its declaration).
a could also be an instance or static variable to the class, then it's accessible in every method of the class (instance variables are not accessible in a static context, though)
why can't we declare variables in the if statement?
Because the Java Language Specification does not allow it.
if I write if(int i){} then I could use i only for if the scope
You can use blocks
public void someMethod() {
{
int i = 1; // visible only to the current block
} {
int i = 0; // visible only to the current block
if (i == 0) {
System.out.println("i = " + i);
}
}
// compiler error, because i is not visible outside the block
System.out.println(i);
}
But this decreases the readability of your code. So I would recommend to NOT use it.
An if statement is a test, so declaring a variable in an if does not make any sense.
Think about it, an if is for something like this:
if(a == 1){
// blan
}
If you declare a in the if condition, you are essentially comparing 2 static values.
Lots of languages let you declare an "iterator" vairable in a for loop:
if(int a = 0 ; a < somelist.length ; a++){
// Do something
}
// a is out of scope here
You can restrict the scope of your variable to make it visible only in the if statement like this:
System.out.println("Hello World!");
//use a codeblock to restrict access
{
int i = 4;
if(i!=0)
{
System.out.println("i = "+i);// this is OK
}
}
System.out.println("i = "+i);//this is not OK
why can't language support it
That's the wrong question to ask. The real question is:
Is there a compelling reason for the language to support it?
That is, is there a compelling reason to implement it, exhaustively test it for all possible edge cases, and maintain it in all future versions of the language?
In this case, no. There isn't. It might be handy in a small number of cases, but it's not a core feature of the language and isn't really necessary. So there's no compelling reason to make the implementation of the language more complex and incur significant cost now and well into the future to support it.
if is a conditional and there is no valid use-case when you declare a variable inside the conditional.
If your conditional is more complex, you can implement a few methods for it and inside those methods you can use those variables, however, if you need that variable outside the if, then define it outside the if in the correct scope.
Related
I do have the following statement:
isEnabled = false;
if(foo(arg) && isEnabled) {
....
}
public boolean foo(arg) {
some really long running code
}
Does it make sense to swap the statements inside the if?
if(isEnabled && foo(arg)) { ... }
Or does the compiler the optimization for me?
Note that the two expressions don't have the same behavior if foo() also has side effects.
If it is manipulating the state of the program, it makes a lot of difference if you always invoke it, or if you invoke it only as a dependency of the value of isEnabled.
For example, consider:
boolean foo(Object arg) {
someLocalVariable = arg;
//do some calculation and return an answer
}
It matters if you always invoke foo(), or if you invoke it only in the case where isEnabled is turned on, resulting in the following two expressions to be completely different from each other:
if (isEnabled && foo(arg)) { ...} //local variable changes only if isEnabled==true
if (foo(arg) && isEnabled) { ...} //local variable always changes
The compiler will not do any optimization in this case.
if(isEnabled && foo(arg)) { ... }
Is always the better approach.
Because i guess you know that when isEnabled is false it will not evaluate foo(arg). And compiler will maintain your sequence of instruction.
Does it make sense to swap the statements inside the if?
Yes. && will only evalute the sub-expressions until one is false. Then the complete exprission will be false, no matter what the other expressions evaluate to.
Since the compiler would have to keep the logic as it is (which includes the order of statements) it won't optimize that.
Suppose foo() has a side effect which some other part of the code relies on, changing the order might break that. Of course this isn't good style in most cases but the compiler can't rely on or enforce style so it has to trust the developer here.
Example:
int x = 0;
boolean foo(int arg) {
x = arg;
return x > 0;
}
void someMethod(int arg) {
boolean isEnabled = false;
if(foo(arg) && isEnabled) {
//whatever
}
//here you use x, I'll simply print it
System.out.println("x=" + x);
}
void someOtherMethod(int arg) {
boolean isEnabled = false;
if(isEnabled && foo(arg)) {
//whatever
}
//here you use x, I'll simply print it
System.out.println("x=" + x);
}
Now calling the methods:
someOtherMethod(7); //foo(7) will not be called so x will still be 0
someMethod(5);
you'll get the output
x=0
x=5
First of all, the Java compiler (which turns java source into bytecode) is pretty dumb. Out of the many optimization techniques known to compiler constructors, just a handful (like constant folding) are implemented by javac.
Whereas the Java just-in-time compiler does many many more things; but even the JIT will not change the order of arguments for you (as that can change the semantics of the underlying program).
Finally, when thinking about this code, performance should not be the motivation behind you changing it. Instead, you should worry about the semantics too. Do you want that foo() is executed (for side effects); or maybe do you not want that foo() runs all the time?
Of course, "foo()" could be doing many many things; and not executing it might gain some performance. But most likely: it will not matter (from a performance perspective).
In other words: stay away from micro-optimisations, see here for backing reasons to that recommendation.
I see some code like
public void foo() {
final int x = 3;
final Object z = new Object();
.......
}
I know that x can't be modified since it is final but is there any other reason/explaination for that? compare to without using final? Or the developer just added final to that variable because he just likes to. Thanks.
Declaring a variable immutable (final) is a pretty good reason by itself. Besides adding clarity to the code, it also provides some valuable information to the compiler that might be able to optimize code better when it knows that some things are not going to change.
One other reason might be hidden in your example behind the ellipsis: if there is a closure somewhere in that function, that references this local variables, it would not compile if they were not final. Imagine something like this for example:
public void foo() {
final int x = 3;
final Object z = new Object();
new Thread() {
public void run() {
for(int i = 0; i < x; i++) {
System.out.println(z);
}
}
}.start();
}
For this to work, x and z must be declared final. Why? Well, local variables are created on stack, and, once the function returns, they disappear completely. But the code inside the Thread.run() method defined here, might still be executing, after the function that created it returns. Because the variables are final, their values are known to the JVM at the time the closure is created, so it can simply copy the values into the closure. If they weren't final, it would not be possible, because the copies would become stale as soon as the original value is modified.
1) A final class cannot be extended
2) A final method cannot be overridden
3) Final fields, parameters, and local variables cannot change their value once set
4) Declaring primitive fields as final automatically ensures thread-safety for that field
5) Clearly communicates your intent
6) Allows the compiler and virtual machine to perform minor optimizations
7) Clearly flags items which are simpler in behaviour - final says, "If you are looking for complexity, you won't find it here."
No there is no other reason, other than not letting others change the value (objects, primitives) but this doesn't prevent them from changing values in the class (for example, final Dog dog = new Dog() would prevent others from changing the reference to the dog object, but wouldn't prevent us from changing the variable inside it, for example, the size value of the dog)
This question already has answers here:
Anonymous code blocks in Java
(11 answers)
Closed 9 years ago.
It's kind of hard to exactly search for this. I've seen this in a few places and I've even tried it in code to see how it works but just so that I know exactly how they can be used and to make sure I wont be abusing them I thought i'd ask on here.
public void doSomethingSpecial()
{
String strHello = null;
// What is the following section in braces for
{
strHello = "Hello World"
}
for(int i = 0; i < 10; i++)
{
// What is the significance of them it in a loop?
{
strHello = "Hello";
// Do something else...
}
.
.
.
}
}
Can someone clarify what these brace blocks braces are for?
I assume they work like a method and would restrict the scope of anything within as long as it isn't specified outside the block, but is there another use?
What is the exact name for them?
Thanks in advance
The braces define scope. For example, if you define a local variable within the braces and assign a value to it like this:
{
int foo = 10;
}
Then foo's scope (i.e. the section of code where it is define and has a value) is limited to the area within the braces.
The same goes for your for loop. Within those braces, the counter i is defined and has meaning, but not outside. So this code would not compile:
for (int i = 0; i < 5; i++) {
// Do something with i
}
i = 10; // Won't compile. i is undefined as a variable.
The benefits of this are numerous in that you can precisely control the scope for different variables. You can also define the scope of things like exceptions in the context of exception handling, etc.
You can also do things like this:
int i = 0;
for (; i < 5; i++) {
// Do something with i.
}
for (; i < 10; i++) {
// Do something else with i
}
In this case i is defined in a larger scope space (that of the enclosing method or constructor) and the for loops are only incrementing its value. So you are sharing a variable among two different areas of scope.
Lastly you can use them outside of a method or constructor as initialization blocks in a class. They allow you to initialize member variables that, for example, cannot easily be initialized with a single line of code.
Within the class, they form a static initializer, it runs once when the class is loaded, which happens first.
Within the method, they mark a scope. They are basically useless in your code.
But if the code is the following
{
String str = "test";
System.out.println(str);
}
{
System.out.println(str);
}
The second print will report a compilation error, since the scope of str is in the first scope.
So found something I thought I would post on here for anyone as none of the other questions seem to exactly clarify this.
When used outside of a method in class scope:
public class doSomethingSPecial() {
{
System.out.println("This is a constructor");
}
public doSomeThingSpecial() {}
public doSomethingSpecial(String specialString) { }
public doSomethingSpecial(int specialNumber) { }
}
"The Java compiler copies initializer blocks into every constructor. Therefore, this approach can be used to share a block of code between multiple constructors." - Java API Tutorial (Thanks to Soririous Delimanolis)
So the inline braces will be called each time a constructor is called.
As for the other questions regarding use within a method and loop the braces seem to be just to limit scope.
"In practice, though, if you find yourself using such a code block that's probably a sign that you want to refactor that block out to a method" - Credit to Robert Munteanu Top Answer: Anonymous code blocks in Java
That's basically everything I've come up with so far
Suppose we have a case where a variable is declared in certain conditions:
if (x = 1)
boolean z = true;
Later on, we'd like to test if the variable z exists with try-catch. Is this possible and if so, what exception should we catch?
try {
if (z)
//do smth
} catch (<exception?> ex) {
//do smth_else
}
Of course it would be possible to declare z before and change it's value accordingly in if block, but just hypothetically, is the above possible in Java?
Python for example has NameError that will be raised when accessed local or global variable is not declared.
Thanks!
HSI.
What if you declared your variable like this:
Boolean x = null;
In that case you could check for it being null or not.
An even better alternative would be using an enum to represent the uninitialized value:
public enum MyEnum {
UNINITIALIZED, TRUE, FALSE;
}
because if you will try to maintain your code several months later you (or someone else) may be puzzled about the Boolean being null.
we'll get compilation error if the variable we are using is not declared or is not visible in current scope.
If it is declared we can check for NullPointerException if that was object. In case of primitive data types we should check for default values.
Suppose we have a case where a variable is declared in certain conditions:
Well it is difficult to assume because that would not compile:
you should use == to test for equality
you can't declare a variable in an if statement unless there is a block
Now assuming you enclose that declaration inside a block, the scope of that variable would be that block and you wouldn't be able to use it in your try / catch block (unless it is inside the if block of course, but I don't think that's what you want).
No, this is not possible in Java. You have to have the variable declared before you can refer to it, otherwise you will get a compilation error.
Boolean z = null;
if (x = 1){
z = true;
}
if(z == null){
//not initialized
}else{
//initialized
}
it's not possible, Java is a strongly typed programming language because every variable must be declared with a data type before it can be used.
int x = 1;
boolean z = null;
if (x == 1)
z = true;
try {
if (z)
//do smth
} catch (NullPointerException npe ) {
//do smth_else
}
So far I understand , you wont be able to compile this piece of code. I can not remember any exception class but what I think is even if you "Invent" exception for this type of error. It won't compile. Because default values of primitive types are assigned to uninitialized class variables called fields but for variable used in method body, it gives compile time error
In Java, unlike in C++, we can provide an initial value for a field in its declaration:
public class BedAndBreakfast {
public int capacity = 10; //initialize to 10
private boolean full = false; //initialize to false
}
Why was there a need to allow this while it can be done more clearly in a constructor?
Why was there a need to allow this while it can be done more clearly in a constructor?
Which is a highly subjective statement. Obviously the Java developers felt differently (as do I, for one).
It is clearer if you define the default value with the property. If you have multiple constructors, you will have to define the values in each constructor, which is ugly.
Ultimately, the compiler puts these values in each constructor, so the net result is the same. It's just more readable and easy to support this way.
Update: As BalusC noted in his comment, you can use an initializer block, which is again appended to each constructor by the compiler:
{
var1 = 10;
var2 = false;
}
Many people consider it to be clearer that way, the values goes together with the declaration.
Also, the order differs, as these assignments will go before the constructor begins (except the special first constructor line, of course).
To add to what other posted have written...
Consider that C++ also allows specifying certain variables' values inline:
const unsigned MAX_SPEED = 85;
In Java, the parallel is a static final variable:
static final int MAX_SPEED = 85;
Sure, even static final variables' values can be assigned separate from their declarations:
static final int MAX_SPEED;
static {
MAX_SPEED = 85;
}
But my point is that once some types of variables' assignments are allowed in declaration, why not allow all (from a language design point of view)?