Использование определений классов внутри метода в 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. У меня есть следующие вопросы.
- какой смысл когда-либо иметь определение класса внутри метода?
- будет ли создан файл класса для
DummyClass
- мне трудно представить себе эту концепцию в объектно-ориентированном виде. Имея определение класса внутри поведения. Возможно, кто-то может сказать мне с эквивалентным реальным миром образцы.
- абстрактные классы внутри метода звучит немного сумасшедшим для меня. Но никакие интерфейсы не разрешены. Есть ли причина?
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());что касается интерфейсов: я не уверен, что есть техническая проблема, которая делает локально определенные интерфейсы проблемой для компилятора, но даже если нет, они не добавят никакого значения. Если бы локальный класс, реализующий локальный интерфейс, использовался вне метода, интерфейс был бы бессмысленным. И если локальный класс будет использоваться только внутри метода, как интерфейс, так и класс будет реализован в этом методе, поэтому определение интерфейса будет избыточным.
Это называется локальные классы. Вы можете найти подробное объяснение и пример здесь. Пример возвращает конкретную реализацию, о которой нам не нужно знать за пределами метода.
класс не может быть замечен (т. е. создан, его методы доступны без отражения) извне метода. Кроме того, он может получать доступ к локальным переменным, определенным в testMethod(), но перед определением класса.
Я на самом деле думал: "такой файл не будет записан."пока я просто не попробовал: О да, такой файл создается! Это будет называться что-то вроде$1B.class, где A-внешний класс, А B-локальный класс.
особенно для функций обратного вызова (обработчики событий в графических интерфейсах, например onClick () при нажатии кнопки и т. д.), вполне обычно использовать "анонимные классы" - прежде всего потому, что вы можете получить их много. Но иногда анонимные классы недостаточно хороши - особенно, вы не можете определить конструктор на них. В этих случаях эти локальные классы методов могут быть хорошей альтернативой.
реальная цель этого-позволить нам создавать классы, встроенные в вызовы функций, чтобы утешить тех из нас, кто любит притворяться, что мы пишем на функциональном языке;)
единственный случай, когда вы хотели бы иметь полномасштабный внутренний класс функции против анонимного класса (a. K. A. Java closure), когда выполняются следующие условия
- вам нужно предоставить интерфейс или абстрактную реализацию класса
- вы хотите использовать некоторые конечные параметры, определенные в вызове функции
- вам нужно записать некоторое состояние выполнения вызова интерфейса.
например, кто-то хочет
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 ); }перед использованием этого шаблона, однако, пожалуйста, оцените, если простой старый класс верхнего уровня, или внутренний класс, или статический внутренний класс являются лучшими альтернативами.
основная причина определения внутренних классов (внутри метода или класса) заключается в том, чтобы иметь дело с доступностью членов и переменных заключающего класса и метода. Внутренний класс может искать частные члены данных и работать с ними. Если в рамках метода он может иметь дело с конечной локальной переменной, а также.
наличие внутренних классов помогает убедиться, что этот класс недоступен для внешнего мира. Это особенно верно для случаев программирования пользовательского интерфейса в GWT или GXT и т. д., где JS генерация кода написана на java и поведение для каждой кнопки или события должно быть определено путем создания анонимных классов
Comments