我在大学类里面关于子类型关系的笔记中有这样的声明:
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 <: long
即 int
是 long
的子类型根据 JLS。所以如果
int
是 long
的子类型,然后是为 long
类型的变量编写的代码也可以安全地用于 int
类型的变量.如果我有一段代码,这对我来说没有意义
long x = 2e63 - 1
然后通过上面的语句,我可以使用int x = 2e63 - 1
这显然会导致溢出。在我看来,语句的第二部分应该颠倒过来,即“如果为 T 类型的变量编写的代码可以安全地用于 S 类型的变量,T 是 S 的子类型”。但是,在我寻找答案的过程中,似乎在其他地方的其他类(class)笔记中重复了这一陈述。我只是误解了吗?也许我给出的例子不是该语句的有效案例?
最佳答案
So if
int
is a subtype oflong
, then code written for variables of typelong
can also be safely used on variables of typeint
.
好的...我可以看出这是子类型的有效表征。
然而,这并不是 JLS 实际指定和使用子类型关系
<:
的方式。 .在 JLS 中,子类型主要是关于值的使用方式。因此,例如,
int <: long
( int
是 long
的子类型)意味着 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
实际上是一个(双)浮点文字。 (所有使用 e
或 E
表示法的文字都是浮点数,无论文字中是否有明确的小数点。没有 f
或 F
后缀的浮点文字表示 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/