• 第2章 一切都是对象



    2.1 用引用操纵对象
    reference:引用
    你拥有一个引用,并不一定需要一个对象与它关联。通常,一种安全的做法是:创建一个引用的同时便进行初始化

    2.2 必须由你创建所有对象

    一旦创建了一个引用,就希望它能与一个新的对象相关联。通常用 new 操作符来实现这一目的。new关键字的意思是“给我一个新对象。”
    String s = new String ("asdf") ;

    2.2.1 存储到什么地方

    程序运行时,对象是怎么进行放置安排的呢?特别是内存是怎样分配的呢?对这些方面的了解会对你有很大的帮助。有五个不同的地方可以存储数据:

    1)寄存器。这是最快的存储区,因为它位于不同于其他存储区的地方—处理器内部。但是寄存器的数量极其有限,所以寄存器根据需求进行分配。你不能直接控制,也不能在程序中感觉到寄存器存在的任何迹象(另一方面,C和C十+允许您向编译器建议寄存器的分配方式)。

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

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

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

    5)非RAM存储。如果数据完全存活于程序之外,那么它可以不受程序的任何控制,在程序没有运行时也可以存在。其中两个基本的例子是流对象和持久化对象。在流对象中,对象转化成字节流,通常被发送给另一台机器。
    在“持久化对象”中,对象被存放于磁盘上,因此,即使程序终止,它们仍可以保持自己的状态。这种存储方式的技巧在干:把对象转化成可以存放在其他媒介上的事物,在需要时,可恢复成常规的、基于RAM的对象。
    Java提供了对轻量级持久化的支持,而诸如JDBC和Hibernate这样的机制提供了更加复杂的对在数据库中存储和读取对象信息的支持。

    2.2.2 特例:基本类型

    在程序设计中经常用到一系列类型,它们需要特殊对待。可以把它们想像成“基本”类型。之所以特殊对待,是因为new将对象存储在“堆”里,故用new创建一个对象——特别是小的、简单的变量,往往不是很有效。
    因此,对于这些类型,Jave 采取与C和C十材目同的方法。也就是说,不用new来创建变量,而是创建一个并非是引用的“自动”变量;这个变量直接存储“值”,并置于堆栈中,因此更加高效。


    Jave 要确定每种基本类型所占存储空间的大小。它们的大小并不像其他大多数语言那样随机器硬件架构的变化而变化。这种所占存储空间大小的不变性是Java程序比用其他大多数语言编写的程序更具可移植性的原因之一。

    基本类型具有的包装器类,使得可以在堆中创建一个非基本对象,用来表示对应的基本类型。例如:

    Char c = 'x' ;
    Character ch = new Character(c);

    也可以这样用:
    Character ch = new Character ('x');

    Java SE5 的自动包装功能将自动地将基本类型转换为包装器类型:
    Character ch = 'x';
    并可以反向转换:
    Char c = ch;


    高精度数字

    Java 提供了两个用于高精度计算的类:BigInteger 和 BigDecimal 虽然它们大体上属于“包装器类”的范畴,但二者都没有对应的基本类型。不过,这两个类包含的方法,提供的操作与对基本类型所能执行的操作相似。
    也就是说,能作用于 int 或 float 的操作,也同样能作用于Biginteer 或 BigDecimal 。只不过必须以方法调用方式取代运算符方式来实现。由于这么做复杂了许多,所以运算速度会比较慢。在这里,我们以速度换取了精度。

    BigInteger 支持任意精度的整数。也就是说,在运算中,可以淮确地表示任何大小的整数值,而不会丢失任何信息。
    BigDecimal 支持任何精度的定点数,例如,可以用它进行精确的货币计算。关于调用这两个类的构造器和方法的详细信息,请查阅JDK文档。

    2.2.3 Java 中的数组

    Java的主要日标之一是安全性,所以许多在C和C++里困扰程序员的问题在Java里不会再出现。Java确保数组会被初始化,而且不能在它的范围之外被访问。这种范围检查,是以每个数组上少量的内存开销及运行时的下标检查为代价的。但由此换来的是安全性和效率的提高,因此付出的代价是值得的(并且Java有时可以优化这些操作).。

    当创建一个数组对象时,实际上就是创建了一个引用数组,并且每个引用都会自动被初始化为一个特定值,该值拥有自己的关键字null。一旦Java看到null ,就知道这个引用还没有指向某个对象。在使用任何引用前:必须为其指定一个对象;如果试图使用一个还是nul的引用,在运行时将会报错。因此,常犯的数组错误在Java中就可以避免。

    还可以创建用来存放基本数据类型的数组。同样,编译器也能确保这种数组的初始化,因为它会将这种数组所占的内存全部置零。

    2.3 永远不需要销毁对象

    2.3.1 作用域

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

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

    2.3.2 对象的作用域

    Java对象不具备和基本类型一样的生命周期。当用 new 创建一个 Java 对象时,它可以存活于作用域之外。所以假如你采用代码

    {
    String s = new String ("a string");
    } // End of scope

    引用 S 在作用域终点就消失了。然而,S指向的 String 对象仍继续占据内存空间。在这一小段代码中,我们无法在这个作用域之后访问这个对象,因为对它唯一的引用已超出了作用域的范围。

    事实证明,由 new 创建的对象,只要你需要,就会一直保留下去。这样,许多C十十编程问题在Java中就完全消失了。在C++中,你不仅必须要确保对象的保留时间与你需要这些对象的时间一样长,而且还必须在你使用完它们之后,将其销毁。

    这样便带来一个有趣的问题。如果Java让对象继续存在,那么靠什么才能防止这些对象填满内存空间,进而阻塞你的程序呢?这正是C++里可能会发生的问题。这也是Java神奇之所在。
    Java 有一个垃圾回收器,用来监视用new创建的所有对象,并辨别那些不会再被引用的对象。随后,释放这些对象的内存空间,以便供其他新的对象使用。
    也就是说,你根本不必担心内存回收的问题。你只需要创建对象,一旦不再需要,它们就会自行消失。这样做就消除了这类编程问题(即‘内存泄漏”),这是由于程序员忘记释放内存而产生的问题。


    2.4 创建新的数据类型:类

    2.4.1 字段和方法

    一旦定义了一个类(在Jave 中你所做的全部工作就是定义类,产生那些类的对象,以及发送消息给这些对象),就可以在类中设置两种类型的元素:字段(有时被称作数据成员)和方法(有时被称作成员函数)。
    字段可以是任何类型的对象,可以通过其引用与其进行通信,也可以是基本类型中的一种。如果字段是对某个对象的引用,那么必须初始化该引用,以便使其与一个实际的对象(如前所述,使用new来实现)相关联。

    基本成员默认值

    若类的某个成员是基本数据类型,即使没有进行初始化,Java也会确保它获得一个默认值。当变量作为类的成员使用时,Java才确保给定其默认值,以确保那些是基本类型的成员变量得到初始化,防止产生程序错误。
    但是、这些初始值对你的程序来说,可能是不正确的,甚至是不合法的。所以最好明确地对变量进行初始化。


    2.5 方法、参数和返回值

    Java的方法决定了一个对象能够接收什么样的消息。方法的基木组成部分包括:名称、参数、返回值和方法体。下面是它最基本的形式:

    ReturnType methodName (/*Argument list*/) {
    /* Method body */
    }

    返回类型描述的是在调用方法之后从方法返回的值。参数列表给出了要传给方法的信息的类型和名称。方法名和参数列表(它们合起来被称为“方法签名”)唯一地标识出某个方法。

    Java 中的方法只能作为类的一部分来创建。方法只有通过对象才能被调用,且这个对象必须能执行这个方法调用。如果试图在某个对象上调用它并不具备的方法,那么在编译时就会得
    到一条错误消息。通过对象调用方法时,需要先列出对象名,紧接着是句点,然后是方法名和参数列表。如:

    objectName.methodName(arg1,arg2,arg3);

    int x = a.f(); 返回值的类型必须要与 x 的类型兼容。
    这种调用方法的行为通常被称为发送信息给时象。在上面的例子中,消息是 f() ,对象是a 。面向对象的程序设计通常简单地归纳为一“向对象发送消息”。

    参数列表:

    方法的参数列表指定要传递给方法什么样的信息。正如你可能料想的那样,这些信息像 Java 中的其他信息一样,采用的都是对象形式。
    因此,在参数列表中必须指定每个所传递对象的类型及名字。像Java中任何传递对象的场合一样,这里传递的实际上也是引用,并且引用的类型必须正确。
    如果参数被设为String 类型,则必须传递一个String 对象,否则,编译器将抛出错误。

    2.6 构建一个 Java 程序

    2.6.1 名字可见性

    名字空间

    2.6.2 运用其他构件

    import 指示编译器导入一个包,也就是一个类库

    2.6.3 static 关键字

    通常来说,当创建类时,就是在描述那个类的对象的外观与行为。除非用 new 创建那个类的对象,否则,实际上并未获得任何对象。
    执行 new 来创建对象时,数据存储空间才被分配,其方法才供外界调用。

    有两种情形用上述方法是无法解决的,一种情形是,只想为某特定域分配单一存储空间,而不去考虑究竟要创建多少对象,甚至根本就不创建任何对象。
    另一种情形是,希望某个方法不与包含它的类的任何对象关联在一起。也就是说,即使没有创建对象,也能够调用这个方法。

    通过static关键字可以满足这两方面的需要。当声明一个事物是static时,就意味着这个域或方法不会与包含它的那个类的任何对象实例关联在一起。
    所以,即使从未创建某个类的任何对象,也可以调用其static方法或访问其static域。通常,你必须创建一个对象,并用它来访问数据或方法。因为非static域和方法必须知道它们一起运作的特定对象。

    引用static变量有两种方法。如前例所示,可以通过一个对象去定位它;也可以通过其类名直接引用,而这对于非静态成员则不行。

    尽管当 static 作用于某个字段时,肯定会改变数据创建的方式(一个 static 字段对每个类来说都只有一份存储空间, 而非static 字段则是对每个对象有一个存储空间。)
    但是如果 static 作用于某个方法,差别没有那么大。 static 方法的一个重要用法就是在不创建任何对象的前提下就可以调用它。


    2.7 你的第一个 Java 程序

    类的名字必须和文件名相同

    2.7.1 编译和运行

    要编译、运行这个程序以及书本中其他所有的程序,受限必须要有一个 Java开发环境。


    2.8 注释和嵌入式文档 TODO 掌握这个,并做好练习

    2.8.1 注释文档
    2.8.2 语法
    2.8.3 嵌入式HTML
    2.8.4 一些标签示例

    2.9 编码风格

    在 “Java 编程语言编码约定”中,代码风格是这样规定的:类名的首字母要大写;如果类名由几个单词构成,那么把它们并在一起(也就是说,不要用下划线来分隔名字),其中每个内部单词的首字母都采用大写形式。例如:

    class AllTheColorsOfTheRainbow { // ...

    这种风格有时称作“驼峰风格”。几乎其他所有内容——方法、字段(成员变量〕以及对象弓引用名称等,公认的风格与类的风格一样,只是标识符的第一个字母采用小写。例如:

    class AllTheColorsOfTheRainbow {
    int anIntegerRepresentingColors;
    void changeTheHueOfTheColor (int newHue){
    //...
    }
    // ...

    }

    『愿你我既可以朝九晚五,又能够浪迹天涯』
  • 相关阅读:
    [IOI2013]Dreaming
    Lost Cows
    Mobile Service
    [POI2005]Bank notes
    [CTSC2007]动物园zoo
    [CF1093F]Vasya and Array
    [雅礼集训 2017 Day1]市场
    [APIO2014]序列分割
    [CEOI2004]锯木厂选址
    [APIO2010]特别行动队
  • 原文地址:https://www.cnblogs.com/zjwwljty/p/6270350.html
Copyright © 2020-2023  润新知