Making new ArrayList with same name behaving different [duplicate] - java

This question already has answers here:
Re-declaring variables inside loops in Java
(7 answers)
Closed 4 years ago.
So I was just trying to experiment with ArrayList and I came to this problem:
Why do Java say 'ArrayList already is declared' when I do this:
ArrayList<Integer> myList = new ArrayList<>();
ArrayList<Integer> myList = new ArrayList<>();
But Java won't say the list is already declared when I do this (and compiles with no error):
for(int i=0; i<5; i++){
ArrayList<Integer> myList = new ArrayList<>();
}

1. However, you CANNOT create same name variables within same scope in java.
2. About declaring same variable inside loop. This is called variable shadowing:
variable shadowing occurs when a variable declared within a certain scope (decision block, method, or inner class) has the same name as a variable declared in an outer scope. At the level of identifiers (names, rather than variables)
Scope of Variables In Java
public class Test
{
// All variables defined directly inside a class
// are member variables
int a;
private String b;
void method1() {
// Local variable (Method level scope)
int x;
}
int method2() {....}
char c;
}
In your case,
after each loop, the scope is destroyed, and the variable is gone. In the next loop, a new scope is created, and the variable can be declared again in that scope.
With this:
for(int i=0; i<5; i++){
ArrayList<Integer> myList = new ArrayList<>();
}
A new block is created on every iteration. And there is only 1 variable named myList in each block.
Refer here

In the first case, you define two variables having the same name in the same scope.
In the loop case, the scope of the myList variable is only inside the loop. That means each time you enter in the loop the variable is initiated and then destroyed at the end of the loop.
Have a look to : https://www.geeksforgeeks.org/variable-scope-in-java/

Related

