Java学习笔记--一切皆对象

  • 引用操纵对象
  • 创建对象
  • 基本类型
  • 销毁对象
  • 创建类
  • 方法、参数和返回值
  • 构建Java程序
  • 第一个程序
  • 注释和嵌入式文档
  • 编码风格
  • 总结

1.引用操纵对象

创建了一个引用不一定关联了一个对象,就像有一个遥控器,不一定这个遥控器就需要操纵一个家电一样。

创建一个String引用

这里创建的只是引用,并不是对象。如果此时向s发送一个消息,就会返回一个运行时错误。这是因为此时s实际上没有与任何事物相关联。

安全的做法是:创建一个引用的同时便进行初始化。

字符串使用带引号的文本初始化 

2.创建对象

一旦创建了一个引用,就希望它能与一个新的对象相关联。通常用new操作符来实现这一目的。new关键字的意思是“给我一个新对象”,上面的例子可以改成:

 

数据存储

有五个地方可以存储数据:

1).寄存器---最快的存储区,位于处理器内部,但是数量有限,所以寄存器根据需求进行分配。不能直接控制,但是在c和c++中允许向编辑器建议寄存器的分配方式

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

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

4).常量存储---常量值通常直接存放在程序代码内部,这样做是安全的,因为它们永远不会被改变。在嵌入式系统中,通常将常量值单独存储在ROM中,与程序本身进行分隔。

5).非RAM存储---如果数据完全存活于程序之外,那么它可以不受程序的任何控制,在程序没有运行时也可以存在。其中连个基本的例子就是:流对象和持久化对象。

流对象:对象转化成字节流,通常发送给另一台机器

持久化对象:对象被存放于磁盘上,因此,即使程序终止,它们仍可以保持自己的状态。技巧:把对象转化成可以存放在其他媒介上的事物,在需要时,可恢复成常规的、基于RAM的对象。

Java提供了对轻量级持久化的支持,而诸如JDBC和Hibernate这样的机制提供了更加复杂的对在数据库存储中存储和读取对象信息的支持。

3.基本类型

new将对象存放在“堆”里,故用new创建一个对象---特别是小的、简单的变量,往往不是很有效的。对于Java中的基本类型,Java采取与C++相同的方法,不用new来创建变量,而是创建一个并非是引用的“自动”变量。这个变量直接存储“值”,并置于堆栈中,因此更加高效。

Java之所以可移植,是因为限制了变量所占存储空间大小的不变性:

 

所有数值类型都有正负号,boolean类型所占存储空间的大小没有明确指定,仅定义为能够取字面值true和false。

包装器类:

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

也可以这样使用:

 

Java SE5的自动包装功能自动地将基本类型转换为包装器类型

且可以反向转换:

 

高精度数字

Java提供了两个用于高精度计算的类:BigInteger和BigDecimal。虽然它们大致属于“ 包装器类"的范畴,但二者都没有对应的基本类型。但这两个类包含的方法,提供的操作与对基本类型所能执行的操作相似。也就是说,能用于int或float的操作,也能作用于BigInteger或BigDecimal。只不过必须以方法调用方式取代运算符方式来实现

 数组

数组在C++中很不安全,因为直接操作内存块,在Java中,确保数组会被初始化,而且不能在它的范围之外被访问。这种范围检查,是以每个数组上少量的内存开销及运行时的下表检查为代价的。但由此换来的是安全性和效率的提高。

当创建一个数组对象时,实际上就是创建了一个引用数组,并且每个引用都会自动被初始化为一个特定值,该值拥有自己的关键字null。

在使用任何引用之前,必须为其指定一个对象;如果试图使用一个还是null的引用,在运行时将会报错。 

4.销毁对象

作用域

作用域决定了在其内定义的变量名的可见性和生命周期。作用域由花括号的位置决定:

而下面的操作是不合法的:

对象的作用域

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

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

由new创建的对象,只要需要,就会一直保留下去。在C++中,不尽必须要确保对象的保留时间与你需要这些对象的时间一样长,而且还必须在使用完它们之后,将其摧毁

Java中有一个垃圾回收器,用来监视new创建的所有对象,一旦不再需要,垃圾回收器就会将其删除。 

5.创建类

创建方法:使用class来定义一个新的类,class关键字后紧跟新类的名称:

