本章学习内容
- Java 程序的基本组成部分
- 核心:理解 Java 中(几乎)一切都是对象。
- Java 是 混合型语言
1. 引用操纵对象
Java 中通过操纵对象的 “引用” 来操纵内存中的元素。可以理解为通过遥控器(引用)操纵电视(对象),只要握住遥控器,就能保持和电视的连接。同时通过操控遥控器(引用)来简介操控电视(引用)。
另外,即使没有电视,遥控器也可单独存在,也就是说我们可以建立一个空引用,而没有任何一个对象与之关联,比如通过 String s;
建立一个 String 引用,记住这只是一个引用,而不是对象,此时向 s 发送一个消息,会发生错误,因为没有可以操作的对象。
因此正常的用法是:创建引用的同时便进行初始化。如 String s = "hello world";
2. 对象的创建
(1) 一旦创建了一个引用,就希望它能与一个新的对象相关联。通常用 new 关键字实现。比如上面的例子可以写成 String s = new String("hello world");
(2) 存储位置:
- 寄存器:速度最快,位于处理器内部,数量有限。无法直接控制。
- 堆栈:速度仅次于寄存器,位于 RAM 中。堆栈指针向下移动分配内存,向上移动释放内存。Java 系统需要知道存储在堆栈内所有项的生命周期。对象的引用 存于堆栈中。(注意! 基本类型也存于此)
- 堆:通用内存池,位于 RAM,用于存放所有的 Java 对象。编译器不需要知道存储的数据在堆里存活多长时间,因此需要对象时,只需 new 一个对象,然后会自动在堆中进行存储分配。
- 常量存储:常量值通常直接存放在程序代码内部。
- 非 RAM 存储:完全存活于程序之外的数据不受程序的任何控制。比如:流对象和持久化对象。
(3) 特例:基本类型
-
特殊之处:一般来说,通过 new 将对象存储在 ”堆“中;而对于基本类型,不用 new 来创建变量,而是创建一个并非是引用的”自动“变量。这个变量直接存储”值“,并置于堆栈中。
-
基本类型的大小、范围以及包装器如下:
基本类型 大小 最小值 最大值 包装器类型 boolean —— —— —— Boolean char 16 bits Unicode 0 Unicode 2^16 - 1 Character byte 8 bits -128 +127 Byte short 16 -2^15 +2^15-1 Short int 32 -2^31 +2^31-1 Integer long 64 -2^63 +2^63-1 Long float 32 IEEE754 IEEEE754 Float double 64 IEEE754 IEEE754 Double void —— —— —— Void 所有数值类型都有正负号,即 不存在无符号类型
-
关于包装器:可以通过包装器类,在堆中创建一个非基本对象,用来表示对应的基本类型:
char c = 'x'; Character ch = new Character(c); //或者如下 Character ch = new Character("x"); //也可以反向转换 Character ch = 'x'; char c = ch;
至于包装基本类型的原因此处没解释。
-
高精度数字:BigInteger 和 BigDecimal
- BigInteger 支持任意精度的整数
- BigDecimal 支持任意精度的定点数
(4) Java 中的数组
- Java 确保数组会被初始化,并且不能再它的范围之外被访问。
- 创建数组时,实际上创建的是引用数组,每个引用都会自动被初始化为一个特定值 null,表明这个引用还没有指向某个对象。使用 null 的引用会报错。
- 同时也可以创建用来存放基本数据类型的数组
3. 对象的销毁
(1) 作用域 (基本类型)
-
作用域决定了在其内定义的变量名的可见性和生命周期。
-
由花括号 {} 的位置决定,如:
{ int x = 12; //only x available { int q = 96; //both x & q available } // only x available // q is out of scope }
-
作用域里定义的变量只能用于作用域结束之前。
(2) 对象的作用域
-
Java 对象 可以 存活 于作用域之外,而其 引用 会在作用于终点 消失。
-
带来问题:如何防止这些存活的 Java 对象填满内存空间,进而阻塞程序?
- Java 的垃圾回收器:用来监视用 new 创建的所有对象,并辨别那些不会再被引用的对象。随后释放这些对象的内存空间。简单来说,我们尽管创建对象,不需要的时候,它们会自行消失。
4. 创建新的数据类型:类
(1) 如何创建 ?
通过 "class 关键字 + 类名" 来定义一个新的类型,如:
class TypeName{
/* class body goes here /*
}
之后就可以通过 new 来创建这个类型的对象,尽管此时它什么都不能做,确切地说是在定义它的方法之前,都不能向它发送任何有意义的消息:
TypeName type = new TypeName();
(2) 字段和方法
Java 中我们所作的工作核心就是:定义类,产生类的对象,以及发送消息给这些对象
-
类中可以设置两种元素:字段和方法
- 字段(数据成员/成员变量):可以是任何类型的对象,可以通过其引用与其进行通信;也可以是基本类型
- 方法(成员函数):会在下一小节介绍
// 此处举一个只有字段但无方法的类 class DataOnly{ int i; double d; boolean b; }
-
通过 “对象引用名称 + ’.‘ + 内部成员名称“ 的方式来引用一个对象的成员,如:
objectReference.member
。该模式可用于对象的“嵌套”,即objectReference.menberObjectReference.menber
-
基本成员默认值
如果某个成员是基本数据类型,没有进行初始化时,Java 会为其设置默认值(默认初始化),如下表所示:
基本类型 默认值 boolean false char '\uoooo'(null) byte (byte)0 short (short)0 int 0 long 0L float 0.0f double 0.0d 注意:只有成员变量才会进行默认初始化,局部变量并不会进行默认初始化。而如果局部变量未经人为初始化就进行使用,会在编译时返回错误。
5. 方法、参数和返回值
(1) 方法
-
表示 “做某些事情的方式”,决定了一个对象能够接收什么样的信息
-
基本组成包括:名称、参数、返回值和方法体。最基本的形式如下:
ReturnType methodName( /* Argument list */ ) { /* Method Body */ }
-
返回类型:调用方法之后从方法返回的值
-
参数列表:要传给方法的信息类型和名称
方法名和参数列表 唯一的标识出某个方法。针对以后的 重载 理解
-
-
方法只能作为类的一部分,只有通过对象才能被调用
这句话是针对非静态 static 方法而言的
static 方法是针对类调用的,不依赖于对象
-
方法的调用形式:对象名 + '.' + 方法名 + 参数列表,如:
objectName.methodName(arg1, arg2, arg3);
-
利用方法赋值时,需要保证返回值与对象的类型兼容
-
比如类 A 中有一个 int 类型的方法 f(),而 a 是 A 的一个对象,那么就可以这样写
int x = a.f();
,将 f() 的返回值赋给 x
-
-
调用方法的行为通常被称为 发送消息给对象。上面的例子中,消息是 f(),对象是 a。
(2) 参数列表
-
指定要传递什么样的信息,必须指定每个所传递对象的类型以及名字
- 传递对象时:实际上传递的是对象的引用
- 传递基本数据类型时,传递的是值
-
举例:
int storage(String s){ return s.length() * 2; }
该方法接收 String 为其参数,参数类型是 String,参数名是 s。将 s 传递给此方法后,该方法就可以对 s 动手动脚了。
-
return 关键字
- 首先代表“已经完成,离开此方法”
- 其次,如果此方法产生了一个值,这个值通过 return 回传。
- 如果是 void 类型的方法,那么 return 就只是用来退出方法。
6. 构建一个 Java 程序
(1) 名字可见性
- 为库设置名字时采取反转域名,如 com.leanjava.whdalive 。
(2) 使用其他类
-
通过 import 关键字导入包,即导入一个类库,如:
import java.util.ArrayList;
,也可以使用通配符 “*” 导入 util 下所有的类:import java.util.*;
(3) static 关键字
-
当声明一个事物是 static 时,意味着这个域或方法不会与包含它的那个类的任何对象实例关联在一起。所以,及时从未创建某个类的任何对象,也可以调用其 static 方法或访问其 static 域。
可以理解为 static 的方法或域是和类绑在一起的,直接通过 类 访问。
非 static 的情况下:
当执行 new 创建对象时,数据存储空间才分配,方法才供外界调用。
-
static 成员占有单一存储空间
-
举例:
class StaticTest{ static int i = 47; } StaticTest st1 = new StaticTest(); StaticTest st2 = new StaticTest();
此时,st1.i 和 st2.i 指向同一存储空间,也可以直接通过 StaticTest.i 访问,一般建议通过 类名 访问。
-
类似的,静态方法也建议直接通过 ClassName.staticMethod() 的方式调用。
-
7. 第一个 Java 程序
叨叨了半天了,终于能开始写 Java 程序了,感动不感动
直接上个例子吧:
//HelloData.java
import java.util.*;
public class HeloDate{
public static void main(String[] args){
System.out.println("Hello,it's ");
System.out.println(new Date());
}
}
解释:
- 我们需要使用 Date 这个类,位于 Java.util 下,通过 import 引入
- public 关键字表示这是一个可由外部调用的方法,后面会讲解。
- main 方法的写法是固定的,指明程序的入口,args 参数用来存储命令参数,此例中未用到。
- System.out.println 用来打印到控制台,完成后换行。
8. 注释和嵌入式文档
(1) 注释
- 单行注释:// 起头,到句末都是注释
- 多行注释:/* */,/* 和 */ 中间的都会被注释掉
(2) 文档
- 通过 Javadoc 命令
- 语法:在 /** 注释中出现,结束于 */
- 嵌入式 HTML
- 标签
9. 编码风格
驼峰风格,示例如下:
class AllTheColorsOfTheRainbow{
int anIntegerRepresentingColors;
void changeTheHueOfTheColoc(int newHue);
}
- 类名首字母大写,每个单词首字母均大写
- 方法、字段等标识符的首字母小写,其余单词的首字母大写。
小结
本章的内容也是属于偏入门的,从对象入手介绍 Java 是如何面向对象编程的。当然也只是简单的介绍一下,只通过这一章就能了解的非常透彻显然是不现实的。
对于老手而言(显然我不是),可能遗漏的绝对不是如何写代码,这太 low 了;还是需要了解代码背后的思想,为什么我要这么写,这么写有什么便利之处?
看到这里,估计也能感觉的出来吧,末尾这一部分我就是完全在水了,因为没什么好总结的。就是一种会的依旧会,不常用的还是不太清楚,需要用的时候仍然需要查阅资料(比如 javadoc 生成文档,我重温 Java 一时半会又不会去写底层代码,等到我需要的时候早忘光了好不好)。
漫漫 Java 之路,共勉。
网友评论