我有一个已编译的可执行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());
}
是否可以在我的JAR文件中包含此代码,以便我可以拥有一个一致的代码库?
答案 0 :(得分:8)
使用Brian's answer作为基础,我能够使用以下代码使用OS X特定方法设置Mac停靠图标图像。与其他答案不同,这个答案包含一个完整的示例,并没有尝试将对象转换为OS X特定类对象的问题。
代码的作用:
Class.forName(String)
来获取与OS X特定类关联的Class
对象,而不是导入OS X特定库。在此示例中,com.apple.eawt.Application
库用于设置停靠图标图像。getClass()
用于获取Application
对象,getMethod().invoke()
用于调用getApplication()
和setDockIconImage()
方法。我收录的评论显示了通常在OS X独占程序中使用的代码,以明确反映代码正在替换的内容。 (如果您要创建只需要在Mac上运行的程序,请参阅How do you change the Dock Icon of a Java program?以获取设置停靠图标图像所需的代码。)
// 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();
}
虽然这个代码有效,但这个方法似乎仍然是一个混乱的解决方法,如果有人对如何在Mac和Windows上使用的程序中包含OS X特定代码提出任何其他建议,那将会很棒。< /子>
答案 1 :(得分:4)
您是否尝试使用Class.forName动态加载周围的类?
Class.forName("com.myproject.ClassContainingApple");
这样,您可以在一个类中引用所有Apple特定的类,并在isOSX()
分支中动态加载它。你必须这样做,因为你无法加载引用其他不可用类的类 - 你必须确定你是否在OSX中,而只有加载任何东西指的是仅限OSX的类。
如果您有更多特定于操作系统的要求,那么可扩展的方法是在操作系统之后命名您的类,然后根据检测到的操作系统加载类名。例如给你的课程WindowsExtensions
,OSXExtensions
,LinuxExtensions
等打电话(你必须查找相应的名字 - 我只是提供例子)
e.g。这是一个使用示例:
String className = ""java.util.ArrayList";
Class cls = Class.forName(className);
List list = (List)cls.newInstance();
答案 2 :(得分:0)
这是不可能的,因为java正在加载类(可能)在类的实例化期间使用的所有类,因此命名类不可用。
您可以尝试将代码放在项目的另一个类中,并且仅当您在OSX上运行时才实例化此类。
如果这不起作用,你必须使用反射,因为当你通过反射加载它时,VM只能检测到这个类。
HTH