2012-04-26 11 views
11

Tengo la siguiente configuración que me da un mensaje que indica que "El constructor llama al método" Overridable ". Sé que esto está sucediendo, pero mi pregunta es cómo solucionarlo para que el código siga funcionando y el mensaje desaparezca.Cómo reparar el "Método de llamadas sobreconstruibles del constructor"

public interface Foo{ 
    void doFoo(); 
} 
public class FooImpl implements Foo{ 
@Override{ 
public void doFoo(){ 
    //.. Do important code 
} 
} 
public class Bar{ 
    private FooImpl fi; 
    public Bar(){ 
    fi = new FooImpl(); 
    fi.doFoo(); // The message complains about this line 
    } 
} 

¡Gracias!

+0

El código que ha mostrado está llamando al método * overridable * después de * se llama el constructor, no * del * constructor, ¿verdad? ¿O me estoy perdiendo algo? – NPE

+0

Mostrar código que en realidad inhibe la advertencia probablemente sea una gran idea. – Voo

+0

aix- Está elevando el mensaje porque Bar llama a fi.doFoo() dentro del constructor de Bar. Voo - El código es demasiado largo para copiar/pegar. Este es un ejemplo recortado de lo que está pasando – user973479

Respuesta

6

Usted podría declarar doFoo como definitiva si no se necesita reemplazar ese método después:

public final void doFoo() { }

0

El IDE está diciendo que, debido a que es potencialmente inseguro. Puede proporcionar cualquier implementación o doFoo y hacer que todos los objetos de Bar sean diferentes al inicio. Esto parece una mala elección de diseño en la mayoría de los casos.

Parece que está utilizando un patrón de estrategia, en un constructor. No es aconsejable utilizar una estrategia o cualquier otro comportamiento sobredimensionable en el constructor. Úselo en otro lugar.

+0

¿Cómo es potencialmente inseguro llamar a un método no final de una clase completamente diferente en el constructor? – Voo

+0

¿Su respuesta negativa es porque no comprende las implicaciones que tiene un comportamiento anulable en un constructor? Este artículo explica el peligro potencial de utilizar un método de invocación overridale en un constructor: http://www.javapractices.com/topic/TopicAction.do?Id=215 – Terraego

+1

Si realmente hubiera leído mi publicación, habría notamos que la pregunta es acerca de llamar a un método virtual en un objeto ya completamente construido. Las bien conocidas caídas de los métodos virtuales de llamada en el objeto construido son bien conocidos, pero no se aplican aquí. – Voo

0

El origen del error que se ve es PMD (búsqueda allí para "overr"), y cuando la construcción de su ejemplo de nuevo, esta advertencia no se desencadena por esta versión del PMD (4.2.6). Sonar solo integra PMD, Checkstyle y otras herramientas, y proporciona una visión general. Por lo tanto, compruebe qué versión de Sonar (y PMD) está utilizando.

Puede ver eso en Sonar: Sonar > Quality Profiles > Search for "overr" debe resaltar la regla que está utilizando.

En Sonar, puede verificar qué versión de PMD está utilizando. Vaya a Sonar > Configuration > Update Center, y mire allí la versión de PMD que está utilizando.

14

Como dice @Voo,

su pregunta es acerca de llamar a un método virtual en un objeto ya completamente construida. Las caídas bien conocidas de llamar métodos virtuales en el objeto construido a son bien conocidos, pero no se aplican aquí

De Effective Java 2nd Edition, Tema 17: Diseño y documentos para la herencia, o de lo contrario lo prohíben :

Hay algunas restricciones más que una clase debe obedecer para permitir herencia. Los constructores no deben invocar métodos invalidables, directa o indirectamente. Si infringe esta regla, la falla del programa dará como resultado . El constructor de la superclase se ejecuta antes del constructor de la subclase , por lo que el método de anulación en la subclase se invocará antes de que se haya ejecutado el constructor de la subclase. Si el método de anulación depende de cualquier inicialización realizada por el constructor de la subclase, , el método no se comportará como se espera.

La invocación de un método reemplazable durante la construcción del objeto puede dar como resultado el uso de datos no inicializados, lo que lleva a excepciones de tiempo de ejecución o resultados imprevistos.

los constructores deben invocar únicos métodos que son finales o privada

usted podría utilizar métodos de fábrica estáticas para solucionar el problema que usted tiene que crear sus objetos de la Bar class.

Effective Java, Punto 1: Considere métodos de fábrica estáticas en lugar de constructores

la forma normal de una clase para permitir que un cliente obtener una instancia de misma es proporcionar un constructor público. Existe otra técnica, , que debería formar parte del conjunto de herramientas de cada programador. Una clase puede proporcionar un método público de fábrica estático, que es simplemente un método estático que devuelve una instancia de la clase.

Por lo tanto, usted va a tener la interfaz:

public interface Foo { 
    void doFoo(); 
} 

y la puesta en práctica:

public class FooImpl implements Foo { 
    @Override 
    public void doFoo() { 
    //.. Do important code 
    } 
} 

para crear su clase con el método de fábrica se puede trabajar de esta manera:

  • Utilice la interfaz para definir la variable de su clase private Foo fi en lugar de private FooImpl fi, el uso de interfaces sobre tipos concretos es la clave para una buena encapsulación y para un acoplamiento flexible de su código.

  • Haga que su constructor predeterminado sea privado para evitar la creación de instancias de su clase en el exterior.

    bar privado() {// Evita la creación de instancias }

  • Retire todas las llamadas a reemplazar los métodos que están presentes en su constructor.

  • Crear su método de fábrica estática

Finalmente se obtiene una clase Bar con un método de fábrica como:

public class Bar { 
    private Foo fi; 

    private Bar() {// Prevents instantiation 
     fi = new FooImpl(); 
    } 

    public static Bar createBar() { 
     Bar newBar = new Bar(); 
     newBar.fi.doFoo(); 

     return newBar; 
    } 
} 

Mi jefe dice: “las advertencias sonar son unos síntomas, no sobre la enfermedad . Lo mejor es cuando puedes tratar la enfermedad ".

Cuestiones relacionadas