【问题标题】:How to get class name of any java file如何获取任何java文件的类名
【发布时间】:2014-05-25 21:39:09
【问题描述】:

java 是否提供了一种简单的方法来做到这一点?

我知道如何使用 Foo.class.getName()) 获得此信息

但是对于我可能通过某种方法传入的任何对象,我如何才能做到这一点?说

public String getClass(File file){
          // Get file class
}

其中 file 是一些带有 .java 扩展名的 java 文件。我知道如果我直接将 java 类的名称硬编码到Foo.class.getName() 中,它会起作用,但我的方法包括在当前目录或包中找不到的 java 文件。有人指导我正确的方向吗?提前致谢。

【问题讨论】:

  • 所以您不是在询问查找对象的类,而是询问文件声明的public class
  • 这是一个.java 文件 - 即您要从中提取类名的 Java 源代码;或.class 文件 - 即您要加载的已编译 Java 类?
  • 要清除它,可以说文件名是 HelloWorld.java。文件对象是 java.io.File 的实例,内容来自 HelloWorld.java。 OP想知道的是如何通过这个文件对象来检索HelloWorld
  • 请下次发布您真正的问题,而不是其中的一部分。这样,您可以获得更好、更准确的帮助。
  • @LuiggiMendoza 嘿,很抱歉。我已经完成了方法计数部分,我遇到的唯一问题是对包外的任何文件进行此操作

标签: java


【解决方案1】:

.java 文件需要与其中的类或枚举具有相同的名称,所以我们可以使用文件名:

public String getClass(File file){
  return removeExtension(file.getName());
}

removeExtension有很多不同的实现方式,这里只是一种:

public static String removeExtension(String file){
  return file.replaceFirst("[.][^.]+$", "");
}

更多:How to get the filename without the extension in Java?

...我想这样做的原因是我可以计算类中的方法。

好的,这不是这样做的方法,您应该考虑反思:What is reflection and why is it useful?

【讨论】:

  • 为了在类上使用反射,必须先加载它。如果您正在评估包之外的类并且在尝​​试加载它们时可能会遇到问题,那么在这种情况下使用反射可能不起作用。最好的方案是解析 Java 文件并获取所需的信息。
  • Class.getName() 不完全相同,后者也为您提供了包名称。这可能也需要阅读包声明。
  • @LuiggiMendoza 好点,但是由于 OP 正在努力从文件中获取类名,他们将有一段地狱般的时间来解析文件的其余部分,所以我希望他们是没有尝试。
  • @BheshGurung 好点子,如果需要的话,打开文件并从中正则表达式包名应该是一件容易的事。
  • @LuiggiMendoza 我不会说真正的问题是计算类中的方法。完成了,我遇到的所有问题就是获取课程本身。
【解决方案2】:

这是在JavaParser 的帮助下从源代码获取类名的示例代码。

这也适用于命名错误的源文件。

import com.github.javaparser.*;
import com.github.javaparser.ast.*;
import com.github.javaparser.ast.body.*;
import java.io.*;
import java.util.*;

public class ClassnameLister {

    private static String parseClassname(File filename) throws Exception {
        try (FileInputStream fin = new FileInputStream(filename)) {
            CompilationUnit cu = JavaParser.parse(fin);
            String packagePrefix = cu.getPackage().getName().toString();
            if (!packagePrefix.isEmpty()) packagePrefix += ".";
            for (TypeDeclaration type : cu.getTypes())
                if (type instanceOf ClassOrInterfaceDeclaration 
                        && ModifierSet.isPublic(type.getModifiers()))
                    return packagePrefix + type.getName();
        }
        return null;
    }

    public static void main(final String[] args) throws Exception {
        System.out.println(parseClassname(new File(args[0])));
    }
}

【讨论】:

    【解决方案3】:

    您可以利用文件名。无需使用getClass()。你要做的是用getName()获取File的文件名,然后你需要strip off the extension

    在使用 Apache 的 FilenameUtils 的那个 SO 问题中,第二部分有一个 solution。对你来说,它会是这样的:

    import org.apache.commons.io.FilenameUtils;
    
    public String getClass(File file) {
        return FilenameUtils.removeExtension(file.getName());
    }
    

    当然,如果您已经创建了File,那么您应该已经有了它的名字。我刚刚使它适合您的存根函数。

    如果您总是要处理.java 文件,那么您可以只关闭split() 扩展名:

        return file.getName().split(".java")[0];
    

    【讨论】:

    • 我非常接近赞成这一点以及韦斯顿的回答,阻止我的是第三方库的要求,当它可以通过正则表达式完成时......
    • @JonK 因此,我添加了一条关于 OP 是否可以知道扩展的注释。他说他知道这将是一个.java 文件,但我不应该假设。
    • 好吧,您的编辑添加了一种不依赖库的方式,所以这是您的 +1
    • @JonK apache 公共库都是开源的。如果您不想/不需要添加库,只需复制代码并将其添加到项目中的实用程序类/方法中即可。
    • @LuiggiMendoza 确实如此,尽管我个人不会那样做。话又说回来,这就是我!
    【解决方案4】:

    您必须自己解析文件。

    1. 包 搜索以\\s*package 开头的行。 如果您没有找到匹配的行,则没有声明任何包。

    2. 类名 外部类定义包含class,但可以使用更多关键字开始和引导。最好的方法是首先出现类,然后检查最终键。

    用一个点添加你的包和类名,你就完成了。

    【讨论】:

      猜你喜欢
      • 2017-08-02
      • 2021-08-04
      • 2012-01-21
      • 2019-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-24
      • 1970-01-01
      相关资源
      最近更新 更多