変数は内部クラス内でアクセスされます。最終的に宣言する必要がある


116

タイトルがすべてを物語っています。内でコンパイルエラーが発生しますonClick

これがコードです。

public class fieldsActivity extends Activity {

Button addSiteButton;
Button cancelButton;
Button signInButton;


/**
 * Called when the activity is first created.
 */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // to create a custom title bar for activity window
    requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);

    setContentView(R.layout.fields);
    // use custom layout title bar
    getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.topbar);

    Pager adapter = new Pager();
    ViewPager mPager = (ViewPager) findViewById(R.id.fieldspager);
    mPager.setAdapter(adapter);
    mPager.setCurrentItem(1);



    addSiteButton = (Button) findViewById(R.id.addSiteButton);
    addSiteButton.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
           mPager.setCurrentItem(2, true); //Compilation error happens here.
        }


    });


    cancelButton = (Button) findViewById(R.id.cancel_button);
    signInButton = (Button) findViewById(R.id.sign_in_button);

}

1
Eclipseを使用している場合は、エラーを選択してCtrl-1(OS XではCmd-1)を押すと、変更が必要な箇所を示すクイックフィックスが表示されます。もっとここを参照してください:depth-first.com/articles/2008/01/11/...
Intrications

回答:


130

最終的にしたくない場合は、いつでもグローバル変数にすることができます。


1
@KevinZhao初期化されたグローバル変数は最終的なものですか?
the_prole 2015年

@the_prole finalはJavaで使用できると思いますが、Androidアプリの作成時にそれを使用できるかどうかはわからないので、グーグルするのは良い考えかもしれません:-)
Kevin Zhao

15
振り返ってみると、初心者でない限り、グローバル変数を使用することは避けられますが、グローバル変数を使用することはお勧めできません。以下は、グローバル変数が悪い考えである理由を説明する優れた記事です。
the_prole 2015年

65

変数finalを宣言するか、インスタンス(またはグローバル)変数にすることができます。最終的に宣言した場合、後で変更することはできません。

メソッドで定義され、匿名の内部クラスによってアクセスされる変数はすべてfinalでなければなりません。それ以外の場合は、その変数を内部クラスで使用できます。変数が内部クラスで変更され、後でその変数が外側のスコープで使用された場合、内側のクラスで行われた変更は外側のスコープで永続化されません。基本的に、内部クラスで発生することは内部クラスにとどまります。

ここで、より詳細な説明を書きました。また、インスタンス変数とグローバル変数をfinalと宣言する必要がない理由についても説明します。


44

エラーはそれをすべて言います、変更:

ViewPager mPager = (ViewPager) findViewById(R.id.fieldspager);

final ViewPager mPager = (ViewPager) findViewById(R.id.fieldspager);

87
理由:2つのメソッドが同じローカル変数を参照する場合、Javaはそれを変更しないことを誓うように求めます- final、Javaでは。参照パラメーターが存在しないことと合わせて、このルールはローカルが所属するメソッドでのみ割り当てられることを保証します。したがって、コードはより読みやすくなります。
イグニス

@ignis NullPointerExceptionエラーが発生しaddSiteButton.setOnClickListener(new View.OnClickListener() {ます。なぜこれが発生するのか、何かわかりますか?
PhDeOliveira 2013年

1
@PhDeOliveira NPEは通常、を含む変数に対してメソッドを呼び出すとスローされますnull。おそらく、findViewByIdがを返していnullます。Androidプログラマではないので、これ以上は言えません。別の質問を開くことをお勧めします。確かに、それは内部クラス、最終的に、とは何の関係もありませんらsimiliaを
イグニス2013年

25

ここに面白い答えがあります。

最後の1要素の配列を宣言して、配列の要素を必要なすべてに変更できます。このコンパイラルールが最初に実装されたまさにその理由を破るに違いありませんが、今日のようにタイムバインドされている場合は便利です。

私は実際にこれのクレジットを請求することはできません。IntelliJの推奨でした!少しハックを感じます。しかし、グローバル変数ほど悪くないように思われるので、ここで言及する価値があると思いました。これは問題の解決策の1つにすぎません。必ずしも最高のものではありません。

final int[] tapCount = {0};

addSiteButton.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View v) {
       tapCount[0]++;
    }

});

上記の場合、参照オブジェクトを変更するのではなく、配列内のコンテンツを変更します。リンクは素晴らしい説明があります。
Abilash

はい、知っています。問題を回避するためのハックのようです。他の人のためにそれを明確にするあなたのコメントをありがとう。
the_new_mr 2018

4

@Vegerが言ったfinalように、変数を内部クラスで使用できるようにすることができます。

final ViewPager pager = (ViewPager) findViewById(R.id.fieldspager);

メソッドでローカル変数として使用しているのではpagerなく、それを呼び出しmPagerましたonCreate。のm接頭辞はcusomarilyクラスのメンバ変数(クラスの先頭で宣言され、すべてのクラスメソッドに利用できますすなわち変数)のために予約されています。

実際にクラスメンバー変数が必要な場合は、を使用findViewByIdしてその値を設定するために使用できないため、それを最終的にすることはできませんonCreate。解決策は、匿名の内部クラスを使用しないことです。この方法では、mPager変数をfinalで宣言する必要がなく、クラス全体で使用できます。

public class MainActivity extends AppCompatActivity {

    private ViewPager mPager;
    private Button mButton;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // ...

        mPager = (ViewPager) findViewById(R.id.fieldspager);

        // ...

        mButton.setOnClickListener(myButtonClickHandler);
    }


    View.OnClickListener myButtonClickHandler = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            mPager.setCurrentItem(2, true);
        }
    };
}

0
    public class ConfigureActivity extends Activity {

        EditText etOne;
        EditText etTwo;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_configure);

            Button btnConfigure = findViewById(R.id.btnConfigure1);   
            btnConfigure.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            configure();
                        }
                    });
    }

    public  void configure(){
            String one = etOne.getText().toString();
            String two = etTwo.getText().toString();
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.