Внутренние и вложенные классы java. Часть 3
Локальные классы
<<< Часть 1
<<< Часть 2
Локальный класс — это вложенный класс, объявленный внутри другого класса и некоторого блока кода этого класса, то есть объявленный между фигурными скобками {}. Этот блок может быть статическим блоком, циклом, телом if и т.д.
Можно объявить вложенный класс внутри блока кода, например метода, конструктора или блока инициализации. Он будет называться локальным вложенным классом. Чаще всего локальные классы объявляются внутри тела метода.
Локальный класс объявленный внутри блока кода другого класса не является членом класса, к которому относится блок, а принадлежит самому блоку, точно так же, как обычная локальная переменная. Такие классы недоступны за пределами внешнего класса, поскольку нет никаких способов обращения к ним, но их экземпляры – это обычные объекты, которые позволяется, например, передавать в качестве аргументов или возвращать из методов.
Время жизни локального внутреннего класса, это время пока существует хотя бы одна ссылка на него. Такой класс существует внутри блока кода и время его жизни ограниченно этим блоком.
Напишем пример:
/*Учебный пример №12 */
package localclasses;
/**
*
* @author Ar20L80
*/
public class OuterStaticInit {
static
{
class LocalInit{
LocalInit(){
System.out.println("From static iniz");
}
}
LocalInit localInit = new LocalInit();
System.exit(0);
}
public static void main(String[] args) {
System.out.println("From main");
}
}
В нашем примере локальный класс «просуществовал» только в области локальной статичной инициализации. Тело «main» не было вызвано. Единственный модификатор, который допускается применять в объявлении локального класса, – это final, предотвращающий, как обычно, возможность расширения класса. Члены локального класса могут быть объявлены как закрытыми, так и открытыми. К ним применяются модификаторы, которые применимы к обычному классу.( java 8)
Еще раз повторим коротко: Локальный класс – это класс, объявленный в блоке Java кода.
Обычно локальный класс определяется в методе, но он также может быть объявлен в инициализаторе экземпляра класса, в конструкторе класса.
/**
* Учебный пример №13
* @author Ar20L80
*/
public class OuterLocal {
OuterLocal(){
// начало блока конструктора
/*объявление локального класса в конструкторе OuterLocal*/
class LocalInnerClass {
LocalInnerClass(){}
}
/* создаем экземпляр в том же блоке*/
LocalInnerClass localObj = new LocalInnerClass();
// окончание блока конструктора
}
Поскольку все блоки Java кода находятся внутри определения класса, то все локальные классы вложены в окружающие классы. К локальному классу применяются правила обычной локальной переменной. Область видимости такого класса — это область видимости окружающего его блока.
/**
* Учебный пример №14
* @author Ar20L80
*/
public class OuterLocal {
OuterLocal(){
/*объявление локального класса в конструкторе OuterLocal*/
class LocalInnerClass {
LocalInnerClass(){}
}
/* создаем экземпляр в том же блоке*/
LocalInnerClass localObj = new LocalInnerClass();
}
public static void main(String[] args) {
// LocalInnerClass localObj = new LocalInnerClass(); не можем создать объект локального класса
// вне области видимости содержащего его блока
}
}
Свойства локального класса:
Подобно вложенным нестатическим классам, локальные классы связаны с окружающим экземпляром и имеют доступ ко всем членам, включая private члены окружающего класса. Локальный класс нельзя объявить с каким-либо модификатором доступа, кроме как static final.
/*Учебный пример пример №15 */
public class OuterStaticLocal {
OuterStaticLocal(){
// static class Local{} ошибка не может быть статичным
}
}
Потому что, модификаторы доступа для членов класса мы можем применять только к членам класса. Эти модификаторы не доступны для объявления локальных переменных или классов, находящихся в блоке и не являющиеся членами класса.
/**
* Учебный пример №16
* @author Ar20L80
*/
public class OuterLocal2 {
OuterLocal2(){
final class LocalInnerClass {
LocalInnerClass(){}
}
}
}
Как и нестатические вложенные классы, и по тем же причинам, локальные классы не могут иметь static поля, исключение составляют константы, объявленные как static final.
/**
* Учебный пример №17
* @author Ar20L80
* тут я вернул переменную локального класса через iTemp внешнего класса
*/
public class OuterClass {
private int iTemp;
OuterClass(){
// объявим внутри конструктора класс
/* здесь мы не можем использовать private, public
применительно к локальному классу*/
final class LocalInnerClass01{
/* сам локальный класс может содержать
как private, так и public */
private static final int INT_FIN = 10;
LocalInnerClass01(){
iTemp = Return_INT_FIN();
}
int Return_INT_FIN(){
return INT_FIN;
}
}
class LocalInnerClass02{
// public static int i=11; ошибка не может быть не константой внутри
// локального вложенного класса
}
/* создаем локальные объекты локальных классов в том же конструкторе*/
LocalInnerClass01 localInnerClass1 = new LocalInnerClass01();
LocalInnerClass02 localInnerClass2 = new LocalInnerClass02();
}
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
System.out.println(outerClass.iTemp ); // = 10
//OuterClass.LocalInnerClass1 innerObject = outerClass.new LocalInnerClass1(); ошибка - это не
// внутренний класс, а локальный. И мы не имеем к нему доступа.
}
}
Применение:
Основное применение локальные классы находят в тех случаях, когда необходимо написать класс, который будет использоваться внутри одного метода. Создание локального класса – способ не загромождать пространство имен.
Если класс определяется в теле метода, то его называют локальным внутренним классом. Пример доступа к переменным внешнего класса из локального внутреннего класса: