我正在阅读OCaml,并且从维基开始,它说:
*its static type system renders runtime type mismatches impossible*
我理解为什么,但我认为,为什么这在OCaml(和FP)中如此特别?如何在Java中导致运行时类型不匹配? e.g。
boolean a = true;
int b = a + 1;
将在编译时返回错误。
编辑1:
的Haskell
func :: Int -> Bool
func i = if i > 0 then True else False
爪哇
boolean func (int i) {
if (i > 0) return true; else return false;
}
是不是这两种情况都会在调用func
时保证参数类型?
答案 0 :(得分:3)
在Java中,您可能导致运行时类型不匹配,如下所示:
Object i = Integer.valueOf(6);
String s = (String) i;
System.out.println(s);
这将编译,因为允许将i
(Object
)的编译时类型强制转换为String
,但是在运行时,{{1}的实际值(i
,6
)与Integer
不兼容。
鉴于此,抛出String
。
答案 1 :(得分:3)
使用数组考虑以下代码:
// create an array of strings
String[] strings = new String[10];
// cast it to an array of objects
Object[] objects = strings;
// insert an object into the array
objects[0] = new Object(); // Run-time error occurs here
Java允许这个编译,尽管将一个字符串数组转换为一个对象数组数组引入了运行时错误的可能性。第8行演示了这一点,导致了专门为这种情况创建的类型的运行时异常:java.lang.ArrayStoreException: java.lang.Object
。
答案 2 :(得分:1)
该wiki正在讨论静态类型系统,并将它们与动态类型语言进行对比,而不是与其他静态类型语言进行对比。 OCaml或Haskell没有特定的关于运行时类型不匹配的内容,这些不匹配并不适用于所有静态类型的语言。
请注意不可能有点不诚实。几乎所有静态类型的语言都能让你以有限的方式进行运行时输入,因为如果没有它,某些任务就非常困难。实际上,您引用的段落列出了一些这样的情况,例如序列化。这里的其他答案在Java中提供了一些很好的例子。但是,绝大多数代码应该能够轻松避免运行时类型不匹配。
答案 3 :(得分:0)
在Java中,类型不匹配是可能的。例如,以下内容将引发ClassCastException
。
Object o = 1;
String s = (String) o;
但是,传递给方法的参数由编译器检查。
无法调用带签名的方法
boolean func (int i)
除非i
是int
,否则无法调用带签名的方法
boolean func2 (String s)
除非s
是String
或null
。
因此,ClassCastException
的正文中,您永远不会在func2
的正文中获得s
,因为String
不是{{1}}。
答案 4 :(得分:0)
在Java中, reifiable types (原始类型,非泛型引用类型,原始类型,所有通配符参数化的类型或元素类型为的数组类型)之间不可能存在类型不匹配reifiable)。
如果您有一个可再生类型的变量,那么它在任何时间点保存的值都保证是该类型的值。对于引用类型,这意味着引用为null或指向其运行时类是变量类型的子类型的对象。这是有保证的,因为Java在存储类型不是变量类型的子类型的值时需要强制转换,而对可再现类型的强制类型是 checked casts ,这意味着它们在运行时被检查,如果类型不兼容,它将抛出异常,而不是让类型不匹配。
另一方面,对于不可再生类型(例如参数化类型),可能存在类型不匹配(在Java术语中称为"堆污染" )。这是因为对不可再生类型的强制转换是未经检查的强制转换。
List<String> foo = new ArrayList<String>();
foo.add("hi");
List<?> bar = foo;
List<Integer> baz = (List<Integer>)bar; // unchecked cast
// now there is a type mismatch