【问题标题】:Interface implements overriding its own methods to create an object of itself as DEFAULT接口实现了覆盖自己的方法来创建自己的对象作为默认值
【发布时间】:2020-04-17 01:00:46
【问题描述】:

我已经阅读了许多带有问题的主题,这些问题看起来像是我要问的问题。但是,我找不到可以应用于我的问题的满意答案,因为我的问题不止一个,分为三个方面。

这是https://github.com/google/ExoPlayer/blob/release-v2/library/core/src/main/java/com/google/android/exoplayer2/text/SubtitleDecoderFactory.java中的SubtitleDecoderFactory接口

据我了解,interace 是抽象的,不能有具体的方法实现(也许新 java 允许这样做,但由于我是 java 新手,让我们坚持 Java 的一般规则)。所以对我来说,接口中有两个抽象方法声明是有意义的,它们是“boolean supportsFormat(Format format)”和“SubtitleDecoder createDecoder(Format format)”。但我不明白,我的问题是:

  1. 为什么这个接口可以实现“SubtitleDecoderFactory DEFAULT = new SubtitleDecoderFactory()”,看起来像是初始化方法的实现?

  2. 这个接口通过重写自己的方法来初始化自己,是不是一个无意义的动作? (一个接口意味着有其他类来实现它,而不是它自己,对吗?)

  3. 假设问题 1 和 2 有效,在接口中创建自身对象有什么好处?

  4. 实现这个接口的类的实例是否会有这个接口的DEFAULT实例?


public interface SubtitleDecoderFactory {


  boolean supportsFormat(Format format);


  SubtitleDecoder createDecoder(Format format);


  SubtitleDecoderFactory DEFAULT =
      new SubtitleDecoderFactory() {

        @Override
        public boolean supportsFormat(Format format) {
          @Nullable String mimeType = format.sampleMimeType;
          return MimeTypes.TEXT_VTT.equals(mimeType)
              || MimeTypes.TEXT_SSA.equals(mimeType)
              || MimeTypes.APPLICATION_TTML.equals(mimeType)
              || MimeTypes.APPLICATION_MP4VTT.equals(mimeType)
              || MimeTypes.APPLICATION_SUBRIP.equals(mimeType)
              || MimeTypes.APPLICATION_TX3G.equals(mimeType)
              || MimeTypes.APPLICATION_CEA608.equals(mimeType)
              || MimeTypes.APPLICATION_MP4CEA608.equals(mimeType)
              || MimeTypes.APPLICATION_CEA708.equals(mimeType)
              || MimeTypes.APPLICATION_DVBSUBS.equals(mimeType)
              || MimeTypes.APPLICATION_PGS.equals(mimeType);
        }

        @Override
        public SubtitleDecoder createDecoder(Format format) {
          @Nullable String mimeType = format.sampleMimeType;
          if (mimeType != null) {
            switch (mimeType) {
              case MimeTypes.TEXT_VTT:
                return new WebvttDecoder();
              case MimeTypes.TEXT_SSA:
                return new SsaDecoder(format.initializationData);
              case MimeTypes.APPLICATION_MP4VTT:
                return new Mp4WebvttDecoder();
              case MimeTypes.APPLICATION_TTML:
                return new TtmlDecoder();
              case MimeTypes.APPLICATION_SUBRIP:
                return new SubripDecoder();
              case MimeTypes.APPLICATION_TX3G:
                return new Tx3gDecoder(format.initializationData);
              case MimeTypes.APPLICATION_CEA608:
              case MimeTypes.APPLICATION_MP4CEA608:
                return new Cea608Decoder(mimeType, format.accessibilityChannel);
              case MimeTypes.APPLICATION_CEA708:
                return new Cea708Decoder(format.accessibilityChannel, format.initializationData);
              case MimeTypes.APPLICATION_DVBSUBS:
                return new DvbDecoder(format.initializationData);
              case MimeTypes.APPLICATION_PGS:
                return new PgsDecoder();
              default:
                break;
            }
          }
          throw new IllegalArgumentException(
              "Attempted to create decoder for unsupported MIME type: " + mimeType);
        }
      };
}

【问题讨论】:

    标签: java object interface overriding new-operator


    【解决方案1】:
    1. 为什么这个接口可以实现“SubtitleDecoderFactory DEFAULT = new SubtitleDecoderFactory()”,看起来像是初始化方法的实现?

    接口没有实现任何东西。你拥有的是一个名为DEFAULTpublicstaticfinal 字段,它被分配了一个SubtitleDecoderFactory 的实例。


    1. 这个接口通过重写自己的方法来初始化自己,是不是一个无意义的动作? (一个接口意味着有其他类来实现它,而不是它自己,对吗?)

    同样,接口不是“初始化自身”,也不是实现自身。你所拥有的是一个匿名类的例子。正是这个匿名类实现了SubtitleDecoderFactory。匿名类被实例化,实例被赋值给DEFAULT字段;当Class初始化时会发生这种情况。


    1. 假设问题 1 和 2 有效,在接口中创建自身对象有什么好处?

    在这种情况下,提供了SubtitleDecoderFactory 的默认实现。这个默认实现也只有一个实例,因为接口中声明的所有字段都是隐式公共的、静态的和最终的;这是一个单例的例子。

    这里的一个可能的优点是您不必声明另一个命名类。而且由于目标显然是拥有一个单例,因此也没有需要命名类。


    1. 实现此接口的类的实例是否将具有此接口的 DEFAULT 实例 [sic]?

    请记住,DEFAULT 是一个引用匿名类实例的字段。 SubtitleDecoderFactory 的所有实现都可以访问该字段吗?是的,但不是特别是因为他们正在实现接口。

    由于接口中声明的所有字段都是公共的、静态的和最终的,DEFAULT 字段是一个常量(尽管不是编译时常量)。静态字段与类相关联,而不是与该类的实例相关联。换句话说,任何可以“看到”SubtitleDecoderFactory 的类都可以访问DEFAULT 字段。例如:

    /* import SubtitleDecoderFactory interface as needed */
    
    public class Main {
    
      public static void main(String[] args) {
        System.out.println(SubtitleDecoderFactory.DEFAULT == SubtitleDecoderFactory.DEFAULT);
      }
    
    }
    

    【讨论】:

    • "...;在初始化类时会发生这种情况。"请问什么时候在哪里初始化Class? (是不是在程序的其余部分第一次引用“DEFAULT”字段的时间和地点?)
    • 是否可以验证这个“DEFAULT”实例是在何时何地在 Android Studio 中创建的?
    • §12.4 of the Java Language Specification 解释类/接口初始化;特别是,§12.4.1 解释了初始化发生的时间。
    【解决方案2】:

    new SubtitleDecoderFactory() { ... } 创建一个实现接口SubtitleDecoderFactoryanonymous inner class 实例。然后将此实例分配给静态字段 DEFAULT(“接口主体中的每个字段声明都隐含为 publicstaticfinal”、JLS, §9.3) .

    在程序的其余部分,可以通过SubtitleDecoderFactory.DEFAULT 访问匿名类的实例。

    【讨论】:

    • 谢谢。这个匿名类的实例是否只能由实现接口 SubtitleDecoderFactory() 的类的实例访问?或任何课程;如果是这样,谁调用新关键字“new SubtitleDecoderFactory() { ... }”?
    • 该类是匿名的。这意味着该类没有名称,因此无法访问。但是,可以访问字段 DEFAULT(以及通过它,匿名类的唯一现有实例)。
    猜你喜欢
    • 2015-11-11
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 2012-09-24
    • 1970-01-01
    • 2015-11-27
    相关资源
    最近更新 更多