簡體   English   中英

如何使某些東西與數組和集合兼容?

[英]How can I make something be compatible with both an array and a collection?

這聽起來是個愚蠢的問題。 但是,在我使用的API中,版本1.7.2的方法Bukkit.getServer().getOnlinePlayers()返回一個Player[] ,而版本1.7.10的方法將Bukkit.getServer().getOnlinePlayers()返回一個Collection<Player> 我需要使我的插件與兩者兼容。

我都有兩者的API,但是除了創建單獨的插件外,我目前不知道如何執行此操作。

我目前只是將集合轉換為數組。 那么,如果版本小於1.7.9,有什么方法(我已經可以獲取版本)了,不要使用.toArray() ,因為它已經返回了數組?

您可以通過反射來實現。 像這樣:

List<Player> getPlayers() {
    try {
        Method method = getMethod(Server.class, "getOnlinePlayers");
        Object result = method.invoke(Bukkit.getServer());
        if(result instanceof Player[])
            return Arrays.asList((Player[])result);
        else
            return (List<Player>)result;

    } catch(ReflectiveOperationException e) {

        // something went wrong! If you have a better way to handle problems, do that instead
        throw new RuntimeException(e);
    }
}

實際上有兩種方法可以做到這一點。 @immibis的答案給出了第一種方法。 第二種方法涉及為不同版本的Bukkit(在這種情況下)創建具有多個插件實現的“版本適配器” API。 例如

public interface BukkitVersionAdapter {
    Collection<Player> getOnlinePlayers();
    ...
}

public class BukkitVersionAdapterV1dot7 implements BukkitVersionAdapter {
    public Collection<Player> getOnlinePlayers() {
        return Arrays.asList(Bukkit.getServer().getOnlinePlayers());
    }
    ...
}

public class BukkitVersionAdapterV1dot8 implements BukkitVersionAdapter {
    public Collection<Player> getOnlinePlayers() {
        return Bukkit.getServer().getOnlinePlayers();
    }
    ...
}

然后,需要針對各個Bukkit版本的Bukkit API jar編譯特定於版本的適配器類。

然后,當您啟動主應用程序(我猜是Bukkit插件)時,您將執行以下操作:

String version = // get the Bukkit version
String className = // map the version to a class name; e.g.
                   // "pkg.BukkitVersionAdapterV1dot7" or
                   // "pkg.BukkitVersionAdapterV1dot8"
Class clazz = Class.forName(className);
BukkitVersionAdapter adapter = 
         (BukkitVersionAdapter) clazz.newInstance();

// Then ...
Collection<Player> players = adapter.getOnlinePlayers();

這都很麻煩,但是與使用反射進行調用的方法相比,它有兩個好處:

  1. 現在,針對不同Bukkit版本的特定邏輯已隔離到代碼庫的一部分...而不是分散(潛在地)散布在整個地方。

  2. 反射的開銷僅在啟動時發生。 之后,通過適配器API對Bukkit進行的所有方法調用都是常規的Java方法調用。

根據上下文,這些可能會使適配器方法更合適。

如果類org.bukkit.Server只是更改了方法getOnlinePlayers()的返回類型,而不是不贊成使用它,而是引入了一個新方法(yack !!!!!誰敢以這種方式更改已發布的接口?) ,您沒有如何在一個代碼中調用該方法的體面方法。 你根本不能寫像

Server server = Bukkit.getServer();
// One of the branches will not be compilable
if (version <= xxxx) {
    Player[] players = server.getOnlinePlayers();
}
else {
    Collection<Player> players = server.getOnlinePlayers();
}

恐怕唯一的方法就是像其他人推薦的那樣使用反射。

你過得很好 不幸的是,沒有辦法創建可以處理集合和數組的強類型方法。

(您可以創建一個接受Object方法,然后使用instanceof進行檢查,強制轉換並處理集合和數組,但是這種解決方案很難看。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM