在Scala immutable Vector code中有评论说:
原则上,大多数成员应该是私人的。但是,必须谨慎选择访问权限,以防止方法内联
答案 0 :(得分:8)
这通常不适用于Java。访问检查仅在Resolution过程中执行一次。当Java方法进行JIT编译时,符号引用已经过解析和验证。实际上,内联不是在原始字节码上执行,而是在编译器特定的中间表示上执行。因此,访问修饰符通常不具有性能副作用。
但是,我可以编写一个人工测试用例,其中private
/ public
修饰符会显着影响性能:
public class Test {
static final Inner inner = new Inner();
static class Inner {
int x = 1;
int getX1() { return x; }
int getX2() { return getX1(); }
int getX3() { return getX2(); }
int getX4() { return getX3(); }
int getX5() { return getX4(); }
int getX6() { return getX5(); }
int getX7() { return getX6(); }
int getX8() { return getX7(); }
int getX9() { return getX8(); }
private int getPrivate() { return getX9(); }
public int getPublic() { return getX9(); }
}
@GenerateMicroBenchmark
public int inlinePrivate() {
return inner.getPrivate();
}
@GenerateMicroBenchmark
public int inlinePublic() {
return inner.getPublic();
}
}
Benchmark Mode Thr Cnt Sec Mean Mean error Units
b.Test.inlinePrivate thrpt 1 3 5 289480,928 2247,656 ops/msec
b.Test.inlinePublic thrpt 1 3 5 1157970,245 18473,139 ops/msec
此效果由access$000
合成方法解释,javac
生成该方法以允许访问内部类的私有成员。在上面的测试用例中,这个额外的访问器阻止了内联,因为HotSpot中默认的最大内联级别是9(-XX:MaxInlineLevel=9
)。由于getPrivate()
不能直接从外部类调用,因此额外的access$000()
方法进行了第10级调用,因此没有内联。
答案 1 :(得分:1)
我不是"编译器决策的专家"但从逻辑上讲,我会说:
让我们想象这两个类(例如Java):
class A {
private B b;
public void execute(){
b.execute();
}
}
class B {
private int number;
public void execute {
println(number);
}
}
如果B' execute
被编译器内联到A execute
,则会导致非法访问,因为number
在B中是私有的:< / p>
class A {
private B b;
public void execute(){
println(number); //OUPS! number is unreachable directly from A
}
}
所以我会说,当你期望某些&#34;内联&#34;时,更愿意避免一些不兼容的变量的范围。
当然,我认为它在极少数情况下很有用(主要用于性能优化,我不会想象其他情况)..也许你说的情况,否则会导致很多&#34;糟糕的封装&#34; ...