当前位置: 首页 > 面试题库 >

是否可以禁用静态最终变量的javac内联?

爱琪
2023-03-14
问题内容

Java静态编译器(javac)内联一些静态最终变量,并将值直接带到常量池中。考虑以下示例。A类定义了一些常量(公共静态最终变量):

public class A {
    public static final int INT_VALUE = 1000;
    public static final String STRING_VALUE = "foo";
}

B类使用以下常量:

public class B {
    public static void main(String[] args) {
        int i = A.INT_VALUE;
        System.out.println(i);
        String s = A.STRING_VALUE;
        System.out.println(s);
    }
}

当您编译类B时,javac从类A获取这些常量的值,并在B.class中内联这些值。结果,在编译时必须将类A的依赖项B从字节码中删除。这是一个非常特殊的行为,因为在
编译时 要烘焙这些常量的值。您可能会认为这是JIT编译器在运行时可以做的最简单的事情之一。

有什么方法或任何隐藏的编译器选项可让您禁用Javac的这种内联行为吗?对于背景,我们正在考虑进行字节码分析以实现依赖关系,这是字节码分析无法检测到编译时依赖关系的少数情况之一。谢谢!

编辑 :这是一个令人烦恼的问题,因为通常我们不控制所有源代码(例如,定义常量的第三方库)。我们有兴趣从 使用
常量的角度检测这些依赖关系。由于从 使用 常量的代码中删除了引用,因此没有简单的方法可以检测到它们,而无需进行源代码分析。


问题答案:

Java Puzzlers(Joshua Bloch)的第93项说,您可以通过防止将最终值视为常量来解决此问题。例如:

public class A {
  public static final int INT_VALUE = Integer.valueOf(1000).intValue();
  public static final String STRING_VALUE = "foo".toString();
}

当然,如果您无权访问定义常量的代码,则这些都不相关。



 类似资料:
  • 问题内容: 将变量声明为的区别是什么 要么 如果我只希望变量是局部的,并且是常量(以后不能更改)? 谢谢 问题答案: 仅仅具有预期的效果。 声明static使其成为一个类变量,使其可以使用类名进行访问

  • 问题内容: 静态变量只有实例(也就是说,它们是类的一部分)。例如:Math.pi 有什么办法可以有多个静态变量实例吗?我听说有一些与Classloader相关的东西吗? 问题答案: 如果发现需要一个静态变量的多个实例,则强烈表明您不应该首先使用静态变量。 是的,如果同一类加载到不同的类加载器中,则该类的每个副本将具有其自己的静态变量。但是,唯一可以静态引用这些静态变量的代码将是由同一类加载器加载的

  • 问题内容: 通常,最终静态成员,尤其是变量(或静态最终变量,当然可以以任何顺序使用,而不会重叠含义)已广泛用于Java接口中,以定义实现类的 协议行为 ,这意味着实现该类的类(继承)接口必须包含该接口的所有成员。 我无法区分 final 和 final静态 成员。final静态成员是一个声明为final或其他东西的静态成员?在哪些特定情况下应专门使用它们? 永远不能在方法内部,静态方法内部或实例方

  • 问题内容: 我有一个带有静态变量的Java类 如何使用反射访问对象? (我有字符串。我需要访问该对象。) 问题答案: 访问静态字段的方式与普通字段完全相同,只是不需要将任何参数传递给方法(可以传递null)。 试试这个:

  • 问题内容: 在Java中,何时应使用静态非最终变量? 例如 显然,这里我们不是在谈论常量。 根据我的经验,我经常在使用单例时对它们进行辩护,但后来我最终需要拥有多个实例,这使我感到非常头痛和重构。 似乎很少在实践中使用它们。你怎么看? 问题答案: 统计信息收集可以使用非最终变量,例如,计算创建的实例数。另一方面,对于这种情况,您可能还是要使用etc,这时可能是最终的。另外,如果您要收集多个统计信息

  • 这将打印a.a=50 但是,如果我将更改为,那么我可以如何访问该变量呢?