2
import java.util.ArrayList;
public class Team {  

    private String name;
    private ArrayList<Player> team;

    public Team(String name)    {
        this.name = name;
        //how come i have to initialize it here in the constructor to see the full list?          
        this.team = new ArrayList<Player>();
    }

    public void addPlayer(Player player)    {
        //why can't i initialize it here in the method, this gives me a list of only recent add?
        //this.team = new ArrayList<Player>(); 
        this.team.add(player);
    }

    public void printPlayers()  {            
        for(Player players : this.team) {
            System.out.println(players);
        }
    }
    public String getName() { return this.name; }
}
  • 我试图弄清楚为什么this.team = new ArrayList<Player>()必须在构造函数中?
  • 为什么我不能this.team = new ArrayList<Player>()在方法中初始化?
  • 我知道当我使用构造函数中的代码运行它时,它会按预期工作(添加内容时它会给我完整的列表)
  • 但是当它在方法中初始化时,它只列出最后一个给定的添加到列表中。在方法中初始化它是错误的吗?
  • private ArrayList<Player> team = new ArrayList<Player>();像在构造函数之前那样初始化它有什么区别?
4

5 回答 5

1

为什么我不能在方法中初始化 this.team = new ArrayList()?

您每次都创建一个新的 ArrayList 并将其分配给this.team. 因此,每次您调用 时addPlayer,您都将替换 this.team为一个新的空 ArrayList,然后添加一个带有 的播放器this.team.add(player),因此只有最后添加的播放器始终位于 ArrayList 中。

如果您真的不想在构造函数中创建 ArrayList,您可以做的是每次添加播放器时检查是否为nullthis.team,如果 ArrayList 未创建或为空,则只需创建一个。

public void addPlayer(Player player)    {
    if (this.team == null) {
        this.team = new ArrayList<Player>();
    }
    this.team.add(player);
}

另外,将其初始化为 private ArrayList team = new ArrayList(); 有什么区别?在构造函数之前?

如果您想知道private关键字是否有任何改变,您应该阅读有关访问修饰符的 Java 文档:https ://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

除此之外,在这种情况下,在构造函数之前初始化不会改变任何内容。

于 2018-02-16T22:56:10.123 回答
1

只回答问题:

private ArrayList<Player> team = new ArrayList<Player>();像在构造函数之前那样初始化它有什么区别?

team什么都没有,除了之前会被初始化的事实name

字段初始化器是实例初始化器的语法糖。所以这:

private ArrayList<Player> team = new ArrayList<Player>();

与此相同:

private ArrayList<Player> team;

{
  // This is an instance initializer.
  team = new ArrayList<Player>();
}

和实例初始值设定项聚集在一起并插入到调用(隐式或显式)的每个构造函数中super,在调用super和构造函数主体的其余部分之间。所以这:

public class Team {  

    private ArrayList<Player> team = new ArrayList<>();

    public Team(String name)    {
      this.name = name;
    }
}

等同于:

public class Team {  

    private ArrayList<Player> team;

    public Team(String name)    {
      super();

      this.team = new ArrayList<>();

      this.name = name;
    }
}
于 2018-02-16T22:43:13.047 回答
1

由于每个构造函数调用都会产生一个新的不同对象,this.team = new ArrayList<Player>();因此构造函数中的行每个实例只会被调用一次,因此在这种特定情况下,每个对象只会有一个 ArrayList实例。

另一方面,addPlayer可以在给定对象上多次调用该方法,因此this.team = new ArrayList<Player>();addPlayer方法中将替换(覆盖)每个方法调用上的前一个列表。

于 2018-02-16T22:43:58.130 回答
1

我试图弄清楚为什么 this.team = new ArrayList() 必须在构造函数中?

它没有,它必须在使用之前进行初始化。只要您之前不调用 printPlayer() 或 addPlayer(),您就可以在任何您想要的地方初始化它。

为什么我不能在方法中初始化 this.team = new ArrayList()?

你实际上可以。看这个例子:

public void addPlayer(Player player) {
    if (team == null) {
        team = new ArrayList();
    }

    team.add(player);
}

public void printPlayers() {
    if (team != null) {
        for (Player p : team) {
            System.out.println(p);
        }
    }
}

但是当它在方法中初始化时,它只列出最后一个给定的添加到列表中。在方法中初始化它是错误的吗?

不,这没有错。如果您按照上面示例的方式进行操作,它通常被称为“延迟初始化”或“按需”。

另外,将其初始化为 private ArrayList team = new ArrayList(); 有什么区别?在构造函数之前?

不多,区别在于初始化的时间。

public class Example {
    public static List<T> myList = new ArrayList<T>(); // this is done first
    public static List<T> aList;
    public List<T> someList;
    static {
        // this is also done first (on class load)
        aList = new ArrayList<T>();
    }

    { 
        // this is done right before the constructor (I believe)
        // it is called an 'initialization block'
        someList = new ArrayList<T>();
    }

    public Example() {
        // this one you already know...
    }
}
于 2018-02-16T22:47:14.587 回答
1

您可以这样做(以防止在每个 addPlayer 方法调用上重新创建 ArrayList):

    public void addPlayer(Player player)  {
        if (this.team == null) {
            this.team = new ArrayList<Player>();
        }
        this.team.add(player);
    }

但这将是非常奇怪的代码...更好的做法是在构造函数中初始化“团队”列表或在字段声明中内联。他们俩都做同样的事情。我更喜欢在构造函数中初始化字段,但这只是我的习惯。其他程序员可能更喜欢内联版本,这并没有错/不好。

于 2018-02-16T22:47:30.393 回答