Existe una posible optimización que podría aplicar a uno de mis métodos, si puedo determinar que otro método en la misma clase no se reemplaza. Es solo una ligera optimización, por lo que la reflexión está fuera de cuestión. ¿Debo simplemente hacer un método protegido que devuelva si el método en cuestión está anulado, de modo que una subclase puede hacer que devuelva verdadero?Cómo determinar rápidamente si un método se reemplaza en Java
Respuesta
No haria esto. Viola la encapsulación y cambia el contrato de lo que su clase debe hacer sin que los implementadores lo sepan.
Si debe hacerlo, sin embargo, la mejor manera es invocar
class.getMethod("myMethod").getDeclaringClass();
Si la clase que se devuelve es su propia, entonces no es anulado; si es otra cosa, esa subclase lo ha anulado. Sí, esto es reflejo, pero sigue siendo bastante barato.
Aunque me gusta su enfoque de método protegido. Eso sería algo como esto:
public class ExpensiveStrategy {
public void expensiveMethod() {
// ...
if (employOptimization()) {
// take a shortcut
}
}
protected boolean employOptimization() {
return false;
}
}
public class TargetedStrategy extends ExpensiveStrategy {
@Override
protected boolean employOptimization() {
return true; // Now we can shortcut ExpensiveStrategy.
}
}
Bueno, mi optimización es un rendimiento pequeño caso por caso, y solo acelera mucho las cosas porque se llama cientos de veces por segundo. Con la reflexión, ese rendimiento se reduciría a tal punto que la optimización no tiene sentido. Una buena respuesta, así que estoy votando esto de todos modos. – bgw
Si realmente lo necesita, puede determinar si los métodos están sobrecargados a través de un inicializador estático y almacenar el resultado en un booleano. Alternativamente, puede agregar esto a través de aspect0 – vickirk
Use Class.getMethod en su lugar. Class.getDeclaredMethod elevará NoSuchMethodException si pregunta sobre un método heredado que la subclase no anula. Por supuesto, podría usar la excepción como indicador (deficiente) de que el método no fue anulado. –
¿Cuántas veces espera que se llame a la función durante la vida útil del programa? La reflexión sobre un único método específico no debería ser tan malo. Si no vale tanto tiempo durante la vida útil del programa, mi recomendación es mantenerlo simple y no incluir la pequeña optimización.
Jacob
Es un método muy comúnmente llamado. – bgw
Déjame aclarar mi respuesta. Estaba sugiriendo que si tiene este patrón común, y las instancias son todas del mismo tipo, podría almacenar en caché el valor de la reflexión que se realiza una vez. Usted determina la configuración la primera vez y usa ese valor en todo momento. De esta manera, la sobrecarga de reflexión sería una vez y las llamadas serían un número mucho mayor. Si esto se llama repetidamente en cada instancia, una variable de instancia declarada en la clase padre e inicializada en la primera llamada (usando la reflexión) podría darle un impulso. – TheJacobTaylor
La reflexión se puede utilizar para determinar si un método se reemplaza. El código es un poco complicado. Por ejemplo, debe tener en cuenta que tiene una clase de tiempo de ejecución que es una subclase de la clase que anula el método.
Vas a ver las mismas clases de tiempo de ejecución una y otra vez. Para que pueda guardar los resultados del cheque en un WeakHashMap
ingresado en el Class
.
Vea mi código en java.awt.Component
que trata con coalesceEvents
para un ejemplo.
que no puedo hacer, el valor cambia ligeramente cada vez. – bgw
@PiPeep: la instancia real es irrelevante. Como digo, la clave del mapa se basa en la clase de tiempo de ejecución. –
Anotar subclases que anulan el método particular. @OverridesMethodX.
Realice el trabajo reflector necesario en la carga de clase (es decir, en un bloque static
) para que publique la información a través de un indicador booleano final. Luego, consulta la bandera donde y cuando la necesites.
bloques estáticos rompen la herencia. – bgw
Sé que huele. Pero la optimización que desea ya está subvirtiendo el polimorfismo. –
Bueno, mi optimización es un rendimiento pequeño caso por caso, y solo acelera mucho las cosas porque se llama cientos de veces por segundo.
Es posible que desee ver lo que el optimizador de Java puede hacer. Su optimización codificada a mano puede no ser necesaria.
Si decide que la optimización codificada a mano es necesaria, el método de método protegido que describió no es una buena idea porque expone los detalles de su implementación.
+1 Me parece un buen consejo, no sé por qué no votó. – vickirk
quizás haya una manera más clara de hacerlo a través del Strategy Pattern, aunque no sé cómo se modelan el resto de la aplicación y los datos, pero parece que podría encajar.
Me hizo de todos modos cuando me enfrentaba con un problema similar.Podría tener una heurística que decida qué estrategia utilizar dependiendo de los datos que se procesarán.
De nuevo, no tengo suficiente información sobre su uso específico para ver si esto es excesivo o no. Sin embargo, me abstendría de cambiar la firma de clase para dicha optimización específica. Por lo general, cuando siento la necesidad de ir en contra de la corriente, interpreto que no había imaginado un caso de esquina cuando diseñé el producto y que debería refactorizarlo para obtener una solución más completa y más limpia.
Sin embargo, tenga en cuenta que tal refactorización cuando se realiza únicamente en terrenos de optimización casi inevitablemente conduce a un desastre. Si este es el caso, tomaría el enfoque reflexivo sugerido anteriormente. No altera el contrato de herencia, y cuando se hace correctamente debe hacerse una sola vez por subclase que lo requiere para la vida útil de la aplicación.
Sé que esto es una pregunta un poco viejo, pero por el bien de otros empleados de Google:
me ocurrió una solución diferente utilizando interfaces.
class FastSub extends Super {}
class SlowSub extends Super implements Super.LetMeHandleThis {
void doSomethingSlow() {
//not optimized
}
}
class Super {
static interface LetMeHandleThis {
void doSomethingSlow();
}
void doSomething() {
if (this instanceof LetMeHandleThis)
((LetMeHandleThis) this).doSomethingSlow();
else
doSomethingFast();
}
private final void doSomethingFast() {
//optimized
}
}
o al revés:
class FastSub extends Super implements Super.OptimizeMe {}
class SlowSub extends Super {
void doSomethingSlow() {
//not optimized
}
}
class Super {
static interface OptimizeMe {}
void doSomething() {
if (this instanceof OptimizeMe)
doSomethingFast();
else
doSomethingSlow();
}
private final void doSomethingFast() {
//optimized
}
void doSomethingSlow(){}
}
private static boolean isMethodImplemented(Object obj, String name)
{
try
{
Class<? extends Object> clazz = obj.getClass();
return clazz.getMethod(name).getDeclaringClass().equals(clazz);
}
catch (SecurityException e)
{
log.error("{}", e);
}
catch (NoSuchMethodException e)
{
log.error("{}", e);
}
return false;
}
Ha publicado exactamente la misma respuesta aquí y [aquí] (http://stackoverflow.com/questions/4821704/java-how-to-find-if-a-method-is-overridden-from-base-class/19637356# 19637356). Si puede dar exactamente la misma respuesta, debe marcar ** la pregunta como duplicada **, ** no la respuesta duplicada ** también. –
- 1. Cómo determinar si MethodInfo reemplaza el método base
- 2. ¿Cómo puedo determinar si se implementa un método abstracto?
- 3. Usando Moq para determinar si un método se llama
- 4. ¿Es posible determinar/afirmar que si una función virtual queda anulada, otra también se reemplaza?
- 5. ¿Cómo determinar qué métodos se llaman en un método?
- 6. ¿Cómo determinar si un personaje es una letra en Java?
- 7. Cómo determinar por reflexión si un Método devuelve 'nulo'
- 8. ¿Cómo determinar si una lista está ordenada en Java?
- 9. determinar rápidamente si un número es primo en Python para los números <1 mil millones
- 10. ¿Cómo puedo determinar si un método es un ejemplo genérico de un método genérico
- 11. ¿Cómo puedo determinar si se gestiona un proceso en C#?
- 12. ¿cómo se reemplaza por un setFrame UILabel
- 13. ¿Cómo determinar rápidamente qué hojas tienen macros en Excel Workbook?
- 14. ¿Cómo se reemplaza un método de un objeto Moose en tiempo de ejecución?
- 15. ¿Cómo puedo determinar si se muestra un botón de retroceso?
- 16. ¿Cuál es el código hash de un objeto si hashCode() no se reemplaza?
- 17. ¿Cómo puedo determinar si se tocó un UILabel?
- 18. ¿Cómo puedo determinar si se difiere un objeto jQuery?
- 19. Determinar si los carriles se ejecuta en un servidor web
- 20. Determinar si se pasó un parámetro con nombre
- 21. ¿Cómo se reemplaza un signo de libra (moneda) en javascript?
- 22. ¿Cómo puedo determinar si un objeto implementa un método en Perl?
- 23. AbstractMethodError se produjo cuando el método privado del paquete reemplaza
- 24. ¿Por qué mi método virtual no se reemplaza?
- 25. no reemplaza ni implementa un método desde un supertipo
- 26. ¿Cómo puedo determinar si un archivo es un archivo PDF?
- 27. ¿Cómo ofuscar el código de Java rápidamente?
- 28. Determinar si un archivo es un duplicado
- 29. ¿Cómo determinar si un campo tiene foco?
- 30. ¿Cómo verificar rápidamente si un archivo zip está dañado?
¿Qué tal que no optimizan? Parece que la optimización no es lo suficientemente significativa como para realmente importar. –
Anon: El método se llama cientos de veces por segundo. – bgw
Luego busque reflexión y guarde el resultado en un campo privado. –