方法的可见性及其成本

时间:2016-09-17 16:44:12

标签: java visibility

我最近阅读了杰克沃顿的this article。这是针对Android的,但对我认为的java也非常有效。

请考虑以下代码:

public class A {

    private String someField = "abc";

    class B {

        public void doSomething() {
            System.out.println(someField);
        }

    }
}

我们有一个简单的类A和一个内部类B(它有一个对A的引用并且可以访问它的成员)。 B类正在访问A中的字段someField,即使它是私有的。根据这篇文章,这是由生成synthetic accessor methods的编译器完成的,它允许内部类访问该字段 现在我的方式更基本的问题:为什么编译器在编译代码时甚至关心可见性?正如我们在这个例子中看到的,生成了一种新方法,它基本上只是引入了开销 可见性对于构建好的软件来说是件好事,但是如果编译器根据声明的visibilies检查一切是否正确,为什么不优化这些方法(例如,只是将所有内容都公开并允许调用它)? /> 首先我认为这是出于安全原因,但据我所知,反射允许所有领域的访问,而不是关心可见性。

这可能是对我的基本误解,如果是这样的话,如果有人能向我解释,我会很高兴。

2 个答案:

答案 0 :(得分:3)

  

编译代码时,为什么编译器甚至关心可见性?

JVM不允许访问类外的private方法/构造函数/字段。对于在设计此规则后添加的嵌套类,它没有特殊规则。相反,编译器添加了访问器方法,因此语言可以支持JVM没有的访问方式。

  

正如我们在这个例子中看到的,生成了一个新方法,它基本上只引入了开销。

仅当方法未被调用且未经过优化时才会被优化。

添加任何简单方法(On Hotspot,任何35字节或更少的方法)将非常快速地内联并且对性能没有影响(除非达到最大内联级别)

  

为什么不优化这些方法

它在运行时执行此操作,以便继续执行先前的规则。

  

反射允许所有字段的访问,而不是据我所知的那样关心可见性。

虽然默认情况下不是这样,但你必须明确地想要这个作为一个选项而没有一个防止它的SecurityManager。

答案 1 :(得分:0)

如果编译器在编译时将所有私有字段转换为公共字段,则在将项目编译到库并由其他人重用时会发生一个问题。在这种情况下,您的所有私人字段都将公开。

有一些工具可以优化它。在Android中,有一个名为ProGuard的工具可将所有getter / setter转换为直接字段访问。