【问题标题】:@Override on method in subclass "appears" ignored at runtime@Override 子类中的方法“出现”在运行时被忽略
【发布时间】:2013-07-05 23:09:48
【问题描述】:

我真的希望我只是错过了一些简单的东西,但我正在阅读以下内容:http://docs.oracle.com/javase/tutorial/java/IandI/override.html

我有两个类和一个接口。从字面上看,这个 Oracle 文档页面中显示的“用例”。但是,当我运行 JUnit 测试时 - 仅调用超类中的方法,并且该方法具有我不想调用的简单默认值:

接口包含此方法签名:

public interface RecordServiceInterface {
    List<String> searchRecords(String id) throws ServiceException;
}

实现该接口的超类包含此方法并具有默认值 - Eclipse IDE 在发现实现类未实现的缺失方法时插入此方法。

public class RecordService implements RecordServiceInterface {
    public List<String> searchRecords(String id) throws ServiceException {
        // TODO Auto-generated method stub
        return null;
    }
}

在运行时,当我逐步通过调试器时,只调用上述内容……每次。

然后子类扩展超类并拥有想要覆盖的真实实现:

public class MyRecordService extends RecordService {
    @Override
    public List<String> searchRecords(String id) throws ServiceException {  
        List<String> myList = new ArrayList<String>();

        // ...

        return myList;
    }
}

我一定完全错过了@Override 的意思。在执行期间,它反复无法进入带有@Override 注释的方法。

【问题讨论】:

  • 你能提供测试的来源吗?

标签: java overriding


【解决方案1】:

@Override 注解所做的只是让编译器在类继承中没有可以被覆盖的任何对应方法时生成错误。因此,它旨在确保您覆盖的方法实际上覆盖了某些内容。

如果没有调用来自 MyRecordService 的方法,而是调用 RecordService 类中的方法,那么我猜想实例化了错误的对象。所以你面前的是一个 RecordService 类型的对象,而不是 MyRecordService 类型的对象。

由于您没有提供那部分代码,这只是一个猜测,基于您的继承看起来不错的事实。

【讨论】:

  • Jan - 非常感谢...我发现了这个问题,这与我被这些类的实例化方式所困扰的事实有关,正如你在这里提到的那样。我实际使用的超类使用带有 getInstance() 方法的单例模式。该 getInstance() 方法需要根据传入的 2 个构造函数参数之一的值将正确的类参数传递给 synchronized() 方法。我添加了该逻辑以进行区分,它现在可以正确执行。衷心感谢您的时间和投入。
  • 不客气。随意将我的答案标记为正确,然后;-)
【解决方案2】:

@Override 是一个编译时注解,用于验证被注解的方法实际上是否覆盖了超类/接口中的某些内容。它不影响运行时行为。

发布您的测试代码,以便我们更清楚地了解您想要做什么。

【讨论】:

    【解决方案3】:

    正如您在@Overridejavadoc 中看到的,@Override 的保留策略是 SOURCE。换句话说:它在编译时使用但不会生成生成的二进制代码(类文件)。

    特别是,SOURCE 保留政策是defined

    注释将被编译器丢弃。

    【讨论】:

      【解决方案4】:

      @Override 实际上只是在尝试覆盖 super class' 或 instance 的方法时捕获拼写错误的一种方法,以及偶尔尝试覆盖 final 方法的尝试(按设计不可覆盖)。

      当考虑到一个呼叫的选择时,覆盖的行为使得堕落方法覆盖方法。

      例如:

      RecordServiceInterface service = new RecordService();
      RecordService service2 = new RecordService();
      

      同时使用serviceservice2,将调用来自RecordService 的实现。现在考虑:

      RecordServiceInterface service3 = new MyRecordService();
      RecordService service4 = new MyRecordService();
      MyRecordService service5 = new MyRecordService();
      

      使用service3service4service5,将调用来自MyRecordService 的实现。

      覆盖不会替换父类型的方法,除非它是链的一部分(例如,在最后一个块中创建的所有三个实例,35)。如果您的Object 的实例不是类型(在这种情况下为MyRecordService),则该方法不会以其行为覆盖该实例。 serviceservice2 仍将调用 RecordService 的实现。

      再举一个例子可能会更清楚:

      public interface Runnable {
          void run();
      }
      
      public class RunnableA implements Runnable {
          @Override
          public void run() { System.out.println("A"); }
      }
      
      public class RunnableB extends RunnableA {
          @Override
          public void run() { System.out.println("B"); }
      }
      
      public class RunnableC implements Runnable {
          @Override
          public void run() { System.out.println("C"); }
      }
      

      您只能拥有其中任何一个的实例,因此每次调用instance.run() 只会输出一行。它取决于实例的实现,而不是类路径中存在的内容。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-06
        • 2014-03-10
        • 1970-01-01
        相关资源
        最近更新 更多