引入了一种新的类型,就可以对其使用new来创建对象:

这个类只包含一条注释语句,所以还不能完成更多的事情。

字段和方法

一个类由字段和方法组成,字段有时又称为数据成员,属性;方法有时被称为成员函数。字段可以是任何类型的对象,可以通过其引用与其进行通信,也可以是基本类型的一种,

如果字段是对某个对象的引用,那么必须初始化该引用,以便使其与一个实际的对象相关联。

每个对象都有用来存储其字段的空间;普通字段不能在对象间共享。

 

创建该类的一个对象:

 

引用一个对象的成员:在对象引用的名称之后紧接着一个句点,然后再接着是对象内部的成员名称。

 

给对象成员赋值:

 

修改位于对象所包含的其他对象中:其中leftTank是一个对象,capacity是对象leftTank的一个字段。

 

基本成员默认值

 若类的某个成员是基本数据类型,即使没有进行初始化,Java也会默认给其一个默认值。

 

注意,只有变量作为类的成员使用时,Java才确保给定其默认值,以确保那些是基本类型的成员变量得到初始化,防止程序产生错误。这些初始值并不保证你的程序是正确的,所以最好还是自己对字段进行初始化。

上述确保初始化的方法并不适用于“局部”变量(即并非某个类的字段)。比如:int x;x会得到一个任意值,而不会被自动初始化为0.因此在使用x之前,必须对其赋一个适当的值。

6.方法、参数和返回值

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

基本形式:

 

返回类型:描述调用方法之后从方法返回的值

参数列表:要传递给方法的信息的类型和名称

方法名和参数(合起来称为"方法签名")唯一地标识出某个方法

方法的调用:先列出对象名,紧接着是句点,然后是方法名和参数列表:Java中的方法只能作为类的一部分,方法只能通过对象才能被调用,且这个对象必须能执行这个方法调用。

这种调用方法的行为通常被称为:发送消息给对象。消息是方法名methodName,对象是objectName。OOP程序设计简单的归纳为“向对象发送消息”。

参数列表:

方法的参数列表指定要传递给方法什么样的消息。这些信息采用的都是对象形式。因此,在参数列表中必须指定每个所传递对象的类型和名字

这些传递的实际上也是引用,并且引用的类型必须正确。如果参数被设定为String类型,则必须传递一个String对象。

return关键字的作用:
1).已经做完,离开此方法

2).如果此方法产生了一个值,这个值要放在return语句后面。

若返回类型是void,return关键字的作用只是用来退出方法。碰到return,就退出该方法 

7.构建Java程序

1).名字可见性

问题:如果程序的某个模块使用了一个名字,而其他人在这个程序的另一个模块里也使用了相同的名字,如何区分它们并防止二者互相冲突?

解决方案:C++引入名字空间的概念,通过名字空间名进行函数调用。Java采用了全新的方法来避免上述所有问题,使用包名。Java设计者反过来使用自己的Internet域名。

这种机制意味着所有的文件都能够自动存活于它们自己的名字空间内,而且同一文件内的每个类都有唯一的标识符

2).运用其他构件

如果想在自己的程序里使用预先定义好的类,那么编译器就必须知道怎么定位它们。

若这个类就在发出调用的那个源文件中,就可以直接使用这个类--即使这个类在文件的后面才会被定义。

若这个类处于其他文件中,需要消除所有可能的混淆情况,使用import来准确地告诉编译器你想要的类是什么。

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

例如:这行代码告诉编译器,你想使用Java的ArrayList类。若想导入util包含的众多的类,可以使用通配符"*"来达到这个目的: 

3).static关键字

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

两种情形用上述方法无法解决:

1).只想为某特定域分配单一存储空间,而不去考虑究竟要创建多少对象,甚至根本不需要创建任何对象

2).希望某个方法不与包含它的类的任何对象关联在一起,也就是说,即使没有创建对象,也能够调用方法

static可以满足这两方面的需要。当声明一个事物是static时,意味着:这个域或方法不会与包含它的那个类的任何对象实例关联在一起

使用static声明一个方法或字段,即使没有创建包含该方法/字段的类的对象,也可以根据类名直接调用该static方法或访问其static域

只需将static关键字放在定义之前,就可以将字段或方法设定为static。例:下面代码生成了一个static字段,并对其进行了初始化:

 

