【问题标题】:Getting a List from another class从另一个类获取列表
【发布时间】:2017-07-06 18:57:48
【问题描述】:

我一直在试图弄清楚如何使 ClassA 中的 List 可供 ClassB 访问 我尝试创建列表的实例/对象,但是当我获得列表的大小时它总是返回空(而在主类中它不是空的)。

示例:

A 类:

List<String> players = new ArrayList<String>();

如果我在这里使用players.size(),它将返回例如 2

在 ClassB 中,我尝试了以下方法:

 ClassA classA = new ClassA();
 List<String> newList = classA.players;

newList.size() 无论如何都会返回 0。

我也尝试过使用 getter,但这似乎没有什么不同。

示例:

A 类:

List<String> players = new ArrayList<String>();
public List<String> getList(){
    return this.players;
}

B 类:

ClassA.getList().size()

这也将始终返回 0

我该如何正确地做到这一点?我尝试使用静态,这似乎有效,但有人告诉我:

“静态不是这项工作的正确工具。它是一种内存管理 工具,而不是访问修饰符。”

他告诉我:

您可以通过传递而不是静态而不是创建新实例 通过将实例作为参数添加到其他类 构造函数

但是我真的不明白他的意思。如果有人可以用一个例子来解释这一点,那就太棒了。提前致谢!

编辑:由于你们中的很多人都不太了解我想去的地方,所以我将发布我的来源: 在示例中称为 ClassA

public class TeamManager {

String prefix = new Messages().prefix;
List<String> players = new ArrayList<String>();
List<String> human = new ArrayList<String>();
List<String> infected = new ArrayList<String>();

void join(Player p){
    if(!players.contains(p.getName())){
        players.add(p.getName());
        teleportToLobby(p);
        for (String temp : players) {
            Bukkit.getPlayer(temp).sendMessage("§e§l"+p.getName()+ " has joined infection. §7("+players.size()+"/16)");
        }
    }else{
        p.sendMessage(prefix + "§cFailed. You are already in the game!");
    }
}
void leave(Player p){
    if(players.contains(p.getName())){
        p.teleport(Bukkit.getWorlds().get(0).getSpawnLocation());
        players.remove(p.getName());
        for (String temp : players) {
            Bukkit.getPlayer(temp).sendMessage("§7§l"+p.getName()+ " has left infection. §7("+players.size()+"/16)");
        }
    }else{
        p.sendMessage(prefix + "§cYou are not in a game!");
    }
}
void addToHumans(String playername){
    human.add(playername);
}
void removeFromHumans(String playername){
    human.remove(playername);
}
void addToInfected(String playername){
    infected.add(playername);
}
void removeFromInfected(String playername){
    infected.remove(playername);
}

void teleportToLobby(Player p){
    Location lobby = getLocFromConfig("lobby");
    if(lobby != null){
        p.teleport(lobby);
        p.sendMessage(prefix + "§aSuccessfully added to game!");
    }else{
        p.sendMessage(prefix + "§cLobby not set! Make sure to set a lobby using /infection setlobby");
    }
}
void startGame(){
    /*if(human.size() >= 4){
    }*/
    for (String temp : players) {
        Bukkit.getPlayer(temp).sendMessage("Game will start shortly!");
    }
}
Location getLocFromConfig(String locationName){
    if(Main.plugin.getConfig().get("lobby") != null){
        double x = Main.plugin.getConfig().getInt(locationName+".x");
        double y = Main.plugin.getConfig().getInt(locationName+".y");
        double z = Main.plugin.getConfig().getInt(locationName+".z");
        World world = Main.plugin.getServer().getWorld(Main.plugin.getConfig().getString(locationName+".world"));
        Location l = new Location(world, x, y, z);
        return l;
    }else{
        Bukkit.getLogger().warning("[Infection] Lobby has not been set!");
        return null;
    }
}
int getPlayersInLobby(){
    return players.size();
}

public List<String> getPlayers(){
    List<String> players = this.players;
    return players;
}
public List<String> getHumans(){
    return human;
}
public List<String> getInfected(){
    return infected;
}

}

