2017-09-11 21 views
-1

我有这种方法只能在Windows上运行,并且使用来自sun.awt.shell的类,但应用程序可以在非Windows系统上运行,并且在Java上它可以与OpenSdk一起使用,我怀疑这不包括sun.awt.shell类。如何在某些系统上不存在引用类的情况下编写java类

我已经从类中删除了sun.awt.shell导入语句,因此类名只能在此方法中引用,并且我可以保证此方法永远不会在非Windows计算机上运行。

但是,这是足够的,否则类将无法加载系统丢失这些类,我是否需要重写方法来使用反射?

public static boolean isRemote(String newPath) 
    { 
     try 
     { 
      Path root = Paths.get(newPath).getRoot(); 
      sun.awt.shell.ShellFolder shellFolder = sun.awt.shell.ShellFolder.getShellFolder(root.toFile()); 
      sun.awt.shell.ShellFolderColumnInfo[] cols = shellFolder.getFolderColumns(); 
      for (int i = 0; i < cols.length; i++) 
      { 
       if (cols[i].getTitle().equals(WINDOWS_SHELL_SIZE) 
         && ((String) shellFolder.getFolderColumnValue(i)).startsWith("Network Drive")) 
       { 
        return true; 
       } 
       else if (cols[i].getTitle().equals(WINDOWS_SHELL_ATTRIBUTES) 
         && ((String) shellFolder.getFolderColumnValue(i)).startsWith("\\")) 
       { 
        return true; 
       } 
      } 
     } 
     catch (Exception ex) 
     { 
      MainWindow.logger.log(Level.SEVERE, ex.getMessage(), ex); 
      return false; 
     } 
     return false; 
    } 
+0

为什么接近,特别是没有理由! –

+0

“请问班级是否无法加载缺少这些班级的系统?”嗯,是。事实上,你的班级不会无法加载。失败的方法是调用'isRemote'。如果包'sun.awt.shell'中的类在运行时不存在,您将得到一个'NoClassDefFoundError'。这与'import'语句无关,这是一个仅编译时的特性。 – Seelenvirtuose

+0

您可以检查,例如'Class.forName(“sun.awt.shell.ShellFolder”)'并在使用它之前监视'ClassNotFoundException'? – c0der

回答

0

我跟的解决方案是简单地将所有需要在Windows上提供的类的方法放到一个类中。然后,我打电话之前,任何这些方法形成另一个阶级总是有检查,以确保在Windows操作系统上运行

if(Platform.isWindows()) 
{ 
    return WindowsUtilsFS.isRemote(newPath) 
} 

所以因此类不会被调用或加载。我已将此部署到生产环境中,并且没有错误报告,因此我认为它工作正常。

0

但是,这足以或将类不能错失这些类系统加载反正。

如果这些类在运行时不存在,那么程序将失败。如果您正在使用编译后引用,则在启动期间通常会获得NoClassDefFoundError

我是否需要重写使用反射的方法?

反思没有帮助。如果您尝试使用Class.forName加载课程(例如),如果课程不属于JRE,您将获得ClassNotFoundException


我不完全明白是什么代码实际上做的,但它似乎是使用根本不会在Linux系统(例如)在工作机制。事实上,在Linux系统上并没有真正的“远程”文件的明确概念。

如果你解释你正在使用这种方法,这可能会有所帮助。我怀疑,这只是在Windows上才有意义。

作为一般规则,你应该避免使用sun.*类,因为: - 他们往往是特定的操作系统平台, - 它们可能发生改变,或没有通知被移除。


我明白你在问什么。您实际上不希望 isRemote可以在非Windows系统上工作。

有几个选择:

  • 你可能该方法分为两个部分,并使用动态类加载来加载系统的特定部分。或者使isRemote方法成为动态加载的系统专用插件中的方法。 (基本上是同一个想法......)在任何一种情况下,动态加载的类都可以使用普通的Java调用调用ShellFolder

  • 您可以使用Class.forName("sun.awt.shell.ShellFolder")(试图)加载类,然后使用反射来调用它的方法。

但是,我关于sun.*的说明依然存在。 Sun/Oracle通常会更改或删除这些内部类。

1 - 或者也许你会这么做,但是你已经放弃了它不会的事实。

+0

您误会了我在Windows上编译代码,然后将其部署在Windows,OSX,Linux环境中。我知道这种方法在Linux中不起作用,它永远不会在Linux上被调用,它是针对Windows上的特定任务的,但我不想在构建系统中为此进行调整。但是当这个类加载到内存中时,在这个类中仅仅存在这个方法会导致在没有引用shell类的linux系统上出现问题。 –

+0

是的。我误解了你。 –

+0

我说得很对,如果我只是将这个isRemote()方法移动到仅包含此方法的新类中。然后因为isRemote()在某些系统上没有被调用过,所以类永远不会被加载,因此没有问题。顺便说一句,我宁愿不使用这些类,但它似乎没有一个解决方案,只使用泛型Java - https://stackoverflow.com/questions/46077551/in-java-how-do-i-find-actual-path-远程文件系统安装在Windows上 –

相关问题