Друзья, как вы уже заметили, в конце июня у нас стартует немало новых групп, среди них очередной поток полюбившегося всем курса «Разработчик Java». Прямо сейчас делимся с вами новым переводом подготовленным для студентов данного курса.
При добавлении в язык программирования новых фич, разработчики языка обычно обращают внимание на конфликты с текущими возможностями языка, на изменения, приводящие к несовместимости с предыдущими версиями, на ошибки и любые ситуации, которые могут привести к неопределенному или непредвиденному поведению.
Однако, часто не обращают достаточного внимания на незначительные изменения в новых, практических приемах написания кода. Эти изменения часто являются побочными эффектами новых возможностей. Такого рода изменения не являются, строго говоря, новыми фичами. Это малозаметные изменения, которые появились из-за других фич или их комбинаций.
Class$X
, где Class
представляет собой внешний класс, а X
— число, представляющее собой порядок создания экземпляров внутренних классов во внешнем классе. Например, AnonDemo$3
— третий внутренний класс, созданный в AnonDemo
. Вы не можете вызывать эти классы обычным способом. И, в отличие от других видов внутренних классов, анонимный внутренний класс всегда неявно является дочерним классом типа, на основе которого он создан (за исключением использования var
, что мы скоро рассмотрим)./* AnonDemo.java */
class Anon { };
public class AnonDemo {
public static void main (String[] args) {
Anon anonInner = new Anon () {
public String toString() {
return "Overriden";
};
public void doSomething() {
System.out.println("Blah");
};
};
System.out.println(anonInner.toString());
anonInner.doSomething(); // Не скомпилируется!
};
};
new Anon() { public void foo() { System.out.println("Woah"); } }.foo();
Class$X
) для того, чтобы указать его в исходном коде.toString()
для объекта анонимного внутреннего класса дал бы нам переопределенное значение “Overridden”, однако вызов doSomething()
приведет к ошибке компиляции. В чем причина?/* AnonDemo.java */
class Anon { };
public class AnonDemo {
public static void main(String[] args) {
var anonInner = new Anon() {
public void hello() {
System.out.println(
"New method here, and you can easily access me in Java 10!\n" +
"The class is: " + this.getClass()
);
};
};
anonInner.hello(); // Работает!!
}
}
hello()
! Дьявол кроется в деталях. Если вы знакомы с var
, то вы уже поняли, что здесь происходит. Используя зарезервированное имя типа var
, Java смогла определить точный тип анонимного внутреннего класса. Следовательно, мы больше не ограничены ссылкой на базовый класс для доступа к объекту подкласса.Anon anonInner2 = new Anon() {
public void hello() { System.out.println("Woah! "); };
};
anonInner2.getClass().getMethod("hello").invoke(anonInner2);
public class VarAnonInner {
public static void main (String[] args) throws Exception {
var anonInner = new Anon() {
public void hello() {
System.out.println("New method here, and you can easily access me in Java 10!\n" +
"The class is: " + this.getClass()
);
};
};
anonInner.hello();
Anon anonInner2 = new Anon() {
public void hello() { System.out.println("Woah! "); };
};
anonInner2.getClass().getMethod("hello").invoke(anonInner2);
new Anon() { public void hello() { System.out.println("Woah!!! "); }; }.hello();
// VarAnonInner$1 vw = anonInner;
/*
Anon anonInner4 = new Anon() {
public void hello() {
System.out.println("New method here!\n" +
"The class is: " + this.getClass()
);
};
};
anonInner4.hello();
*/
}
}
class Anon { };
К сожалению, не доступен сервер mySQL