[英]Why is it allowed to make a non-static reference from static object?
这是一个例子:
public class Test extends Activity {
Button button;
public int i;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button = (Button) findViewById(R.id.Button01);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
i = 10; // How can this be possible?
}
});
}
}
那不是静态对象。 这就是为什么有可能的原因。
匿名(内部)类(在这种情况下为new View.OnClickListener()
)不是静态的,它们是非静态的内部类。
非静态内部类与包含其创建内部类的外部类(在本例中为Test
)的实例具有隐式关系。 它像内部类一样具有隐含的ivar,它指向外部类的相关实例。
内部类可以访问实例变量,像i
通过该关系,其外部类的。
静态对象在哪里? 您拥有的是一个匿名内部类,但是当您使用new关键字调用构造函数时,您在其中实例化了它。
i = 10; // How can this be possible?
i
是班级成员,可以通过班级方法访问您的代码,
您期望什么?
这里没有可见的静态物体。 您有一个匿名内部类的实例( View.OnClickListener
),但是没有静态对象。
编辑:我想知道您是否将static
变量与局部( 非成员) final
变量混淆了。 这与静态变量没有直接关系,但是我可以看到(自我描述的)新手如何使它们困惑。
任何在内部类中使用但未声明的局部变量,形式方法参数或异常处理程序参数都必须声明为
final
,并且必须在内部类主体之前进行明确分配。
修改你的榜样,下面是不是允许的情况下:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
int i = 0; // This is non-final; access to it from an inner class is not allowed.
button = (Button) findViewById(R.id.Button01);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
i = 10; // Compiler error
}
});
}
这里还有另一种是不允许的:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final int i = 0; // This is final; read-only access to it from an inner class is allowed.
button = (Button) findViewById(R.id.Button01);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
i = 10; // Compiler error -- can't modify a final variable.
}
});
}
但这是允许的:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final int i = 0; // This is final; read-only access to it from an inner class is allowed.
button = (Button) findViewById(R.id.Button01);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int j = i; // OK
}
});
}
对此进行解释:可能是因为您正在创建的View.OnClickListener
类型的(匿名)类不是静态的,因此对它的外部类保留了隐藏的引用。 话虽如此:
@Override
public void onClick(View v) {
i = 10;
}
等效于:
@Override
public void onClick(View v) {
Test.this.i = 10;
}
那有意义吗?
我认为混淆来自于OnClickListener
由View
限定的事实。 它实际上不是static
。 以下是等效的:
import android.view.View;
...
button.setOnClickListener(new View.OnClickListener() {
和
import android.view.View;
import android.view.View.OnClickListener;
...
button.setOnClickListener(new OnClickListener() {
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.