现在即使创建了两个StaticTest对象,StaticTest.i也只有一份存储空间。这两个对象共享同一个i。比如:

 

在这里,st1.i和st2.i指向同一存储空间,因此它们具有相同的值47。

引用static变量的方法:

1).通过对象定位它

2).通过类名直接引用,这两种方法对于非静态成员则不行。

StaticTest.i++

此时,st1.i和st2.i仍具有相同的值48。

使用类名是引用static变量的首选方式,这不仅是因为它强调了变量的static结构,而且在某些情况下它还为编译器进行优化提供了更好的机会

类似逻辑也应用于静态方法。

总结:

1.static关键字定义的方法或变量,即使没有创建包含该方法/变量的类的对象,也可以对其进行调用,使用类名。

2.不管有多少个对象,static定义的方法或变量永远只有一份

3.既可以通过对象名对static关键字定义的方法或变量进行调用,也可以通过类名直接进行调用

4.使用类名直接引用是首选方式。

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

static方法可以创建或使用与其类型相同的被命名对象,因此,static方法常用来做"牧羊人"的角色,负责看护与其隶属同一类型的实例群。

8.第一个程序

 

在每个程序文件的开头,必须声明import语句,以便引入在文件代码中用到的额外类。有一个特定类会自动被引入到每一个java文件中:java.lang

JDK文档下载地址:http://java.sun.com

Date类在java.util包中,所以程序需要另外导入这个包,完整的路径:java.util.Date

对于java.lang.system类,其中包含out,它是一个静态的PrintStream对象。因为是静态的所以不用创建对象即可使用system.out.println()。能够使用out做哪些事,由它的类型PrintStream决定。

类的名字必须和文件名相同。且这个类必须包含一个名为main()的方法,形式如:

 

public关键字意指这是一个可由外部调用的方法。main方法的参数是一个String类型。这个程序中并未用到args,但是java编译其要求必须这么做,因为args要用来存储命令行参数

对于这行代码:

传递的参数是一个Date对象,一旦创建它之后,就可以直接将它的值(它被自动转换为String类型)发送给println。当这条语句执行完毕后,Date对象就不再被使用,而垃圾回收器会发现这一情况,并在任意时候将其回收。

main()的第一行将显示从运行程序的系统中获取所有“属性”,可以提供环境信息;list()方法将结果发送给它的参数:System.out;System.getProperty("user.name")查询了用户名,System.getProperty("java.library.path");查询java.library.path路径。 

编译和运行

1.javac HelloDate.java 

2.java HelloDate

9.注释和嵌入式文档

Java有两种注释风格:

1).传统的C语言风格的注释:/*.........*/

2).单行注释://

注释文档:

问题:如果文档与代码是分离的,每次修改代码都需要修改相应的文档,这是一件很不合理的事情

解决方案:将代码同文档“链接”起来。

为达这个目的,最简单的方法就是将所有东西都放在同一个文件内,但是还需要一种特殊的注释语法来标记文档;此外还需要一种工具用于提取那些注释,并将其转换为有用的形式。

javadoc便是用于提取注释的工具。采用Java编译器的某些技术,查找程序内的特殊注释标签。不仅解析由这些标签标记的信息,也将毗邻注释的类名或方法名抽取出来。

javadoc输出一个HTML文件,若想对javadoc处理过的信息执行特殊的操作(例如,产生不同格式的输出),那么可以通过编写你自己的被称为"doclets"的javadoc处理器来实现。

javadoc基本语法

