Java 变量是在内部类中访问的。需要宣布为最终决定

Java 变量是在内部类中访问的。需要宣布为最终决定,java,android,Java,Android,我的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) {

我的
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);

}

错误说明了一切,更改:

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


如果不想将其设置为最终变量,则始终可以将其设置为全局变量。

您可以将该变量声明为最终变量,或将其设置为实例(或全局)变量。如果您将其声明为最终版本,则以后将无法更改它

在方法中定义并由匿名内部类访问的任何变量都必须是final。否则,您可以在内部类中使用该变量,而不知道如果该变量在内部类中发生更改,然后在随后的封闭范围中使用该变量,则在内部类中所做的更改不会在封闭范围中持久存在。基本上,在内部类中发生的事情留在内部类中

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

我写了一篇更多的文章。它还解释了为什么实例和全局变量不需要声明为final。

正如@Veger所说,您可以将其设置为final,以便在内部类中使用该变量

final ViewPager pager = (ViewPager) findViewById(R.id.fieldspager);
我称它为
pager
而不是
mPager
,因为您在
onCreate
方法中将它用作局部变量。
m
前缀通常保留给类成员变量(即在类的开头声明并可用于所有类方法的变量)

如果您确实需要一个类成员变量,那么将其设置为final是不可行的,因为在
onCreate
之前,您不能使用
findViewById
设置其值。解决方案是不使用匿名内部类。这样,
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);
        }
    };
}
这里有一个有趣的答案

您可以声明最后一个单元素数组,并根据需要更改数组的元素。我确信它打破了编译器规则最初被实现的原因,但是当你像我今天这样处于时间约束中时,它很方便

事实上,我不能为这件事负责。这是IntelliJ的推荐!感觉有点不舒服。但似乎没有全局变量那么糟糕,所以我认为这里值得一提。这只是解决问题的一个办法。不一定是最好的

final int[] tapCount = {0};

addSiteButton.setOnClickListener(new View.OnClickListener() {

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

});

如果您使用的是Eclipse,那么可以在选择错误的情况下按Ctrl-1(OSX上的Cmd-1)查看快速修复程序,该程序将显示需要更改的内容。更多信息请参见:原因:如果两个方法看到相同的局部变量,Java希望您发誓不会更改它-
final
,用Java语言说。再加上没有按引用参数,该规则确保局部变量只在它们所属的方法中赋值。代码因此更具可读性。@ignis我在addSiteButton.setOnClickListener(new View.OnClickListener()上遇到NullPointerException错误{你知道为什么会出现这种情况吗?@PhDeOliveira NPE通常是在你调用一个包含
null
的变量的方法时抛出的。可能是返回
null
。我不能再说了,不是一个Android程序员;我建议你打开一个单独的问题。当然,它与内部类无关ses,final,et similia。@igins“如果两个方法看到相同的局部变量”,这与上下文无关。OP使用的是接口,Java希望确保提供的对象在其上执行“任务”时不会被同时修改。“因此代码更具可读性。”这显然是一句误导性的话。Java试图降低并发修改错误和此警告(或编译错误)与可读性无关。@KevinZhao在初始化后是否为全局变量final?@prole我认为您可以在Java中使用final,但我不确定在构建Android应用程序时是否可以使用final,所以用谷歌搜索可能是个好主意:-)回顾过去,如果可以避免使用全局变量,则使用全局变量是一个坏主意,除非您是初学者,在这种情况下,使用全局变量使程序过于复杂是一个很好的学习体验。这是一篇很好的文章,解释了为什么全局变量是一个坏主意。在上述情况下,您不是在更改引用的对象,而是在更改数组中的内容。有很好的解释。是的,我知道。这看起来像是一个解决问题的黑客。感谢你的评论为其他人澄清。在这种情况下,在我看来,全局变量更好…当然,如果你需要从内部类更新外部类状态,这是一个解决方案。请投票说明明显的问题!
    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();
    }
}