事件类(在示例中称为 ClassB)

public class Events implements Listener{

TeamManager teamman = new TeamManager();
List<String> players = teamman.getPlayers();
List<String> humans = teamman.getHumans();
List<String> infected = teamman.getInfected();
@EventHandler
public void onPlayerJoin(PlayerJoinEvent e){
    //Player p = (Player) e.getPlayer();
    //e.setJoinMessage("["+lvl+"]" + e.getPlayer().getName() +"has joined the game!");
    //p.setDisplayName("[lvl1]"+p.getName());

}
@EventHandler
public void onPlayerDamage(EntityDamageByEntityEvent  e){
    if(e.getEntity() instanceof Player){
        Player p = (Player) e.getEntity();
        Bukkit.getServer().broadcastMessage("Players: "+ players);
        if(players.contains(p.getName())){
            if((p.getHealth() - p.getLastDamage()) < 1){
                for (String temp : players) {
                    Bukkit.getPlayer(temp).sendMessage("§c"+p.getName()+" got infected by "+p.getKiller().getName()+"!");
                }
                e.setCancelled(true);
                 p.setHealth(20);
                 teamman.addToInfected(p.getName());
                 teamman.removeFromHumans(p.getName());
                 p.sendMessage("§cYou have been infected!!");
            }
        }
    }
}

}

如上所述,我希望能够从 TeamManager 访问列表并在事件中使用它们。正如所解释的,players 在 Events 类中是空的。我希望这会有所帮助。

【问题讨论】:

  • 您的列表中没有任何玩家。您可以在构造函数中添加玩家,在创建列表时创建玩家,或者创建一个允许您将玩家添加到列表的方法。
  • @ThomasK 我知道如何添加到列表中,为了简单起见,我把它省略了。
  • 如果getList() 不是静态的,你怎么能打电话给ClassA.getList().size()?一旦你将getList设为静态,你就必须将players设为静态。但仅当您想要一个独立于实例的列表时才将其设为静态。但是您需要独立于实例的列表这一事实告诉我,您的设计可以改进。
  • @svasa 如果我使用静态列表,它可以工作。但我被建议不要使用它。所以这就是为什么我要求一种不同的方法。
  • @DarkEyeDragon 另一种方法是将 A 类本身或列表传递给 B 类的构造函数,如下面的答案所示。

标签: java list class


【解决方案1】:

我认为您的问题是您没有独立考虑对象。只有在 B 类中初始化 A 类的实例时,该实例才能发生变异。

然后您可以将对象从 B 类传递到您想要的任何位置,但是您不能从 A 类初始化 A 类然后直接在 B 类中使用它,除非您将它传递给 B 类

【讨论】:

  • 我真的完全不明白这个答案。从表面上看,这是错误的。您可以在不从B 初始化的情况下更改A 的实例,因此“[o]nly when you...”部分是错误的。 “将对象从 B 类传递到您想要的任何 [sic] 是什么意思?您当然可以从B 内部创建一个A 类型的对象,而无需进行任何“传递”。并且您通过引用A 的任何静态成员或实例化它以及其他技术来“初始化A 类”。请澄清并更正您的答案。
  • 我会编辑它,但你误读了它。我没有说你必须在任何地方传递它,我说一旦初始化它就可以传递......“在 B 类中初始化 A 类的实例”
【解决方案2】:

每次都这样做

ClassA classA = new ClassA();
List<String> newList = classA.players;

将创建/拥有在 ClassA 中声明的 ArrayList 的新实例。

而且,因为下面的代码行是一个实例变量。所以,每个实例都会有不同的副本。

List<String> players = new ArrayList<String>();

所以,解决方案是:

 ClassA classA = new ClassA();
 classA.players.add("A");
 List<String> newList = classA.players;