所有javadoc命令只能在“/**”注释中出现;使用javadoc的方式主要有两种:嵌入HTML或使用“文档标签”

独立文档标签:以@字符开头的命令,且要置于注释行的最前面(但是不算前导*之后的最前面)

行内文档标签:可以出现在javadoc注释中的任何地方,也是以@开头,但要求出现在或括号内

共有三种类型的注释文档,分别对应于注释位置后面的三种元素:类,域和方法。类注释位于类定义之前;域注释位于域定义之前;方法注释位于方法定义之前。如下图:

注意:javadoc只能为public和protected成员进行文档注释。private和包内可访问成员的注释会被忽略掉。但是如果一定想要private的注释,可以使用:-private进行标记,以便把private成员的注释也包括在内。

这样的原因是:只有public和protected成员才能在文件之外被使用

嵌入式HTML:

javadoc通过生成的HTML文档传送HTML命令,这使你能够充分利用HTML。当然,其主要目的还是为了对代码进行格式化:

 

也可以像在其他web文档中那样运用HTML,对普通文本按照你自己所描述的进行格式化:

在文档注释中,位于每一行开头的星号和前导空格都会被javadoc丢弃。javadoc会将所有内容重新格式化,使其与标准的文档外观一致。需注意:不能在嵌入式HTML中使用标题标签:如<h1>或<hr>,因为javadoc会自己插入自己的标题,不然会产生冲突。 

标签示例:

1).@see:引用其他类

@see标签允许用户引用其他类的文档。javadoc会在其生成的HTML文件中,通过@see标签链接到其他文档。格式如下:

@see classname

@see fully-qualified-classname

@see fully-qualified-classname#method-name

javadoc不会检查你所提供的超链接是否有效。

2).{@link package.class #member label}

该标签与@see及其相似,只是它用于行内,并且是用“label”作为超链接文本而不用“see alse”

3).{@docRoot}

该标签产生到文档根目录的相对路径,用于文档树页面的显式超链接。

4).{@inheritDoc}

该标签从当前这个类的最直接的基类中继承相关文档到当前的文档注释中

5).@version

该标签的格式如下:

@version version-information

其中,“version-information”可以是任何你认为适合包含在版本说明中的重要信息。如果javadoc命令行使用了“-version”标记,那么就从生成的HTML文档中特别提取出版本信息。

6).@author

该标签的格式如下:

@author author-information

其中,author-information一看便知是你的名字,但是也可以包括电子邮件地址或者其他任何适宜的信息。如果javadoc命令行使用了-author标记,那么就从生成的HTML文档中特别提取作者信息

可以使用多个标签,以便列出所有作者,但是它们必须连续放置。全部作者信息会合并到同一段落,置于生成的HTML中。

7).@since

该标签允许你制定程序代码最早使用的版本,可以在HTML Java文档中看到它被用来指定所用的JDK版本的情况。

8).@param

该标签用于方法文档中,形式如下:

@param parameter-name description

其中,param parameter-name是方法的参数列表中的标识符,description是可延续数行的文本,终止于新的文档标签出现之前。可以使用任意多个这种标签,大约每个参数都有一个这样的标签。

9).@return

该标签用于方法文档,格式如下:

@return description

其中,“description”用来描述返回值的含义,可以延续数行

10).@throws

“异常”,是由于某个方法调用失败而“抛出”的对象,尽管在调用一个方法时,只出现一个异常对象,但是某个特殊方法可能会产生任意多个不同类型的异常,所有这些异常都需要进行说明。异常的标签如下:

@throws fully-qualified-class-name description

其中fully-qualified-class-name给出一个异常类的无歧义的名字,而该异常类在别处定义。description告诉你为什么此特殊类型的异常会在方法调用中出现。

11).@deprecated

该标签用于指出一些旧特性已由改进的新特性取代,建议用户不要再使用这些旧特性,因为在不久的将来它们很可能会被删除。如果使用一个标记为@deprecated的方法,则会引起编译器发布警告。

现在的版本(Java SE5以后),javadoc标签中的@deprecated已经被@Deprecated取代

文档示例

Java程序:

第一行采用我自己独特的方法,用一个":"作为特殊记号说明这是包含源文件名的注释行。该行包含文件的路径信息。object代表所在的包,随后是文件名。最后一行也是注释,这个“///:~”标志源代码清单的结束。自此,在通过编译器和执行检查后,文档就可以自动更新成本书的文问。

/*Output标签表示输出的开始部分将由这个文件生成,通过这种形式,它会被自动地检测以验证其准确性。(55% match)向测试系统说明程序的每一次运行和下一次运行的输出存在着很大的差异,因此它们与这里列出的输出预期只有55%的相关性。 

10.编码风格

驼峰风格:

类名:首字母要大写;如果类名由几个单词构成,那么把它们并在一起(不要用下划线将他们分隔开),其中每个内部单词的首字母都采用大写字母。

方法、字段(成员变量):与类名的命名规则一样,只是标识符的第一个字母采用小写。

例如:

 

 

11.总结

 

posted @ 2019-07-16 20:20  ifreewolf  阅读(400)  评论(0编辑  收藏  举报