人以群分,物以类聚
文章来源:《Head First Java》修炼感悟。
上一章,Guess 想必让师兄们留下「深刻」印象,也见到了 OOP 应有的样子。 本章老白继续学习 Java 变量相关的知识,感兴趣的师兄可以继续往下看。
一、变量的分类
Java 的数据类型可分为两大类:
- 基本数据类型
- 引用数据类型
1.1 基本数据类型
基本类型用于直接存储变量的值,可分为以下 8 种:
基本类型 | 类型名称 | 位数 | 取值范围 |
---|---|---|---|
boolean | 布尔型 | 8 | true 或者 false |
char | 字符型 | 16 | 0~65535 |
byte | 字节型 | 8 | -128~127 |
short | 短整型 | 16 | -32768~32767 |
int | 整型 | 32 | -2147483648~2147483647 |
long | 长整型 | 64 | -9223372036854775808~9223372036854775807 |
float | 浮点型 | 32 | -3.4028e+38~3.4028e+38 |
double | 双精度浮点型 | 64 | -1.797e+308~1.797e+308 |
1.2 引用数据类型
引用类型包括类,接口和数组。引用变量存储的是对象的引用值(内存地址),对象本身存储在可回收的内存堆中。
老白顿悟: 虽然引用变量保存的是对象的内存地址,但不要试图通过「指针」去操作对象。 Java 没有「指针」概念,但你完全可以放心地把对象交给 JVM 去管理。
二、变量的声明和初始化
Java 是一种强类型语言,为确保类型安全,每个变量在使用前必须声明其类型。
2.1 变量的命名规则
- 变量名不能以数字开头;
- 变量名必须以字母,下划线
_
或者美元符号$
开头; - 变量名应该取一些有实际意义的名字,比如
totalImg
要好过img1
; - 变量名不能使用 Java 关键字(附在本章最后);
- 如果变量名是由多个单词组成,建议使用「驼峰」命名法。
老白顿悟:没有必要把 Java 的所有关键字都背下来,用久了自然就会记住。 如果不小心使用了关键字也没关系,编译器不会让你顺利通过。
2.2 变量的声明
type variableName [= value];
2.3 变量的初始化
声明变量时,可同时进行初始化(即赋值),也可以以后再赋值。 例如:
// 基本变量初始化
int number = 2;
int value;
value = 3;
// 引用变量初始化
Dog dog = new Dog();
Cat cat;
cat = new Cat();
三、变量的作用域
Java 作用域可以限制变量的访问范围,分以下三种:
3.1 局部变量
局部变量是在方法、构造器或块中声明的变量,只能在这些区域内访问。
public class Dog {
public static void main(String[] args) {
// String 类型的局部变量,只能在这个 main 方法中访问
String name = "小白";
System.out.println("老白和" + name);
}
}
3.2 实例变量
实例变量是在方法之外声明的变量,是类的实例变量,每个对象都有属于自己的实例变量。
public class Dog {
// 声明 String 类型的实例变量
public String name = "小白";
// 通过实例对象+圆点符号访问实例变量 name
public static void main(String[] args) {
Dog dog = new Dog();
System.out.println("老白和" + dog.name);
}
}
3.3 类变量(静态变量)
类变量使用 static
关键字修饰,它只属于当前类,不属于类的实例对象,所有类的实例对象共享这个类变量。 换句话说,无论你创建了多少这个类的实例对象,始终只有这一个类变量。 例如:
public class Dog {
// String 类型的静态变量,注意使用了 static 关键字
public static String name = "小白";
// 在其它类中可以通过圆点符号直接访问 Dog 类的静态变量 name
public static void main(String[] args) {
System.out.println("老白和" + Dog.name);
}
}
四、数组对象
数组,是由相同类型的多个变量组成的对象, 数组元素可以是任何数据类型。
4.1 数组的特点
- 数组元素必须是同一种类型;
- 数组元素可以是基本类型,也可以是引用类型;
- 数组的长度固定不变,所占内存空间大小固定。
4.2 定义数组的两种语法
type arrayName[];
type[] arrayName;
4.3 初始化数组两种形式
- 静态初始化,显式指定每个数组元素的值,系统自动推测数组长度
arrayName = new type[] {element1, element2, element3, ...};
- 动态初始化,显式指定数组长度,系统自动分配默认值。
arrayName = new type[length];
4.4 访问数组元素
通过索引访问数组元素,数组的索引从 0 开始,最后一个索引值为数组长度减一。如果超出索引范围,会引发 ArrayIndexOutOfBoundException(数组越界异常)。 例如:
public class StringDemo {
public static void main(String[] args) {
// 基本数据类型初始化
int[] nums = new int[3];
nums[0] = 0;
nums[1] = 1;
nums[2] = 2;
System.out.println("" + nums[0] + nums[1] + nums[2]); // 012
// 引用数据类型初始化
String[] str = new String[] {"Hello", " ", "Java"};
System.out.println(str[0] + str[1] + str[2]); // Hello Java
// 试图访问 str[3] 时引发异常,超出索引范围
// System.out.println(str[3]);
}
}
老白顿悟: 数组始终都是对象,需要按照对象方式来处理,即便数组元素是基本数据类型也不例外。
老白顿悟: 数组元素为引用类型时要注意,初始化结束后应该通过某种方式为每一个数组元素赋值。 初学阶段,遇到最多的异常可能就是 NullPointerException(空指针异常)。 大部分原因就是因为数组元素没有实例化,导致引用了一个null 对象。
五、Dog 在「堆」中的生活
很久以前,「堆」中没有任何对象。 自从使用了 new,「堆」中便时常传出「汪汪汪」的叫声:
Dog dogA = new Dog("阿花");
Dog dogB = new Dog("阿草");
上述语句声明了两个引用变量 dogA 和 dogB,同时新建了两个 Dog 对象 「阿花」和 「阿草」。 通过赋值运算符 =
把 Dog 对象赋给两个引用变量,此刻,「堆」中多出了两只狗狗。
很快,狗狗的叫声吸引了路人,情况又有了些变化:
Dog dogC = dogB;
起初,引用变量 dogC 还没有自己的 Dog 对象,仅仅做出了声明。 引用变量 dogB 说,你可以试试「阿草」,于是把自己的值赋给了 dogC 。 现在,dogB 和 dogC 共同拥有了「阿草」。
由于「阿草」精力过于旺盛,dogA 劝说 dogB 放弃「阿草」并把自己的值赋给了 dogB。
dogB = dogA;
这样一来,dogA 和 dogB 都拥有了「阿花」,而 dogC 独享「阿草」。
终于有一天,dogC 再也无法忍受「阿草」,决定放弃领养。 于是:
dogC = null;
此时再来看看「堆」中的情况:
dogA 和 dogB 依然拥有「阿花」,而可怜的「阿草」成为了无主的 Dog 对象,等待它的将是被 GC(垃圾收集器)无情销毁的命运。 其实,「阿草」并没有错,因为它知道,如果不能引起「引用变量」的关注只能是灭亡。
老白顿悟: 如果「堆」中对象不存在任何引用,GC 将适时销毁该对象并释放所占用的资源。
六、本章回顾
- Java 有两种数据类型:基本类型和引用类型;
- 声明变量时必须要有类型和名称;
- 基本数据类型存储的是变量的实际值;
- 引用数据类型存储的是堆中对象的引用值(地址);
- 引用变量通过圆点运算符访问对象的实例变量和方法;
- 如果引用变量没有引用任何对象,其值为 null;
- 无论数组元素是什么类型,数组始终是对象。
附:Java 关键字
Java8,共 50 个
- | - | - | - | - |
---|---|---|---|---|
abstract | continue | for | new | switch |
assert | default | if | package | synchronized |
boolean | do | goto | private | this |
break | double | implements | protected | throw |
byte | else | import | public | throws |
case | enum | instanceof | return | transient |
catch | extends | int | short | try |
char | final | interface | static | void |
class | finally | long | strictfp | volatile |
const | float | native | super | while |
Java17,新增 17 个
- | - | - | - | - |
---|---|---|---|---|
exports | opens | requires | uses | module |
permits | sealed | var | non-sealed | provides |
to | with | open | record | transitive |
yield | _ (underscore) |
Java23(最新版本),新增 1 个
- | - | - | - | - |
---|---|---|---|---|
when |
截止目前为止,Java 关键字共计 68 个。
《 上一篇 无聊的 Guess,有趣的 OOP |
---|