I am learning Java and I understand that you cannot name a variable declared within an inner scope the same name as a variable declared in an outer scope as shown below
public class Practice {
public static void main(String[] args){
int x = 10;
if (x == 10){
int x = 10;
}
}
}
However, I noticed that the following is not illegal
public class Practice {
int x = 10;
public static void main(String[] args){
int x = 10;
if (x == 10) {
}
}
}
Is this not a variable that is declared twice??
Is this not a variable that is declared twice??
No, it is not. Because they both are in different scope. x outside of main function has class level scope while x inside of main has method/function level scope.
It is legal for 2 variables in different scope to have same name.
Please DO read §6.3. Scope of a Declaration from JLS. Below are few of the statement from that section.
The scope of a declaration is the region of the program within which
the entity declared by the declaration can be referred to using a
simple name, provided it is visible (§6.4.1).
A declaration is said to be in scope at a particular point in a
program if and only if the declaration's scope includes that point.
The scope of a local variable declaration in a block (§14.4) is the
rest of the block in which the declaration appears, starting with its
own initializer and including any further declarators to the right in
the local variable declaration statement.
There are lot of concepts related to scope like shadowing, so do read §6.4. Shadowing and Obscuring.
JLS is the best place to learn what is allowed and what is not allowed in Java. Feel free to read sections there.
In the second case when x is declared outside the method, it is an instance variable of the class Practice. Within the method, scope of x(declared inside main) is limited to the main method.
In the first case when you declare x within the method, you cannot declare it inside if because it is already declared in the scope of the method outside if.
The first code snippets shows the variables are in method's scope. So two variable are belonging to same method which is not allowed.
But in the second example one variable is on instance level and the other one in method's scope, so there is no duplicate. In the second example if you want to access the instance variable, you have to do it using this.x.
Check more on scope and lifetime of variables here
http://www.javawithus.com/tutorial/scope-and-lifetime-of-variables
Why can you have a duplicate variable name in java for a variable outside of a method?
It is not illegal because it is allowed by the Java Language Specification. (Yes ... circular explanation)
As with all such questions, we cannot tell you for sure why it is allowed, because the Java language was designed behind closed doors. However, a couple of possible reasons are:
Java was originally designed to be "palatable" to C and C++ programmers, and this is a case where doing it differently (banning shadowing) would have caused objections.
A lot of people actually like it that they don't have to think of different names for variables; e.g.
public class Foo {
private Bar bar;
public Foo() {
Bar bar = new Bar();
this.bar = bar;
}
}
Admittedly, there is a downside. Sometimes, people mistakenly declare local variables that shadow instance (or static) variables. Particularly newbies :-)
Is this not a variable that is declared twice??
No. It is actually two >>distinct<< variables. Both exist. Within the method, the local declaration of x shadows the instance declaration of x. But you can still refer to the latter as this.x.
Related
I just found that Java handles variable initialization in different ways.
Case-1:
class A {
boolean x;
public static void main(String[] args) {
A a = new A();
System.out.println(a.x);
}
}
When I ran above program it shows like "false" as output. But now I am posting other piece of code:
Case-2:
class A {
public static void main(String[] args) {
boolean x;
System.out.println(x);
}
}
Now, above piece of code shows that
java.lang.Error: Unresolved compilation problem:
The local variable x may not have been initialized
Why the same thing is handled in very different ways?
Thanks in advance!
From the Oracle documentation on Java Primitive Data Types:
Local variables are slightly different; the compiler never assigns a
default value to an uninitialized local variable. If you cannot
initialize your local variable where it is declared, make sure to
assign it a value before you attempt to use it. Accessing an
uninitialized local variable will result in a compile-time error.
So this is an interesting nuance. If a primitive type variable is locally declared, you must specify a value for it.
There are three distinct types of variables:
static variables - within class;
member variables - within object
local variables - having scope limited to a function or block of code
Assumming the variables are not final.
The first two default to 0 or false (when var is a primitive) or
null (when var is an object) when accessed for read. The last one must be set to a value prior to reading, otherwise the code will not compile.
All of variable types (local, member, static) must be assigned a particular value if defined as final. Such Initialisation of static final variable can be an inline assignment to a value or it can be done in static initialisation block. Initialisation of final member variables can be done inline, within Initialisation block or within object's constructor (most common - best practice).
Final local variables initialized inline. There is also "effectively final" variable that is inferred by compiler when it sees that variable will not be changed. Final variables allow compiler to treat and optimize handling of data.
Thats just a couple of basic items to start with. Hope it is helpful.
Cheers.
If this question is about why local variables are treated different from non-final member variables: in the example above I do not see any use do declare boolean x; instead of boolean x = false;, but the last one makes the intent of the programmer clear. Also you are allowed to declare boolean x; if you initialize x later. Here the compiler error you get is helpful so you don't forget to initialize it in some rare edge case. The compiler couldn't check that if it would be initialized by default.
It's also common to have code like
int i;
if (a > b)
i = 8; // loong code
else
i = 42; // loong code
Initializing i would be useless here.
Static and non-static members (non final) are different because the compiler always nulls all fields before running initializers and constructors. Not initializing them to 0 manually is a slight performance improvement.
Explanation
Your two examples use different kinds of variables:
a field (also called instance variable, or member)
a local variable
You can only use a variable if it has a value / refers to an instance. For fields, if you do not explicitly assign a value, they are defaulted. That is not the case for local variables, thus the error.
The default value is null for objects and special values for primitives, like 0, 0.0, false and similar.
Java Language Specification
The JLS clearly defines this behavior and explains how it works. Take a look at chapter 4.12.5 Initial Values of Variables where it states (relevant excerpts):
Every variable in a program must have a value before its value is used:
Each class variable, instance variable, or array component is initialized with a default value when it is created (§15.9, §15.10.2):
For type boolean, the default value is false.
A local variable (§14.4, §14.14) must be explicitly given a value before it is used, by either initialization (§14.4) or assignment (§15.26), in a way that can be verified using the rules for definite assignment (§16 (Definite Assignment)).
For example
Class Moon{
int a;
void mango()
{
a=9; // put 9 in instance variable "a"
}
void orange()
{
int a; // declare local variable with same name as of instance variable
}
}
How this is possible that we can modify the value of instance variable inside method and also we can declare the local variable with same name as of instance variable?
When there is an instance variable and a local variable you can use the instance variable with this.a and use the local with just a.
Common use:
public void setA(int a) {
this.a = a
}
Modifying instance variables from within methods is:
prescribed by the java language specification, and
pretty much necessary: that's how object-oriented programming works.
(I mean, if you could not modify an instance variable from within a method, then where would you modify it from?)
If you want a particular instance variable to not be modifiable from within methods, then you must mark it with the final keyword, like this: final int a; --you will still be able to initialize it from the constructor.
Declaring a local variable with the same name as an instance variable is perfectly valid java; however, it is not advised, and that's why you can usually configure your IDE to issue a warning when you do that. Actually, if your IDE is not giving you a warning, then this may mean that you are not compiling with enough warnings enabled. Always enable as many warnings as you can.
I am learning Java and I understand that you cannot name a variable declared within an inner scope the same name as a variable declared in an outer scope as shown below
public class Practice {
public static void main(String[] args){
int x = 10;
if (x == 10){
int x = 10;
}
}
}
However, I noticed that the following is not illegal
public class Practice {
int x = 10;
public static void main(String[] args){
int x = 10;
if (x == 10) {
}
}
}
Is this not a variable that is declared twice??
Is this not a variable that is declared twice??
No, it is not. Because they both are in different scope. x outside of main function has class level scope while x inside of main has method/function level scope.
It is legal for 2 variables in different scope to have same name.
Please DO read §6.3. Scope of a Declaration from JLS. Below are few of the statement from that section.
The scope of a declaration is the region of the program within which
the entity declared by the declaration can be referred to using a
simple name, provided it is visible (§6.4.1).
A declaration is said to be in scope at a particular point in a
program if and only if the declaration's scope includes that point.
The scope of a local variable declaration in a block (§14.4) is the
rest of the block in which the declaration appears, starting with its
own initializer and including any further declarators to the right in
the local variable declaration statement.
There are lot of concepts related to scope like shadowing, so do read §6.4. Shadowing and Obscuring.
JLS is the best place to learn what is allowed and what is not allowed in Java. Feel free to read sections there.
In the second case when x is declared outside the method, it is an instance variable of the class Practice. Within the method, scope of x(declared inside main) is limited to the main method.
In the first case when you declare x within the method, you cannot declare it inside if because it is already declared in the scope of the method outside if.
The first code snippets shows the variables are in method's scope. So two variable are belonging to same method which is not allowed.
But in the second example one variable is on instance level and the other one in method's scope, so there is no duplicate. In the second example if you want to access the instance variable, you have to do it using this.x.
Check more on scope and lifetime of variables here
http://www.javawithus.com/tutorial/scope-and-lifetime-of-variables
Why can you have a duplicate variable name in java for a variable outside of a method?
It is not illegal because it is allowed by the Java Language Specification. (Yes ... circular explanation)
As with all such questions, we cannot tell you for sure why it is allowed, because the Java language was designed behind closed doors. However, a couple of possible reasons are:
Java was originally designed to be "palatable" to C and C++ programmers, and this is a case where doing it differently (banning shadowing) would have caused objections.
A lot of people actually like it that they don't have to think of different names for variables; e.g.
public class Foo {
private Bar bar;
public Foo() {
Bar bar = new Bar();
this.bar = bar;
}
}
Admittedly, there is a downside. Sometimes, people mistakenly declare local variables that shadow instance (or static) variables. Particularly newbies :-)
Is this not a variable that is declared twice??
No. It is actually two >>distinct<< variables. Both exist. Within the method, the local declaration of x shadows the instance declaration of x. But you can still refer to the latter as this.x.
I have a class in that I need two variables one is a static one another one is Non-static. What my problem is when we declaring two variables, can we declare them with same name?
Why I ask this question is the static variables and non-static variables are stored in two different areas (static variables in Method area and non-static(instance) variables in heap area).
So, what happens if I declare them with same name? If it is wrong, what is the reason?
No, you can't do the following:
public class X{
int a;
static int a = 10; //Illegal
public X(int a){
this.a = a;
}
}
The reason is that both as are in scope for an instance of x. For:
X x = new X(5);
x.a; //were the static field with name a legal, this refers to both 5 and 10.
it is unclear which version of a is being referred to. Thus to prevent confusion it is illegal.
You can have a variable inside of your method that has the same name as a class-scoped variable. In general, the variable in your method has priority over the class-scoped variable when the variable name is referred to from inside of that method. To be more clear in your code and to make sure you're accessing the correct one, use the this keyword to refer to the variable inside of the method and use the super keyword to refer to the class-scoped variable.
Why is it that curly braces do not define a separate local scope in Java? I was expecting this to be a feature common to the main curly brace languages (C, C++, Java, C#).
class LocalScopeTester
{
public static void main(String... args)
{
Dog mine = new Dog("fido");
if (mine.getName().equals("ace"))
{
Dog mine = new Dog("spot"); // error: duplicate local
}
else
{
Dog mine = new Dog("barkley"); // error: duplicate local
{
Dog mine = new Dog("boy"); // error: duplicate local
}
}
}
}
They do define a separate local scope, but you still cannot mask local variables from a parent scope (but you can of course mask instance variables).
But you can define new variables (with different names) and their scope will be limited to within the braces.
Local variable shadowing is prohibited in Java on purpose (see this answer).
The idea is that this helps decreasing bugs.
The braces do scope the variable but anything inside a brace can also 'see' further up the brace. In all the cases you have, mine is already defined as fido.
To put it more succinctly. The children are scoped to their parents as well but not vice versa.
They do define a separate local scope, just it is an error if a local variable hides another.
Try defining a variable (with a unique name) inside a block, then accessing from outside that block to see that it is indeed scoped to the block, and only that block.
Blocks define a local scope, but don't allow you to redefine a variable with the same name as another variable in an outer local scope. If it did, there would be no way to access the "hidden" variable.
It does define a local scope... the variables declared inside curly braces have the braces' scope. However what you are trying to do is redeclare an already existing variable. In my opinion, it's not Java that's wrong in this case, but C++ for letting you do it (I assume that's what you were comparing it to). Nonetheless, even if the language would allow it, why would you do it? Poor readability right there, and possible cause for bugs.
Run this and you'll get an error that the variable is already declared as int i=5 and one cannot redefine. So, the Parent never takes what its child got.
So, what if the Parent sacrifices and removes his declaration of int i=5?
public class Ouch {
public static void main(String[] args) {
int i=5;
for(int i=0;i<5;i++);
for(int i=0;i<5;i++);
}
}
Now, the Parent sacrificed its declaration and both the children enjoy and the code runs successfully.
public class Ouch {
public static void main(String[] args) {
//int i=5;
for(int i=0;i<5;i++);
for(int i=0;i<5;i++);
}
}
It's forgotten in Java but I think Java is wrong because in ALL "block structured" languages it is authorized to do this (not only in C++ but also in Pascal, ADA, C, and so on...) and sometime we want to hide a variable of the enclosing block.