简体   繁体   English

如何在另一个类中使用列表?

[英]how to use a list in another class?

I want to create a list, add blocks to it and then use it in a BlockBreakEvent to check if the block is in the list and cancel the event if it's not.我想创建一个列表,向其中添加块,然后在 BlockBreakEvent 中使用它来检查块是否在列表中,如果不在则取消事件。 But I can't seem to create and add things in it any other way than in the actual event itself (which looks to me like it would create issues).但我似乎无法以任何其他方式在其中创建和添加东西,而不是在实际事件本身中(在我看来它会产生问题)。 The only thing that is working for me is creating the list in the event and adding blocks to it one by one which looks really messy compared to: creating the list in a separate class and just checking the list with if(Listname.contains(block)) does anyone know how I can achieve this?唯一对我有用的是在事件中创建列表并一一添加块,这看起来真的很混乱:在单独的类中创建列表并仅使用 if(Listname.contains(block )) 有谁知道我怎么能做到这一点? Whether its dependency injection, or whatever else.无论是依赖注入,还是其他。 I just can't figure out how to put it to use.我只是不知道如何使用它。

Here's what I've tried and is currently working for me, but I believe it's theoretically incorrect:这是我尝试过并且目前正在为我工​​作的方法,但我认为它在理论上是不正确的:

public class Event implements Listener {
@EventHandler
public void onBreak(BlockBreakEvent e) {
    List<Material> allowedblocks = new ArrayList<Material>();
    allowedblocks.add(Material.STONE);
    //repeat this 10-50 times for whatever item
    
    
    Player p = e.getPlayer();
    Material block = e.getBlock().getType();
    
    if(allowedblocks.contains(block)){
        p.sendMessage("Invalid block. Break cancelled");
        e.setCancelled(true);
    }else{
        p.sendMessage("Valid Block");
    }
    }

}

You can make allowedBlocks List a class field and fill it with elements inside of the constructor.您可以让 allowedBlocks List 成为一个类字段,并用构造函数内的元素填充它。

public class YourClass {
    private List<Material> allowedBlocks = new ArrayList<>();    

    public YourClass() {
        allowedBlocks.add(Material.STONE);
        //repeat this 10-50 times for whatever item
    }

    @EventHandler
    public void onBreak(BlockBreakEvent e) {
        Player p = e.getPlayer();
        Material block = e.getBlock().getType();
    
        if(allowedBlocks.contains(block)){
            p.sendMessage("Valid Block");
        } else {
            p.sendMessage("Invalid block. Break cancelled");
            e.setCancelled(true);
        }
    }
}

Another approach would be to make the list static and fill it with values inside of a static block.另一种方法是使列表静态并用静态块内的值填充它。 I would not recommend making the list static if you are planning to change its values, but if your allowed blocks are going to remain the same, it may be a good idea to even go further and make it public, so you can access it from anywhere without an instance of YourClass如果您打算更改列表的值,我不建议您将列表设为静态,但如果您允许的块保持不变,那么进一步公开它可能是个好主意,这样您就可以从任何没有 YourClass 实例的地方

public class YourClass {
  public static final List<Material> allowedBlocks;    

  static {
      List<Materials> list = new ArrayList<>();
      list.add(Material.STONE);
      //repeat this 10-50 times for whatever item

      //use an unmodifiable list, 
      //so you do not accidentally change its content later
      allowedBlocks = Collections.unmodifiableList(list);
  }

  @EventHandler
  public void onBreak(BlockBreakEvent e) {
      Player p = e.getPlayer();
      Material block = e.getBlock().getType();

      if(allowedBlocks.contains(block)){
          p.sendMessage("Valid Block");
      } else {
          p.sendMessage("Invalid block. Break cancelled");
          e.setCancelled(true);
      }
  }
}

In the first case, there will be a list of allowedBlocks per instance of YourClass, which means, that every time you call new YourClass() a new List will be created and filled.在第一种情况下,每个 YourClass 实例都会有一个 allowedBlocks 列表,这意味着每次调用new YourClass()都会创建并填充一个新列表。 In the second case, there will be only one list which will be created and populated on class loading (at the very beginning of the program) start up.在第二种情况下,只有一个列表将在类加载(在程序的最开始)启动时创建和填充。

PS I would rather use a Set instead of a List here, considering you are using contains very often. PS 我宁愿在这里使用 Set 而不是 List ,考虑到您经常使用contains

Since you are using an enum to store your Material types, you can simply call the static .values() method through Material.由于您使用枚举来存储材质类型,因此您可以简单地通过材质调用静态.values()方法。

Ex:前任:

@EventHandler
public void onBreak(BlockBreakEvent e) {
    Player p = e.getPlayer();
    Material block = e.getBlock().getType();
    if(List.of(Material.values()).contains(block)){
        p.sendMessage("Invalid block. Break cancelled");
        e.setCancelled(true);
    }else{
        p.sendMessage("Valid Block");
    }
    }

}

If you need to be able to customize what values are in the List you can use the singleton pattern to access that information globally.如果您需要能够自定义 List 中的值,您可以使用单例模式来全局访问该信息。

The instance can be accessed statically from anywhere in the application:可以从应用程序中的任何位置静态访问该实例:

import java.util.List;

public class BlockController {
        
    public static BlockController instance = new BlockController();
    
    private List<Material> allowedBlocks; 
    
    public BlockController() {
        this.allowedBlocks = new ArrayList<>();
    }
    
    public void addAllowedBlock(Material mat) {
        this.allowedBlocks.add(mat);
    }
    
    public void removeAllowedBlock(Material mat) {
        this.allowedBlocks.remove(mat);
    }
    
    public boolean containsBlock(Material mat) {
        return this.allowedBlocks.contains(mat);
    }
    
    public void clear() {
        this.allowedBlocks.clear();
    }
    
/**
 * You can add more functionality here...
 * This class can be accessed anywhere in the application
 * 
 * use:
 * 
 * BlockController controller = BlockController.instance;
 * controller.containsBlock(Material.BLOCK);
 */

} }

Try to create the List in a static context.尝试在静态上下文中创建列表。 This way the list is the same for all instances:这样,所有实例的列表都是相同的:

public class MyClass {
    
    public static List<Material> allowedblocks = new ArrayList<Material>();

    @EventHandler
    public void onBreak(BlockBreakEvent e) {
        allowedblocks.add(Material.STONE);
        ...

Then you can call the List from everywhere like this (eg if statement):然后你可以像这样从任何地方调用 List(例如 if 语句):

if(MyClass.allowedblocks.contains(block)) 

Your problem seems simmilar to this question, maybe this answer helps too: .您的问题似乎与这个问题相似,也许这个答案也有帮助:.

One approach to creating the list in a separate class is to use a static initializer block:在单独的类中创建列表的一种方法是使用静态初始化块:

public class MyClass {
    public static final List<Material> ALLOWED_MATERIALS = new ArrayList<>();

    static {
        ALLOWED_MATERIALS.add( Material.STONE );
    }

    public static List<Material> getAllowedMaterials() {
        return Collections.unmodifiableList( ALLOWED_MATERIALS );
    }
    ...
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM