2016-10-30 2 views
3

Я создаю MediaPlayer с seekbar.Here, mp - объект MediaPlayer, а искатель - это объект поиска, созданный в классе MainActivity.Почему компилятор принимает не конечную переменную во внутреннем классе?

Мое понимание состоит в том, что доступ к анонимному внутреннему классу доступны только конечным членам. Затем как осуществляется доступ к этим объектам (mp и seeker).

 h = new Handler(); // create a handler for the MainActivity 

//create a runnable activity to change the progress of seekbar in MainThread for every 1 sec 
    Runnable r = new Runnable() { 
     @Override 
     public void run() { 
      if (mp != null) { 
       seeker.setProgress(mp.getCurrentPosition()/1000); 
      } 
      h.postDelayed(this, 1000); 
     } 
    }; 

    this.runOnUiThread(r); 

Примечание: код работает отлично. Спасибо за помощь.

+1

@ user3215142 ... и было правило, что такие переменные должны были быть «final», на что собственно и вопрос. Ваше несогласное утверждение о том, что «рекомендуемый способ состоит в том, чтобы ваши статические станы» нуждались в обосновании. – EJP

ответ

4

Это происходит, потому что есть что-то под названием эффективно окончательное.

jls-8.1.3:

Любая локальная переменная, формальный параметр, или параметр исключения используется, но не объявлен во внутреннем классе должна либо быть объявлена ​​окончательным или эффективно окончательным (§4.12.4), или компиляции когда происходит попытка использования.

jls-4.12.4:

Если переменная эффективно окончательным, добавив окончательный модификатор к его декларации не будет вводить какие-либо ошибки во время компиляции. И наоборот, локальная переменная или параметр, объявленный окончательно в действительной программе, становится окончательно окончательным, если последний модификатор удален.

Когда переменная установлена ​​только один раз и используется во внутреннем классе, компилятор превратит модификатор переменной в final.

Рассмотрим этот код Tests.java:

public class Tests { 
    public static void main(String[] args) throws Throwable { 
     String value = "Hello"; 

     Runnable runnable = new Runnable() { 
      @Override 
      public void run() { 
       System.out.println(value); 
      } 
     }; 
    } 
} 

Код выше, при компиляции будет производить этот код ниже. Вы видите, что компилятор меняет модификатор value на окончательный?

Tests.class (декодируется):

public class Tests { 
    public Tests() { 
    } 

    public static void main(String[] args) throws Throwable { 
     final String value = "Hello"; 
     Runnable var10000 = new Runnable() { 
      public void run() { 
       System.out.println(value); 
      } 
     }; 
    } 
} 

Но, если вы измените значение переменной (см кода, приведенную ниже), он не будет компилироваться, потому что компилятор знает, что это не так эффективная конечная переменная:

public class Tests { 
    public static void main(String[] args) throws Throwable { 
     String value = "Hello"; 
     value = "world"; 

     Runnable runnable = new Runnable() { 
      @Override 
      public void run() { 
       System.out.println(value); 
      } 
     }; 
    } 
} 
Смежные вопросы