Java 中任何对象的编译时类型与运行时类型有什么区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14963943/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 18:01:56  来源:igfitidea点击:

What is the difference between a compile time type vs run time type for any object in Java?

javagenericseffective-java

提问by Geek

What is the difference between compile time and run time type of any object in Java ? I am reading Effective Javabook and Joshua Bloch mentions about compile time type and run time types of array instances in Item 26 many times mainly to describe that suppressing cast warnings can be safe sometimes.

Java 中任何对象的编译时和运行时类型有什么区别?我正在阅读Effective Java书籍,Joshua Bloch 在 Item 26 中多次提到数组实例的编译时类型和运行时类型,主要是为了描述有时抑制强制转换警告是安全的。

// Appropriate suppression of unchecked warning
public E pop() {
 if (size == 0)
   throw new EmptyStackException();
   // push requires elements to be of type E, so cast is correct
   @SuppressWarnings("unchecked") E result = (E) elements[--size];
   elements[size] = null; // Eliminate obsolete reference
   return result;
}

Here the author is talking about these different types of typesin context of arrays . But through this question I would like to understand the difference between compile time typesvs run time typesfor any type of object .

在这里,作者正在谈论types数组上下文中的这些不同类型。但是通过这个问题,我想了解任何类型对象的compile time typesvs之间的区别run time types

回答by Antimony

Java is a statically typed language, so the compiler will attempt to determine the types of everything and make sure that everything is type safe. Unfortunately static type inference is inherently limited. The compiler has to be conservative, and is also unable to see runtime information. Therefore, it will be unable to prove that certain code is typesafe, even if it really is.

Java 是一种静态类型语言,因此编译器将尝试确定所有内容的类型并确保所有内容都是类型安全的。不幸的是,静态类型推断本质上是有限的。编译器必须保守,也无法看到运行时信息。因此,它无法证明某些代码是类型安全的,即使它确实是。

The run time type refers to the actual type of the variable at runtime. As the programmer, you hopefully know this better than the compiler, so you can suppress warnings when you know that it is safe to do so.

运行时类型是指运行时变量的实际类型。作为程序员,您希望比编译器更了解这一点,因此当您知道这样做是安全的时,您可以抑制警告。

For example, consider the following code (which will not compile)

例如,考虑以下代码(不会编译)

public class typetest{
    public static void main(String[] args){
        Object x = args;
        String[] y = x;

        System.out.println(y[0])
    }
}

The variable xwill always have type String[], but the compiler isn't able to figure this out. Therefore, you need an explicit cast when assigning it to y.

该变量x将始终具有 type String[],但编译器无法弄清楚这一点。因此,在将其分配给y.

回答by newacct

Java is statically typed. That means that every expression (including variables) in the language has a type that is known at compile time according to the rules of the language. This is known as the static type (what you call "compile-time type"). The types in Java are the primitive types and the reference types.

Java 是静态类型的。这意味着语言中的每个表达式(包括变量)都有一个根据语言规则在编译时已知的类型。这称为静态类型(您称之为“编译时类型”)。Java 中的类型是原始类型和引用类型。

Also, each object at runtime in Java has a "class" (here, "class" includes the fictitious array "classes"), which is known at runtime. The class of an object is the class that an object was created with.

此外,Java 中的每个对象在运行时都有一个“类”(这里,“类”包括虚构的数组“类”),它在运行时是已知的。对象的类是创建对象时使用的类。

Part of the confusion comes from the fact that each class (and interface and array type) in Java has a corresponding reference type, with the name of the class (or interface or array type). The value of a reference type is a reference, which can either be nullor point to an object. The Java language is designed so that a reference of reference typeX, if not nullwill always point to an object whose class is the classX or a subclass thereof (or for interfaces, whose class implements the interfaceX).

部分混淆来自这样一个事实,即 Java 中的每个类(以及接口和数组类型)都有一个对应的引用类型,带有类的名称(或接口或数组类型)。引用类型的值是一个引用,它可以是null或指向一个对象。Java 语言被设计成引用类型引用X(如果不是)null将始终指向类是X 或其子类(或对于接口,其类实现接口X)的对象。

Note that the runtime class applies objects, but objects are not values in Java. Types, on the other hand, apply to variables and expressions, which are compile-time concepts. A variable or expression can never have the value of an object, because there are no object types; it can have a value of a reference that points to an object.

请注意,运行时类应用对象,但对象不是 Java 中的值。另一方面,类型适用于变量和表达式,它们是编译时概念。变量或表达式永远不能有对象的值,因为没有对象类型;它可以具有指向对象的引用值。

回答by blue_note

Simple

简单的

Number x;

if (userInput.equals("integer")) {
    x = new Integer(5);
} else {
    x = new Float(3.14);
}

There are two typesrelated to x

两种相关的类型x

  • the type of the namex. In the example, it's Number. This is determined at compile-timeand can never change, hence it's the static type
  • the type of the valuexrefers to. In the example, it can be Integeror Float, depending on some external condition. The compiler cannot know the type at compilation time. It is determined at runtime (hence dynamic type), and may change multiple times, as long as it's a subclass of the static type.
  • 名称的类型x。在示例中,它是Number. 这是在编译时确定的,永远不会改变,因此它是静态类型
  • 的类型x所指。在示例中,它可以是IntegerFloat,具体取决于某些外部条件。编译器在编译时无法知道类型。它是在运行时确定的(因此是动态类型),并且可以多次更改,只要它是静态类型的子类。

回答by arcy

I think of "compile time type" as ANY type a variable can be shown to have at compile time. That would include the declared class, any superclasses, and any implemented interfaces.

我认为“编译时类型”是在编译时可以显示变量的任何类型。这将包括声明的类、任何超类和任何实现的接口。

At runtime, a given object only has one lowest-level class; it can legally be cast to or assigned to a variable of that class, but also to any variable of any of its subclasses or implemented interfaces. The compilerwill (often, anyway) allow you to cast it to anything, but the runtime will throw an exception if you attempt to assign something that is not legal.

在运行时,给定的对象只有一个最低级别的类;它可以合法地强制转换或分配给该类的变量,也可以分配给其任何子类或实现的接口的任何变量。该编译器会(通常是这样),您可以将其转换为任何东西,但如果你尝试给一些不合法运行时会抛出异常。

Once an object is assigned to the variable, then the compiler will treat it as though it is of the type of the variable. So another use of "compile time" could be the variable type, and you can get around that at compile time by casting to a different type as long as you know the cast will be legal at runtime.

一旦将对象分配给变量,编译器就会将其视为变量类型。因此,“编译时”的另一个用途可能是变量类型,您可以在编译时通过强制转换为不同的类型来解决这个问题,只要您知道强制转换在运行时是合法的。

If I speak of just one type, I think of the 'runtime type' of a variable as the actual bottom (top?) level subclass of the variable; the lowest sub-class to which it could be cast. But I also routinely think of any object as an instantiation of any of its legal types.

如果我只说一种类型,我认为变量的“运行时类型”是变量的实际底层(顶层?)子类;它可以投射到的最低子类。但我也经常将任何对象视为其任何合法类型的实例化。

Hope that helps.

希望有帮助。