Java中任何对象的编译时间和运行时类型有什么区别?我正在阅读Effective Java书,Joshua Bloch多次提到项目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;
}
在这里,作者在数组的上下文中讨论了这些不同类型的types
。但是通过这个问题,我想了解compile time types
与run time types
之间对于任何类型对象的区别。
答案 0 :(得分:13)
Java是一种静态类型语言,因此编译器将尝试确定所有类型,并确保一切都是类型安全的。不幸的是,静态类型推断本质上是有限的。编译器必须保守,并且也无法查看运行时信息。因此,它无法证明某些代码是类型安全的,即使它确实存在。
运行时类型是指运行时变量的实际类型。作为程序员,您希望比编译器更好地了解这一点,因此当您知道这样做是安全的时候可以禁止警告。
例如,请考虑以下代码(不会编译)
public class typetest{
public static void main(String[] args){
Object x = args;
String[] y = x;
System.out.println(y[0])
}
}
变量x
将始终具有类型String[]
,但编译器无法解决此问题。因此,在将其分配给y
时需要显式强制转换。
答案 1 :(得分:1)
Java是静态类型的。这意味着语言中的每个表达式(包括变量)都具有在编译时根据语言规则已知的类型。这称为静态类型(您称之为“编译时类型”)。 Java中的类型是基本类型和引用类型。
此外,Java中运行时的每个对象都有一个“类”(这里,“class”包括虚构数组“classes”),这在运行时是已知的。对象的类是使用它创建对象的类。
部分混淆来自于Java中的每个类(以及接口和数组类型)都具有相应的引用类型,具有类的名称(或接口或数组类型)。引用类型的值是引用,可以是null
或指向对象。 Java语言的设计使得引用类型 X
的引用(如果不是null
)将始终指向其类为类的对象X或其子类(或接口,其类实现接口 X)。
请注意,运行时类应用对象,但对象不是Java中的值。另一方面,类型适用于变量和表达式,它们是编译时概念。变量或表达式永远不能具有对象的值,因为没有对象类型;它可以具有指向对象的引用值。
答案 2 :(得分:0)
我认为“编译时类型”是一个变量可以在编译时显示的任何类型。这将包括声明的类,任何超类和任何已实现的接口。
在运行时,给定对象只有一个最低级别的类;它可以合法地转换或分配给该类的变量,但也可以转换为任何子类或实现的接口的任何变量。 编译器将(通常,无论如何)允许您将其强制转换为任何内容,但如果您尝试分配不合法的内容,运行时将抛出异常。
将对象分配给变量后,编译器会将其视为变量类型。因此,“编译时”的另一个用法可能是变量类型,只要你知道演员在运行时是合法的,你就可以在编译时通过转换到另一种类型来解决这个问题。
如果我只提到一种类型,我认为变量的'运行时类型'是变量的实际底部(顶部?)级子类;它可以投射的最低子类。但我也经常将任何对象视为其任何合法类型的实例化。
希望有所帮助。
答案 3 :(得分:0)
简单
Number x;
if (userInput.equals("integer")) {
x = new Integer(5);
} else {
x = new Float(3.14);
}
与x
x
。在示例中,它是Number
。这是在编译时确定的,并且永远不会更改,因此它是静态类型 x
的类型。在示例中,根据某些外部条件,它可以是Integer
或Float
。编译器在编译时无法知道类型。它是在运行时确定的(因此为动态类型),并且可以多次更改,只要它是静态类型的子类即可。答案 4 :(得分:0)
Java数组被称为“协变量”,这意味着String []是Object []的子类型,并且在COMPILE时检查类型规则。
Java数组会在RUNTIME处检查您想存储到其中的对象(例如String,Integer,WhatEver)是否与实际创建的数组类型兼容。
例如:
String[] strings = new String[2];
strings[0] = "I am text";
Object[] objects = strings;
objects[1] = new Date(); // Compiles, but at runtime you get an ArrayStoreException