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

Java 在交付单个jar并使用反射时,如何避免在命令行上指定完全限定的类名?,java,reflection,ant,classpath,Java,Reflection,Ant,Classpath,我有一个代码库,我想生成几个可交付的jar文件,每个文件都将从命令行运行,并访问代码库的一些功能。运行时,一些命令行参数是jar中的其他类,然后由反射创建。它可以很好地工作,但是我必须指定该类的非常长的完全限定路径,即使这些类在jar文件中 我正在使用ant编译然后jar一系列目录。从最小示例build.xml文件: <property name="build" location="build"/> <property name="jars" location="${build

我有一个代码库,我想生成几个可交付的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>
现在,要运行代码,我需要:

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

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

java-jar-TokenizeFile.jar test.txt文件标记器PorterTokenizer


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

简短而简单的回答是,这是不可能的;类名也只有在包中才是明确的

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

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


您提到您正在过渡到Java。最终,当类出现在这样的情况下时,我希望它们以完整的包前缀名来指定类,因此对于习惯Java的人来说,缩写版本可能会更容易混淆

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


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

好吧,我喜欢这不是一个答案,但这并不意味着这不是正确的答案。。我会把这个问题留一段时间,看看是否有其他人提出了其他的想法。实际上,我在我工作的项目中使用了带有自动可选前缀的变体,我认为它非常方便,同时仍然允许充分的灵活性。我也不认为它很难理解,所以我可能也会在这里使用它。
<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>
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