如何实例化此接口?

时间:2016-06-17 21:15:09

标签: java interface minecraft

这是来自Minecraft服务器源代码,也称为Minecraft Bukkit API,现在你和我一样了解。

有一个名为Server的接口:

public interface Server extends PluginMessegeRecipient {
    public String getVersion();
}

PluginMessageRecipient也是一个接口。

有一个名为Bukkit的类实例化Server:

public final class Bukkit {
    private static Server server;

}

Bucket类中的内部方法,它们从服务器对象调用方法。例如:

server.getVersion();

问题是,Server接口中没有getVersion的代码,只是方法签名。 PluginMessageRecipient接口中也没有代码,也没有扩展任何代码。

我已经阅读了所有问题和答案,说我需要一个匿名类或内部类,这似乎不适合那些解决方案。

3 个答案:

答案 0 :(得分:1)

  

有一个名为Bucket的类可以实例化Server:

实际上Bucket并未实例化Server。课程Bucket包含对Server的引用。你还没有表明它是如何设置的,所以我们不知道实际的课程。

但是,保证 分配给该引用(Bucket.server),假设它不是null,是一个具体的对象实现 Server的类。该类将提供getVersion()的实现,这就是所谓的。

答案 1 :(得分:0)

Bukkit只是一个Modding API。如果你想实现Bukkit,你需要自己创建这样一个实例并将其传递给那里。

以Bukkit包含的单元测试为例: https://github.com/Bukkit/Bukkit/blob/f210234e59275330f83b994e199c76f6abd41ee7/src/test/java/org/bukkit/TestServer.java#L77

允许您运行Bukkit服务器的真正实现是Spigot。

答案 2 :(得分:0)

如果我没记错的话,选择的特定具体类是在运行时通过反射确定的。因为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返回版本字符串。允许它们进入此类的工具可能会根据以下条件执行此操作:

  1. 该类具有默认访问权限
  2. 该类只有一个默认访问自身的静态引用
  3. 该类只有一个默认访问静态字符串字段。
  4. 该类有一个具有默认访问权限的方法,返回String,返回值为3中的FieldRef
  5. 这通常只返回一个类。如果返回多个(通常在新的Bukkit版本的开发阶段),他们会更加具体地了解他们的条件,以确保他们只返回正确的类。他们为他们需要识别的每个领域,类和方法执行此操作。

    由于他们现在知道哪个类是Server类,所以他们可以继续进行更改。首先,他们需要实现界面

    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";
    }
    

    现在,我们有一个符合Bukkit API的类。

    当他们需要实例化该类时,他们只是按照

    的方式做一些事情
    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();
    }