Değişkene iç sınıf içinden erişilir. Kesin olarak beyan edilmesi gerekiyor


116

Yani başlık her şeyi söylüyor. İçinde bir derleme hatası alıyorum onClick.

İşte kod.

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 kullanıyorsanız, neyin değiştirilmesi gerektiğini size gösteren bir Hızlı Düzeltme görmek için hata seçili olarak Ctrl-1 (OS X'te Cmd-1) tuşlarına basabilirsiniz. Burada daha fazlasını görün: deep-first.com/articles/2008/01/11/…
Karmaşıklıklar

Yanıtlar:


130

Son yapmak istemiyorsanız, onu her zaman küresel bir değişken yapabilirsiniz.


1
@KevinZhao Global değişkenler başlatıldıktan sonra nihai mi?
the_prole

@the_prole Java'da final kullanabileceğinizi düşünüyorum, ancak Android uygulamasını oluştururken kullanıp kullanamayacağınızdan emin değilim, bu yüzden Google'da çalışmak iyi bir fikir olabilir :-)
Kevin Zhao

15
Geriye dönüp bakıldığında, eğer kaçınılabiliyorsa, küresel değişkenleri kullanmak kötü bir fikirdir, acemi değilseniz, bu durumda programınızı globallerle aşırı karmaşık hale getirmek iyi bir öğrenme deneyimidir. İşte küresel değişkenlerin neden kötü bir fikir olduğunu açıklayan güzel bir makale.
the_prole

65

Değişkeni final olarak bildirebilir veya bir örnek (veya genel) değişken yapabilirsiniz. Son olarak ilan ederseniz, daha sonra değiştiremezsiniz.

Bir yöntemde tanımlanan ve anonim bir iç sınıf tarafından erişilen herhangi bir değişken son olmalıdır. Aksi takdirde, iç sınıftaki değişkenin değişmesi ve daha sonra kapalı kapsamda kullanılması durumunda iç sınıfta yapılan değişikliklerin çevreleyen kapsamda kalmayacağının farkında olmadan bu değişkeni iç sınıfta kullanabilirsiniz. Temel olarak, iç sınıfta olanlar iç sınıfta kalır.

Burada daha derinlemesine bir açıklama yazdım . Aynı zamanda örnek ve global değişkenlerin neden son olarak bildirilmesine gerek olmadığını da açıklar.


44

Hata her şeyi söylüyor, değiştirin:

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

için

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

87
Sebep: Eğer iki yöntem aynı yerel değişkeni görürse, Java sizden onu değiştirmeyeceğinize yemin etmenizi ister - finalJava dilinde. Referans ile parametrelerin olmamasıyla birlikte bu kural, yerellerin yalnızca ait oldukları yöntemde atanmasını sağlar. Bu nedenle kod daha okunabilir.
ignis

@ignis Bir NullPointerException hatası alıyorum addSiteButton.setOnClickListener(new View.OnClickListener() {, bunun neden ortaya çıkacağı hakkında bir fikriniz var mı?
PhDeOliveira

1
@PhDeOliveira NPE, içeren bir değişkende bir yöntem çağırdığınızda tipik olarak atılır null. Muhtemelen findViewById geri dönüyor null. Daha fazlasını söyleyemem, bir Android programcısı olmamak; Size ayrı bir soru açmanızı tavsiye ederim. Kesinlikle, bunun iç sınıflarla, final vb . İle ilgisi yoktur .
ignis

25

İşte komik bir cevap.

Son bir tek öğeli dizi bildirebilir ve dizinin öğelerini görünüşte istediğiniz kadar değiştirebilirsiniz. Eminim bu derleyici kuralının ilk etapta uygulanmasının nedenini kırmaktadır, ancak bugün olduğu gibi bir zaman sınırlamasındayken kullanışlıdır.

Aslında bunun için kredi talep edemem. IntelliJ'in tavsiyesiydi! Biraz huysuz hissediyor. Ancak küresel bir değişken kadar kötü görünmüyor, bu yüzden burada bahsetmeye değer olduğunu düşündüm. Sorunun sadece bir çözümü. Mutlaka en iyisi değil.

final int[] tapCount = {0};

addSiteButton.setOnClickListener(new View.OnClickListener() {

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

});

Yukarıdaki durumda, başvurulan nesneyi değiştirmiyorsunuz, ancak dizi içindeki içeriği değiştiriyorsunuz. bağlantının güzel açıklaması var.
Abilash

Evet biliyorum. Sorunu çözmek için bir hack gibi görünüyor. Başkaları için açıklığa kavuşturan yorumunuz için teşekkür ederiz.
the_new_mr

4

@Veger'in dediği gibi, finaldeğişkenin iç sınıfta kullanılabilmesi için bunu yapabilirsiniz.

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

Yöntemde yerel bir değişken olarak kullandığınız için pagerdeğil, onu çağırdım . Önek cusomarily sınıf üyesi değişkenleri için (sınıfın başında ifade ve tüm sınıf yöntemlerine temin edilebilir yani değişkenler) ayrılmıştır.mPageronCreatem

Eğer gerçekten bir sınıf üyesi değişkenine ihtiyacınız varsa, bu değişkeni son haline getirmek için çalışmaz, çünkü findViewByIddeğerini ayarlamak için kullanamazsınız onCreate. Çözüm, anonim bir iç sınıf kullanmamaktır. Bu şekilde mPagerdeğişkenin nihai olarak bildirilmesine gerek yoktur ve sınıf boyunca kullanılabilir.

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();
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.