method ¿Cuál es el punto de la "clase final" en Java?




static int java (19)

Un escenario en el que el final es importante, cuando se quiere evitar la herencia de una clase, por razones de seguridad. Esto le permite asegurarse de que el código que está ejecutando no pueda ser anulado por alguien.

Otro escenario es para la optimización: me parece recordar que el compilador de Java incluye algunas llamadas a funciones de las clases finales. Por lo tanto, si llama a ax() y a se declara final , sabemos en tiempo de compilación cuál será el código y podemos integrarlo en la función de llamada. No tengo idea de si esto realmente se hace, pero con la final es una posibilidad.

Estoy leyendo un libro sobre Java y dice que puedes declarar a toda la clase como final . No puedo pensar en nada donde usaría esto.

Solo soy nuevo en programación y me pregunto si los programadores realmente usan esto en sus programas . Si lo hacen, ¿cuándo lo usan para que pueda entenderlo mejor y saber cuándo usarlo?

Si Java está orientado a objetos y declara una clase final , ¿no detiene la idea de que la clase tiene las características de los objetos?


Una ventaja de mantener una clase como final:

La clase de cadena se mantiene finalizada para que nadie pueda anular sus métodos y cambiar la funcionalidad. Por ejemplo, nadie puede cambiar la funcionalidad del método length (). Siempre devolverá la longitud de una cadena.

El desarrollador de esta clase no quería que nadie cambiara la funcionalidad de esta clase, por lo que la mantuvo como final.


Si lo hacen, ¿cuándo lo usan para que pueda entenderlo mejor y saber cuándo usarlo?

Una clase final es simplemente una clase que no se puede extender .

(Esto no significa que todas las referencias a objetos de la clase actúen como si fueran declaradas como final ).

Cuando es útil declarar una clase como final se cubre en las respuestas de esta pregunta:

Si Java está orientado a objetos y declara una clase final , ¿no detiene la idea de que la clase tiene las características de los objetos?

En cierto sentido sí.

Al marcar una clase como final, inhabilitas una característica poderosa y flexible del idioma para esa parte del código. Sin embargo, algunas clases no deberían (y en ciertos casos no pueden ) diseñarse para tener en cuenta las subclases de una buena manera. En estos casos, tiene sentido marcar la clase como final, aunque limita la POO. (Sin embargo, recuerde que una clase final aún puede extender otra clase no final).

Artículo relacionado: Java: cuándo crear una clase final


piensa en FINAL como el "Fin de la línea", ese tipo ya no puede producir descendencia. Entonces, cuando lo veas de esta manera, hay un montón de escenarios del mundo real que encontrarás que requieren que marques un marcador de 'fin de línea' a la clase. Es Diseño impulsado por dominio: si su dominio exige que una ENTIDAD (clase) determinada no pueda crear subclases, entonces márquela como FINAL.

Debo tener en cuenta que no hay nada que le impida heredar una clase de "debería etiquetarse como final". Pero eso generalmente se clasifica como "abuso de herencia" y se hace porque la mayoría de las veces le gustaría heredar alguna función de la clase base de su clase.

El mejor enfoque es mirar el dominio y dejar que dicte sus decisiones de diseño.


El mejor ejemplo es

final de clase pública cadena

que es una clase inmutable y no puede ser extendida. Por supuesto, hay algo más que hacer que la final de la clase sea inmutable.


La orientación a objetos no se trata de la herencia, se trata de la encapsulación. Y la herencia rompe la encapsulación.

Declarar una final de clase tiene mucho sentido en muchos casos. Cualquier objeto que represente un "valor" como un color o una cantidad de dinero podría ser definitivo. Ellos están de pie por su cuenta.

Si está escribiendo bibliotecas, finalice sus clases a menos que las guarde para derivarlas explícitamente. De lo contrario, las personas pueden derivar sus clases y anular métodos, rompiendo sus suposiciones / invariantes. Esto también puede tener implicaciones de seguridad.

Joshua Bloch en "Java efectiva" recomienda diseñar explícitamente para la herencia o prohibirla y señala que el diseño para la herencia no es tan fácil.


