Java 的类型
Java对于程序员来说, 是简单优美的. 程序员可以很好的实践,实现OO的思想,设计.我们学语言的时候第一个开始学的就是类型. 我接触Java语言应该是很久了, 最近才开始用心的学习, 仔细的研究. 学习就应该经常总结, 自己感觉写点东西可以让自己理解的更深,记的更牢. 发布出来, 也多些和大家多交流的机会. 请大家多指教, 我的email是: Justin@ipedo.com . 有兴趣的朋友请和我发email交流.
Java类型总的来说就两种, 基本(Primitive)类型和对象.
Primitive类型包括int, long, byte, char, short, double, float, boolean. 这些类型都是放在Stack里面的. 学习过c/c++的朋友可以和c/c++里面一样用他们. 但是和c/c++里面不一样的是你无法得到他们的地址, 或者说索引(reference). 所以一个基本类型在有效范围外就会被释放. 看下面的代码:
class TestPrimitive {
public static void ShowPrimitive() {
int i = 1;
System.out.println( “The integer is:” + i );
}
public static void main(String[] args) {
ShowPrimitive();
}
}
上面代码中的i是在Stack中分配, 在ShowPrimitive(可以看作i的作用域)代码执行完毕后, i就会从Stack中清除. 你不能从Heap中分配一个基本类型, 除非他本身是一个对象的成员变量. 而c/c++就不同, 只要用new就可以在Heap中分配任何类型.
在.NET中可以分配在Stack中的类型要多一种Struct .
另外一点, 在c/c++中如果不对int等类型的变量赋值的话, 哪这个变量可能是任何值, 而Java对一个基本类型的变量会赋值一个初始化的值, int, long的类型是0, float, double是0.0, boolean是false.
有人说Java里没有对象, 全部是指针. 这个观点有一定的道理. 和基本类型相反, 你不可能在一个Stack中分配一个对象, 只能通过new(或者其它隐含的方法调用构造方法)在Heap中分配一个对象. 而我们每定义一个对象, 如下面代码:
Object ob = new Object();
我们通过new Object()创建一个Object对象, 而我们实际得到的ob是一个对象引用(Object Reference), 这个对象引用指向Heap中的对象实体. 我们也可以把Object reference当作是一个基本类型, 它在Stack中存在, 也和其它基本类型一样, 在作用域的代码执行完成后就会直接从Stack清除. 但是它实际指向的Heap中的对象依然在Heap中存在. 如果没有任何其它的Object reference指向这个对象的时候, 当Java虚拟机调用垃圾收集代码(Garbage Collection)的时候, 就会被从堆中清除掉.
同样, Java也会对每一个定义的对象索引赋初始值为null. 从这一点我们也可以看出我们所以定义的对象和c++中不同, 可以全部对应于指针, 而没有非指针对应的对象变量存在.
每一个基本类型都对应一种对象-外包类(Wrapper Class). 所有的基本类型Java都有对应的外包类, 即对象类型的int, float等.具体的对应表格抄录如下:
int
Integer
long
Long
short
Short
byte
Byte
char
Character
float
Float
double
Double
boolean
Boolean
基本类型和对象最大的不同除了所处的内存区域不同之外就是对象可以使用点操作符, 而基本类型不可以. 大家看一下的代码:
int i = 10;
Integer integ = new Integer(10);
System.out.println( i.toString() ); // 错误代码
System.out.println( integ.toString() ); // 正确代码
对象有自己的方法(Method)和成员变量(Member), 而基本类型没有, 所以对基本类型变量i调用.toString是错误的, 虽然在语义上i和integ都代表一个值为10的整数.
基本类型最大的优点就是在Stack中分配内存, 速度当然比在Heap中快, 而且节约内存.所以在使用大量的数值类型的时候建议使用基本类型而非对象. 让我们看下一段代码, 以便有个感性认识:
public class FreeMem {
public static void main(String[] args){
long first = Runtime.getRuntime().freeMemory();
int[] ar = new int[1000];
for( int i=0; i<1000; i++ )
ar[i] = i;
long second = Runtime.getRuntime().freeMemory();
System.out.println( first - second );
Integer[] ar2 = new Integer[1000];
for( int i=0; i< 1000; i++ )
ar2[i] = new Integer(i);
long third = Runtime.getRuntime().freeMemory();
System.out.println( second - third );
}
}
下面是我得到的结果:
4016
20848
可以明显的看到使用基本类型比使用对象耗费的内存要少的多. 所以能用到基本类型的地方要尽量使用基本类型, 以节省内存, 增加代码执行速度.
就像我们都是炎黄子孙一样, Java所有的对象都有一样的祖宗-Object. 这就是Java的单根结构. 很多C++类库(或其它面向对象语言的类库)都采用了单根结构, 比如MFC的CObject, VCL的TObject, 但是Java从语言本身保证了这一点. 使用MFC你完全可以定义一个类不是从CObject继承而来, 但在Java中你如果定义一个类不从任何类继承, 那么它就缺省继承自Object类. 单根结构为一些工具类的开发提供了很好的特性. 比如一些集群类: Vector, HashMap等, 在设计的时候根本无法知道它们要容纳什么样的数据. C++使用template来完成这个特性, 而Java在语言级别上未实现template, 但由于所有的Java对象都继承自Object, 集群类只要容纳Object类就可以了.