Why do I get this compiler warning? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am trying to get a list of the longest words from each line in a block of text. I cant get the information to print from my main which is in processing.class. The information is processed in Tools.class. and there is also a Counters.class that is involved but it is immutable.
However, it gives me this warning: The value of the local variable longestWords is not used in my counter code, on the line where i declare longestWords =h;. Why is this, and how can I fix it?
This is my code:
(Processing)
longestWords = stat.getLongestWords();
for(i = 0; i < longestWords.size(); i++){
System.out.print(longestWords.get(i));
}
Error thrown: Exception in thread "main" java.lang.NullPointerException
at deol5210_a1.Processing.main(Processing.java:66)
which points to for(i = 0; i < longestWords.size(); i++){
(Tools)
}else {
currentWord = lineScanner.next();
if(currentWord.contains("$")){
currentWord.replace("$", "");
moneySpent += Double.parseDouble(currentWord.replace("$", ""));
}else if (currentWord.length() > lineLongestWord.length()){
lineLongestWord = currentWord;
}
if(currentWord.length() > longestWord.length()){
longestWord = currentWord;
lineLongestWord = currentWord;
wordCount++;
} else {
wordCount++;
}
(Counters)
public ArrayList<String> getLongestWords(){
return longestWords;
}
public Counters(int a, double b, int c, int d, double e, double f, String g, ArrayList<String> h){
lineCount = a;
avgWordCount = b;
wordCount = c;
purchaseCount = d;
moneySpent = e;
avgSpent = f;
longestWord = g;
ArrayList<String> longestWords = h;
}
Initializing a variable is different from using it, the warning will disappear when you use the variable (print it, pass it to a method, etc').
Basically it's the same as saying:
int i = 0;
and then not doing anything with i.
The statement
ArrayList<String> longestWords = h;
creates a new local variable longestWords and then does nothing with it, if you have a member called longestWords the statementshould be simply:
longestWords = h;
Another criticism, you never declare the variable i, but you try to assign it to a value. You need to change the following:
for(i = 0; i < longestWords.size(); i++)
to
for(int i = 0; i < longestWords.size(); i++)
As for your warning, you are declaring longestWords within the block scope of your Counters constructor. This is most likely supposed to be an instance variable within Counters, not a private variable within the constructor.
Get rid of the declaration there, and instead use the variable that is most likely already defined in your class. From:
ArrayList<String> longestWords = h;
to
longestWords = h;
Java variables have something called "scope". A variable declared inside a method, like your longestWords variable, is a local variable. Its scope is restricted to that method. That means that outside of that method, the definition of longestWords as it is declared in the method does not exist. You are trying to access a local variable from outside the method in which it was declared. By definition, a local variable does not exist outside of the method in which it is declared.
If you want to use a variable in multiple methods, you need to declare it outside of any methods, making it a global variable.
If there is ever a local variable that is declared with the same name as a global variable, that variable name will refer to the local variable within the method, and to the global variable outside the method (because the local variable doesn't exist outside the method in which it was declared). So if you initialize that variable inside the method, it will not affect the value of the global variable.

Does this statement calls constructor obj=new checker[10]? [duplicate]

This question already has answers here:
Why doesn't Java initialize Array Objects?
(2 answers)
Closed 6 years ago.
class checker
{
public checker()
{
System.out.println("In the constructor");
}
}
public class StringTesting {
static String string1;
static String string2;
public static void main(String[] args)
{
checker[] obj;
obj=new checker[10];
}
}
What can i do to call the constructor of all the 10 objects of class checker?obj=new checker[10] statement doesn't call the constructor i want to know why?
Your current code doesn't create any objects of type checker - it just creates an array which is capable of holding references to objects of type checker. Initially every element in the array has a value of null. It's important to understand that the array element values aren't checker objects - they're just references. Multiple elements could hold references to the same object, for example, just like multiple variables of type checker could have values referring to the same object. (You can think of an array as a collection of variables.)
If you want to call the constructor, you need to do so explicitly. For example:
// Names fixed to be more conventional
Checker[] checkers = new Checker[10];
for (int i = 0; i < checkers.length; i++) {
checkers[i] = new Checker();
}
obj=new checker[10]; means you are creating an array that can hold 10 instances of checker. This does NOT create 10 instances of checker. So the checker constructor will not be called.
What can i do to call the constructor of all the 10 objects of class
checker?
Create new instances of checker in a loop (or in some other way) and add them to your array.
obj=new checker[10] just sets obj to an array of checker objects. It does not fill the array with new checkers. To do that, you will need to do something like this:
obj=new checker[10];
for (int i = 0; i < obj.length; i++) {
obj[i] = new checker();
}
To answer your question more generally, to call the constructor, you must invoke the new keyword explicitly.
You are creating ten empty boxes(null references) to hold references of ten objects. For calling constructor for ten objects, you have to loop through these ten empty boxes and store reference of a new object in each box. i.e.
Checker[] chkArray = new Checker[10];
for (int i = 0; i < checkers.length; i++) {
chkArray[i] = new Checker();
}

Initializing static variables in java

What exactly is meant by "Static variables are initialized when a class is loaded"? I read lots of discussions available on the net but still I am confused. Step 2 is be the initialization step, right? Then what happens in step 1 "when the class is loaded"?
public class NewClass {
static int[] arr; //Step 1
NewClass(){
arr = new int[10]; //Step 2
for(int i= 0;i<10;i++){
arr[i] = i;
}
}
}
If you want to initialize it when the class is loaded, then you should use the static initializer:
public class NewClass {
static int[] arr; //Step 1
static {
arr = new int[10]; //Step 2
for(int i= 0;i<10;i++){
arr[i] = i;
}
}
}
Initializing a static member in the constructor defeats the purpose of static members, since they don't belong to any instance, and each new instance you'll create will override the value of your static array.
You should either initialize the static variable when it's declared or in a static initialization block.
static int[] arr = new int[10];
or
static {
arr = new int[10];
}
The initialization (i.e. the execution of the static declarations and static initialization blocks) will occur when the class is loaded, which happens when your application first accesses any member (constructor, static method, static variable) of your class.
Step 2 is be the initialization step, right?
No, It's called construction of array. The initialization of array means putting things into it that you are doing after step 2.
Then what happens in step 1 "when the class is loaded"?
when the class is loaded all static variables are initialized with their default values. In case of Object it's default value is null or you can say a reference that is pointing to nothing. No memory is allocated to array at this point of time.
What happens till Step 2 ?
When the object of type NewClass is created using keyword new at that time constructor is called and the array is constructed and memory is assigned for 10 int values in the heap with all zero as default value (till step 2)
What happens after Step 2?
After Step 2 you are actually initializing the array i.e putting the values in it.
static int[] arr; // declaration
arr = new int[10]; // construction
arr[i] = i; // initialization
If you want to read more about it then read book SCJP Sun Certified Programmer for Java 6
When the class is loaded by Class Loader, the job of linker starts. Linker verifies the Java code, whether it is written as per specifications given in Java Language & JVM. If it found valid Java Code then it starts allocating memory for fields, methods, interfaces, etc. Create a reference to that memory locations. Once reference is assigned to memory location, all field variables, methods, interfaces, etc are initialized to there default values, if not specified explicitly. Otherwise, it assigns whatever value is set as its initial value.

Difference between {} and {{}} initialization in Java

public class A{
}
A a = new A(){{
final int x = 1; // IT HAS TO BE FINAL HERE. WHY?
}};
A aa = new A(){
int x = 1; // THIS NEED NOT BE FINAL. WHY?
final int y = 1; // STILL FINAL IS ALLOWED HERE. WHY?
public int getX(){
return x;
}
};
Can somebody please answer the questions mentioned inside the snippet?
Thanks
The outer set of {} declares an anonymous subclass
The inner set declares an initialization block within that subclass.
With the following example, it becomes easier to understand what's going on:
List<String> strings = new ArrayList<String>() {{
add("string");
add("another string");
}};
You basically say: I want a subclass of List, which calls method add at initialization.
It's similar to:
List<String> strings = new ArrayList<String>();
strings.add("string");
strings.add("another string");
A a = new A(){{
final int x = 1; // IT HAS TO BE FINAL HERE. WHY?
It needn't.
The difference between the two is that in the first case, you're writing the code used to initialize each object in the double braces. That x is its local variable (doesn't have anything to do with objects of class A).
In the second case, you're defining the classes body. x would be its member variable. If it were static, its class variable. If final a (basically) constant.
I wonder, why would you want to use the first version of the code (the one with {{}}). The x variable declared inside it's not useful at all, it's local only to the block scope in which it was defined, and being inside an anonymous class, you won't be able to reference it anywhere in the code.
And anyway, the first version of x declaration does not need to be final, it compiles just as fine, with or without final.
In your first example the inner braces create something called an instance initializer. It's an obscure way to initialize variables and call instance methods when an object is constructed. So the first example creates an anonymous subclass of A and creates a local variable within the scope of the initializer. It doesn't have to be final.
In the second example you're creating an anonymous subclass of A but not creating an instance initializer, the variables you create are instance variables of the anonymous subclass.
The first instance A a = new A(){{... has an initialisation block inside the declaration. Another way of writing it would be like this:
A a = new A()
{
{
final int x = 1; // This is inside an initialisation block
}
};
Changing the formatting makes it a bit more obvious.

What is the scope of a Java variable in a block? [duplicate]

This question already has answers here:
Why does Java not have block-scoped variable declarations?
(6 answers)
Closed 5 years ago.
I know in C++ variables have block scope, for example, the following code works in C++:
void foo(){
int a = 0;
for (int i = 0; i < 10; ++i){
int a = 1; // Redefine a here.
}
}
But this snippet doesn't work in Java, it reports "duplicate local variable a", does it mean Java variables don't have BLOCK scope?
They have block scope. That means that you can't use them outside of the block. However Java disallows hiding a name in the outer block by a name in the inner one.
java variables do have a block scope but if you notice int a is already defined in scope
{
int a = 0;
{
{
}
}
}
all subscopes are in scope of the uppermost curly braces. Hence you get a duplicate variable error.
Section §14.4.2 says:
The scope of a local variable
declaration in a block (§14.2) is the
rest of the block in which the
declaration appears, starting with its
own initializer (§14.4) and including
any further declarators to the right
in the local variable declaration
statement.
The name of a local variable v may not
be redeclared as a local variable of
the directly enclosing method,
constructor or initializer block
within the scope of v, or a
compile-time error occurs.
The previous answers already stated the reason, but I just want to show that this is still allowed:
void foo(){
for(int i = 0; i < 10; ++i){
int a = 1;
}
int a = 0;
}
In this case the a inside the loop doesn't hide the outer a, so it's valid.
Also IMHO it should be this way in C++ too, it's less confusing and prevents accidental declaration of variable with same name.
It does, but it's nested, so the "a" you defined in foo() is available in all blocks within foo.
Here is an example of what you're looking for:
void foo(){
{
int a = 0;
// Do something with a
}
for(int i = 0; i < 10; ++i){
int a = 1; //define a here.
}
}

Categories