Использование определений классов в методе в Java

Пример:

public class TestClass {

    public static void main(String[] args) {
        TestClass t = new TestClass();
    }

    private static void testMethod() {
        abstract class TestMethod {
            int a;
            int b;
            int c;

            abstract void implementMe();
        }

        class DummyClass extends TestMethod {
            void implementMe() {}
        }

        DummyClass dummy = new DummyClass();
    }
}

Я узнал, что вышеупомянутая часть кода совершенно законна в Java. У меня есть следующие вопросы.

  1. Каково использование когда-либо наличия определения класса в методе?
  2. Будет файл класса быть сгенерированным для DummyClass
  3. Мне трудно вообразить это понятие Объектно-ориентированным способом. Наличие определения класса в поведении. Вероятно, может кто-то говорить мне с эквивалентными примерами реального мира.
  4. Абстрактные классы в методе звучат немного сумасшедшими мне. Но никакие интерфейсы не позволяются. Есть ли какая-либо причина позади этого?
100
задан Mahozad 29 July 2018 в 09:26
поделиться

6 ответов

Это называется локальный класс.

2 - самый простой: да, файл класса будет сгенерирован.

1 и 3 - это вроде бы один и тот же вопрос. Вы будете использовать локальный класс там, где вам никогда не нужно инстанцировать его или знать о деталях реализации где-либо, кроме одного метода.

Типичное использование - это создание отбрасываемой реализации некоторого интерфейса. Например, часто можно увидеть что-то вроде этого:

  //within some method
  taskExecutor.execute( new Runnable() {
       public void run() {
            classWithMethodToFire.doSomething( parameter );
       }
  }); 

Если вам нужно создать кучу таких интерфейсов и что-то с ними сделать, вы могли бы изменить это на

  //within some method
  class myFirstRunnableClass implements Runnable {
       public void run() {
            classWithMethodToFire.doSomething( parameter );
       }
  }
  class mySecondRunnableClass implements Runnable {
       public void run() {
            classWithMethodToFire.doSomethingElse( parameter );
       }
  }
  taskExecutor.execute(new myFirstRunnableClass());
  taskExecutor.execute(new mySecondRunnableClass());

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

67
ответ дан 24 November 2019 в 04:55
поделиться

Настоящая цель этого состоит в том, чтобы позволить нам создавать классы, встроенные в вызовы функций, чтобы утешить тех из нас, кто любит делать вид, что мы пишем в функциональный язык;)

7
ответ дан 24 November 2019 в 04:55
поделиться

Они называются локальными классами . Вы можете найти подробное объяснение и пример здесь . Пример возвращает конкретную реализацию, о которой нам не нужно знать вне метода.

15
ответ дан 24 November 2019 в 04:55
поделиться

Единственный случай, когда вы хотели бы иметь полноценный внутренний класс функции vs анонимный класс (он же Java-закрытие), это когда выполняются следующие условия

  1. Вам нужно предоставить интерфейс или абстрактную реализацию класса
  2. Вы хотите использовать некоторые конечные параметры, определенные в вызове функции
  3. , вам нужно записать некоторое состояние выполнения вызова интерфейса.

Например, кто-то хочет Runnable, и вы хотите записать, когда выполнение началось и закончилось.

С анонимным классом это невозможно сделать, с внутренним классом вы можете это сделать.

Вот пример, демонстрирующие мою точку зрения

private static void testMethod (
        final Object param1,
        final Object param2
    )
{
    class RunnableWithStartAndEnd extends Runnable{
        Date start;
        Date end;

        public void run () {
            start = new Date( );
            try
            {
                evalParam1( param1 );
                evalParam2( param2 );
                ...
            }
            finally
            {
                end = new Date( );
            }
        }
    }

    final RunnableWithStartAndEnd runnable = new RunnableWithStartAndEnd( );

    final Thread thread = new Thread( runnable );
    thread.start( );
    thread.join( );

    System.out.println( runnable.start );
    System.out.println( runnable.end );
}

Прежде чем использовать этот шаблон, пожалуйста, оцените, являются ли простые старые классы верхнего уровня, или внутренние классы, или статические внутренние классы лучшими альтернативами.

4
ответ дан 24 November 2019 в 04:55
поделиться

Основная причина определения внутренних классов (внутри метода или класса) - иметь дело с доступностью членов и переменных включающего класса и метода. Внутренний класс может искать члены частных данных и работать с ними. Если внутри метода, он также может иметь дело с конечной локальной переменной.

Наличие внутренних классов действительно помогает убедиться, что этот класс недоступен для внешнего мира. Это особенно актуально для случаев программирования пользовательского интерфейса в GWT или GXT и т. Д., Когда код генерации JS написан на java, а поведение для каждой кнопки или события должно определяться путем создания анонимных классов

2
ответ дан 24 November 2019 в 04:55
поделиться
  1. Класс нельзя увидеть (т.е. инстанцировать, получить доступ к его методам без Reflection) вне метода. Также, он может получить доступ к локальным переменным, определенным в testMethod(), но до определения класса.

  2. На самом деле я подумал: "Такой файл не будет записан", пока не попробовал: О да, такой файл создается! Он будет называться что-то вроде A$1B.class, где A - внешний класс, а B - локальный класс.

  3. Особенно для функций обратного вызова (обработчиков событий в графических интерфейсах, таких как onClick() при нажатии на кнопку и т.д.) довольно часто используются "анонимные классы" - прежде всего потому, что в итоге их может оказаться очень много. Но иногда анонимные классы недостаточно хороши - особенно, если вы не можете определить для них конструктор. В этих случаях хорошей альтернативой могут стать локальные классы методов.

9
ответ дан 24 November 2019 в 04:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: