如何为我的跨平台Jar调用特定于OS X的方法?

Red*_*ite 5 java windows macos cross-platform

我有一个编译的可执行JAR文件在Windows平台上失败.

原因是我想要正确地集成某些特定于OS X的属性 - 例如" 关于"窗口.

即使我特意使用条件封锁了代码,JAR仍然NoClassDefFoundError在第一行执行时崩溃.

if (isOSX()) {
    com.apple.eawt.Application application = com.apple.eawt.Application.getApplication();
    application.setAboutHandler(new com.apple.eawt.AboutHandler() {
        @Override
        public void handleAbout(com.apple.eawt.AppEvent.AboutEvent ae) {
            new AboutWindow();
        }
    });
    application.setDefaultMenuBar(MenuSystem.createMenu());
}
Run Code Online (Sandbox Code Playgroud)

是否可以在我的JAR文件中包含此代码,以便我可以拥有一个一致的代码库?

Tot*_*Zam 9

使用Brian的答案作为基础,我能够使用以下代码使用OS X特定方法设置Mac Dock图标图像.与其他答案不同,此答案包含一个完整的示例,并且没有尝试将对象强制转换为OS X特定类对象的问题.

代码的作用:

  1. 此代码不是导入OS X特定库,而是Class.forName(String)用于获取Class与OS X特定类关联的对象.在此示例中,com.apple.eawt.Application库用于设置停靠图标图像.
  2. 然后使用反射从OS X特定类调用方法.getClass()用于获取Application对象,getMethod().invoke()用于调用getApplication()setDockIconImage()方法.

我已经包含了一些注释,显示了通常在OS X独占程序中使用的代码,以明确反射代码正在替换的内容.(如果要创建只需要在Mac上运行的程序,请参阅如何更改Java程序的Dock图标?以获取设置停靠图标图像所需的代码.)

// Retrieve the Image object from the locally stored image file
// "frame" is the name of my JFrame variable, and "filename" is the name of the image file
Image image = Toolkit.getDefaultToolkit().getImage(frame.getClass().getResource(fileName));

try {
    // Replace: import com.apple.eawt.Application
    String className = "com.apple.eawt.Application";
    Class<?> cls = Class.forName(className);

    // Replace: Application application = Application.getApplication();
    Object application = cls.newInstance().getClass().getMethod("getApplication")
        .invoke(null);

    // Replace: application.setDockIconImage(image);
    application.getClass().getMethod("setDockIconImage", java.awt.Image.class)
        .invoke(application, image);
}
catch (ClassNotFoundException | IllegalAccessException | IllegalArgumentException
        | InvocationTargetException | NoSuchMethodException | SecurityException
        | InstantiationException e) {
    e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)

虽然这段代码有效,但这种方法似乎仍然是一个混乱的解决方法,如果有人对如何在Mac和Windows上使用的程序中包含OS X特定代码有任何其他建议,那将会很棒.


Bri*_*new 5

您是否尝试过使用Class.forName动态加载周围的类?

Class.forName("com.myproject.ClassContainingApple");
Run Code Online (Sandbox Code Playgroud)

这样,您可以在一个类中引用所有特定于Apple的类,并在isOSX()分支中动态加载它。您必须这样做,因为您无法加载引用其他不可用类的类-您必须确定您是否在OSX中,然后加载引用OSX的类。

如果您有更多特定于操作系统的要求,那么执行此操作的可扩展方法是在操作系统之后命名您的类,然后根据检测到的操作系统加载类名。例如,打电话给你的班WindowsExtensionsOSXExtensionsLinuxExtensions等。(你将不得不查找适当的名字-我只是提供例子)

例如,这是用法示例:

String className = ""java.util.ArrayList";
Class cls = Class.forName(className);
List list = (List)cls.newInstance();
Run Code Online (Sandbox Code Playgroud)