java - Java 中原始类型的子类型化

标签 java primitive jls subtype subtyping

我在大学类里面关于子类型关系的笔记中有这样的声明:

T is a subtype of S if code written for variables of type S can also be safely used on variables of type T


Java Language Spec 的第 4.10.1 节, 描述了 Java 中原始类型之间的子类型关系。特别是,我使用的事实是 int <: longintlong 的子类型根据 JLS。
所以如果 intlong 的子类型,然后是为 long 类型的变量编写的代码也可以安全地用于 int 类型的变量.
如果我有一段代码,这对我来说没有意义
long x = 2e63 - 1
然后通过上面的语句,我可以使用
int x = 2e63 - 1
这显然会导致溢出。
在我看来,语句的第二部分应该颠倒过来,即“如果为 T 类型的变量编写的代码可以安全地用于 S 类型的变量,T 是 S 的子类型”。但是,在我寻找答案的过程中,似乎在其他地方的其他类(class)笔记中重复了这一陈述。我只是误解了吗?也许我给出的例子不是该语句的有效案例?

最佳答案

So if int is a subtype of long, then code written for variables of type long can also be safely used on variables of type int.


好的...我可以看出这是子类型的有效表征。
然而,这并不是 JLS 实际指定和使用子类型关系 <: 的方式。 .在 JLS 中,子类型主要是关于值的使用方式。
因此,例如,int <: long ( intlong 的子类型)意味着 int value 可以在需要 long 的上下文中使用值(value)。
这里有些例子:
 int i = 1;
 long l = i;            // OK - int used where a long is needed
 long ll = i + 1L;      // OK - int used where a long is needed

 public void methodWithLongArg(long arg) { ... }

 methodWithLongArg(i);  // OK - int used where a long is needed
请注意,在上面的每一个中,JLS 都表示使用原始扩展转换来转换 int值到 long值(value)。
那么你的例子呢:
long x = 2e63 - 1;   // NOT OK
int i = 2e63 - 1;    // NOT OK
事实上,这些都不是合法的 Java。文字 2e63实际上是一个(双)浮点文字。 (所有使用 eE 表示法的文字都是浮点数,无论文字中是否有明确的小数点。没有 fF 后缀的浮点文字表示 double 值。 ) 所以 2e63 - 1计算结果为 double和一个 double不能分配给 long (或 int )除非你明确地转换它。
这与子类型一致。 JLS 规则意味着 long <: double .所以这意味着 long可以在需要 double 的上下文中使用.但是在上面,我们需要一个 double在需要 long 的上下文中使用(或 int)。这就是 对面子类型关系允许的内容。
事实上,你的例子还有另一个问题。 263 写成(十进制)为 9223372036854775808L .并且只有在它前面有一个一元减号运算符时才能使用它。同样,它也不能表达为 long Java 二进制、八进制或十六进制文字语法中的文字。

我认为真正的问题是你误解了你的讲师所说的话。
他实际上是说代码为父类(super class)型编写的可以应用于子类型的值。
所以,在我的例子中,methodWithLongArg(long arg)方法是为父类(super class)型编写的代码;即 long .它可以在子类型的值上使用(调用);即 int 的值多变的。

Am I simply misunderstanding it? Maybe the example I gave is not a valid case of the statement?


基本上,是的。海事组织。

关于java - Java 中原始类型的子类型化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65715716/

相关文章:

java - 如何使用poi从excel表中检索百分比类型的值

java - 如何在 Java 中暂停 Swing?

c# - 覆盖 Json.Net 中的默认基元类型处理

java - 在原始流上使用收集器

java - 通过反射获取 Java 字段,而不是通过其 String 名称

java - double 和 long 的非原子处理

java.lang.IllegalAccessError : tried to access method android. 部件.LinearLayout

java - Java 语言规范示例 8.1.2-1(相互递归类型变量边界)

Java "fresh type variable"

java.net.ProtocolException : content-length promised 16280 bytes, 但收到 16272