2012-05-28 20 views
16

Aquí está un ejemplo simple de un código que compila utilizando Java 6, pero no compila en Java 7.Cambios en el acceso de las variables para las clases genéricas en Java 7

public class Test<T extends Test> { 

    private final int _myVar; 

    public Test(int myVar) { 
    _myVar = myVar; 
    } 

    public int get(TestContainer<T> container){ 
    T t = container.get(); 
    return t._myVar; 
    } 

    private static class TestContainer<T extends Test> { 
    private final T _test; 
    private TestContainer(T test) { 
     _test = test; 
    } 
    public T get(){ 
     return _test; 
    } 
    } 
} 

En Java 7, no logra compilar en el método get(TestContainer<T> container), con el error:

error: _myVar has private access in Test

no entiendo por qué esto ya no compila - en mi mente que debería. La variable t es del tipo T, que debe extenderse Test. Está intentando acceder al campo _myVar de una instancia de Test desde dentro de la clase Test.

De hecho, si cambio el método get(TestContainer<T> container) a la siguiente, que compila (sin advertencias):

public int get(TestContainer<T> container){ 
    Test t = container.get(); 
    return t._myVar; 
} 
  • ¿Por qué esto no pudiera compilar?
  • ¿Esto es un error en Java 6? Si es así, ¿por qué?
  • ¿Es esto un error en Java 7? comentario

He tenido un Google y búsquedas en la base de datos Oracle de errores, pero no he encontrado nada en este ...

+5

Esto fue un error en Java 6: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7022052 – pingw33n

+0

@ pingw33n, usted debe enviar una respuesta que a medida. –

+0

@ pingw33n, y luego puedo aceptarlo ... aunque si alguien que tiene una mejor comprensión del JLS puede explicar la sección 'Evaluación' del informe de fallos, también lo agradecería. – amaidment

Respuesta

9

§4.9 ... Then the intersection type has the same members as a class type (§8) with an empty body, direct superclass Ck and direct superinterfaces T1', ..., Tn', declared in the same package in which the intersection type appears.

Desde mi entendimiento de esa parte JLS, su caso con un tipo de variable <T extends Test> crea el siguiente cruce:

package <the same as of Test>; 

class I extends Test {} 

Por lo tanto, cuando se accede a miembros del tipo T que realmente acceder a los miembros de la intersección tipo I. Como los miembros privados nunca son heredados por subtipos, el acceso a dicho miembro falla con el error de compilación. Por otra parte, el acceso al paquete-privada (por defecto) y los miembros protegidos está permitido por el hecho de la intersección es

... declared in the same package in which the intersection type appears.

0

Ver @ pingw33n de la respuesta, pero la manera de solucionar este problema es para eliminar los parámetros genéricos en la clase anidada. A menos que tenga un caso de uso donde las T internas y externas pueden ser diferentes, son redundantes. Todo lo que están haciendo está causando este dolor.

+0

¿Está sugiriendo que sea simplemente: 'private static class TestContainer'? Dado que la clase interna estática, no se puede (en las palabras cortas del compilador) * hacer una referencia estática al tipo no estático T *. –

+0

Tengo un caso de uso, el equivalente de TestContainer es en realidad una clase separada por completo, pero esto es solo un SSCCE para demostrar el problema del compilador que estaba enfrentando. – amaidment

0

Una solución para esto es para echar la instancia genérica para el supertipo concreta que declara el ámbito privado, p.ej

public int get(TestContainer<T> container){ 
    T t = container.get(); 
    return ((Test) t)._myVar; 
} 
Cuestiones relacionadas