Опубликован: 04.12.2009 | Доступ: свободный | Студентов: 8424 / 660 | Оценка: 4.30 / 3.87 | Длительность: 27:27:00
Лекция 11:

Встроенные классы

< Лекция 10 || Лекция 11: 123 || Лекция 12 >

11.3. Внутренние (inner) классы

Внутренний класс задается так же, как вложенный, но только без модификатора static перед именем этого класса:

class ИмяВнешнегоКласса{
     тело внешнего класса
     
     class ИмяВнутреннегоКласса{
     тело внутреннего класса
     }
     
     продолжение тела внешнего класса
}

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

Синтаксис таков:

Сначала идет создание экземпляра внешнего класса:

ИмяВнешнегоКласса имяОбъекта = new ИмяВнешнегоКласса(параметры);

Затем создается нужное число экземпляров внутреннего класса:

ИмяВнешнегоКласса.ИмяВнутреннегоКласса имя1 =
                           имяОбъекта.new ИмяВнутреннегоКласса(параметры);
ИмяВнешнегоКласса.ИмяВнутреннегоКласса имя2 =
                           имяОбъекта.new ИмяВнутреннегоКласса(параметры);

и так далее.

Достаточно часто из внутреннего класса необходимо обратиться к объекту внешнего класса. Такое обращение идет через имя внешнего класса и ссылку this на текущий объект:

ИмяВнешнегоКласса.this

- это ссылка на внешний объект (его естественно назвать родительским объектом). А доступ к полю или методу внешнего объекта в этом случае, естественно, идет так:

ИмяВнешнегоКласса.this.имяПоля
ИмяВнешнегоКласса.this.имяМетода(список параметров)

К сожалению, в Java, в отличие от языка JavaScript, нет зарезервированного слова parent для обращения к родительскому объекту. Будем надеяться, что в дальнейшем в java будет введен этот гораздо более читаемый и удобный способ обращения к родителю.

Пример работы с внутренними классами:

package java_gui_example;
public class OuterClass {
    int a=5;
    public OuterClass() {
    }
    
    public class InnerClass{
        int x=1,y=1;
        
        public class InnerClass2 {
            int z=0;
            InnerClass2(){
               System.out.println("InnerClass2 object created");
            };
            
            void printParentClassNames(){
               System.out.println("InnerClass.this.x="+InnerClass.this.x);
               System.out.println("OuterClass.this.a="+OuterClass.this.a);
            }
        }
    }
    
    InnerClass inner1;
    InnerClass.InnerClass2 inner2;
    
    public void createInner() {
        inner1=this.new InnerClass();
        inner2=inner1.new InnerClass2();
        System.out.println("inner1 name="+inner1.getClass().getName());
        System.out.println("inner1 canonical name="+
                            inner1.getClass().getCanonicalName());
    }
}

Если в приложении задать переменную типа OuterClass и создать соответствующий объект

OuterClass outer1=new OuterClass();

то после этого можно создать объекты внутренних классов:

outer1.createInner();

Доступ к внешним объектам иллюстрируется при вызове метода

outer1.inner2.printParentClassNames();

Заметим, что при создании внутреннего класса в приложении, а не в реализации класса OuterClass, вместо

InnerClass inner1=this.new InnerClass();

и

InnerClass.InnerClass2 inner2= inner1.new InnerClass2();

придется написать

OuterClass.InnerClass inner3=outer1.new InnerClass();
OuterClass.InnerClass.InnerClass2 inner4=inner3.new InnerClass2();

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

11.4. Локальные (local) классы

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

class LocalClass1 {
    public LocalClass1(){
        System.out.println("LocalClass1 object created");
    }
};
LocalClass1 local1=new LocalClass1();

Этот код можно вставить в любой метод. Например, в обработчик события нажатия на кнопку. Конечно, данный пример чисто иллюстративный.

11.5. Анонимные () классы и обработчики событий

Анонимный (безымянный) класс объявляется без задания имени класса и переменных данного безымянного типа – задается только конструктор класса вместе с его реализацией. У анонимного класса может быть только один экземпляр, причем он создается сразу при объявлении класса. Поэтому перед объявлением анонимного класса следует ставить оператор new. Анонимный класс должен быть наследником какого-либо класса или интерфейса, и соответствующий тип должен быть указан перед списком параметров конструктора.

Синтаксис задания анонимного класса таков:

new ИмяПрародителя(список параметров конструктора) {
  тело класса
}

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

Пример использования анонимного класса в "слушателе" события (о них речь пойдет в следующем параграфе):

addMouseMotionListener(
   new java.awt.event.MouseMotionAdapter(){
     public void mouseDragged(java.awt.event.MouseEvent e){
        System.out.println("Mouse dragged at: x="+
                            e.getX()+" y="+e.getY()
                           );
     }
   }
);
< Лекция 10 || Лекция 11: 123 || Лекция 12 >
Полетаев Дмитрий
Полетаев Дмитрий
Не очень понятно про оболочечные Данные,ячейки памяти могут наверно размер менять,какое это значение те же операции только ячейки больше,по скорости тоже самое
Максим Старостин
Максим Старостин

Код с перемещением фигур не стирает старую фигуру, а просто рисует новую в новом месте. Точку, круг.