You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java程序中第二个Player对象实例为何覆盖第一个实例?

问题:所有Player对象被视为同一实例的原因及修复方案

我正在编写一个程序,允许用户输入Player对象的四个特征并将该对象添加至Player对象的ArrayList中,但所有Player对象均被视为同一对象。我怀疑程序仅向ArrayList中添加了对同一对象的多个引用,却无法生成具有不同实例变量的独立对象。若将Player类的所有字段改为非静态,会出现"nonstatic variable/method cannot be referenced from a static context"错误。

测试时,输入球员"Babe Ruth"(球衣1号,体重155,身高70)后,再输入球员"Joe Dimaggio"(球衣2号,体重170,身高75),程序未存储后者信息,所有实例均显示前者属性。

实际输出(列出所有球员):

Name: Babe Ruth
Jersey number: 1
Weight: 155
Height: 70
Name: Babe Ruth
Jersey number: 1
Weight: 155
Height: 70

预期输出:

Name: Babe Ruth
Jersey number: 1
Weight: 155
Height: 70
Name: Joe Dimaggio
Jersey number: 2
Weight: 170
Height: 75


驱动类代码(MainMenu.java)

package playerdatamanager;

import java.util.*;

public class MainMenu {

    public static void main(String[] args) {
        
        ArrayList<Player> playerRoster = new ArrayList<>();

        Scanner input = new Scanner(System.in);

        int exitMenu = 0;

        while (!"7".equals(exitMenu)) {

            System.out.println("Please choose an option or press 7 to exit [1-7].");
            System.out.println("1. " + "Add a player");
            System.out.println("2. " + "Update a player");
            System.out.println("3. " + "Delete a player");
            System.out.println("4. " + "List all players");
            System.out.println("5. " + "Calculate the average BMIs for the players");
            System.out.println("6. " + "Display the details of the tallest player");
            System.out.println("7. " + "Exit");

            int menuOption = Integer.parseInt(input.nextLine());

            switch (menuOption) {
                case (1):

                    System.out.println("Please enter the name of the player.");

                    String newPlayerName = input.nextLine();

                    System.out.println("Please enter the jersey number of the player.");

                    int newPlayerJerseyNumber = Integer.parseInt(input.nextLine());

                    System.out.println("Please enter the height of the player.");

                    double newPlayerHeight = Double.parseDouble(input.nextLine());

                    System.out.println("Please enter the weight of the player.");

                    double newPlayerWeight = Double.parseDouble(input.nextLine());

                    playerRoster.add(new Player(newPlayerName, newPlayerJerseyNumber, newPlayerHeight, newPlayerWeight));

                    break;

                case (2):
                    System.out.println("Which player would you like to update?");

                    System.out.println(playerRoster.toString());

                    int playerIndex = Integer.parseInt(input.nextLine());

                    System.out.println("Selected" + playerRoster.get(playerIndex).toString());

                    System.out.println("Enter the value you would like to change[1. name ,2. jersey number,3. weight,4. height]");

                    int userValueUpdate = Integer.parseInt(input.nextLine());

                    switch (userValueUpdate) {

                        case (1):
                            System.out.println("Please enter the new value for the player's name.");

                            Player.setName(input.nextLine());

                            break;

                        case (2):
                            System.out.println("Please enter the new value for the player's jersey number.");

                            Player.setJerseyNumber(Integer.parseInt(input.nextLine()));

                            break;

                        case (3):

                            System.out.println("Please enter the new value for the player's weight.");

                            Player.setWeightInPounds(Double.parseDouble(input.nextLine()));

                            break;

                        case (4):
                            System.out.println("Please enter the new value for the player's height.");

                            Player.setHeightInInches(Double.parseDouble(input.nextLine()));

                            break;
                    }

                    break;
                case (3):

                    System.out.println("Which player would you like to delete?");

                    int userDeletion = Integer.parseInt(input.nextLine());

                    playerRoster.toString();

                    playerRoster.remove(userDeletion);

                    break;

                case (4):

                for (int i = 0; i < playerRoster.size();i++) {
                    
                    System.out.print("Name: " + playerRoster.get(i).getName() + "\nHeight: " + Double.toString(playerRoster.get(i).getHeight()) + "\nWeight: " + Double.toString(playerRoster.get(i).getWeight()) + "\nJersey Number: " + Integer.toString( playerRoster.get(i).getJerseyNumber()) + "\n\n");
                }

                    break;
            }
        } 
    }
}

Player类代码(Player.java)

package playerdatamanager;

public class Player {

    private static String name;
    private static int jerseyNumber;
    private static double height;
    private static double weight;

    /**
     * The default constructor for the Player object.
     */
    public Player() {
    }

    /**
     * Overloaded constructor to initialize Player object with user values.
     *
     * @param name The name of the Player
     * @param jerseyNumber The Jersey Number of the Player
     * @param height The height of the Player
     * @param weight
     */
    public Player(String name, int jerseyNumber, double height, double weight) {
        this.name = name;
        this.jerseyNumber = jerseyNumber;
        this.height = height;
        this.weight = weight;
    }

    /**
     * setter method to set the player's name.
     *
     * @param userName The name given by the user.
     */
    public static void setName(String userName) {
        name = userName;
    }

    /**
     * setter method to set a player's jersey number.
     *
     * @param userJerseyNumber The jersey number given by the user.
     */
    public static void setJerseyNumber(int userJerseyNumber) {
        jerseyNumber = userJerseyNumber;
    }

