Замыкание это объект, который хранит информацию из контекста в котором он был создан. Из этого описания, Вы можете видеть, что внутренний класс замкнут на объектах, поскольку он не содержит каждый из кусочков из внешнего класса ( контекста, в котором он был создан), но он автоматически содержит ссылку на этот внешний класс, где у него есть доступ к элементам класса, даже к private.
Наиболее неоспоримым аргументом для включения можно назвать разновидность указательного механизма в Java позволяющего осуществлять обратные вызовы (callbacks). С обратным вызовом, некоторые другие объекты, могут получить кусочек информации, которая позволит им в дальнейшем передать управление в исходящий объект. Это очень мощная концепция, как Вы увидите потом, в Главе 13 и Главе 16. Если обратный вызов реализуется через использование указателя, то Вы должны очень осторожно с ним обращаться. Как Вы наверное уже могли понять, в Java имеется тенденция для более осторожного программирования, поэтому указатели не включены в этот язык.
"Замыкание" предоставляемое внутренними классами - лучшее решение, чем указатели. Оно более гибкое и намного более безопасное. Вот пример:
//: c08:Callbacks.java
// Использование внутренних классов для возврата
interface Incrementable { void increment(); }
// Очень просто реализовать интерфейс:
class Callee1 implements Incrementable { private int i = 0; public void increment() { i++; System.out.println(i); } }
class MyIncrement { public void increment() { System.out.println("Other operation"); } public static void f(MyIncrement mi) { mi.increment(); } }
// Если ваш класс должен реализовать increment() по другому,
// Вы должны использовать внутренний класс:
class Callee2 extends MyIncrement { private int i = 0; private void incr() { i++; System.out.println(i); } private class Closure implements Incrementable { public void increment() { incr(); } } Incrementable getCallbackReference() { return new Closure(); } }
class Caller { private Incrementable callbackReference; Caller(Incrementable cbh) { callbackReference = cbh; } void go() { callbackReference.increment(); } }