Четко сказано, что у интерфейсов нет конструкторов. Но при использовании анонимных внутренних классов мы создаем объект интерфейса и переопределяем его методы. Если в интерфейсах нет конструкторов, как это возможно. Например,
interface A{
void print();
}
class B{
public static void main(String args[]){
A a=new A(){
void print(){
System.out.println("Message");
}
};
}
}
Как это A a = new A () возможно, если интерфейс не имеет конструкторов?
Ответ в вопросе: это конструктор анонимный внутренний класс, который реализует интерфейс A.




Каждый класс имеет конструктор по умолчанию, который является конструктором без аргументов, если вы не определяете другой конструктор. И анонимный класс, реализующий интерфейс, автоматически сгенерирует его, если вы не определите другой конструктор.
На самом деле это не так. При создании экземпляра анонимного класса вы должны вызвать один из объявленных конструкторов. Не все классы имеют конструкторы по умолчанию.
@Logan Спасибо. Если нет объявленных конструкторов, он будет использовать конструктор по умолчанию, верно?
Да, это правильно!
Код
interface A {
void print();
}
class B {
public static void main(String[] args) {
A a = new A() {
public void print() {
System.out.println("Message");
}
};
}
}
это сокращение для
interface A {
void print();
}
class B {
public static void main(String[] args) {
class B$1 extends java.lang.Object implements A {
B$1() {
super();
}
public void print() {
System.out.println("Message");
}
}
A a = new B$1();
}
}
За одним исключением: если класс B$1 объявлен явно, его можно расширить с помощью class C extends B$1. Однако невозможно расширить анонимный класс B$1 (JLS §8.1.4), даже если он не является final (JLS §8.1.1.2).
То есть анонимные классы по-прежнему остаются классами. Как и все классы (кроме самого java.lang.Object), даже эти классы прямо или косвенно расширяют java.lang.Object. Если анонимный класс указан с использованием интерфейса, он расширяет java.lang.Object и реализует этот интерфейс. Если анонимный класс указан с использованием класса, он расширяет этот класс. Если у конструктора есть аргументы, они передаются в super().
Вы даже можете (хотя это определенно не рекомендуется) вставить A a2 = new B$1(); позже в main(), если хотите. Но на самом деле, не делайте этого, я просто говорю об этом, чтобы показать, что происходит под капотом.
Вы можете наблюдать это сами, поместив исходный код в отдельный каталог, скажем, в AB.java, скомпилировав его, а затем
javap -c B$1, чтобы увидеть, как javac сгенерировал анонимный класс.Я знаю, что это всего лишь пример, но разве определение вашего класса B$1 не должно выходить за рамки метода main?
@Phil Почему это должно быть вне метода main? В конце концов, это все еще локальный класс, то есть класс, объявленный в методе. Попробуйте добавить метод public void foo() { new B$1(); } - если класс B$1 объявлен вне main(), метод foo() будет компилироваться, если класс B$1 объявлен внутри main(), метод foo() не будет компилироваться.
Да, вы можете определять классы внутри методов.
Анонимный внутренний класс такой же, как
class InternalNameWhoCares implements A.