如果我可以确定同一类中的另一个方法没有被覆盖,那么可以对我的一个方法应用可能的优化。这只是一个小小的优化,所以反思是不可能的。我是否应该创建一个受保护的方法来返回有问题的方法是否被覆盖,以便子类可以使它返回true?
答案 0 :(得分:33)
我不会这样做。它违反了封装并改变了你的类应该做的事情的合同,而没有实施者知道它。
但是,如果必须这样做,最好的方法是调用
class.getMethod("myMethod").getDeclaringClass();
如果返回的类是您自己的类,那么它不会被覆盖;如果它是别的东西,那个子类已经覆盖了它。是的,这是反思,但它仍然相当便宜。
我确实喜欢你的保护方法。这看起来像这样:
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.
}
}
答案 1 :(得分:7)
嗯,我的优化是一个很小的收益率,并且它只是加速了很多东西,因为它被称为每秒数百次。
您可能希望了解Java优化器可以执行的操作。您的手动编码优化可能没有必要。
如果您认为有必要进行手工编码优化,那么您所描述的受保护方法方法并不是一个好主意,因为它会公开您的实施细节。
答案 2 :(得分:2)
您希望在程序的生命周期内调用函数多少次?对特定单一方法的反思不应该太糟糕。如果在整个程序的生命周期中不值得花费那么多时间,我的建议是保持简单,并且不包括小优化。
雅各
答案 3 :(得分:1)
注释覆盖特定方法的子类。 @OverridesMethodX。
对类加载(即在static
块中)执行必要的反射工作,以便通过最终布尔标志发布信息。然后,在需要的地方和时间查询标志。
答案 4 :(得分:1)
也许有一种更简洁的方法可以通过Strategy Pattern执行此操作,但我不知道您的应用程序和数据的其余部分是如何建模的,但它似乎可能适合。
无论如何,当我遇到类似的问题时,它对我有用。您可以使用启发式方法来决定使用哪种策略,具体取决于要处理的数据。
同样,我没有足够的关于您的具体用法的信息,看看这是否有点过分。但是,我会避免更改此类特定优化的类签名。通常当我感觉到与现在相反的冲动时,我把它作为一种唱歌,当我设计这个东西时我没有预见到一个角落的情况,我应该将它重构为更清洁更全面的解决方案。
但请注意,仅在优化的基础上进行此类重构几乎不可避免地导致灾难。如果是这种情况,我会采取上面建议的反思方法。它不会改变继承契约,并且当正确完成时,只需要为每个子类执行一次,这需要它在应用程序的运行时间内。答案 5 :(得分:1)
我知道这是一个稍微陈旧的问题,但是为了其他googlers:
我想出了一个使用接口的不同解决方案。
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
}
}
或者相反:
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(){}
}
答案 6 :(得分:1)
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;
}
答案 7 :(得分:0)
可以使用反射来确定是否覆盖了方法。代码有点棘手。例如,您需要知道您有一个运行时类,它是覆盖该方法的类的子类。
您将一遍又一遍地看到相同的运行时类。因此,您可以在WeakHashMap
上键入Class
保存结帐。
请参阅java.awt.Component
处理coalesceEvents
的代码。
答案 8 :(得分:0)
这可能是另一个替代方法,它类似于重写另一个受保护的方法返回true / false
我建议创建一个空接口,即标记接口,然后让子类实现此接口,并在调用重写的昂贵方法之前,在超类内部检查此实例是否为instanceof
此接口。