Ответ 1
Если вы не хотите делать это окончательным, вы всегда можете просто сделать глобальную переменную.
Итак, название говорит все. Я получаю ошибку компиляции внутри моего 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);
}
Если вы не хотите делать это окончательным, вы всегда можете просто сделать глобальную переменную.
Вы можете объявить переменную final или сделать ее переменной экземпляра (или глобальной). Если вы объявите его окончательным, вы не сможете изменить его позже.
Любая переменная, определенная в методе и доступная анонимным внутренним классом, должна быть окончательной. В противном случае вы можете использовать эту переменную во внутреннем классе, не сознавая, что если переменная изменяется во внутреннем классе, а затем она используется позже в охватывающей области, изменения, сделанные во внутреннем классе, не сохраняются в охватывающей области. В основном, то, что происходит во внутреннем классе, остается во внутреннем классе.
Я написал более подробное объяснение здесь. Он также объясняет, почему экземпляры и глобальные переменные не должны быть объявлены окончательными.
Ошибка говорит все, измените:
ViewPager mPager = (ViewPager) findViewById(R.id.fieldspager);
к
final ViewPager mPager = (ViewPager) findViewById(R.id.fieldspager);
Здесь забавный ответ.
Вы можете объявить окончательный одноэлементный массив и, по-видимому, изменить все элементы массива. Я уверен, что это нарушает саму причину, по которой это правило компилятора было реализовано в первую очередь, но это удобно, когда вы находитесь в привязке ко времени, как я был сегодня.
Я на самом деле не могу претендовать на кредит за это. Это была рекомендация IntelliJ! Чувствует себя немного хакером. Но не так плохо, как глобальная переменная, поэтому я подумал, что стоит упомянуть здесь. Это всего лишь одно решение проблемы. Не обязательно лучший.
final int[] tapCount = {0};
addSiteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tapCount[0]++;
}
});
Как сказал @Veger, вы можете сделать его final
, чтобы переменная могла использоваться во внутреннем классе.
final ViewPager pager = (ViewPager) findViewById(R.id.fieldspager);
Я назвал его pager
, а не mPager
, потому что вы используете его как локальную переменную в методе onCreate
. Префикс m
зарезервирован для переменных класса (т.е. Переменных, объявленных в начале класса и доступных для всех методов класса).
Если вам действительно нужна переменная-член класса, она не работает, чтобы сделать ее окончательной, потому что вы не можете использовать findViewById
для установки ее значения до onCreate
. Решение состоит в том, чтобы не использовать анонимный внутренний класс. Таким образом, переменная mPager
не должна быть объявлена окончательной и может использоваться во всем классе.
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);
}
};
}
Когда вы создаете inner class
About, фактически компилятор генерирует новый класс - <ClassName>$<Counter>.class
и передает следующие параметры в конструкторLocal variable on stack
Невозможно переназначить переменную из конструктора (или метода), но просто изменить состояние передаваемой переменной. Вот почему вы можете использовать:
Object
...) будет очищенаint
...) и передайте ее как ссылочный тип (IntelliJ IDEA
предлагает вам преобразовать переменную в окончательный массив из одного элемента)