Rit*_*tes 14 java eclipse performance java-synthetic-methods
我在eclipse中做了一些新的警告设置.有了这些新设置,我面临一个奇怪的警告.阅读后我知道它是什么,但找不到删除它的方法.
这是我的示例代码问题
public class Test {
private String testString;
public void performAction() {
new Thread( new Runnable() {
@Override
public void run() {
testString = "initialize"; // **
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
带**的行在eclipse中给我一个警告
Read access to enclosing field Test.testString is emulated by a synthetic accessor method.
Increasing its visibility will improve your performance.
Run Code Online (Sandbox Code Playgroud)
问题是,我不想更改访问修饰符testString
.另外,不想为它创建一个getter.
应该做些什么改变?
More descriptive example
public class Synthetic
{
private JButton testButton;
public Synthetic()
{
testButton = new JButton("Run");
testButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae)
{
/* Sample code */
if( testButton.getText().equals("Pause") ) {
resetButton(); // **
} else if( testButton.getText().equals("Run") ) {
testButton.setText("Pause"); // **
}
}
}
);
}
public void reset() {
//Some operations
resetButton();
}
private void resetButton() {
testButton.setText("Run");
}
}
Run Code Online (Sandbox Code Playgroud)
线条**
给了我同样的警告.
dim*_*414 27
从Method
类(和它的父类)开始,Member
我们了解到合成成员是" 由编译器引入的 ",而JLS§13.1将告诉我们更多.它指出:
如果Java编译器发出的构造与源代码中显式或隐式声明的构造不对应,则必须将其标记为合成构造
由于本节讨论的是二进制兼容性,因此JVMS也值得参考,而JVMS§4.7.8增加了更多的上下文:
必须使用
Synthetic
属性标记未出现在源代码中的类成员,否则必须ACC_SYNTHETIC
设置其标志.此要求的唯一例外是编译器生成的方法,这些方法不被视为实现工件....该
Synthetic
属性是在JDK 1.1中引入的,以支持嵌套类和接口.
换句话说,"合成"方法是Java编译器引入的实现工件,以便支持JVM本身不支持的语言功能.
你遇到了一个这样的案子; 您正试图private
从匿名内部类访问类的字段.Java语言允许这样做,但JVM不支持它,因此Java编译器生成一个合成方法,将该private
字段公开给内部类.这是安全的,因为编译器不允许任何其他类调用此方法,但它确实引入了两个(小)问题:
简而言之,他们真的不错.除非你有一个具体的理由要避免合成方法(即你已经确定它们是你的应用程序的瓶颈),你应该让编译器按照它认为合适的方式生成它们.如果它打扰你,请考虑关闭Eclipse警告.
如果你真的想阻止编译器生成合成方法,你有几个选择:
protected
可以直接访问内部类的包私有或字段.特别是像Swing应用程序这样的东西应该没问题.但是你说你想避免这种情况,所以我们走了.
保持字段不变,但显式创建一个protected
或public
getter,然后使用它.这基本上是编译器最终自动为您做的事情,但现在您可以直接控制方法的行为.
这是更多的代码,但它是我个人的最爱,因为你正在明确内部和外部类之间的关系.
public Synthetic() {
// Create final local instance - will be reachable by the inner class
final JButton testButton = new JButton("Run");
testButton.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent ae) {
/* Sample code */
if( testButton.getText().equals("Pause") ) {
resetButton();
} else if( testButton.getText().equals("Run") ) {
testButton.setText("Pause");
}
}
});
// associate same instance with outer class - this.testButton can be final too
this.testButton = testButton;
}
Run Code Online (Sandbox Code Playgroud)
这并不总是你想要做的事情.例如,如果以后testButton
可以更改为指向另一个对象,则需要ActionListener
再次重建(虽然这也很明确,所以可以说这是一个特性),但我认为它是最清楚地展示其意图的选项.
您的示例Test
类不是线程安全的 - testString
正在单独设置,Thread
但您没有在该分配上进行同步.标记testString
为volatile
足以确保所有线程都能看到更新.该Synthetic
示例没有此问题,因为testButton
仅在构造函数中设置,但由于这种情况,建议将其标记testButton
为final
.
在您的第二个示例中,无需testButton
直接访问;您可以通过检索操作事件的来源来访问它。
对于该resetButton()
方法,您可以添加一个参数来传递要执行操作的对象,如果您这样做了,那么降低其访问限制并不是一个大问题。
归档时间: |
|
查看次数: |
9432 次 |
最近记录: |