Использование конечных полей в анонимных классах, объявление статического вложенного класса внутри метода и определение статических членов внутри внутреннего класса

У меня есть три вопроса.

1- Как можно использовать неконечные поля в классе анонимного класса, если их значение может измениться?

class Foo{
    private int i;
    void bar(){
        i = 10
        Runnable runnable = new Runnable (){
            public void run (){
                System.out.println(i); //works fine
            }//end method run
        }//end Runnable
    }//end method bar
}//end class Foo 

2- Почему статические вложенные классы не могут быть объявлены внутри методов, поскольку внутренние классы могут иметь имя (локальные классы)?

Class Foo {
    void bar(){
        class LocalClass{ //static nested classes are NOT allowed here
            //define members
        }//end class LocalClass
    }//end method bar
}//end class Foo

3- Почему внутренний класс не может определять статические члены, кроме статических конечных полей?

class Foo {
    class Bar{
        static int x; //NOTallowed
        static final int y; //allowed

        static void doSomething(){} //NOT allowed
    }//end class Bar
}//end class Foo

Что касается третьего вопроса, я знаю, что внутренние классы связаны с экземплярами их внешних классов, но для меня это все еще неубедительный ответ. Мы могли бы просто использовать что-то вроде new Foo().Bar.doSomething();, если бы были разрешены статические методы.


person kzidane    schedule 06.10.2013    source источник


Ответы (1)


1- Как можно использовать неконечные поля в классе анонимного класса, если их значение может измениться?

class Foo{
    private int i;
    void bar(){
        i = 10;
        Runnable runnable = new Runnable (){
            public void run (){
                System.out.println(i); //works fine
            }//end method run
        }//end Runnable
    }//end method bar
}//end class Foo 

Позволяет сломать код эквивалентно -

class Foo{
        private int i;
ublic static void bar() {
    i = 10;
    Runnable r = new ARunnable();
    r.run();
}

private static class ARunnable implements Runnable {

    @Override public void run() {
        System.out.println(i);
    }
}
}

Объявленный анонимный класс Runnable по сути является вложенным классом в методе bar(), который является локальным для функции bar(). Таким образом, анонимный класс имеет доступ к полям родительского класса. Но если переменная i была локальной для функции bar(), мы не хотим разрешать доступ к ней какой-либо другой функции. Для функции внутреннего класса в методе bar() мы можем разрешить ее чтение, но не изменять ее, иначе это будет выглядеть странно и нарушит этику локального.

class Foo{
   // private int i;
    void bar(){
        final int i = 10;  // adding `final` as i is local to function bar 
        Runnable runnable = new Runnable (){
            public void run (){
                System.out.println(i); 
            }//end method run
        }//end Runnable
    }//end method bar
}/  

2- Почему статические вложенные классы не могут быть объявлены внутри методов, как это могут делать внутренние классы?

Как сказано в спецификации Java:

Областью действия объявления локального класса, непосредственно заключенного в блок (§14.2), является остальная часть непосредственно заключающего блока, включая его собственное объявление класса.

Если мы объявляем локальный класс внутри блока, он должен работать в контексте окружающего блока. Ни один блок (метод) не знает о локальных экземплярах другого блока (метода), поскольку все, что объявлено внутри блока, должно быть локальным для этого блока. Таким образом, блок (метод), для которого он является локальным, должен быть единственным, кто может его создать. Было бы бессмысленно объявлять его как static. То же самое справедливо и для модификаторов доступа к классу private, public и protected.

3-Почему внутренний класс не может определять статические члены, кроме статических конечных полей?

внутренние классы не являются статическими. Вложенный статический класс называется вложенным классом, а не внутренним классом. Он должен работать в контексте включающего экземпляра. Каким-то образом разрешение статических переменных и методов противоречит этой мотивации. Однако для получения более подробной информации об ответах на этот вопрос: см. здесь и здесь.

person Community    schedule 06.10.2013
comment
Вложенные классы делятся на две категории: статические и нестатические. Вложенные классы, объявленные статическими, называются статическими вложенными классами. Нестатические вложенные классы называются внутренними классами. Таким образом, статический вложенный класс и внутренний класс называются вложенными классами. В любом случае спасибо за ваш ответ. - person kzidane; 07.10.2013
comment
Чтобы ответить на ваш первый вопрос, я ответил, предполагая, что внутренний класс (не статический вложенный класс), поскольку это означает более точное его использование. - person Sage; 07.10.2013
comment
Я правильно понял ваш первый вопрос? почему-то я так не думаю. :( - person Sage; 07.10.2013
comment
Я думаю, что вы этого не сделали. Просто для большей ясности: если вы попытаетесь заставить метод run() использовать неконечную локальную переменную для передачи в метод println(), вы получите ошибку компиляции. Я знаю [причину][1] этого. Однако, когда вы используете поле, отличное от конечного, ваша программа компилируется без каких-либо жалоб, и это немного сбивает меня с толку, когда я сравниваю его случай с причиной, позволяющей использовать только локальные переменные final в анонимном классе. [1]goo.gl/xHqksx - person kzidane; 07.10.2013
comment
Спасибо за разъяснения. обновил ответ. Надеюсь, что все поймут, что я хотел сказать. - person Sage; 07.10.2013
comment
Таким образом, анонимный класс имеет доступ к полям родительского класса. Если мы можем полагаться на это, то можем сказать, что анонимный класс также имеет доступ к локальным переменным (объявленным перед ним) метода. И так же, как нам не нужна никакая функция для доступа к локальной переменной метода, нам не нужна никакая функция для доступа к анонимному классу, объявленному в методе (на этом его область видимости заканчивается — закрывающая фигурная скобка тела метода ). - person kzidane; 07.10.2013
comment
Извините. Я думаю, ты меня не понял. Я плохо объясняю, использую намного больше слов, чем необходимо. Английский тоже не мой родной. :( - person Sage; 08.10.2013