在传递单个jar并使用反射时,如何避免在命令行上指定完全限定的类名



我有一个代码库,我想生成几个可交付的jar文件,每个文件都要从命令行运行,并访问代码库的一些功能。运行时,一些命令行参数是jar中的其他类,然后通过反射创建这些类。它工作得很好,但我必须指定类的非常长的完全限定路径,即使类在jar文件中。

我正在使用ant编译并jar一系列目录。从一个最小的示例build.xml文件:

<property name="build" location="build"/>
<property name="jars" location="${build}/jars"/>
<property name="classes" location="${build}/classes"/>
<property name="src" location="src/dom/place/proj"/>
<target name="utility">
 <javac 
    includeantruntime="false" 
    srcdir="${src}/utility" destdir="${classes}" 
    classpathref="classpath" />
 <jar 
    destfile="${jars}/utility.jar" 
    basedir="${classes}" 
    includes="**/utility/**" />
</target>
<target name="tokenizers" depends="utility">
 <javac 
    includeantruntime="false" 
    srcdir="${src}/tokenizers" 
    destdir="${classes}" 
    classpathref="classpath" />
 <jar 
    destfile="${jars}/tokenizers.jar" 
    basedir="${classes}" 
    includes="**/tokenizers/**" />
</target>

稍后,我将创建一个包含所有所需类的jar文件,并将运行一个命令,例如:

<target name="tokenize-file-jar">
 <jar destfile="${dist}/TokenizeFile.jar">
  <zipgroupfileset dir="${jars}">
    <include name="utility.jar"/>
    <include name="tokenizers.jar"/>
  </zipgroupfileset>
  <manifest>
    <attribute name="Main-Class" value="dom.place.proj.tokenizers.TokenizeFile"/>
  </manifest>     
 </jar>    
</target>

这一切都有效,并且在jar文件中查看,所有的类都在那里。

prompt > unzip -l TokenizeFile.jar 
Archive:  TokenizeFile.jar
Length     Date   Time    Name
--------    ----   ----    ----
        0  01-11-12 11:07   META-INF/
      286  01-11-12 11:07   META-INF/MANIFEST.MF
        0  01-11-12 10:16   dom/
        0  01-11-12 10:16   dom/place/
        0  01-11-12 10:16   dom/place/proj/
        0  01-11-12 10:16   dom/place/proj/tokenizers/
     1737  01-11-12 11:07   dom/place/proj/tokenizers/FileTokenizer.class
     1411  01-11-12 11:07   dom/place/proj/tokenizers/PorterTokenizer.class
     1754  01-11-12 11:07   dom/place/proj/tokenizers/TokenizeFile.class
      992  01-11-12 11:07   dom/place/proj/tokenizers/Tokenizer.class
        0  01-11-12 10:16   dom/place/proj/utility/
     1106  01-11-12 11:07   dom/place/proj/utility/BoundedExecutor.class
     3128  01-11-12 11:07   dom/place/proj/utility/Converter.class
     1107  01-11-12 11:07   dom/place/proj/utility/ExceptionHandler.class

现在,要运行代码,我需要:

java -jar TokenizeFile.jar test.txt dom.place.proj.tokenizers.FileTokenizer dom.place.proj.tokenizers.PorterTokenizer

它是有效的。耶!但我希望我的客户端不必在命令行上为每个类指定完全限定的名称——这是一个小示例,可能有很多项。在我的代码或构建过程中,我可以更改什么来允许这样做:

java -jar TokenizeFile.jar test.txt FileTokenizer PorterTokenizer

谢谢你的帮助。我正在从C++/make过渡,到目前为止我非常喜欢ant和Java。

简短而简单的答案是,这是不可能的;类名只有在给定包的情况下才是明确的。

让调用方更简单的一种选择是让应用程序在它们提供的每个类参数前加上"dom.place.proj.tokenizers.",这样您的较短的首选示例的行为将与第一个示例相同。

然而,伴随着巨大的简单性而来的是力量的削弱;用户再也不可能定义自己的自定义类并将其传入,因为包不匹配。(在某种程度上,如果类名不包含句点(.),则只需在默认包前加上前缀就可以解决此问题,但添加的特殊情况越多,就越难理解…)


您提到您正在向Java过渡。最后,当类出现在这种情况下时,我会期望用其完整的包前缀名称指定类,因此缩写版本可能会让习惯Java的人更困惑。

因此,我的建议是保持现状,基本上更习惯于第一个版本的命令行。即使在这种特殊情况下要解决这个问题,也有许多其他第一方和第三方Java应用程序和工具需要在命令行上指定类,而且它们都需要完全限定的类名。

如果这看起来不是一个答案,我很抱歉,但我相信这是在这种情况下最好的做法。

相关内容

  • 没有找到相关文章

最新更新