简体   繁体   English

是否有可能在Java中运行时类型不匹配?

[英]Is it possible to have Runtime type mismatch in Java?

I am reading up OCaml and from wiki, it says: 我正在阅读OCaml和维基,它说:

*its static type system renders runtime type mismatches impossible*

I understand why, but then I think, why is this so special in OCaml (and FP)? 我理解为什么,但我认为,为什么这在OCaml(和FP)中如此特别? How do you cause a runtime type mismatch in, say, Java? 如何在Java中导致运行时类型不匹配? eg 例如

boolean a = true;
int b = a + 1;

will return an error in compile time. 将在编译时返回错误。

EDIT 1: 编辑1:

Haskell 哈斯克尔

func :: Int -> Bool
func i = if i > 0 then True else False

Java Java的

boolean func (int i) {
    if (i > 0) return true; else return false;
}

Isn;t it the case that both will guarantee the argument type when the func is called? 是不是这两种情况都会在调用func时保证参数类型?

In Java, you can cause a Runtime type mismatch like this: 在Java中,您可能导致运行时类型不匹配,如下所示:

Object i = Integer.valueOf(6);
String s = (String) i;   
System.out.println(s);

This will compile, because the compile-time type of i ( Object ) is allowed to be cast to String , however at Runtime, the actual value of i ( 6 , as Integer ) will be incompatible to String . 这将编译,因为允许将编译时类型的iObject )强制转换为String ,但是在运行时, i的实际值( 6 ,作为Integer )将与String不兼容。

Given this, a ClassCastException is thrown. 鉴于此, ClassCastException

Consider the following code using arrays: 请考虑使用数组的以下代码:

// 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 allows this to compile, despite the fact that casting a array of strings to an array of objects array introduces the possibility of run-time errors. Java允许这个编译,尽管将一个字符串数组转换为一个对象数组数组引入了运行时错误的可能性。 Line 8 demonstrates this, causing a run-time exception of a type created specifically for this situation: java.lang.ArrayStoreException: java.lang.Object . 第8行演示了这一点,导致了专门为这种情况创建的类型的运行时异常: java.lang.ArrayStoreException: java.lang.Object

See Java generics and type erasure 请参阅Java泛型并键入擦除

That wiki is discussing static type systems in general, and contrasting them with dynamically-typed languages rather than other statically-typed languages. 该wiki一般讨论静态类型系统,并将它们与动态类型语言进行对比,而不是与其他静态类型语言进行对比。 There's nothing specific to OCaml or Haskell about runtime type mismatches that doesn't apply to all statically-typed languages. OCaml或Haskell没有特定的关于运行时类型不匹配的内容,这些不匹配并不适用于所有静态类型的语言。

Note that impossible is a little disingenuous. 请注意, 不可能有点不诚实。 Pretty much all statically-typed languages give you the ability to also do runtime typing in a limited way, because certain tasks are extremely difficult without it. 几乎所有静态类型的语言都能让你以有限的方式进行运行时输入,因为如果没有它,某些任务就非常困难。 In fact, the very paragraph you're quoting lists a couple of those cases, like serialization. 实际上,您引用的段落列出了一些这样的情况,例如序列化。 Other answers here have provided some good examples in Java. 这里的其他答案在Java中提供了一些很好的例子。 However, the vast majority of your code should be able to easily avoid runtime type mismatches. 但是,绝大多数代码应该能够轻松避免运行时类型不匹配。

In Java, type mismatches are possible. 在Java中,类型不匹配是可能的。 For example, the following throws a ClassCastException . 例如,以下命令抛出ClassCastException

Object o = 1;
String s = (String) o;

However, the arguments passed to a method are checked by the compiler. 但是,传递给方法的参数由编译器检查。

It is impossible to invoke a method with signature 无法使用签名调用方法

boolean func (int i) 

unless i is an int , and it is impossible to invoke a method with signature 除非i是一个int ,并且不可能调用带签名的方法

boolean func2 (String s)

unless s is a String or null . 除非sStringnull

Therefore you will never get a ClassCastException at runtime within the body of func2 because s is not a String . 因此,在func2的主体内,您永远不会在运行时获得ClassCastException ,因为s不是String

In Java, it is impossible to have a type mismatch between reifiable types (primitive types, non-generic reference types, raw types, types parameterized by all wildcards, or array types whose element type is reifiable). 在Java中,不可能在可再现类型 (基本类型,非泛型引用类型,原始类型,所有通配符参数化的类型或其元素类型可重新生成的数组类型)之间存在类型不匹配。

If you have a variable of a reifiable type, then the value it holds at any point in time is guaranteed to be a value of that type. 如果您有一个可重新类型的变量,那么它在任何时间点保存的值都保证是该类型的值。 For reference types, this means that the reference is either null or points to an object whose runtime class is a subtype of the variable's type. 对于引用类型,这意味着引用为null或指向运行时类为变量类型的子类型的对象。 This is guaranteed because Java requires a cast when storing a value whose type is not a subtype of the variable's type, and casts to reifiable types are checked casts , which means they are checked at runtime, and if the type is not compatible it will throw an exception rather than let there be a type mismatch. 这是有保证的,因为Java在存储类型不是变量类型的子类型的值时需要强制转换,并且对可再现类型进行强制转换强制转换类型,这意味着它们在运行时被检查,如果类型不兼容,它将抛出一个例外,而不是让类型不匹配。

On the other hand, for non-reifiable types (eg parameterized types), it is possible to have a type mismatch (which is called "heap pollution" in Java terminology). 另一方面,对于不可再生类型 (例如参数化类型),可能存在类型不匹配(在Java术语中称为“堆污染”)。 This is because casts to non-reifiable types are unchecked casts . 这是因为对不可再生类型的强制转换未经检查的强制转换

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 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM