上次编译的Java打印时间

zer*_*lus 23 java

我想嵌入一段代码,打印出上次编译当前类的时间.如何在Java中实现?

kri*_*ico 14

很久以前这个问题已得到解答.但是,如果有人在这里摆动一个适合我的解决方案,类似于Supah Fly建议但支持jar和文件.

private long classBuildTimeMillis() throws URISyntaxException, IllegalStateException, IllegalArgumentException {
    URL resource = getClass().getResource(getClass().getSimpleName() + ".class");
    if (resource == null) {
        throw new IllegalStateException("Failed to find class file for class: " + 
                                        getClass().getName());
    }

    if (resource.getProtocol().equals("file")) {

        return new File(resource.toURI()).lastModified();

    } else if (resource.getProtocol().equals("jar")) {

        String path = resource.getPath();
        return new File(path.substring(5, path.indexOf("!"))).lastModified();

    } else {

        throw new IllegalArgumentException("Unhandled url protocol: " + 
                resource.getProtocol() + " for class: " +
                getClass().getName() + " resource: " + resource.toString());
    }
}
Run Code Online (Sandbox Code Playgroud)

但这不会处理zip文件或静态上下文,如果事情向南发生,它会抛出异常而不是返回null.这有点友好:

private static final Date buildDate = getClassBuildTime();

/**
 * Handles files, jar entries, and deployed jar entries in a zip file (EAR).
 * @return The date if it can be determined, or null if not.
 */
private static Date getClassBuildTime() {
    Date d = null;
    Class<?> currentClass = new Object() {}.getClass().getEnclosingClass();
    URL resource = currentClass.getResource(currentClass.getSimpleName() + ".class");
    if (resource != null) {
        if (resource.getProtocol().equals("file")) {
            try {
                d = new Date(new File(resource.toURI()).lastModified());
            } catch (URISyntaxException ignored) { }
        } else if (resource.getProtocol().equals("jar")) {
            String path = resource.getPath();
            d = new Date( new File(path.substring(5, path.indexOf("!"))).lastModified() );    
        } else if (resource.getProtocol().equals("zip")) {
            String path = resource.getPath();
            File jarFileOnDisk = new File(path.substring(0, path.indexOf("!")));
            //long jfodLastModifiedLong = jarFileOnDisk.lastModified ();
            //Date jfodLasModifiedDate = new Date(jfodLastModifiedLong);
            try(JarFile jf = new JarFile (jarFileOnDisk)) {
                ZipEntry ze = jf.getEntry (path.substring(path.indexOf("!") + 2));//Skip the ! and the /
                long zeTimeLong = ze.getTime ();
                Date zeTimeDate = new Date(zeTimeLong);
                d = zeTimeDate;
            } catch (IOException|RuntimeException ignored) { }
        }
    }
    return d;
}
Run Code Online (Sandbox Code Playgroud)

  • 这个旧的答案没有处理类似于weblogic上的部署war文件的zip文件,并且它抛出异常而不是返回null的日期无法确定,并且它没有处理静态上下文.但我修改它来做那个:). (3认同)

mdm*_*dma 12

在java中没有直接的支持,因为没有预处理器.最接近的等价物是JAR清单中的"Build-Date"属性.许多构建系统默认添加此属性,或提供添加它的方法.

然后,您可以在运行时读取JAR的清单以获取日期.这个SO问题的答案描述了如何从JAR清单中读取值.

另一种方法是使用资源过滤将日期添加到属性文件中,然后在运行时读取.这是非常特殊的,非标准的,如果你有很多罐子,编译时间不同,那么这很快就会变得难以管理,除非你可以将这个因素分解为所有罐子的构建方式.


Yes*_*Man 12

由于这一点从未被提及过,任何想要通过任何必要手段解决这个问题的人都可能会发现这是一个合适而又笨拙的解决方案:

new Date(new File(getClass().getClassLoader().getResource(getClass().getCanonicalName().replace('.', '/') + ".class").toURI()).lastModified()))
Run Code Online (Sandbox Code Playgroud)

它可能不太漂亮,而且很可能在其他平台上不兼容,但这是我发现在本机Java中找出当前类的编译日期的唯一方法.


Sco*_*ott 5

它有点笨重,但你可以用Ant过滤来做到这一点.

在您的班级中弹出以下方法:

public static String timeBuilt(){
    return "Built at @timeBuilt@ on @dateBuilt@";
}
Run Code Online (Sandbox Code Playgroud)

然后将以下内容放入Ant构建文件中.

<target name="get-time">
    <tstamp>
        <format property="buildTime" pattern="HH:mm:ss" locale="en,UK"/>
        <format property="buildDate" pattern="dd-MM-yyyy" locale="en,UK"/>
    </tstamp>
</target>

<target name="copy-files" depends="get-time">
    <filter token="timeBuilt" value="${buildTime}"/>
    <filter token="dateBuilt" value="${buildDate}"/>
    <copy includeemptydirs="false" todir="build" filtering="true">
        <fileset dir="src"/>
    </copy>
</target>
Run Code Online (Sandbox Code Playgroud)

这会将"src"目录中的所有内容复制到"build",并且这样做会分别将@ timeBuilt @和@ dateBuilt @替换为构建的时间和日期.只需使您的构建目标依赖于copy-files并从"build"目录构建 - 而不是"src"目录.

替换静态方法的内容的优点是,它将在每个类的基础上运行 - 如果您要获取生成的类文件并将它们与另一个时间构建的其他类文件组合,他们每个人都知道当它们建成时 属性文件是明智的,但除非你有多个属性文件,否则你只能拥有整个包的构建时间.