Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何快速确定方法是否在Java中被重写_Java_Oop_Optimization_Methods_Overriding - Fatal编程技术网

如何快速确定方法是否在Java中被重写

如何快速确定方法是否在Java中被重写,java,oop,optimization,methods,overriding,Java,Oop,Optimization,Methods,Overriding,如果我可以确定同一类中的另一个方法没有被重写,那么我可以对我的一个方法应用一个可能的优化。这只是一个轻微的优化,所以反射是不可能的。我是否应该创建一个受保护的方法来返回所讨论的方法是否被重写,这样子类就可以使其返回true?在程序的生命周期内,您希望调用函数多少次?对特定单一方法的反射不应该太糟糕。如果在程序的生命周期中不值得花那么多时间,我的建议是保持简单,不要包含小的优化 雅各布我不会这么做的。它违反了封装,并在实现者不知道的情况下更改了类应该做的事情的约定 但是,如果必须这样做,最好的方法

如果我可以确定同一类中的另一个方法没有被重写,那么我可以对我的一个方法应用一个可能的优化。这只是一个轻微的优化,所以反射是不可能的。我是否应该创建一个受保护的方法来返回所讨论的方法是否被重写,这样子类就可以使其返回true?

在程序的生命周期内,您希望调用函数多少次?对特定单一方法的反射不应该太糟糕。如果在程序的生命周期中不值得花那么多时间,我的建议是保持简单,不要包含小的优化


雅各布我不会这么做的。它违反了封装,并在实现者不知道的情况下更改了类应该做的事情的约定

但是,如果必须这样做,最好的方法是调用

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.
  }
}

反射可用于确定方法是否被重写。代码有点复杂。例如,您需要知道您有一个运行时类,它是重写该方法的类的子类

您将一次又一次地看到相同的运行时类。因此,您可以将检查结果保存在
上键入的
WeakHashMap


有关示例,请参见
java.awt.Component
中处理
合并事件的我的代码。

注释重写特定方法的子类@重写方法

在类加载上执行必要的反射工作(即,在
静态
块中),以便通过最终的布尔标志发布信息。然后,在需要的位置和时间查询标志


好吧,我的优化是一个小的产量在个案的基础上,它只加快了很多事情,因为它被称为数百次每秒

您可能想看看Java优化器可以做什么。您的手工编码优化可能没有必要


如果您认为手工编码的优化是必要的,那么您描述的受保护方法方法不是一个好主意,因为它公开了您的实现的细节。

也许有一种更干净的方法可以通过来实现这一点,尽管我不知道您的应用程序和数据的其余部分是如何建模的,但它似乎适合您

不管怎样,当我面临类似的问题时,它对我产生了影响。您可以使用一种启发式方法,根据要处理的数据决定使用哪种策略

再说一次,我没有足够的关于你的具体用法的信息来判断这是否是过度使用。但是,我不会为这种特定的优化更改类签名。通常,当我感到有逆潮流而动的冲动时,我会认为我在设计这个东西时没有看到一个角落,我应该将它重构成一个更干净、更全面的解决方案


然而,要小心,如果仅仅基于优化的理由进行重构,几乎不可避免地会导致灾难。如果是这种情况,我会采取上面建议的反射方法。它不会改变继承契约,正确完成后,在应用程序的运行期内,每个需要继承契约的子类只需要执行一次。

我知道这是一个有点老的问题,但为了其他谷歌用户:

我提出了一个使用接口的不同解决方案

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(){}
}
私有静态布尔值isMethodImplemented(对象对象对象,字符串名称)
{
尝试
{

类这可能是另一种类似于重写另一个受保护的方法返回true/false的解决方法


我建议创建一个空接口,标记接口,然后让子类实现这个接口,在调用重写的昂贵方法之前,在超类内部检查这个实例是否是
instanceof
这个接口。

不优化它怎么样?听起来优化不够重要真的很重要。Anon:该方法每秒调用数百次。然后进行反射,并将结果缓存在私有字段中。Anon:有可能,只是有点不干净。这是一种非常常见的调用方法。让我澄清我的答案。我的意思是,如果你有这种通用模式,并且实例都是相同类型的,你可以ld缓存一次执行的反射的值。您第一次确定配置,并在整个过程中使用该值。这样,反射开销将是一次,调用次数将大得多。如果在每个实例上重复调用该值,则在父类和惰性initia中声明一个实例变量在第一次调用时被激活(使用反射)可能会给你一个提振。好吧,我的优化是一个小的收益率在个案的基础上,它只会加快很多事情,因为它被称为每秒数百次。有了反射,该收益率将降低到这样一个点,优化是无意义的。一个好答案,所以我无论如何都投票。如果你真的需要它,你可以d确定该方法是否在静态初始化器中通过重载,并将结果存储在布尔值中。或者,您可以通过aspectjUse Class.getMethod添加该结果。如果您询问子类未重写的继承方法,Class.getDeclaredMethod将引发NoSuchMethodException。当然,您可以将该异常用作(较差的)指示该方法未被重写。@vickirk:静态缓存不起作用。超类不知道(没有反射)调用它的子类是什么,所以它不能缓存r
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;
}