写在前面:
该学习笔记基于《Head First Java》一书,仅供个人参考备忘使用,可能会存在诸多问题,也会随着学习的推进不断修改,因此请酌情将其当作参考。
基础知识:
变量的存储位置:
紧接Chapter1,先介绍一下Java中不同类型变量的存储方式:
primitive主数据类型 | 引用类型 | |
---|---|---|
局部 | 存储在栈中 | 变量本身存储在栈中,实际对象存储在堆中 |
实例 | 存储在堆中 | 变量本身和实际对象都存储在堆中 |
基于不同的存储模式,Java对于变量的声明和初始化有不同的方式。
变量的声明与初始化:
(1)局部primitive主数据类型:
type a = value;
// 实际上由两个部分构成:
type a; //声明变量
a = value; //初始化值
Java的特点是只经过定义、没有经过初始化的局部变量,是无法被使用的。
(2)局部引用类型:
type a = new type();
// 实际上由三个部分构成:
type a; //声明引用变量
new type() //在堆区新建对象
a = new type(); //建立引用变量到堆区对象的引用关系
一般数组:
在Java中,数组通常会采用ArrayList这个类创建和使用,普通类型的数组反倒是很少使用。但是对于普通数组的声明方式,还是要有所了解:
// 形式1:
type[] a = new type[n];
a[0] = xxx;
a[1] = xxx;
……
// 形式2:
type[] a = {a1, a2, ……}
这两种形式看起来差异很大,甚至会让人误以为第一种所创建的数组位于堆区,而第二种位于栈区。但实际上两种定义方式是等价的,而普通数组的成员和对象一样,是在堆区被创建,然后通过数组名(在栈区的一个局部变量)进行访问。可以直接把普通数组看作是对象。
(3)实例变量:
(public/private) type a;
实例变量作为类的属性,一般来说是不需要进行初始化的,只需要声明即可。但是这并不代表它们没有值。Java对于不同类型的实例变量,会预设不同的的初值,当实例变量被声明时,便自动被赋上了这个初值,之后的赋值都只是在此基础上进行覆盖。常见类型的初值见下表:
类型 | 初值 |
---|---|
int | 0 |
浮点 | 0.0 |
boolean | false |
引用类型 | null(空指针) |
变量的比较:
面向过程一般来说仅需要一种比较方式,即比较值是否相同。Java中“==”这一运算符被用于判断两个变量是否相等,其主要功能是判断primitive主数据类型变量的值是否相等,以及判断两个引用类型变量是否指向一个对象。
Java针对判断两个对象在意义上是否相等,设置了.equals()方法。举例来说,.equals()可以判断两个String对象中的字符串本身是否相同。
封装(Encapsulation)——更安全的存取方式:
封装是面向对象的另一大特色。其主要目的是隐藏对象的部分属性和实现细节,仅提供接口供用户读取和修改。下面这张图稍微能够体现这种类似于“黑匣子”的功能:
(画技有限,请多包涵。)
最常见、最简单的封装形式,就是将变量设置为私有(private),并设置setter和getter进行存取。下面的表格体现了对象在封装前和封装后读写实例变量的区别:
封装前 | 封装后 | |
---|---|---|
读取实例变量 | object.variance | getter() |
修改实例变量 | object.variance = xxx; | setter(xxx) |
在封装之后,对实例变量进行读取和修改的操作变得更加可控。
一些零碎的小知识点:
(1)Java中的“列表解析”:
for循环在Java中有两种形式,一种是普通的:
for(int i=0; i<10;i++)
另一种是针对数组、集合等变量形式的:
for(type name : collection)
如果有学过一点python,应该理解起来会更加容易,这个语句就相当于python中的
for name in collection:
其实质也就是对数组或集合collection中的所有元素进行遍历,每次都将当前遍历的元素赋值给name这个变量。