I have an issue regarding variable scope in the following piece of code. Can someone give a quick overview as to why java "cannot find the symbol" for output when it is printed? Thanks.
class Main
{
public static void main(String[] args) {
String text = "hello";
if (text.indexOf(" ") == -1) //if a space doesn't exist
{
String output = "one word";
}
else
{
String output = "more than one word";
}
System.out.println(output);
}
}
The variable output is only existent within the containing code block which currently seems to be within the if block and else block, if you want to access the variable output outside of the if and else block, you'll need to define it before the if block.
Local variables
A local variable is the one that is declared within a method or a constructor (not in the header). The scope and lifetime are limited to the method itself.
In addition to the local variables defined in a method, we also have variables that are defined in blocks, e.g. the if block and an the else block. The scope in this case is constrained by the block itself.
Related
Shouldn't the last print statement output "Vince"? I'd like to know why it didn't and the concept behind it.
See code below:
public class Example
{
static String name;
public static void main(String[] args)
{
Example.name = "Vince";
System.out.println(Example.name) // will print "Vince"
name = "Tony";
System.out.println(name); // will still print "Tony"
System.out.println(Example.name); // will print "Tony"
}
}
There are no other symbols called name in scope (e.g. no local variables), so name refers to the same thing as Example.name.
If the code said, for example:
String name; // a local variable with the same name
name = "Tony";
System.out.println(name); // will still print "Tony"
System.out.println(Example.name);
then the last line would print Vince, because then you are assigning Tony to the local variable.
Attempt 2 at answering this question.
name is a static field. static means that this field/attribute is shared amongst all objects of the same type. This means that if I were to make an instance of Example, called it Nancy, and then I did Nancy.name = "Drew", it would mean that System.out.println(name) would now equal "Drew" since static fields are shared across all objects of the same type.
Point is, by having the field be static, it was guaranteed to change to whatever value that Example.name or this.name changed it to, depending on which one was more recent.
link for this keyword - https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html
A nice example of this playing out, but a bit differently - https://stackoverflow.com/a/47035964/10118965
Example code:
public class SalCal {
public static void main(String[] args) {
int a=0;
if (a > 1)
String string = "fds";//hint:not a statement
}
}
Intellij IDEA hints at String string = "fds";
not a statement
But if I add braces on the either hand of String string = "fds"; , it will not hint like before anymore. Why?
Intellij IDEA says that because it is not a statement. It is a declaration1.
When you add the braces, you are turning it into a block statement ... which is a statement.
But here's the rub. If this code was legal it would be useless.
if (a> 1)
String string = "fds";
Why? Because the scope of the declaration has to end when the if statement ends. You would be declaring a variable that cannot be used.
Here are a couple of alternatives:
1) This version declares the variable in the if-block
if (a> 1) {
String string = "fds";
// you can use 'string' here
}
// ... but not here, because it is now out-of-scope.
2) This version declares and initializes the variable before the if statement and assigns a new value to it in the if:
String string = "asdf";
if (a> 1) {
string = "qwerty"; // assignment, not declaration
}
// OK to use 'string' here.
#Maroun's answer gives the technical reason why what you have written is not valid Java code.
1 - Actually, the Intellij IDEA compiler is being "loose with the truth". In fact, the JLS calls that a "local variable declaration statement". So it is technically a "statement" ... but it is special kind that cannot be used in all contexts that an ordinary one can be used.
The answer is in the JLS - 6.1. Declarations:
A local variable, one of the following:
A local variable declared in a block (§14.4)
A local variable declared in a for statement (§14.14)
Your case is none of the above, so you're getting:
error: variable declaration not allowed here
There are many solutions for this:
Declare string in an outer scope
Add parenthesis to the if statement.
The line String string = "fds"; is a declaration with an initializer, not a statement (such as a method call or an assignment to an existing variable). When you use braces, you're introducing a new block scope in which it can make sense to declare block-local variables, but in a bare "then", it's completely useless to declare a variable.
1.)First
String string = "asdf";
//if you don't have a curly braces here you've just like
//all of those things that is inside the if will follow the condition
if (a> 1)
//statement
2.)Second
//you use those {} just to block your statements
String string = "asdf";
if(a>1){// and this is always a statement;
//statement string
}
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.
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