第二章:一切都是对象

来源:互联网 发布:app 暂无数据图片素材 编辑:程序博客网 时间:2024/06/05 19:26

一切都是对象

用引用操作对象

  • 书中有一个很有趣的例子:遥控器(引用)操作电视机(对象)。我们拥有的是对象的引用,即遥控器。我们对对象的操作都是通过引用去操作的。如果我们想在房间里走走,同时还能操作电视机。那我们应该携带遥控器而不是电视机(简化)。此外,遥控器可以独立存在,也就是说你可以拥有一个引用,但并不一定有对象与它关联(这也是我们经常出现NPE异常的原因)。

必须由你创建所有对象

  • 一旦创建一个引用,就希望它能与一个对象关联。我们通常使用new操作符来实现这个目的。

存储到什么地方

  • 程序运行时,对象是如何安置的?内存是如何分配的?有五个地方可以存储数据:
    1. 寄存器。这是最快的存储区,因为它位于处理器内部。但数量有限,它会根据需求进行分配,且你不能直接控制。
    2. 堆栈。位于通用RAM(随机访问存储器)中,通过堆栈指针可以从处理器那里直接获得支持。创建程序时,java系统必须知道存储在堆栈内所有项的确切生命周期,以便分配或释放内存。这个约束限制了程序的灵活性(比如某个对象在某方法执行完毕后需不需要释放?很难搞清楚该对象有没有被其它方法引用。所以限制了程序的灵活性)。故对象并不存储在堆栈中(存的是引用)。
    3. 。一种通用的内存池(也是位于RAM),用于存放所有的java对象。堆不同于堆栈的好处是:编译器不需要知道存储的数据在堆里存活多长时间(释放内存有一套垃圾回收机制)。所以它有极大的灵活性,但是这也给内存分配和清理带来一定的处理时间。
    4. 常量存储。就是我们通常所说的常量池。
    5. 非RAM存储。如果数据完全存活在程序之外,那么它可以不受程序的任何控制,在程序没用运行时也可以存在。其中两个基本的例子是流对象(QQ网络聊天)和持久化对象(保存数据到磁盘)。

特例:基本类型

  • 在用new创建一个对象,若这个对象只是一个简单的变量,那这种方式往往不是特别有效率。因此,对于这些类型(通常称为基本类型),java不使用new来创建变量,而是创建一个并非是引用的“自动”变量(int a=1;)。这个变量直接存储“值”,并置于堆栈中,因此更加高效。
    这里写图片描述
  • Java SE5的自动包装功能能将基本类型转换为包装器类型,也可以反向转换。这个以后再详细讨论。下面是两个高精度类型(速度换精度):
    1. BigInteger:支持任何精度的整数。
    2. BigDecimal:支持任何精度的定点数。

Java中的数组

  • Java中的数组和C++中是有区别的。C++中的数组就是内存块。所以在C++中访问自身内存块之外的数据(别的内存块的随机值),或是在初始化之前访问内存(之前保留的随机值),都会产生难以预料的后果(括号里)。
  • Java则不同,如果不初始化直接访问会抛异常,并且自带范围检查(这种检查是有效率代价的)。
  • 创建了一个数组对象时(注意是创建不是声明),实际上就是创建了一个引用数组。每个引用对会自动被初始化为一个特定值,该值拥有自己的关键字null。在使用任何引用前,必须为其指定一个对象。
String []a = new String[10];System.out.println(a[0]);//nullString b;System.out.println(b);//编译不通过
  • 看上面的代码。我们创建了一个数组对象a,a[0]被初始化为null。如果我们想使用a[0],则得为其创建对象。而第三行代码只是声明了b引用,它就一个引用,没有对应的”电视机”(a[0]有对应的”电视机”:null),结果连编译都无法通过。
  • 当创建基本类型数组时,同样,编译器也能确保这种数组的初始化,因为它会将这种数组所占的内存全部置0。

永远不需要销毁对象

  • 变量生命周期的概念?变量需要存活多长时间?如果要销毁对象该何时进行?

作用域

  • 作用域(scope)决定了在其内定义的变量名的可见性生命周期。在C、C++和Java中,作用域由花括号的位置决定(JavaScript是以Function为作用域)。例如:
{    int x = 1;    {        int q = x + 2;//能够访问x    }//q的生命在此结束    x = q + 2;//q cannot be resolved to a variable}

对象的作用域

  • Java对象不具备和基本类型一样的生命周期。当new创建一个java对象时,它可以存活于作用域之外
{    String s = new String("a string");}//End of scope  此处只是s引用的生命周期结束,但是它指向的对象仍然占据内存空间。
  • 上面的代码的确无法在花括号外面再次引用对象实体,但是它的对象的确仍然占据内存空间(对象不可达,最终会被垃圾回收)。来看下面的例子:
StringBuffer p;{    StringBuffer p2 = new StringBuffer("123");    p = p2;//此时该对象被两个指针引用    System.out.println(p2.toString());    p2.append("456");}//p2的生命周期终止,但对象并不会终止。System.out.println(p);//可以通过p去引用这个对象实体

创建新的数据类型:类

字段和方法

  • 定义了一个类后,就可以在类中设置两种类型的元素:字段(也称为数据成员)和方法(成员函数)。字段可以是任何类型的对象,可以通过其引用与其进行通信,当然也可以是基本类型。由于创建对象时,必须为该对象分配已知大小的空间(声明是不占空间的),所以数据成员都必须进行初始化。如果不进行初始化,对象也会为其分配默认值(基本类型见下表,引用类型为null)。
    这里写图片描述
  • 但是如果是局部变量的话,在get前就必须赋值,否则会报错。

方法、参数和返回值

  • 方法的基本组成部分包括:名称参数返回值方法体方法名参数列表唯一的标识出了某个方法。通过对象调用方法的行为通常被称为发送消息给对象

题外话

  • 本章其实还有很多内容,但是我都比较熟悉,就不再记录到本篇文章中。
原创粉丝点击