引言
Java作为一种静态类型语言,每个变量和表达式都具有在编译时就确定的类型。
Java还是一种强类型语言,类型限制了变量可以持有的值和表达式可以产生的值,限定了在这些值上可以进行的操作,并且确定了这些操作的含义。强类型机制有助于在编译时探测错误。
类型、变量、对象、引用、实例,这些在java编程中经常遇到的概念并非晦涩难懂,但真正让一些开发者说出来它们的概念时,还是会模糊不清。这篇文章就从定义上明确这些概念,并结合简短的代码示例加以解释,希望读完这篇文章,上面说的那些概念都能清晰明确地呈现在我们的脑海中。
简单类型和引用类型
一切概念都要从java中的类型开始,类型是后面所有概念的基础。
Java语言中的类型可以分为两类:简单类型和引用类型。简单类型包括boolean类型和数字类型,其中数字类型包括整数类型byte、short、char、int和long以及浮点数类型float和double。引用类型包括类类型、接口类型和数组类型,另外还有一个特殊的空类型。
如果只是为了做出区分而将类型分为两种,那是没有什么意义的。简单类型和引用类型作为具有明显界限的两种类型,是有很多区别的,特别是在值的定义上。
变量和值
简单类型和引用类型分别对应简单值和引用值,它们是被存储在变量中的。也就是说,变量可以持有值,不管是简单类型值还是引用类型值。看下面的代码:
public class TypeTest {
public int i = 12;
public SimpleObject simpleObject = new SimpleObject();
}
这里的i和simpleObject就是变量,从对象内存布局的角度来看,当我使用new创建一个TypeTest的实例后,这个TypeTest对象被分配在堆上,i和simpleObject这两个变量就在这个对象的实例数据部分,而i和simpleObject不同的是,在实例数据部分中的i,持有的就是12这个简单类型的数字值,而simpleObject持有的只是一个引用,这个引用指向堆上的SimpleObject对象,所以,这就是简单类型变量持有的值和引用类型的变量持有的值的区别,对于简单类型,变量持有的是直接就是数字值,对于引用类型,变量持有的是对对象的引用。或者你可以这样来理解:简单类型值就是数字值本身,引用类型值是对对象的引用,它们被变量持有。
再看下面的例子:
public static void main(String[] args) {
int i = 12;
SimpleObject simpleObject = new SimpleObject();
}
在main方法中,有两个变量i和simpleObject,它们在方法栈上,对于i来说,栈上的这个变量值就是12,而对于引用类型simpleObject来说,栈上的变量持有的是一个引用值,SimpleObject对象在堆上被创建,栈上的引用指向这个堆上的对象。
而变量可以简单的理解一个存储位置。《java语言规范》中对简单类型有这样的描述:
简单类型的变量总是持有简单值,其类型与该简单类型精确匹配。
类类型T的变量可以持有空引用,或者是对T类一个T的任意子类的实例的引用。
接口类型的变量可以持有空引用,或者是对实现了该接口的任意类的实例的引用。
对象和实例
上面已经涉及到了对象和实例的概念,这里给出明确的定义:
对象是动态创建出来的类类型的实例或者动态创建的数组。注意是类类型的实例或者数组,所有基本数据类型是没有对象和实例的概念的。引用类型有对象的概念,才会使引用类型值是对对象的引用有了成立的前提。
小结
有了上述这些概念作为前提,才能理解java语言中的很多其他东西。之后,我们讲解简单类型对应的包装类型,包装类型就是一种引用类型了。