Синтаксический Сахар Java
сегодня я столкнулся с этим блоком кода, и я не знаю, как это работает. Я знаю, как сделать анонимные классы, но я привык видеть подпись метода, а не только пару скобок. Код между этими скобками помещен в статический блок? Входит ли он в конструктор? Или это нечто иное?
conext.checking(new Expectations() {
{ // <- what does this pair of braces do?
oneOf(alarm).getAttackAlarm(null);
}
});
7 ответов
Это инициализатор экземпляра, который вызывает код в контексте созданного объекта.
Это эквивалентно
Expectations exp = new Expectations();
exp.oneOf(alarm).getAttackAlarm(null);
conext.checking(exp)
тот, кто написал это, мог подумать, что он был более эффективным, не объявляя переменную (не правда) или что это был более чистый код (я не согласен).
основное место, где эти инициализаторы полезны, например, при создании экземпляров карт, т. е.:
Map map = new HashMap() {{
put("key1", "value1");
put("key2", "value2");
}};
что я думаю на самом деле немного больше читаемый.
это блок инициализатора, но не обязательно static инициализатор блок. Это фактически конструктор для анонимного внутреннего класса. Обычно вы увидите этот шаблон "инициализации двойной скобки" для удобного создания и заполнения коллекций:
private final Collection<Integer> FIXED_COLLECTION = Collections.unmodifiableCollection(new HashSet<Integer>()
{ // first set of braces declares anonymous inner class
{ add(1); add(2); add(3); } // second set is initializer block
});
это инициализатор экземпляра (не статический инициализатор).
рассмотрим определение класса
public class Foo {
private int i = getDefaultValue();
private static int getDefaultValue() {
return 5;
}
}
вызов getDefaultValue()
это initalises i
по существу является блоком кода, который запускается каждый раз, когда создается экземпляр Foo. Нотация расширяет эту функцию, чтобы обеспечить более сложную инициализацию. Е. Г.
public class Foo {
private int i;
{
int z = 4 + 5;
i = z + getDefaultValue();
}
private static int getDefaultValue() {
return 5;
}
}
способ, которым он используется в JMock, - это трюк, чтобы придать ожиданиям вид конструкции закрытия.
что происходит ? The внешний фигурные скобки создают новый анонимный класс, производный от Exception. The внутренний фигурные скобки определяют инициализатор и устанавливают oneOf()
etc.
почему это ? Это однострочный трюк для построения и инициализации экземпляра класса. е. вы иногда видите что-то вроде этого:
new Set<String>(){{add("one");add("two")}}
для инициализации содержимого коллекции.
минусы ? Потому что вы создаете анонимный класс внутри содержащего класса этот анонимный класс содержит ссылку this на внешний класс неявно. Обычно это не проблема, но это может вызвать проблемы, если (скажем) вы хотите сериализовать класс, который вы построили так.
Это блок инициализатора. Я не могу сказать, что он делает, не глядя на остальной код.
фокус в том, чтобы представить ,что" новое ожидание () "заменено на" класс что-то расширяет ожидание".
Anynoymous внутренние классы не конструктор, так что вы можете определить экземпляр initilizer такой, т. е. внутренний набор брекеты инициализаторы экземпляра.
new Expectations() {
{
oneOf(alarm).getAttackAlarm(null);
}
}
основной мотивацией этого, я считаю, является создание нового пространства имен, в котором имена определены в Expection
можно было легко ссылаться.
например,java.lang.Math
не является окончательным,
new Math()
{{
double x = sin(23.65);
double y = log(x);
...
}};
это почти как если бы у нас было что-то вроде
with names from Math
{
double x = sin(23.65);
double y = log(x);
...
}