【问题标题】:Java pre-instantiated arrayJava预实例化数组
【发布时间】:2019-10-04 20:25:35
【问题描述】:

尝试在我正在制作的简单 GUI 中预实例化一组 JTextField。我将它们放入一个数组中,这样当我更改状态时,我可以循环它们并使用简单的 for 循环清除数据。在我在构造函数中实例化窗口中使用的每个对象后,程序崩溃了。我已经包含了声明数组和 5 个按钮对象的 2 行。我还包括我如何实例化每个 TextField。 代码在调用我的 clear 方法时崩溃,空指针异常。经过仔细检查,我发现我的字段 [0] 到字段 [4] 都是空的。我不知道为什么。 tf1 到 tf5 不为 null

//instantiation of fields t1, t2, t3, t4, t5 and fields array
private JTextField tf1, tf2, tf3, tf4, tf5;
private JTextField[] fields  = {tf1, tf2, tf3, tf4, tf5};

//In the constructor
tf1 = new JTextField();

//clear method called after all objects are instantiated
private void clear() { for(JTextField f : fields) f.setText(""); }

预期字段[0] 具有相同的 tf1 值,但为空;

【问题讨论】:

  • Java 是按值传递的。它不会“链接”到变量。它将在数组创建时将变量指向的任何内容放入数组中,即null。它不会记住变量并在变量更新时更新。
  • 为什么不fields[0] = new JTextField()

标签: java arrays swing


【解决方案1】:

观察以下代码:

public class Main
{
  public static void main(String[] args)
  {
    Main m = null;
    var ms = new Main[]{m};
    m = new Main();
    System.out.println(m);
    System.out.println(ms[0]);
  }
}

输出:

Main@5acf9800
null

数组在创建时不会保留对变量的引用。相反,它们会及时复制引用的值。即使引用的值发生变化,数组中的值也保持不变。

如果您不希望(根本)更改您的数组,您可以执行以下操作:

//instantiation of fields t1, t2, t3, t4, t5 and fields array
private JTextField tf1, tf2, tf3, tf4, tf5;
private JTextField[] fields;

//In the constructor
tf1 = new JTextField();
//instantiate the others as well if you'd like
fields = new JTextField[] {tf1, tf2, tf3, tf4, tf5};

//clear method called after all objects are instantiated
private void clear() { for(JTextField f : fields) f.setText(""); }
...
// anytime you update tf1 later, update fields[0].
// anytime you update tf2 later, update fields[1].
//     ...            ...            ...

通常最好只保留变量,或者只保留一个数组/集合。管理一组变量已经很烦人了。为什么要通过创建两组来让自己变得更难?

【讨论】:

  • 是的,老实说,我忘记了这一点,保留多个相同的实例变量是没有意义的。我要做一个数组的唯一原因(我想)是为了更快地清除文本字段中的文本,我猜我只是让自己更难了
  • 每个人都会犯错:P
【解决方案2】:

如果您想创建一个包含五个JTextField 对象的数组,您可以简单地执行以下操作...

JTextField[] fields = new JTextField[5];
for (int i = 0; i < 5; i++) {
    fields[i] = new JTextField();
}

【讨论】:

    【解决方案3】:

    当您为 tf1 设置值时,您必须重新添加到列表中。如果你不这样做,只有变量 tf1 会有一个值,而不是 Array 项。如何修复,例如:

    tf1 =(一些价值); fields[0] = tf1;

    【讨论】:

      【解决方案4】:

      使用 unmodifiableList 代替数组

      您的文本字段 tf1、tf2、tf3、tf4、tf5 可能不会改变?

      private List<JTextField> fields = Collections.unmodifiableList( Arrays.asList(
          tf1,
          tf2,
          tf3,
          tf4,
          tf5 ) );
      


      clear() 函数就是

      private void clear() { fields.forEach( f -> f.setText( "" ) ); };
      

      【讨论】:

        【解决方案5】:

        您的 JTextField 引用 tf1tf2tf3tf4tf5 在您初始化数组时未初始化。

        因此考虑到 Java 是 pass-by-value,您的数组将由 null 值初始化。

        当您为 tf1 分配一个值时,它会被分配一个新的对象引用,因此不会影响它指向的前一个对象(如果有的话)。

        【讨论】:

          猜你喜欢
          • 2015-07-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-06-10
          相关资源
          最近更新 更多