开发者

Why is it allowed to make a non-static reference from static object?

Here is an example:

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开发者_如何学C void onClick(View v) {
                i = 10; // How can this be possible?
            }
        });
    }
}


That's not an static object. That's why it's possible.


  • Anonymous (inner) classes (new View.OnClickListener() in this case) are not static, they are non-static inner classes.

  • A non-static inner class has an implied relationship to the instance of the containing outer class (Test in this case) through which the inner class was created. Its like the inner class has an implied ivar to that points to its related instance of the outer class.

  • The inner class can access the ivars, like i, of its outer class through this relationship.


Where is the static object? What you have there is an anonymous inner class- but you made in instance of it when you called the constructor with the new keyword.


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

i is class member and it can be access by class method for your code ,

what did you expect?


There is no static object in sight here. You have an instance of an anonymous inner class (the View.OnClickListener), but no static objects.

EDIT: I'm wondering if perhaps you're confusing static variables with local (non-member) final variables. This has nothing directly to do with static variables, but I can see how a (self-described) newbie might get them confused.

Any local variable, formal method parameter or exception handler parameter used but not declared in an inner class must be declared final, and must be definitely assigned before the body of the inner class.

Modifying your example, here's a case that's not allowed:

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

And here's another that's not allowed:

    @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.
            }
        });
    }

But this is allowed:

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


For an explanation to this: it's possible because the (anonymous) class of type View.OnClickListener you're creating is not static and hence keeps a hidden reference to its outer class. That being said:

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

is equivalent to:

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

Does that make sense?


I think the confusion comes from the fact that the OnClickListener is qualified by the View. It is not actually static. The following are equivalent:

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

and

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