或者有setter方法或者在构造函数中初始化或者声明为静态成员。这一切的解决方案将取决于您的要求。

您可以通过传递而不是静态而不是创建新实例 通过将实例作为参数添加到其他类 构造函数

这意味着您可以使用构造函数将 ClassA 实例传递给 ClassB。

【讨论】:

  • @Jason 我没听懂你吗?所以,你是说你没有得到解释的答案?
  • @Ravi 那不会给出相同的结果吗?我不会查看/编辑现有列表,而是将其添加到新实例中吗?
  • 不,我的意思是,我的答案和你的很接近,但你的更好
  • @DarkEyeDragon 正如我在回答中提到的那样。一切都取决于您的要求。但是,我假设您将只有一个 ClassA 实例。
  • @DarkEyeDragon 我分享了多个解决方案。你可以尝试任何。
【解决方案3】:

A 的列表将始终为空,因为您正在访问一个新实例的列表。如果你想得到一个列表 A,你已经将一个列表 A 作为参数发送给 B 类。示例:

class ClassA{
 List<String> players; 
 ClassA(){
  players = new ArrayList<>();
 }
 public List getPlayers(){
  return this.players;
 }
}

class ClassB{
  private List<String> playersA;

  ClassB(List playersA){
   this.playersA = playersA;
 }
}

// In your main code

ClassA classA = new ClassA();
ClassB classB;
List<String> players = classA.getPlayers();
players.add("P1");
players.add("P2");

classB = new ClassB(players);

【讨论】:

  • 您不必“将列表 A 作为参数发送到类 B”,您可以使用类 A 实例中的 getter 方法从类 B 中获取它。 List&lt;String&gt; players = instanceA.getPlayers();。这有其自身的问题,因为B 代码现在能够更改A 实例中保存的列表。为此,您可能需要防御性(深度)副本。
  • 可能,但情况并非如此。此外,没有指定类 B 是否引用了 A 的实例或在自己内部创建实例 A。
【解决方案4】:

简单的答案是,您需要将创建的同一个 ClassA 实例传递给 ClassB。

创建类时,会创建类定义。每次使用new 关键字时,都会创建该类的一个新实例。假设您有足够的内存,您可以拥有任意数量的类实例。但每个实例都与其他实例分开。

就像 String 和 List 是类并且需要被实例化一样,您的自定义类也是如此。因此,在您的主目录中,或者在您使用 ClassA 和 ClassB 的任何地方,您都需要像这样实例化它们:

ClassA instanceOfClassA = new ClassA();
ClassB instanceOfClassB = new ClassB();

假设您没有指定,您在 main 中执行了该操作。

您的目标是:从 ClassB 中访问特定 ClassA 实例的列表。

您已经在 ClassA 中创建了 getList() 方法。那挺好的。你会使用它。

接下来,您需要在 ClassB 中创建一个 ClassA 类型的数据成员,以及该成员的 getter 和 setter:

public class ClassB {
    ...
    ClassA myInstanceOfClassA;

    public void setClassAInstance(ClassA instance){
        this.myInstanceOfClassA = instance;
    }
    public ClassA getClassAInstance(){
        return this.myInstanceOfClassA;
    }
}

然后,在您更新了 ClassA 实例中的 players 并像上面一样实例化 ClassB 实例之后,回到您的主目录:

instanceOfClassB.setClassAInstance(instanceofClassA);

然后在 ClassB 中,players 的列表可以使用该实例访问。

List<String> playersFromClassA = myInstanceOfClassA.getList();

同样,从 ClassB 内部调用 myInstanceOfClassA.getList().size(); 应该会返回适当数量的玩家。

【讨论】:

  • 我对我的帖子进行了一些编辑。我希望这更有意义。
猜你喜欢
  • 2020-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-13
  • 1970-01-01
  • 2011-10-13
  • 2021-10-19
  • 1970-01-01
相关资源
最近更新 更多