【问题标题】:Static ArrayList accessed from another class is always empty从另一个类访问的静态 ArrayList 始终为空
【发布时间】:2013-12-09 22:55:43
【问题描述】:

我有以下课程

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");        
    }
}

上面类中的静态 ArrayList 是通过下面类的调用动态填充的。

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);
    }
}

我正在尝试访问下面类中的静态 ArrayList。但它总是空的。

public class StaticArrayListAccessTest {

    public static void main(String[] args) throws Exception {   
    System.out.println(TestStaticArrayList.getArrayValues());

    }
}

如果我使用一个

static {
...
}

填充 Arraylist 它工作正常。我有一个动态填充 ArrayList 的用例,这意味着我不能使用静态 {..} 块。在这种情况下如何访问静态 ArrayList。

对此的任何帮助表示赞赏。

【问题讨论】:

  • 等等,你是在两次不同的时间运行程序吗?你有两种不同的main 方法。
  • 是的。首先我运行程序来填充数组列表。然后我尝试访问它。
  • 静态初始化块在类初始化时自动运行。这就是为什么如果你使用 static {} 你的数组已经被填充了。
  • 如果您告诉我们您到底想要达到什么目标也会有所帮助。或者您可能只是在寻找为什么会发生这种行为?
  • 请采纳对您最有帮助的答案。请记住,投票并不总是准确反映您作为提问者是否应该接受答案,但它们确实有助于确定这一点,同时知道给定的答案对您有所帮助。

标签: java arraylist static static-methods static-members


【解决方案1】:

静态字段在程序执行期间保留其值,但仅在一次执行中。静态字段的目的是使值可用,而无需获取任何类的实例。只有一个 main 方法会被隐式调用,因此要么填充并忘记列表,要么从另一个入口点读取空列表。

static { } 阻止工作的原因是它们在检索列表之前的某个时间运行,无论入口点如何

出于这个原因,以下方法将起作用:

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());
    }
}

它将填充 ArrayList,然后尝试在同一执行中读取它。

无论如何,您不需要使用反射,因为在这种情况下它更慢、风险更大且没有根据。只需执行以下操作:

TestStaticArrayList.populateArray();

【讨论】:

  • 所以在我的情况下,当我有一个静态块并且只要我调用TestStaticArrayList.&lt;Somemethod&gt; 时,该静态块下的任何内容都会被执行??
【解决方案2】:

来自 cmets:“是的,我很好奇为什么它适用于静态块而不是静态方法”

静态初始化块在类初始化时自动调用TestStaticArrayList 什么时候初始化?在这里,当您第一次访问它的一个静态方法/字段时(here 更多关于初始化):

System.out.println(TestStaticArrayList.getArrayValues());

当您打印结果时,静态初始化块已经运行。但是,如果您没有任何静态初始化块,那么代码中就没有填充 ArrayList 的位置。这就是为什么在你的第二个程序中ArrayList 是空的。您可以将其填充到自动运行的静态初始化块中,或者在打印其值之前显式调用 populateArray()

【讨论】:

    【解决方案3】:

    它当然是空的。永远不会调用方法populateArray()。如果您需要查看填充列表,您需要这样做:

    TestStaticArrayList.populateArray();
    TestStaticArrayList.getArrayValues();
    

    仅供参考,我强烈建议您更改代码结构。 staticdynamic 是两个截然不同的概念是有原因的!

    【讨论】:

    • 提示:无需创建TestStaticArrayList 的实例,因为您只会调用static 方法。
    • 哦,是的,当然。感谢您指出不必要的行。
    【解决方案4】:

    一个类不仅仅是“执行”的,因为它有一个main 方法。这种方法是启动程序的入口点。如果这不是您的切入点,您将不得不显式调用相应的方法。

    当你调用TestStaticArrayList.getArrayValues() 时,它不会在那里执行main 方法。

    如果您执行该程序两次,它将不知道上次列表中的值:每个工作彼此分开。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-27
      • 2012-09-06
      • 2016-11-15
      • 1970-01-01
      相关资源
      最近更新 更多