    /**
     * setter method to set a player's height in inches.
     *
     * @param userHeight The height in inches given by the user.
     */
    public static void setHeightInInches(double userHeight) {
        height = userHeight;
    }

    /**
     * setter method to set a player's weight in pounds.
     *
     * @param userWeight The weight in pounds given by the user.
     */
    public static void setWeightInPounds(double userWeight) {
        weight = userWeight;
    }

    /**
     * getter method to retrieve the name of a player.
     *
     * @return The player's name.
     */
    public static String getName() {
        return name;
    }

    /**
     * getter method to retrieve the jersey number of a player.
     *
     * @return The player's jersey number.
     */
    public static int getJerseyNumber() {
        return jerseyNumber;
    }

    /**
     * getter method to retrieve the weight in pounds of a player.
     *
     * @return The player's weight in pounds.
     */
    public static double getWeight() {
        return weight;
    }

    /**
     * getter method to retrieve the height in inches of a player.
     *
     * @return The player's height in inches.
     */
    public static double getHeight() {
        return height;
    }

    public static double BMICalculation() {
        double BMI;

        BMI = 703 * (getWeight() / (getHeight() * getHeight()));

        return BMI;
    }

    public static void playerRosterToString(double height, double weight, int jerseyNumber, String name) {

        String playerStats = "Name: " + name + "\nHeight: " + Double.toString(height) + "\nWeight: " + Double.toString(weight) + "\nJersey Number: " + Integer.toString(jerseyNumber);

        System.out.print(playerStats);

    }

}

问题原因及修复方案

核心问题

Player类中所有字段和方法都被声明为static,这意味着这些成员属于类本身,而非类的实例。所有Player对象共享同一组静态变量,所以每次创建新Player时,都会覆盖之前的静态变量值,导致所有实例显示相同的数据。

修复步骤

  1. 移除Player类中所有成员的static修饰符

    • 将字段name、jerseyNumber、height、weight的static去掉,改为实例变量。
    • 将所有getter、setter方法,以及BMICalculation、playerRosterToString方法的static修饰符去掉,改为实例方法。
  2. 修改MainMenu中的调用方式

    • 在更新球员信息时,不能直接通过Player.setXXX()调用静态方法,而是要获取ArrayList中对应的Player实例,再调用实例方法:
      // 原错误代码
      Player.setName(input.nextLine());
      // 修复后
      playerRoster.get(playerIndex).setName(input.nextLine());
      
    • 同理,其他setter调用都要改为针对具体实例的调用。
  3. 可选:重写Player类的toString方法
    原playerRosterToString方法设计不合理,建议重写toString()方法,方便直接打印Player实例信息:

    @Override
    public String toString() {
        return "Name: " + name + "\nHeight: " + height + "\nWeight: " + weight + "\nJersey Number: " + jerseyNumber;
    }
    

修复后的Player类示例

package playerdatamanager;

public class Player {

    private String name;
    private int jerseyNumber;
    private double height;
    private double weight;

    public Player() {
    }

    public Player(String name, int jerseyNumber, double height, double weight) {
        this.name = name;
        this.jerseyNumber = jerseyNumber;
        this.height = height;
        this.weight = weight;
    }

    public void setName(String userName) {
        name = userName;
    }

    public void setJerseyNumber(int userJerseyNumber) {
        jerseyNumber = userJerseyNumber;
    }

    public void setHeightInInches(double userHeight) {
        height = userHeight;
    }

    public void setWeightInPounds(double userWeight) {
        weight = userWeight;
    }

    public String getName() {
        return name;
    }

    public int getJerseyNumber() {
        return jerseyNumber;
    }

    public double getWeight() {
        return weight;
    }

    public double getHeight() {
        return height;
    }

    public double BMICalculation() {
        return 703 * (weight / (height * height));
    }

    @Override
    public String toString() {
        return "Name: " + name + "\nHeight: " + height + "\nWeight: " + weight + "\nJersey Number: " + jerseyNumber;
    }
}

修复后的MainMenu中更新球员的代码片段

case (2):
    System.out.println("Which player would you like to update?");
    for (int i = 0; i < playerRoster.size(); i++) {
        System.out.println(i + ": " + playerRoster.get(i));
    }
    int playerIndex = Integer.parseInt(input.nextLine());
    Player selectedPlayer = playerRoster.get(playerIndex);
    System.out.println("Selected\n" + selectedPlayer);

    System.out.println("Enter the value you would like to change[1. name ,2. jersey number,3. weight,4. height]");
    int userValueUpdate = Integer.parseInt(input.nextLine());

    switch (userValueUpdate) {
        case (1):
            System.out.println("Please enter the new value for the player's name.");
            selectedPlayer.setName(input.nextLine());
            break;
        case (2):
            System.out.println("Please enter the new value for the player's jersey number.");
            selectedPlayer.setJerseyNumber(Integer.parseInt(input.nextLine()));
            break;
        case (3):
            System.out.println("Please enter the new value for the player's weight.");
            selectedPlayer.setWeightInPounds(Double.parseDouble(input.nextLine()));
            break;
        case (4):
            System.out.println("Please enter the new value for the player's height.");
            selectedPlayer.setHeightInInches(Double.parseDouble(input.nextLine()));
            break;
    }
    break;

内容的提问来源于stack exchange,提问作者LibreEstVitae

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 06:30:55