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

Liv*_*ing 3 java ant reflection classpath

我有一个代码库,我想生成几个可交付的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>
Run Code Online (Sandbox Code Playgroud)

后来,我正在创建一个包含所有必需类的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>
Run Code Online (Sandbox Code Playgroud)

这一切都有效,并查看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
Run Code Online (Sandbox Code Playgroud)

现在,为了运行代码,我做:

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一样.

And*_*yle 5

简短而简单的答案是,这是不可能的; 类名也只是在他们的包中也是明确的.

让调用者更简单的一个选择是让你的应用程序"dom.place.proj.tokenizers."在它们提供的每个类参数前面加上- 所以你的简短首选示例的行为与第一个相同.

然而,非常简单,功率降低; 用户不再可能定义自己的自定义类并将其传入,因为包不匹配.(在某种程度上,如果类名不包含句点(.),你可以通过仅预先设置默认包来解决这个问题,但是你添加的特殊情况越多,这将是理解......)


你提到你正在转向Java.在一天结束的时候,我希望在这样的情况下出现由其完整的包装前缀名称指定的类,因此缩写版本可能会让习惯于Java的人更加困惑.

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

如果这看起来不像答案那么道歉,但我相信这是这种情况下最好的行动方案.