为什么允许从静态对象创建非静态引用?

时间:2011-01-24 16:42:37

标签: java android

以下是一个例子:

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?
            }
        });
    }
}

7 个答案:

答案 0 :(得分:5)

那不是一个静态的对象。这就是为什么它可能。

答案 1 :(得分:4)

  • 匿名(内部)类(本例中为new View.OnClickListener())不是静态的,它们是非静态内部类。

  • 非静态内部类与包含外部类(在本例中为Test)的实例之间存在隐含关系,通过该实例创建内部类。它就像内部类有一个暗示的ivar指向它的外部类的相关实例。

  • 内部类可以通过这种关系访问其外部类的ivars,如i

答案 2 :(得分:3)

静态对象在哪里?你所拥有的是一个匿名的内部类 - 但是当你使用new关键字调用构造函数时,你在它的实例中做了。

答案 3 :(得分:1)

 i = 10; // How can this be possible?

i是类成员,可以通过类方法访问代码,

你期待什么?

答案 4 :(得分:1)

这里没有静态物体。你有一个匿名内部类的实例(View.OnClickListener),但没有静态对象。

编辑:我想知道你是否将static变量与local (non-member) final variables混淆。 这与静态变量没什么关系,但是我可以看到一个(自我描述的)新手如何让他们感到困惑。

  

任何局部变量,形式方法   参数或异常处理程序   使用但未在声明中声明的参数   内部类必须声明为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
            }
        });
    }

答案 5 :(得分:0)

对此进行解释:这是可能的,因为您创建的类型View.OnClickListener的(匿名)类是而不是静态,因此保留了对其外部类的隐藏引用。话虽如此:

        @Override
        public void onClick(View v) {
            i = 10;
        }

相当于:

        @Override
        public void onClick(View v) {
            Test.this.i = 10;
        }

这有意义吗?

答案 6 :(得分:0)

我认为混淆来自OnClickListenerView限定的事实。它实际上不是static。以下是等效的:

import android.view.View;
...
button.setOnClickListener(new View.OnClickListener() {

import android.view.View;
import android.view.View.OnClickListener;
...
button.setOnClickListener(new OnClickListener() {