method - static final java
¿Cuál es el punto de la "clase final" en Java? (23)
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
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?
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.
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
.
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.
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
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.
La clase Android Looper es un buen ejemplo práctico de esto. http://developer.android.com/reference/android/os/Looper.html
La clase Looper proporciona cierta funcionalidad que NO está destinada a ser anulada por ninguna otra clase. Por lo tanto, no hay subclase aquí.
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.
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:
- 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.
- 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.
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.
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.
Sí, a veces es posible que desee esto, ya sea por razones de seguridad o de velocidad. Se hace también en C ++. Puede que no sea aplicable para programas, pero sí para marcos. http://www.glenmccl.com/perfj_025.htm
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.
Si la clase está marcada como final
, significa que la estructura de la clase no puede ser modificada por nada externo. Donde esto es lo más visible es cuando estás haciendo la herencia polimórfica tradicional, básicamente la class B extends A
simplemente no funciona. Es básicamente una forma de proteger algunas partes de su código (hasta cierto punto) .
Para aclarar, marcar la clase final
no marca sus campos como final
y, como tal, no protege las propiedades del objeto, sino la estructura de la clase real.
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 ".
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.
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.
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.
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.
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.
La clase final se usa cuando desea estandarizar los métodos y asegurarse de que nadie más los sobrescriba.
Entonces, ¿por qué algunas clases se declaran como final?
- Dado que las clases finales no se pueden extender, puede tratarlas como primitivas y no tiene que preocuparse por el cambio de estas clases.
- Por razones de seguridad, no desea que otra persona anule el código escrito por usted.
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.
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