内部类中访问variables。 需要被宣布为最终

所以标题说明了一切。 我在我的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); } 

如果你不想做最后的决定,你总是可以把它变成一个全局variables。

错误说这一切,改变:

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

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

您可以声明variablesfinal,或者使其成为一个实例(或全局)variables。 如果你声明了最终的结果,你将不能在以后改变它。

任何在方法中定义的和匿名内部类访问的variables必须是最终的。 否则,您可以在内部类中使用该variables,但不知道如果variables在内部类中发生变化,并且稍后在封闭范围中使用,则内部类中所做的更改不会保留在封闭范围内。 基本上,内部阶层发生的事情是留在内部阶层。

我在这里写了一个更深入的解释 。 这也解释了为什么实例和全局variables不需要被声明为最终的。

正如@维格所说,你可以使它成为final以便variables可以在内部类中使用。

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

我把它叫做pager而不是mPager因为你在onCreate方法中使用它作为局部variables。 m前缀是为类成员variables保留的(即,在类的开始处声明的variables,并且可用于所有类方法)。

如果你确实需要一个类成员variables,那么它就不能工作,因为你不能使用findViewById来设置它的值,直到onCreate 。 解决办法是不要使用匿名的内部类。 这样, mPagervariables不需要被声明为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); } }; }