作为 Java 新手,我对class和type的概念感到困惑。例如,对象应该"Hello World!"
属于类型 String
还是类 String
?或者两者兼而有之?
6 回答
类是一种类型。接口是一种类型。原语是一种类型。数组是一种类型。
因此,每种类型也可以是类(包括枚举常量)、接口、基元或数组。
有两种不同的类型:原始类型和引用类型:
- 原始类型的变量始终保存相同类型的原始值。这样的值只能通过对该变量的赋值操作来更改。
- 引用类型的变量始终保存对对象的引用的值。所有对象,包括数组,都支持 class 的方法
Object
。引用类型是类类型(包括枚举类型)、接口类型和数组类型。
每条数据都有一个类型来定义它的结构,即它占用了多少内存,它是如何布局的,更重要的是,你如何与之交互。
原始类型的示例:
int
float
char
boolean
类类型示例:
接口类型示例:
数组类型示例:
int[]
String[]
Integer[][][]
基本上,任何可以称为变量的东西都有一个类型,而类是一种类型。
更多信息在这里:http ://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html
TLDR - 类是 Java 中的类型之一。
注意 - 要完全理解答案,您必须对 Java 中的泛型有一点了解。
要了解区别,让我们首先了解 Java 中的Type是什么。
根据JLS SE 10,
Java 编程语言中 有两种类型:原始类型(§4.2)和引用类型(§4.3)。
什么是原始类型?
a) 整数类型为byte、short、int 和 long,其值分别为 8 位、16 位、32 位和 64 位有符号二进制补码整数,以及char,其值为 16 位表示 UTF-16 代码单元的无符号整数(第 3.1 节)。
b) 浮点类型为float,其值包括 32 位 IEEE 754 浮点数和double,其值包括 64 位 IEEE 754 浮点数。
c) boolean类型正好有两个值:true 和 false。
现在,让我们来看看什么是引用类型?
让我们一一讨论。
如果您在 JLS 中看到,Class是这样定义的:
类声明指定一个新的命名引用类型。
有两种类声明:普通类声明和枚举声明。
ClassDeclaration:
NormalClassDeclaration
EnumDeclaration
NormalClassDeclaration:
{ClassModifier} class TypeIdentifier [TypeParameters] [Superclass] [Superinterfaces] ClassBody
你看[TypeParameters]
,这表明类类型也包括那些泛型类。
class Example<T>{
}
类类型将被调用Example
简而言之,一个类类型涵盖了我们的枚举、我们的常规(非泛型)类String
等以及我们的泛型类。
同样,我希望接口和数组类型也清楚。通过数组类型,我们的意思是 likeint[]
等String[]
。
让我们来到最后一部分——类型变量。这些是什么 ?
类型变量是在类、接口、方法和构造函数主体中用作类型的非限定标识符。
让我们通过下面 JLS 中的示例来了解它。
class Test {
<T extends C & I> void test(T t) {
t.mI(); // OK
t.mCPublic(); // OK
t.mCProtected(); // OK
t.mCPackage(); // OK
}
}
你看到你的方法参数中的对象是类型T
。是的,这T
是类型变量并且是/可以用作参考。是的。(无法理解这个奇怪的例子 - Learn what is generic method in Java)
这完成了答案。
“类型”是更具包容性的类别。Java 中的变量可以有三种类型:8 种“原始”类型,如 int 和 float、接口和类。值(相对于变量)可以是原始实例或类实例。
“类型”定义“它是什么类型的数据”
例如:"hello world" 是 String --> "hello world" 是 String 类型(String 与 int 不同,不是前导数据 .. 所以我们可以说 "hello world" 是字符串类类型)
10 是 int --> 10 是整数数据类型。
这是一个关于编程术语的问题,正如预期的那样,还有另一个可以被认为是有效的答案。
Java 类型系统,正如反射 API 所公开的,有两种类型:Class<T>
类和Type
接口,前者实现。在该系统中,类(由 的实例描述的元素Class<T>
)是使用关键字class
or创建的任何类型interface
、任何原始类型、其任何数组和void
。其他一切都只是一个Type
.
那么其他的一切是什么?虽然在此上下文中的类是运行时在考虑对象的功能时可以看到和可以访问的所有内容,但类型通常是编译器看到的所有内容。这可以是参数化类型(比如ArrayList<String>
——记住类型擦除会导致每个ArrayList<T>
在运行时映射到同一个类)、作为方法或类声明的一部分创建的泛型类型参数、通配符类型及其任何数组。这些类型在类型擦除无效的所有地方都由 API 方法公开,例如在遍历参数类型或基类型时。
类型与变量和表达式等编译时实体相关联,而类与内存中对象等运行时实体相关联。考虑规范15.5 中使用的语言。表达式和运行时检查
如果表达式的类型是引用类型,那么被引用对象的类... 类型是引用类型的表达式可以通过测试
instanceof
来找出对象的类是否被运行时值所引用表达方式...
Robert Harper,Practical Foundations for Programming Languages的作者,做了以下区分
我确实认为将可能附加到对象的类与静态分类器的类型区分开来很重要
Java 泛型是与此区别相关的一个示例。首先考虑以下代码段
String greeting = "Hello" + " " + "world!";
- 变量的编译时类型
greeting
是String
- 表达式的编译时类型
"Hello" + " " + "world!"
是String
Hello world!
变量引用的实例化对象的运行时类greetings
是String
在上述情况下,区别似乎并不重要,但是让我们在以下代码段上尝试类似的推理
List<String> greetings = List.of("Hello World!");
- 变量的编译时类型
greetings
是List<String>
- 表达式的编译时类型
new ArrayList("Hello World!")
是List<String>
- 变量引用的实例化对象的运行时类
greetings
是ImmutableCollections$List1
List<String>
现在我们看到 type和 class之间确实存在差异ImmutableCollections$List1
。我们看到编译时类型在编译器知道元素类型的信息中“更丰富”,String
而在运行时元素类型信息由于类型擦除而丢失。
这是类型和类之间区别的另一个演示
jshell> /set feedback verbose
| Feedback mode: verbose
jshell> List.of("Hi", "Hello")
$1 ==> [Hi, Hello]
| created scratch variable $1 : List<String>
jshell> List.of(42, -11)
$2 ==> [42, -11]
| created scratch variable $2 : List<Integer>
jshell> $1.getClass() == $2.getClass()
$3 ==> true
| created scratch variable $3 : boolean
注意表达式的类型List.of("Hi", "Hello")
和List.of(42, -11)
是不同的,但对应的实例化对象的类是相同的。