Llamada ambigua desde el contexto estático en Java
static ambiguous (4)
El método principal intenta acceder a var, pero da como resultado una llamada ambigua. ¿Por qué? La variable de instancia var en Base1 no es accesible (visible?) Desde el contexto estático de todos modos.
class Base1 {
int var;
}
interface Base2 {
public static final int var = 0;
}
class Test extends Base1 implements Base2 {
public static void main(String args[]) {
System.out.println("var:" + var);
}
}
Inicialmente, en el paso uno, el compilador buscará la variable var en la clase que extienda y la interfaz que implementará. Como encuentra una variable en ambos lugares en el paso dos, muestra ambigüedad.
La regla JLS para ambigüedad de acceso a campos es
Si el identificador nombra varios campos miembros accesibles (§6.6) en el tipo
T
, entonces el acceso al campo es ambiguo y se produce un error en tiempo de compilación.
Y en materia de accesibilidad.
Un miembro (clase, interfaz, campo o método) de un tipo de referencia, o un constructor de un tipo de clase, es accesible solo si el tipo es accesible y el miembro o constructor está declarado para permitir el acceso:
No hace una distinción acerca de si el acceso al campo de la instancia causaría un error de compilación en un contexto static
.
Tenga en cuenta que podría haber tenido
public static void main(String args[]) {
Test test = new Test();
System.out.println("var:" + test.var);
}
Aún tendrías la ambigüedad.
Los contextos estáticos y no estáticos no determinan cómo se permite el acceso a las variables.
Los modificadores de acceso son los que realmente gobiernan esto ...
cambie el modificador de acceso para var en la Base1 a privado y la ambigüedad desaparecerá, aunque esta podría no ser la forma en que desea que se ajuste, pero los modificadores de acceso en realidad dictan la referencia a las variables de instancia en lugar de los contextos estáticos no estáticos.
class Base1 {
private int var;
//static int var=5;
}
interface Base2 {
public static final int var = 0;
}
class ambiguousNonStaticCall extends Base1 implements Base2 {
public static void main(String args[]) {
System.out.println("var:" + var);
}
}
El código anterior compila bien.
Para que sea inequívoco, coloque el nombre de la interfaz como prefijo de calificación:
class Test extends Base1 implements Base2 {
public static void main(String args[]) {
System.out.println("var:" + Base2.var);
}
}