Ten cuidado cuando hagas una clase "final". Porque si desea escribir una prueba de unidad para una clase final, no puede subclasificar esta clase final para usar la técnica de "dependencia de subclases y método de anulación de la dependencia" descrita en el libro "Trabajo efectivo con el código heredado" de Michael C. Feathers . En este libro, Feathers dijo: "En serio, es fácil creer que sellado y final son un error imprudente, que nunca deberían haberse agregado a los lenguajes de programación. Pero la verdadera falla está en nosotros. Cuando dependemos directamente de nosotros Las bibliotecas que están fuera de nuestro control, solo estamos pidiendo problemas ".


En breve, una clase, variable o método declarado como final no se puede cambiar.

Lo que es más importante es mi opinión:

Honestamente, creo que una palabra clave final es un error porque su existencia le permite al usuario definir algo que no es final . Todo en Java debería ser final por defecto, excepto los métodos de interfaz (por su definición). Fue una elección desafortunada dejar que todos los métodos de instancia sean virtual por defecto (en términos de c# ). La clave es forzar al usuario a pensar primero y definir explícitamente vergonzosamente un método como virtual lugar de eso, le haría preguntarse si este método debería permitir a otros anularlo, si really una necesidad o persuadirlo para que rediseñe su código.


Si haces cualquier clase como final, no puedes extenderla.

final class Bike{}  

class Honda1 extends Bike{  
 void run(){System.out.println("running safely with 100kmph");}  

public static void main(String args[]){  
 Honda1 honda= new Honda();  
honda.run();  
  }  
}  

    Output:Compile Time Error

PARA ABORDAR EL PROBLEMA DE LA CLASE FINAL:

Hay dos formas de hacer una final de clase. El primero es usar la palabra clave final en la declaración de clase:

public final class SomeClass {
  //  . . . Class contents
}

La segunda forma de hacer una final de clase es declarar a todos sus constructores como privados:

public class SomeClass {
  public final static SOME_INSTANCE = new SomeClass(5);
  private SomeClass(final int value) {
  }

Marcarlo como final te ahorra el problema si descubres que es una final real, para demostrar el aspecto de esta clase de prueba. Parece público a primera vista.

public class Test{
  private Test(Class beanClass, Class stopClass, int flags)
    throws Exception{
    //  . . . snip . . . 
  }
}

Desafortunadamente, dado que el único constructor de la clase es privado, es imposible extender esta clase. En el caso de la clase de prueba, no hay razón para que la clase sea final. La clase Test es un buen ejemplo de cómo las clases finales implícitas pueden causar problemas.

Así que debes marcarlo como final cuando haces una final de clase implícitamente haciendo que su constructor sea privado.


Lectura relevante: El principio abierto-cerrado de Bob Martin.

Cita clave:

Las entidades de software (clases, módulos, funciones, etc.) deben estar abiertas para la extensión, pero cerradas para la modificación.

La palabra clave final es el medio para aplicar esto en Java, ya sea que se use en métodos o en clases.


Si imagina la jerarquía de clases como un árbol (como está en Java), las clases abstractas solo pueden ser ramas y las clases finales son aquellas que solo pueden ser hojas. Las clases que no caen en ninguna de esas categorías pueden ser tanto ramas como hojas.

No hay violación de los principios de OO aquí, la final es simplemente proporcionar una simetría agradable.

En la práctica, desea utilizar final si desea que sus objetos sean inmutables o si está escribiendo una API, para indicar a los usuarios de la API que la clase no está destinada a la extensión.


Como se indicó anteriormente, si no desea que nadie pueda cambiar la funcionalidad del método, puede declararlo como definitivo.

Ejemplo: ruta del archivo del servidor de aplicaciones para descarga / carga, división de la cadena en función del desplazamiento, tales métodos se pueden declarar como definitivos para que estas funciones de método no se alteren. Y si desea dichos métodos finales en una clase separada, entonces defina esa clase como clase Final. Así que la clase final tendrá todos los métodos finales, donde el método final se puede declarar y definir en la clase no final.


Las clases finales no se pueden ampliar. Entonces, si desea que una clase se comporte de cierta manera y no haga que alguien anule los métodos (posiblemente con un código menos eficiente y más malicioso), puede declarar a toda la clase como métodos finales o específicos que no desea que sean. cambiado

Dado que declarar una clase no impide que se cree una instancia de una clase, no significa que impedirá que la clase tenga las características de un objeto. Es solo que tendrá que atenerse a los métodos tal como están declarados en la clase.


final class puede evitar romper la API pública al agregar nuevos métodos

Supongamos que en la versión 1 de tu clase Base haces:

public class Base {}

y un cliente hace:

class Derived extends Base {
    public int method() { return 1; }
}

Luego, si en la versión 2 desea agregar un método a Base :

class Base {
    public String method() { return null; }
}

rompería el código del cliente.

Si hubiéramos usado final class Base lugar, el cliente no habría podido heredar, y la adición del método no rompería la API.


En Java, los elementos con el modificador final no se pueden cambiar!

Esto incluye clases finales, variables finales y métodos finales:

  • Una clase final no puede ser extendida por ninguna otra clase
  • Una variable final no puede ser reasignada a otro valor
  • Un método final no puede ser anulado

Una clase final es una clase que no puede ser extendida. También los métodos podrían declararse como finales para indicar que las subclases no pueden anularlos.

Evitar que la clase sea subclasificada puede ser particularmente útil si escribe API o bibliotecas y desea evitar que se extienda para alterar el comportamiento de la base.


Digamos que tienes una clase de Employee que tiene un método de greet . Cuando se llama el método de greet , simplemente se imprime Hello everyone! . Así que ese es el comportamiento esperado del método de greet

public class Employee {

    void greet() {
        System.out.println("Hello everyone!");
    }
}

Ahora, deje a GrumpyEmployee subclase Employee y anule el método de greet como se muestra a continuación.

public class GrumpyEmployee extends Employee {

    @Override
    void greet() {
        System.out.println("Get lost!");
    }
}

Ahora, en el siguiente código, eche un vistazo al método sayHello . Toma la instancia de Employee como un parámetro y llama al método de saludo con la esperanza de que diría Hello everyone! ¡Pero lo que obtenemos es Get lost! . Este cambio en el comportamiento se debe a Employee grumpyEmployee = new GrumpyEmployee();

public class TestFinal {
    static Employee grumpyEmployee = new GrumpyEmployee();

    public static void main(String[] args) {
        TestFinal testFinal = new TestFinal();
        testFinal.sayHello(grumpyEmployee);
    }

    private void sayHello(Employee employee) {
        employee.greet(); //Here you would expect a warm greeting, but what you get is "Get lost!"
    }
}

Esta situación se puede evitar si la clase Employee se hizo final . Solo imagine la cantidad de caos que un programador descarado podría causar si String Class no se declarara como final .


La palabra clave final sí misma significa que algo es definitivo y no se debe modificar de ninguna manera. Si una clase se marca como final entonces no puede ser extendida o subclasificada. Pero la pregunta es ¿por qué marcamos una final clase? OMI hay varias razones:

  1. Estandarización: algunas clases realizan funciones estándar y no deben modificarse, por ejemplo, clases que realizan varias funciones relacionadas con la manipulación de cuerdas o funciones matemáticas, etc.
  2. Razones de seguridad : a veces escribimos clases que realizan varias funciones relacionadas con la autenticación y la contraseña y no queremos que nadie más las altere.

He escuchado que la calificación final clase de final mejora la eficiencia pero, francamente, no pude encontrar este argumento para tener mucho peso.

Si Java está orientado a objetos y declara una clase final, ¿no detiene la idea de que la clase tiene las características de los objetos?

Tal vez sí, pero a veces ese es el propósito previsto. A veces hacemos eso para lograr mayores beneficios de seguridad, etc., sacrificando la capacidad de esta clase para extenderse. Pero una clase final aún puede extender una clase si es necesario.

En una nota lateral, deberíamos preferir la composición sobre la herencia y final palabra clave final realidad ayuda a hacer cumplir este principio.





final