【问题标题】:Why is java.net.URL final?为什么 java.net.URL 是最终的?
【发布时间】:2012-09-12 15:51:27
【问题描述】:

我想从java.net.URL 继承,但我不能,因为它是最终的。我得到了错误:

cannot inherit from final java.net.URL

为什么是最终的?

对于为什么String is final 状态,JVM 依赖 String 的问题的一些答案,因为它是一种非常基本的数据类型。我看不出这将如何应用于 URL 类型。

更新

许多答案和 cmets 都给出了理由,为什么避免继承是一种好习惯。有些人甚至认为一切都应该是最终的。但实际情况有所不同。 JDK 中的大多数类不是 final。良好的实践是一个不应该不从 java.net.URL 继承的原因。这甚至可能适用于 JDK 的任何类。但是当某些东西被定义为 final 时,can 不能继承。这仅适用于 String 或 URL 等少数几个类。

所以 URL 和所有其他非 final 类之间肯定有一些不同。问题是:这个 URL 是最终的,有什么区别?

说我不应该关心这个问题,因为无论如何我都不应该继承这个问题。

【问题讨论】:

  • 我想问你为什么要继承它。了解您在继承背后的目的会很有趣。
  • @Gamp:我想将它包装起来以实现项目特定的错误处理。
  • 那我建议你按照 Matt 的建议写一个 Wrapper 类
  • 它是final的所以你不能继承它。这就是final的意思。没有别的意思。
  • @EJP:我知道我不能继承。问题是为什么我不能继承。我的意思是必须而不应该。

标签: java


【解决方案1】:

它是 final 专门防止你扩展它。 However it works internally,它不是为继承而设计的,所以作者阻止你这样做。

记住有效的Java:

  • 第 17 条:“设计和记录继承,否则禁止。”
  • 第 16 项:“优先组合优于继承。”

因此,不要扩展URL创建一个具有URL 字段的类。

【讨论】:

  • 为了澄清,出于安全原因,String 是最终的。出于同样的原因,我认为 URL 是最终的。
  • “安全原因”为String 最终确定的原因描绘了一个相当宽的笔触。不变性还有助于提高性能并使代码更易于推理。
  • 是的,你可以用字符串的子类做很多恶意的事情。
  • @ceving 引用有效的 Java(尽管存在缺陷)通常是一种有效的方式来提出一个很好的论点,很少有堆栈溢出者可以在质量上接近。
  • @MattBall 从某种意义上说,它阻止了不明智的快捷方式,例如不必要地共享可变对象。
【解决方案2】:

我的猜测是这是出于安全原因。如果某个方法需要 URL 对象作为参数,并且您可以扩展 URL 类以执行 URL 类不应执行的操作,那么它可能存在安全问题。

【讨论】:

  • 如果这是正确的,java.io.BufferedInputStream 也必须是最终的,因为它通常用于读取 HTTPS 回复的内容。如果您遭受恶意代码注入 Javas “final” 无法解决您的问题。
  • @ceving URLBufferedInputStream 类在本质上与 Java 中的差异一样大。 URL值对象BufferedInputStream引用对象URL 您可以存储和信任。例如,URL[]File 你需要复制 - 这是狡猾和糟糕的设计。 InputStreams 是对象能力。你不想小心你让谁拥有他们的特定实例
  • @ceving 我认为他们在设计 API 时想要一些可以信任的东西。如果 URL 是安全的,他们可以使代码在内部安全地获取输入流。我没想到有人会在他们知道可以扩展它来做一些恶意的事情时制作一个采用 BufferedInputStream 的 API。如果除了字符串之外没有任何类是最终的,那么所有的 API 都将只接受字符串作为它们的参数。例如,File 类不是最终类,servlet API 将 File 对象作为其参数是不寻常的。
  • @gigadot 实际上InputStream 可以被覆盖来做一些恶意的事情——通常抓取传递给read 方法的byte[] 并在它被用于其他事情时读取/修改它。 File 是通过 Java SE API 传递的(太多),并且一直是漏洞的主题(TOCTOU/TOC2TOU - 检查时间到使用时间由覆盖的File.getPath 返回的不同值)。
【解决方案3】:

AFAIK 该 URL 是 IETF RFC 标准的完整实现,因此您不需要更改或扩展它。

【讨论】:

  • RFC 不是永恒的。如果您查看 RFC 3986,您会发现以下标签:更新:1738;已过时:2732、2396、1808。
  • InetAddress 是已扩展的 RFC 事物示例(针对 IPv6),尽管您仍然无法扩展它。
猜你喜欢
  • 2012-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-03
  • 1970-01-01
  • 1970-01-01
  • 2012-06-22
相关资源
最近更新 更多