相当于Java中的#define?

Jus*_*tin 9 java preprocessor c-preprocessor

我正在编写一个库,如果包含特定的库,需要有一些代码.由于此代码分散在项目周围,如果用户不必自己评论/取消注释,那将是很好的.

在C中,这很容易用#define一个标题,然后是包围的代码块#ifdefs.当然,Java没有C预处理器......

为了澄清 - 我将分发几个外部库.我不想将它们全部包含在内以最小化我的可执行文件大小.如果开发人员确实包含了库,我需要能够使用它,如果没有,那么它就可以被忽略.

在Java中执行此操作的最佳方法是什么?

Ste*_*son 11

没有办法在Java中做你想做的事.您可以预处理Java源文件,但这不在Java的范围内.

你能否抽象出差异然后改变实施方式?

根据您的澄清,听起来您可能能够创建一个工厂方法,该方法将返回来自其中一个外部库的对象或"stub"类,其功能将执行您在"不可用"中所做的操作"条件代码.


Sim*_*ann 6

正如其他人所说,Java中没有#define/#ifdef这样的东西.但是关于你可以使用的可选外部库的问题,如果存在,如果不存在则不使用,使用代理类可能是一个选项(如果库接口不是太大).

我必须为Mac OS X特定的AWT/Swing扩展(在com.apple.eawt.*中找到)执行一次.当然,如果应用程序在Mac OS上运行,那么这些类只在类路径上.为了能够使用它们但仍允许在其他平台上使用相同的应用程序,我编写了简单的代理类,它提供了与原始EAWT类相同的方法.在内部,代理使用一些反射来确定实际类是否在类路径上并且将通过所有方法调用.通过使用java.lang.reflect.Proxy类,您甚至可以创建并传递外部库中定义的类型的对象,而无需在编译时使用它.

例如,com.apple.eawt.ApplicationListener的代理如下所示:

public class ApplicationListener {

    private static Class<?> nativeClass;

    static Class<?> getNativeClass() {
        try {
            if (ApplicationListener.nativeClass == null) {
                ApplicationListener.nativeClass = Class.forName("com.apple.eawt.ApplicationListener");
            }

            return ApplicationListener.nativeClass;
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException("This system does not support the Apple EAWT!", ex);
        }
    }

    private Object nativeObject;

    public ApplicationListener() {
        Class<?> nativeClass = ApplicationListener.getNativeClass();

        this.nativeObject = Proxy.newProxyInstance(nativeClass.getClassLoader(), new Class<?>[] {
            nativeClass
        }, new InvocationHandler() {

            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                String methodName = method.getName();

                ApplicationEvent event = new ApplicationEvent(args[0]);

                if (methodName.equals("handleReOpenApplication")) {
                    ApplicationListener.this.handleReOpenApplication(event);
                } else if (methodName.equals("handleQuit")) {
                    ApplicationListener.this.handleQuit(event);
                } else if (methodName.equals("handlePrintFile")) {
                    ApplicationListener.this.handlePrintFile(event);
                } else if (methodName.equals("handlePreferences")) {
                    ApplicationListener.this.handlePreferences(event);
                } else if (methodName.equals("handleOpenFile")) {
                    ApplicationListener.this.handleOpenFile(event);
                } else if (methodName.equals("handleOpenApplication")) {
                    ApplicationListener.this.handleOpenApplication(event);
                } else if (methodName.equals("handleAbout")) {
                    ApplicationListener.this.handleAbout(event);
                }

                return null;
            }

        });
    }

    Object getNativeObject() {
        return this.nativeObject;
    }

    // followed by abstract definitions of all handle...(ApplicationEvent) methods

}
Run Code Online (Sandbox Code Playgroud)

所有这些只是有意义的,如果您只需要来自外部库的几个类,因为您必须通过运行时的反射来完成所有操作.对于较大的库,您可能需要某种方法来自动生成代理.但是,如果你真的依赖于一个大型外部库,那么你应该在编译时需要它.

Peter Lawrey的评论:(很抱歉编辑,很难将代码放入评论中)

以下示例通过方法是通用的,因此您无需了解所涉及的所有方法.您也可以按类创建这个泛型,这样您只需要编码一个InvocationHandler类来覆盖所有情况.

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    String methodName = method.getName();
    ApplicationEvent event = new ApplicationEvent(args[0]);
    Method method = ApplicationListener.class.getMethod(methodName, ApplicationEvent.class);
    return method.invoke(ApplicationListener.this, event);
}
Run Code Online (Sandbox Code Playgroud)


Vla*_*dim 5

在Java中,可以使用各种方法来实现相同的结果:

Java方法是将行为变为一组通过接口抽象的单独类,然后在运行时插入所需的类.也可以看看: