Java 这个接口是如何实例化的?
这是来自Minecraft服务器的源代码,也称为Minecraft Bukkit API,现在你和我一样了解 有一个称为服务器的接口:Java 这个接口是如何实例化的?,java,interface,minecraft,Java,Interface,Minecraft,这是来自Minecraft服务器的源代码,也称为Minecraft Bukkit API,现在你和我一样了解 有一个称为服务器的接口: public interface Server extends PluginMessegeRecipient { public String getVersion(); } PluginMessageRecipient也是一个接口 有一个名为Bukkit的类实例化服务器: public final class Bukkit { private
public interface Server extends PluginMessegeRecipient {
public String getVersion();
}
PluginMessageRecipient也是一个接口
有一个名为Bukkit的类实例化服务器:
public final class Bukkit {
private static Server server;
}
在Bucket类中的方法内部,它们从服务器对象调用方法。例如:
server.getVersion();
问题是,服务器接口中没有getVersion的代码,只有一个方法签名。PluginMessageRecipient接口中也没有代码,也没有扩展任何内容
我已经阅读了上面的所有问题和答案,所以说我需要一个匿名类或内部类,而这似乎不适合这些解决方案
有一个名为Bucket
的类实例化服务器:
public final class Bukkit {
private static Server server;
}
实际上Bucket
并没有实例化Server
。类Bucket
包含对服务器的引用。你还没有展示它是如何设置的,所以我们不知道实际的类
但是,可以保证分配给该引用(Bucket.server
)的对象(假设它不是null
)是实现server
的某个具体类的对象。该类将提供一个getVersion()
的实现,这就是所调用的。Bukkit只是一个修改API。如果您想要实现Bukkit,您需要自己创建这样一个实例并将其传递给它
以Bukkit包括的单元测试为例:
允许您运行Bukkit服务器的真正实现是spiget。如果我没记错的话,正在选择的特定具体类是在运行时通过反射确定的。因为Minecraft不是开源的,所以开发人员所拥有的都是经过模糊处理的编译类文件
代码搜索minecraft jar中的每个类文件,搜索符合特定条件的类,然后使用字节码库强制该类实现该接口
例如,假设以下(模糊)类是Minecraft代码中真正的Server
类
class a {
String x_x317() {
return q_q98;
}
static a a_a1;
static String q_q98 = "1.9.4";
}
在本例中,方法x_x317
返回版本字符串。允许它们也钩住此类的工具可能会基于以下条件执行此操作:
该类具有默认访问权限
该类只有一个对自身的默认访问静态引用
该类只有一个默认的访问静态字符串字段
该类有一个具有默认访问权限的方法,该方法返回String
,返回的值是在3中找到的FieldRef
这通常只返回一个类。在返回多个类的情况下(通常在新Bukkit版本的开发阶段),它们的条件更加具体,以确保只返回正确的类。他们对需要识别的每个字段、类和方法都这样做
因为他们现在知道哪个类是服务器
类,所以可以继续对其进行更改。首先,他们需要实现接口
class a implements org.bukkit.Server
然后实现该方法
class a implements org.bukkit.Server {
String x_x317() {
return q_q98;
}
public String getVersionNumber() {
return x_x317();
}
static a a_a1;
static String q_q98 = "1.9.4";
}
现在,我们有了一个符合BukkitAPI的类
当他们需要实例化那个类时,他们只是按照
Server server = findAndTransformServerClassFromMinecraftJar();
// ...
Server findAndTransformServerClassFromMinecraftJar() {
// load classes from jar
// map them to the appropriate interfaces
// transform and hook the required classes and methods
Class<?> serverClass = doTheFirstThreeSteps();
return (Server) serverClass.newInstance();
}
Server-Server=findAndTransformServerClassFromMinecraftJar();
// ...
服务器FindTransformServerClassFromMineCraftjar(){
//从jar加载类
//将它们映射到适当的接口
//转换并钩住所需的类和方法
Class serverClass=doTheFirstThreeSteps();
返回(服务器)serverClass.newInstance();
}
我怀疑server
在某个时候被实例化为server
接口的一个实现类。例如:Bucket.server=newversionfiveserver()
和VersionFiveServer实现了server
。服务器是一个接口,因此它没有代码。它将只具有方法签名。这就是接口。其他一些类将实现该接口并包含代码。相关:@CollinD所以你认为有一个名为Server的类和一个名为Sever的接口?你是说Bukkit?!因为这就是代码的来源,我不知道MC的任何“Bucket API”。“Bucket类包含一个对服务器的引用。你没有展示它是如何设置的,所以我们不知道实际的类。”——没有。我不能展示它。这是我的问题。它被设定在某个地方,所以“没有一个”在脸上是假的。你说它是一个API,所以毫无疑问,在某个地方有一个调用,或者在某个地方有一个配置文件(XML、JSON、属性等等),或者在某个地方有一个命令行选项,再加上某个地方的某种初始化代码,指定了实现类。你只是还没有找到它。你试过API的文档了吗?实际上,bukkit是在一个已经除臭的jar上工作的(并且有一个具体的实现,CraftServer
,它是定制的,尽管CraftBukkit的其他部分引用了普通代码)