问题
I have the following classes
import java.util.ArrayList;
import java.util.List;
public class TestStaticArrayList {
public static List<String> numberList = new ArrayList<String>();
public static List<String> getArrayValues(){
return numberList;
}
public static void populateArray() {
numberList.add("1");
numberList.add("2");
numberList.add("3");
}
}
The static ArrayList in the above class is populated dynamically from a call from below class.
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
public class TestStaticInvokationClass {
public static void main(String[] args) throws Exception {
Class staticKlass = Class
.forName("com.sathish.test.TestStaticArrayList");
staticKlass.getMethod("populateArray", null).invoke(null, null);
}
}
I am trying to access the Static ArrayList in the below class.But its always empty.
public class StaticArrayListAccessTest {
public static void main(String[] args) throws Exception {
System.out.println(TestStaticArrayList.getArrayValues());
}
}
If I use a
static {
...
}
to populate the Arraylist it works fine. I have an use case where the ArrayList is populated dynamically which means I cannot use a static {..} block.How can I access the Static ArrayList in this scenario.
Any help on this is appreciated.
回答1:
A static field does not retain its value across program executions, but only within one execution. The purpose of a static field is to make a value available without having to acquire an instance of any class. Only one main method will be called implicitly so either the list will be populated and forgotten, or the empty list will be read from the other entry point.
The reason static { }
blocks work is that they get run sometime before the list is retrieved, no matter the entry point.
The following will work for this reason:
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
public class TestStaticInvokationClass {
public static void main(String[] args) throws Exception {
Class staticKlass = Class
.forName("com.sathish.test.TestStaticArrayList");
staticKlass.getMethod("populateArray", null).invoke(null, null);
System.out.println(TestStaticArrayList.getArrayValues());
}
}
It will populate the ArrayList and then try to read it in the same execution.
Anyway, you need not use reflection, as it's slower, riskier, and unwarranted in this situation. Simply do as follows:
TestStaticArrayList.populateArray();
回答2:
From comments: "Yes,I was curious on why it works with static block and not static methods"
Static initialization blocks are called automatically when a class is initialized. When is TestStaticArrayList
initialized? Right here, when you access one of its static methods/fields for the first time (here is more about initialization ):
System.out.println(TestStaticArrayList.getArrayValues());
The static initialization block will have already run when you print the results. However, if you don't have any static initialization blocks, then there's no place in the code were the ArrayList
is populated. That's why in your second program the ArrayList
is empty. You either populate it in a static initialization block, which is ran automatically, or you call populateArray()
explicitly before printing its values.
回答3:
It will be empty, of course. The method populateArray()
is never called. If you need to see the populated list, you need to do this:
TestStaticArrayList.populateArray();
TestStaticArrayList.getArrayValues();
FYI, I strongly suggest you change your code structure. There is a reason static and dynamic are two very different concepts!
回答4:
A class isn't just "executed" because it has a main
method. Such a method is a point of entry to start your program. You will have to invoke the corresponding methods explicitly if that's not your point of entry.
When you call TestStaticArrayList.getArrayValues()
it will not execute the main
method in there.
If you execute the program twice it will not know about the values that were in the list the last time: each work separate from eachother.
来源:https://stackoverflow.com/questions/20482603/static-arraylist-accessed-from-another-class-is-always-empty