Java中的传递引用

Java中的传递引用,java,reference,dependencies,classpath,transitive-dependency,Java,Reference,Dependencies,Classpath,Transitive Dependency,tldr什么使得在构建路径中包含可传递引用成为必要 解释 我试图分析一些使用eclipse工作区编译的Java源代码。工作区中有大量项目 我尝试检测项目之间未使用的引用 我的第一种方法是遍历所有项目,从.classpath文件中获取所有引用,然后分析同一项目中的所有.java文件。如果.java文件具有来自其他项目的import语句,则需要引用此其他项目。 这样,我在类路径中找到了一些没有“理由”的引用 但当我删除这些引用时,构建就中断了。一种情况是,如果引用的类是从第三个项目扩展的类。此项目是

tldr什么使得在构建路径中包含可传递引用成为必要

解释

我试图分析一些使用eclipse工作区编译的Java源代码。工作区中有大量项目

我尝试检测项目之间未使用的引用

我的第一种方法是遍历所有项目,从.classpath文件中获取所有引用,然后分析同一项目中的所有.java文件。如果.java文件具有来自其他项目的import语句,则需要引用此其他项目。 这样,我在类路径中找到了一些没有“理由”的引用

但当我删除这些引用时,构建就中断了。一种情况是,如果引用的类是从第三个项目扩展的类。此项目是可传递引用的,需要位于构建路径中

我想知道还有什么其他类型的关系(除了继承)会导致类路径中的传递引用? 对于多个继承层,每个继承类位于另一个项目中,该如何处理

  • 具有引用项目B中的类B的类a的项目a
  • 第三个项目C带有ClassC
在这些情况下,您需要从projectA中引用ProjectC

  • 如果ClassB从classC继承/实现,并且ClassA从ClassB调用一个方法
  • 如果ClassA从ClassB调用(!)一个具有包含ClassC(参数或返回值)签名的方法(对于异常也是如此!)
此外,通过查看ClassA的导入语句,还不能找到ProjectA的所有引用

  • 如果ClassC由ClassA使用,并且与ClassA位于同一个包中,则ClassC将不会作为导入列在ClassA中
  • 如果ClassA使用ClassC的全名(包括包名),则不会创建导入语句

    • 什么使它成为必要?

      Java编译的强制规则使其成为必要。Java需要知道代码域中的内容,以便验证所遵循的规则。域是类路径中的jar文件集。 如果实现接口,则非抽象实现类或实现接口的类的非抽象子类需要实现接口。需要满足覆盖注释。从代码角度和人员角度来看,对其他方法的引用都需要是可见的。如果方法使用不同类或接口中的方法,则调用类需要知道该方法的签名

      我将如何处理它?

      我将使用“分类器”来指代类和接口。 您希望从一组已知的已验证分类器和已知的未验证分类器开始。
      从已知的未验证分类器开始,即目标项目中的所有分类器,而已知的验证分类器为空

      检查每个未经验证的分类器,并确定使用的所有未知分类器,并将其添加到未经验证的分类器集中

      验证当前未验证的分类器是否位于类路径上。如果未找到,则返回错误

      将已处理的分类器从未验证移动到已验证

      重复此过程,直到所有分类器都经过验证

      使用的分类器包括字段类型、方法返回类型、方法参数类型、参数中的变量类型、扩展类、实现的接口、注释,在某些情况下还包括Javadoc引用。根据您的项目规则,仅使用导入可能会遗漏一些内容。接口可能在同一个包中,但来源于不同的项目

      为什么反射和Spring配置需要超出范围?

      此类操作使用基于文本的切换来完成代码。反射可以使用字符串“Package.classname”创建类,而不被标识为“used class”。这些概念需要额外的处理,超出了纯源代码分析或字节码分析的范围

      如果您想深入研究,Java虚拟机规范可以让您更深入地了解类文件需要运行什么。特别是Java10规范中的“4.类文件格式”和“5.加载、链接和初始化”。

      您的项目是否使用DLL、Spring XML配置、Java反射或任何其他方面来阻止从纯源代码分析实现此目标?如果两个项目中的两个类在同一个包中,您只需查看导入语句就不会发现它们之间的依赖关系。@ProgrammersBlock我不明白。我做纯源代码分析。@NickL正确。这是一个需要考虑的额外情况。回想起来,“使用的分类器”可能还需要类实现中的每个方法调用,因为类文件将源分类器记录在字节码中。意思是如果你有A.b().c().d();然后,即使没有为b()和c()创建变量或字段,也需要考虑它们的返回类型。感谢该算法。但我想知道哪些情况会导致可传递依赖项(或未声明的导入语句),因为我不想构建编译器。