Java 为什么这种从超级界面到子界面的转换是有效的?

Java 为什么这种从超级界面到子界面的转换是有效的?,java,servlets,Java,Servlets,我从一个角度来看这个例子: 我被这句话弄糊涂了: HttpServletResponse response = (HttpServletResponse) res; 我理解从ServletResponse到HttpServletResponse的转换是必要的,因为后一个接口具有#setHeader()。但是为什么这个演员能工作呢?是否因为传递给该方法的底层对象是HttpServletResponse,所以它可以工作 但撇开运行时不谈,为什么编译器允许这样做?我是Java新手,本以为该转换会失败

我从一个角度来看这个例子:

我被这句话弄糊涂了:

HttpServletResponse response = (HttpServletResponse) res;
我理解从
ServletResponse
HttpServletResponse
的转换是必要的,因为后一个接口具有
#setHeader()
。但是为什么这个演员能工作呢?是否因为传递给该方法的底层对象是
HttpServletResponse
,所以它可以工作

但撇开运行时不谈,为什么编译器允许这样做?我是Java新手,本以为该转换会失败,因为它是从一种不太具体的类型转换为更具体的类型。例如,使用and时,我失败了:

Vertex v = (Vertex) e; // `e` is an `Element`
很好地解释了这一点

5.1.6缩小参考转换

这种转换需要在运行时进行测试,以确定实际引用值是否是新类型的合法值。如果不是,则抛出ClassCastException

i、 当你进行这样的转换时,你显式地将类型S转换为类型T。这样做你告诉编译器“我确信这是可以的”

如果您认为它可能会失败,那么您应该尝试捕获
ClassCastException
,并停止程序意外终止。

非常完美地解释了这一点

5.1.6缩小参考转换

这种转换需要在运行时进行测试,以确定实际引用值是否是新类型的合法值。如果不是,则抛出ClassCastException

i、 当你进行这样的转换时,你显式地将类型S转换为类型T。这样做你告诉编译器“我确信这是可以的”


如果您认为它可能会失败,那么您应该
尝试捕获
类CastException
并停止意外终止的程序。

您可以强制转换到任何子类型,但是如果类型不正确,JVM会在运行时对您大叫,当然,我在尝试从超类型转换为子类型时遇到了编译错误。谢谢@SotiriosDelimanolis,我会读到的。我不知道确切的术语(“向下转换”,等等)。@dimadima这很有意义,不?你可以转换到任何子类型,但是如果类型不正确,JVM会在运行时对你大喊大叫,当然,我在尝试从超类型转换到子类型时出现了编译错误。谢谢@SotiriosDelimanolis,我会读到这一点。我不知道确切的术语(“向下投射”,等等)。@dimadima这是有意义的,不是吗?我想这可能是规范中一个常见的要求/期望的特性,但如果您正在寻找类型安全性,它似乎是一个糟糕的形式?@dimadima并非所有类型安全信息都可以在编译时推断出来。强制转换是开发人员在运行时执行某些操作的显式请求。超级类型的实现甚至可能不在您的代码中,就像在servlet规范中一样。有时API也无法更改参数中的类型以保持向后兼容性。因此,Java作者必须使用额外的方法创建新的子类型,这些方法保证始终作为向下转换工作。例如,在Java Swing中,
Graphics
对象总是可以向下转换为
Graphics2D
@dkatzel,谢谢。这是我提出的“为什么”问题的一个很好的例子。这里的答案是“JLS几乎完美地解释了它。”我不知道为什么描述行为意味着它被完美地解释了。事实上,这是唯一一个能真正解释为什么的例子。@dimadima“为什么这个cast有效?”:JLS指定允许它(根据我答案中的细节)。“编译器为什么允许这样做?”:因为它遵守/强制执行JLS。也许你的第三个“为什么”是“为什么JLS允许NRC引起CCE”:简单的回答是,它是设计的方式;如果没有这些功能,语言中的许多功能将需要重新设计。我想这将是规范中常见的要求/期望的功能,但如果您正在寻找类型安全性,它似乎是糟糕的形式?@dimadima并非所有类型安全信息都可以在编译时推断出来。强制转换是开发人员在运行时执行某些操作的显式请求。超级类型的实现甚至可能不在您的代码中,就像在servlet规范中一样。有时API也无法更改参数中的类型以保持向后兼容性。因此,Java作者必须使用额外的方法创建新的子类型,这些方法保证始终作为向下转换工作。例如,在Java Swing中,
Graphics
对象总是可以向下转换为
Graphics2D
@dkatzel,谢谢。这是我提出的“为什么”问题的一个很好的例子。这里的答案是“JLS几乎完美地解释了它。”我不知道为什么描述行为意味着它被完美地解释了。事实上,这是唯一一个能真正解释为什么的例子。@dimadima“为什么这个cast有效?”:JLS指定允许它(根据我答案中的细节)。“编译器为什么允许这样做?”:因为它遵守/强制执行JLS。也许你的第三个“为什么”是“为什么JLS允许NRC引起CCE”:简单的回答是,它是设计的方式;如果没有这些功能,该语言中的许多功能将需要重新设计。
Vertex v = (Vertex) e; // `e` is an `Element`