2015-10-21 2 views
4

Может ли кто-нибудь объяснить мне, почему приведенный ниже код работает, если final закомментирован, но нет, если final присутствует?Почему я не могу инициализировать последнюю переменную класса через закрытие внутри конструктора Groovy?

public class Person { 
    public /*final*/ String firstName, lastName 

    Person(Map parameters) { 
     // This does *not* work with "final": 
     parameters.each { name, value -> 
      this."$name" = value 
     } 

     // This *does* work with "final": 
     this.lastName = parameters['lastName'] 
    } 
} 

Person p = new Person(firstName: 'Joe', lastName: 'Doe') 
println p.firstName + ' ' + p.lastName 

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

+1

Не отвечая на вопрос, но это должно получиться аналогичным результатом? '@groovy.transform.Immutable public class Person {String firstName, lastName} ' –

+0

Очень приятно,' Immutable' даже уже [предоставляет конструктор на основе карты] (http://docs.groovy-lang.org/latest/html /gapi/groovy/transform/Immutable.html), как тот, который я реализую вручную здесь! – sschuberth

ответ

3

Может ли кто-нибудь объяснить мне, почему приведенный ниже код работает, если окончательный закомментирован, но нет, если окончательный присутствует?

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

+0

Если это было правильно, зачем это работает, если я создаю класс 'Immutable' и использую автоматически предоставленный конструктор карты? В этом случае свойства также являются окончательными, и компилятор также не может знать, что я предоставляю на карте. Я просто попробовал, и если я опустил какую-либо форму собственности, то на карте не будет ошибки, она просто будет «null». – sschuberth

+0

@sschuberth «Если это было правильно, то почему это работает, если я создаю класс Immutable» - он работает, потому что, когда класс помечен как '@ Immutable', компилятор добавляет что-то, что эффективно, как' this.firstName = args.get ('firstName') 'для конструктора, поэтому компилятор может гарантировать, что' firstName' является назначенным значением. «null» является допустимым значением. –

+0

Отметьте класс как '@ Immutable', так и' @ CompileStatic' и декомпилируйте его. Вы увидите что-то вроде https://gist.github.com/jeffbrown/8794211e48e39f1e20b5. '@ CompileStatic' на самом деле не нужен, но декомпилированный код будет иметь больше смысла, если вы не знакомы с внутренними компонентами Groovy. –

Смежные вопросы