![](/img/trans.png)
[英]How do I make JNDI names compatible with both GlassFish and WildFly
[英]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();
这都很麻烦,但是与使用反射进行调用的方法相比,它有两个好处:
现在,针对不同Bukkit版本的特定逻辑已隔离到代码库的一部分...而不是分散(潜在地)散布在整个地方。
反射的开销仅在启动时发生。 之后,通过适配器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.