对象

用引用操作对象

每种编程语言都有自己的操纵内存中元素的方式。有时候,程序员必须注意将要处理的数据是什么类型。你是直接操纵元素。还是用某种语法操纵元素。

在Java中一切都被视为对象,因此可以使用一种固定的语法来操纵元素。虽然一切都被视为对象但实际操作的是对象的一个引用(reference)。可以将这一情形想象成遥控(引用)来操纵电视机(对象),只要保持电视与遥控的链接,不管你需要对电视进行什么操作,实际上都是操作的遥控器,而你也可以在屋中四处走动同时仍能操作电视,而你只需要携带一个遥控,而不是电视。

此外,即使没有电视遥控器仍然能独立存在,也就是说你可以拥有一个引用,并不一定需要有一个对象与他相关联。

例如 String s;

这里只是创建了一个引用,并不是对象,如果此时向s发送一个消息(调用方法),就会返回一个运行时错误,这是因为s实际上没有与任何事物相关联(即,没有电视)。因此一种安全的做法是:创建一个引用的同时便初始化。

String s=”asdf”;

这里用到了一个Java语言的一个特性:字符串可以用带引号的文本初始化。而通常必须对对象采用一种更通用的初始化方法(new);

必须由你创建所有对象

一但引用被创建,就会希望他能与一个对象相关联。通常用new操作符来实现这一目的。new 关键字的意思是“给我一个新对象”。

String s=new String(“asdf”);

他不仅表示“给我一个新的字符串”,而且通过提供一个初始字符串,给出了怎样产生这个String的信息。

对象被储存到什么地方

程序运行时,对象是怎么安排放置的的?内存又是怎样分配的?有五个不同的地方可以储存数据:

1, 寄存器:这是最快的的存储区,它位于处理器内部,但是寄存器的数量极其有限,所以寄存器根据需求进行分配。你不能直接控制,也不能在程序中感觉到寄存器的存在。

2, 堆栈:位于通用RAM(随机访问存储器)中,但通过堆栈指针可以从处理器哪里获得直接支持。堆栈指针若是向下移动,则分配新的内存;若向上移动,则删除那些内存。这是一种快速有效的分配存储方法,仅次于寄存器。创建程序时,Java系统必须知道存储在战队内所有项目多的确切生命周期,以便上下移动堆栈指针。这一约束限制了程序的灵活性,所以虽然某些Java数据存储在堆栈中----特别是对象引用。但是Java对象并不存储于其中。

3, 堆:一种通用的内存池(也位于RAM区),用于存放所有的Java对象。堆不同于堆栈的好处是:编译器不需要知道存储的数据在堆里存活多上时间。因此,在堆里分配存储有很大的灵活性。当需要一个对象时,只需要用new写一行简单的代码,当执行这行代码时,会自动在堆里进行存储分配。但是这种灵活性必须要付出代价:用堆进行存储分配和清理可能比用栈进行存储分配需要更多的时间。

4, 常量存储:常量值通常直接存储在程序代码内部,这样做是安全的,因为它们永远不会被改变。有时,在嵌入式系统中,常量本身会和其他部分隔离开,所以在这种情况下,可以选择将其放在ROM只读存储器中。

5, 非RAM存储:如果数据完全存活于程序之外,那么它可以不受程序的任何控制,在程序没有运行的时候也可以存在。其中两个基本的例子是流对象和持久化对象。在流对象中,对象转化成字节流,通常被发给另一台机器。在“持久化对象”中,对象被存放在硬盘中。因此即便程序终止它们仍可以保持自己的状态。

基本类型

在程序中有一系列经常用到的类型,它们需要特殊对待,因为new将对象存储在“堆”里,故用 new创建一个对象,特别是简单的很小的对象,往往不是很有效率。因此对于这些对象Java把他们称之为基本类型,它们不需要new来创建,而是创建一个并非是引用的“自动”变量。这个变量直接存储“值”,并置于堆栈中,因此更加高效。

Java要确定每种基本类型所占存储空间的大小。正是这种占存储空间大小不变性是Java程序比用其他大多数语言编写的程序更具可移植性的原因之一。

基本类型   大小      最小值        最大值               包装容器类型

boolean   -          -               -                      Boolean

char        16-bit   Unicode 0  Unicode 2(16)-1 Character

byte        9 bits    -128        +127                 Byte

short      16 bits   -2(15)      +2(15)-1           Short

int          32 bits   -2(31)      +2(31)-1           Integer

long        64 bits   -2(63)      +2(63)-1           Long

float        32 bits   IEEE754    IEEE754           Float

double     64 bits   IEEE754    IEEE754           Double

void         -           -              -                      Void

括号内数字代表乘方

所有数值类型都有正负号。

boolean类型所占存储空间的大小没有明确指定,仅定义为能够取字面值true或false.

基本数值都有其包装类,使得可以在堆中创建一个基本对象,用来表示基本数据类型

char x=’c’;

Character ch=new Character(‘x’);

Java SE5能自动的将基本类转化为包装类

Character ch=’x’;

也可反向操作

char x=ch;

高精度数字

Java中提供了两个用于高精度计算的类:BigInteger和BigDecimal,这两种包装类是不存在基本类型与其对应的。

这两个包装类提供的方法与基本类型所能执行的操作相似,也就是说可以执行类似int,float的操作。用调用方法的方式来取代运算符运算来实现,这么做运算速度会比较慢,而相对的精度会提高。

BigInteger支持任意精度的整数,也就是说运算中可以表示任何大小的整数值而不会丢失

BigDecimal则支持任何精度的定点数,例如可以进行精确的货币计算。

不需要销毁对象

大多数程序设计语句需要程序员时刻监视变量,销毁变量。而Java却可以帮助我们完成所有清理工作

作用域

大多数过程语言都有作用域(scope)的概念。作用域决定了在其内定义的变量名的可见性和生命周期,在Java中,作用域由花括号位置决定例如

{

int x=12;

//只能使用x

{

int q=96;

//x和q都可以使用

}

//只可以使用x

//q的作用域外

}

在作用域里定义的变量只可用于作用域结束之前

缩排格式使Java代码更易阅读。由于Java是一种自由格式(free-form)的语言,所以,空格,制表符,换行都不会影响程序的执行结果。

Java中不允许这样的语法

{

int x=12;

{

int x=96;

}

}

编译器将会报告x已经被定义过。

对象的作用域

Java对象不具备和基本数据类型一样的生命周期,当用new创建一个对象的时候,他可以存活于作用域之外。

{

String s=new String(“a string”);

//作用域终点

}

引用s在作用域终点就消失了。然而,s指向的String对象仍继续占据内存空间。在这一段小代码中,我们无法在这个作用于之后访问这个对象,因为对他唯一的引用已经超出作用域范围。但实际在程序的执行中,是可以传递和复制对象引用的

所以实际上,由new创建出的对象,只要你需要就会一直保留下去。那么Java又是靠什么才能防止这些对象填满内存空间呢?Java特有一个垃圾回收机制(GC),用来监视用new创建的所有对象,并辨别哪些不再被引用的对象。随后便释放这些内存空间。

posted on 2011-02-20 22:40  柠檬哥  阅读(263)  评论(0编辑  收藏  举报

导航