代码之家  ›  专栏  ›  技术社区  ›  bgw rmribeiro

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

  •  17
  • bgw rmribeiro  · 技术社区  · 15 年前

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

    8 回复  |  直到 7 年前
        1
  •  33
  •   John Feminella    15 年前

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

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

    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.
      }
    }
    
        2
  •  7
  •   jdigital    15 年前

    嗯,我的优化是一个很小的收益率,一个接一个的,它只会加速很多事情,因为它被称为每秒数百次。

    你可能想看看Java优化器能做什么。可能不需要手动编码优化。

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

        3
  •  2
  •   TheJacobTaylor    15 年前

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

    雅各伯

        4
  •  1
  •   Noel Ang    15 年前

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

    在课堂上进行必要的反思工作(即 static 块),以便通过最终布尔标志发布信息。然后,查询标志的位置和时间。

        5
  •  1
  •   Newtopian    15 年前

    也许有一个更干净的方法通过 Strategy Pattern ,虽然我不知道您的应用程序和数据的其余部分是如何建模的,但看起来它可能适合。

    不管怎样,当我面对类似的问题时。根据要处理的数据,可以有一个启发式方法来决定使用哪种策略。

    再说一次,我没有足够的信息来了解你的具体用法,看这是否是过度杀戮。但是,对于这种特定的优化,我将避免更改类签名。通常,当我感到有逆流的冲动时,我会把它当作一首歌,说我在设计这个东西的时候没有放弃一个角落,我应该把它重构成一个更干净、更全面的解决方案。

    但是要注意的是,如果仅仅基于优化的原因进行重构,几乎不可避免地会导致灾难。如果是这样的话,我会采取上述的反刍方法。它不会更改继承契约,并且当正确完成时,只需要在应用程序的运行时生命周期中需要它的每个子类执行一次。

        6
  •  1
  •   SimonPe    11 年前

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

    我用接口想出了一个不同的解决方案。

    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(){}
    }
    
        7
  •  1
  •   kayz1    11 年前
    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;
    }
    
        8
  •  0
  •   Tom Hawtin - tackline    15 年前

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

    您将一遍又一遍地看到相同的运行时类。所以您可以将签入的结果保存在 WeakHashMap 键控 Class

    查看我的代码 java.awt.Component 处理 coalesceEvents 举个例子。