&引用;“你好,世界”;使用Java注释

&引用;“你好,世界”;使用Java注释,java,annotations,Java,Annotations,问题描述:独立编译2个jar文件,而不必在类路径上包含彼此;在运行时,在一个jar中包含和调用main()以在标准输出上打印字符串。部分输出字符串必须来自第二个jar 约束:解决方案不能依赖于IDE或使用任何其他jar文件 回答到目前为止我做了什么:我的解决方案描述如下 问这个问题的原因:我试图弄清楚是否/如何使用注释来解决这个问题(希望以更优雅的方式),但找不到任何合适的文档或教程。我也很感激你的指点 我的解决方案:一个批处理文件(在Unix上,请将反斜杠改为正斜杠,分号改为冒号,rem改为#

问题描述:独立编译2个jar文件,而不必在类路径上包含彼此;在运行时,在一个jar中包含和调用main()以在标准输出上打印字符串。部分输出字符串必须来自第二个jar

约束:解决方案不能依赖于IDE或使用任何其他jar文件

回答到目前为止我做了什么:我的解决方案描述如下

问这个问题的原因:我试图弄清楚是否/如何使用注释来解决这个问题(希望以更优雅的方式),但找不到任何合适的文档或教程。我也很感激你的指点

我的解决方案:一个批处理文件(在Unix上,请将反斜杠改为正斜杠,分号改为冒号,rem改为#),如下所示:

rem Compile and package the testing class (Main) without any library
javac -d target core\*.java
cd target
jar cvf ..\main.jar .\core
cd ..

rem Compile and package the Greeting and Greeted classes as a library
javac -d lib impl\*.java
cd lib
jar cvf ..\mylib.jar .\impl
cd ..

rem Use the two parts above at runtime and execute main() in Main class
java -cp main.jar;mylib.jar core.Main
impl目录中有2个文件,core中有2个文件,如下所示:

rem Compile and package the testing class (Main) without any library
javac -d target core\*.java
cd target
jar cvf ..\main.jar .\core
cd ..

rem Compile and package the Greeting and Greeted classes as a library
javac -d lib impl\*.java
cd lib
jar cvf ..\mylib.jar .\impl
cd ..

rem Use the two parts above at runtime and execute main() in Main class
java -cp main.jar;mylib.jar core.Main
/*文件:impl/Greeting.java*/

package impl;

public class Greeting {
    public String getGreeting () {
        return "Hello";
}}
/*文件:impl/helleed.java*/

package impl;

public class Greeted {
    public String getGreeted () {
        return "world";
}
/*文件:core/Main.java*/

package core;

public class Main {

    private String  greeting = "Learn annotations",     greeted = "keep using Java",

            // Can read the following 4 values from a configuration file, too
            // Trying to see if we can get these using Java annotations

            greetingClassName = "impl.Greeting",    greetingMethod = "getGreeting",
            greetedClassName = "impl.Greeted",  greetedMethod = "getGreeted";

    public Main () {
        try {
            MyRunTime runTime = new MyRunTime();

            Object gting = runTime.getInstance(greetingClassName),
                gted  = runTime.getInstance(greetedClassName),

                g1Str = runTime.getResponseNoArg (gting, greetingMethod),
                g2Str = runTime.getResponseNoArg (gted, greetedMethod);

            if (g1Str instanceof String)    greeting = (String) g1Str;
            if (g2Str instanceof String)    greeted = (String) g2Str;
        } catch (Exception ex) {
            System.err.println ("Error in Library loading: " + ex.getMessage());
    }}

    public void greet () {
        System.out.println (greeting + ", " + greeted + "!");
    }

    public static void main (String[] args) {
        new Main().greet();
}}
/*文件:core/MyRunTime.java*/

package core;

import  java.lang.reflect.*;

public  class  MyRunTime {

    public Object getResponseNoArg (Object anInstance, String methodName) throws
                    NoSuchMethodException,
                        IllegalAccessException,
                        InvocationTargetException {
        Method method = anInstance.getClass().getMethod (methodName);
        return method.invoke (anInstance);
    }

    public Object getInstance (String className) throws 
                    ClassNotFoundException,
                    InstantiationException,
                    IllegalAccessException {
            Class c = Class.forName (className);
            return c.newInstance();
    }
}

就这样。除非绝对必要,否则我也不想搞乱类加载器。一旦我掌握了如何使用注释实现这一点,我就可以研究传递参数并继续。谢谢您的帮助。

我不会为此使用注释-可能值得介绍什么是注释以及它们在哪里使用得最好

相反,我会这样做:

public class Main {
  public static void main(final String[] args) throws java.lang.Throwable {
    final String list = System.getProperty( "java.class.path" );
    for (String path : list.split( ";" )) {
      java.io.File object = new java.io.File( path );
      if ( object.isDirectory() )
        for ( String entry : object.list() ) { 
          java.io.File thing = new java.io.File( entry );
          if ( thing.isFile() )
            System.out.println( thing );
          else if( object.isFile() )
            System.out.println( object );
        }
    }
  }
}
  • 在每个jar中放置不同的文件
  • 每个jar文件都有一个主类,其作用相同:列出类路径上的文件
我认为这将满足项目要求

要列出类路径上的文件,可以执行以下操作:

public class Main {
  public static void main(final String[] args) throws java.lang.Throwable {
    final String list = System.getProperty( "java.class.path" );
    for (String path : list.split( ";" )) {
      java.io.File object = new java.io.File( path );
      if ( object.isDirectory() )
        for ( String entry : object.list() ) { 
          java.io.File thing = new java.io.File( entry );
          if ( thing.isFile() )
            System.out.println( thing );
          else if( object.isFile() )
            System.out.println( object );
        }
    }
  }
}

你会说,“我正在试图弄清楚是否/如何使用注释来解决这个问题。”为什么?注释中有什么让您希望使用它们来解决所描述的问题?这是家庭作业吗?有没有其他你没有给我们的指示?为什么?好奇的人想知道。有什么。。。?不知何故,我使用过的大多数框架都使用注释进行依赖注入/IoC/不管你怎么称呼它。这些框架的创造者无疑是聪明人,我正试图理解他们的逻辑。不,这不是家庭作业。附加说明:我不确定你的意思,但我所描述的几乎是一个完整的描述。从你的评论来看,我是否应该假设答案是“注释与所描述的问题无关”?是的,这是我的观点。我认为注释不会在解决问题描述的过程中增加太多内容。我看到的大多数注释用法都涉及确定类的其他行为,而不是如何定位它。在编译包含Main.Main(String[])方法的“a.jar”时,我们不知道“b.jar”的存在,甚至不知道它包含的类。主类不知道它需要的对象或要调用的方法(在我的示例中,变量xxClassName和xxMethod将在运行时从配置文件中读入)。您的建议是扫描类路径上的每个jar文件,并检查命名对象(类)是否在其中一个文件中。我已经可以用Class.forName()完成这项工作,并使用反射来检查该方法。这就是我现在正在做的。我正在寻找的是如何在注释(例如greetingClassName)中读取一个值(例如Greeting),然后在运行时找到一个注释为“@Greeting”的类。这样,我就可以有几个问候类的实现(在不同的jar文件甚至包中),并选择一个具有正确注释的实现。这是一种使用注释的好方法,还是我完全偏离了标准?如果在jar a中定义注释,您将在使用它的所有jar中创建编译和运行时依赖关系-这违反了规范。这就是我试图解决的问题。我想从配置文件(比如greetable)中读取接口的名称,并在运行时找到实现greetable的类,创建其实例等等。(1) 我在哪里定义接口(可能在“b.jar”中,因为实现也在“b.jar”中)。你认为这样可以消除编译依赖吗?