Hoje, enquanto trabalhava em um projeto para um curso de “Design Patterns” da faculdade (Java 11 necessário), descobri um problema com a restrição de acesso do modificador de acesso que pode ser ignorado declarando var. Eu sei como var é usado, é apenas um açúcar sintático que deixa a inferência de tipo para o compilador.
Não consigo descobrir que tipo de alias a var realmente é aqui:
- é "Child.InnerChild"? Isso não seria uma incompatibilidade de tipo?
- "InnerParent"? Isso não ignora o restritor de acesso protegido?
Aqui está meu código simplificado:
public abstract class Parent {
protected abstract static class InnerParent {
public InnerParent self() {
return this;
}
}
}
public class Child extends Parent {
public static class InnerChild extends InnerParent {}
}
import anotherpackage.Child;
/**
* Compiling with Java 11:
*/
public class Main {
public static void main(String[] args) {
// As we expected a compilation error: The returned static type does not match the expected type
// Child.InnerChild innerChild = new Child.InnerChild().self();
// As we expected a compilation error: Parent.InnerParent is package visible (protected)
// Parent.InnerParent innerChild = new Child.InnerChild().self();
// Why does it compile and run correctly here?
// var is just syntactic sugar for the compiler type, it should be a Parent.InnerParent alias here,
// why is var allowed to transgress the protected access restriction?
var innerChild = new Child.InnerChild().self(); // perhce' non da' errore ? var e' un alias di cosa ?
System.out.println(innerChild);
System.out.println(innerChild.getClass().getName());
}
}
Também perguntei ao ChatGPT, mas ele não está respondendo tão bem quanto eu gostaria e não tenho certeza se está correto:
Por que
var
funciona
- Tipo inferido : O tipo inferido para
var innerChild
éParent.InnerParent
.- Regras de acesso : como o tipo é inferido e não escrito explicitamente no código, o compilador não impõe restrições de acesso para a variável declarada.
Encontrei um novo problema: por que não consigo acessar getClass()
?
No entanto, é possível compilar dessa maneira.
System.out.println(((Object) innerChild).getClass().getName());
// OUTPUT: com.github.lorenzoyang.anotherpackage.Child$InnerChild