Java学习笔记
一、java命令执行过程
第一步:先启动JVM
第二部:JVM启动之后,JVM会去启动“类加载器classloader”
类加载器的作用:用于加载类。本质上类加载器负责去硬盘上找 “类” 对应的 “字节码” 文件
假设是 java HelloWorld ,那么类加载器回去硬盘上搜索:HelloWorld.class 文件。
第三步:类加载器如果在硬盘上找不到对应的字节码文件,会报错
错误:找不到或无法加载对主类
类加载器如果在硬盘上找到了对应的字节码文件,类加载器会将该字节码文件装载到 JVM 当中,JVM 启动 “解释器” 将字节码文件解释成为 “101011101001…” 这中二进制码,操作系统则执行该二进制码文件和硬件交互。
1.1 classpath
问题: 默认情况下,类加载器 classLoader 去哪找对应的字节码文件?
默认情况下,类加载器(classLoader)会从当前路径下找对应的字节码文件。
问题:那么能不能给类加载器指定一个路径,让类加载器去指定的路径下加载字节码文件呢?
答案:当然可以,但是我们需要设置一个环境变量,叫做 classpath
1.1.1 classpath的写法
classpath=A路径;B路径;C路径
路径之间使用 ; 隔开。
注意: 若将classpath配置为 classpath=D:\DEV 后,classloader今后则只会在D:\DEV目录下查找字节码文件。
二、变量
2.1 整数类型
byte
\ short
\ int
\ long
\ char
在 Java 中有一条非常重要的结论,必须记住:
在任何情况下,整数型的 “字面量/数据”默认被当作 int 类型处理。 如果希望该“整数型字面量”被当作
long
类型来处理,需要在 “字面量” 后面添加L
或l
,如:1234L
这里需要注意: int类型的取值范围为 [-2147483648, 2147483647] 所以,字面量中不能写在该范围之外的数字,否则编译会报错。
2.2.1 自动类型转换
在 Java 中,小容量的类型可以自动转换成大容量的类型,这成为自动类型转换。
public class IntTest01{
public static void main(String[] args) {
// 分析:200这个字面量默认被当作int类型来处理
// b变量是long类型,int类型占4个字节,long类型占8个字节
// 小容量可以自动转换成大容量,这种操作为自动类型转换。
long b = 200;
}
}
2.3 强制类型转换
在 Java 中,大容量的类型要想转换为小容量的类型,需要使用强制类型转换。
但是 Java 会给 byte
、short
、 char
类型开后门,只要当整数型字面量没有超 byte
、short
、char
类型的范围时,允许不加强制类型转换符,直接赋值。
public class IntTest01{
public static void main(String[] args) {
int b = 200L; // 大容量long类型字面值直接复制给小容量int类型的变量,会编译报错
int c = (int)200L; // 使用强制类型转换符进行强转,编译能通过,运行时可能会损失精度。
int d = (int)2147483648; // 这会损失精度
}
}
强制类型转换原理:
比如 long 类型转换为 int 类型,会将前面的四个字节“砍掉”,如下例:
比如整数2147483648L -> (int)2147483648 的过程 二进制: long类型:00000000 00000000 00000000 00000000 10000000 00000000 00000000 00000000 转换为int类型后: 10000000 00000000 00000000 00000000,由于首位表示符号位,故其值为: -2147483648
当一个整数赋值给一个 char
类型变量的时候,会自动转换为 char
字符型,最终的结果是一个字符。
public class CharTest03() {
public static void main(String[] args) {
char c1 = 97; // 这里会做强制类型转换
System.out.println(c1); // 'a'
}
}
2.4 整数类型混合运算
结论:byte
、char
、short
做混合运算的时候,先各自转换成 int
再做运算。
char c1 = 'a';
byte b = 1;
System.out.println(c1 + b); //98
结论:多种数据类型做混合运算的时候,最终的结果是最大容量的对应的类型(char、short、byte除外)。
2.2 浮点型
float
:4个字节double
:8个字节
Java中规定,任何一个浮点型数据字面量默认被当作 double
类型来处理。
如果想让这个浮点型字面量被当作 float
类型来处理,那么请在字面后面添加 f
或 F
。
2.3 布尔型
在Java语言中,boolean类型只有两个值 true
和 false
。
不像 c 或 c++ 中的 0 或 1 也能表示布尔类型。
2.4 八种基本数据类型转换规则
1、八种基本数据类型,除了 boolean
类型不能转换外,其余七种都可以互相转换;
2、如果整数型字面量没有超出 byte
\ short
\ int
\ char
的取值范围,则可以直接赋值给这4 种类型;
3、小容量向大容量转换称为自动类型转换,容量从小到大的排序为:byte < short = char < int < long < float < double
,其中 short
和 char
都占两个字节,但 char
可以表示更大的正整数。
4、大容量转换为小容量,称为强制类型转换,编写时必须加强制类型转换符号,但运行时可能出现精度损失;
5、byte
\ short
\ char
在做混合运算时,先各自转换成 int 类型再做运算;
6、多种数据类型混合运算时,先各自转换成容量最大的那一种,再做运算。
三、运算符
3.1 逻辑运算符
&
逻辑与|
逻辑或!
取反&&
短路与||
短路或
&&、|| 和 &、| 在运算结果上没有任何区别,完全相同。
短路现象:&&
带来的短路现象:当左边表达式为 false 时,右边表达式不会执行;||
带来的锻炼现象:当左边表达式为 true 时,右边表达式不会执行。
int x = 10;
int y = 11;
boolean flag1 = x > y & x > y++; // flag1为false,但y++执行了
System.out.println(y); // 12
int x = 10;
int y = 11;
boolean flag2 = x > y && x > y++; // flag2为false,且y++未执行,出现了短路现象。
System.out.println(y); // 11
3.2 扩展赋值运算符
问题:x +=1
和 x = x + 1
本质上是一样的吗?
答案:不一样!
byte x = 100;
x = x + 1; // 编译器报错,编译器检测到x+1是int类型,int类型无法直接赋值给byte类型。
byte x = 100;
x += 1; // 可以,x = 101。
// 实际上:x += 1 ===> x = (byte)(x + 1)
很重要的语法机制:使用扩展运算符的时候,计算过程中永远都不会改变结果类型!
四、面向对象
4.1 对象的JVM内存结构
4.2 对象与引用
对象:对象时通过 new 出来的,在堆内存中存储。
引用:但凡是变量,并且该变量中保存了内存地址指向了堆内存当中的对象,都是引用。
五、异常
5.1 异常概述
1、什么是异常,Java提供异常处理机制有啥用?
异常是指:在程序执行过程中,出现了不正常的情况 Java语言提供了异常处理机制,若程序在执行过程中出现了不正常的情况, Java会把异常信息打印输出到控制台,供程序员参考。程序员看到异常信息之后,可以对程序进行修改,让程序更加健壮。
5.2 异常继承结构图
5.3 编译时异常与运行时异常
编译时异常和运行时异常,都是发生在程序的运行阶段,编译阶段是不会发生的。
编译时异常必须在编译(编写程序)阶段预先处理,如果不处理,会导致编译器报错。
编译时异常也称为受检异常
运行时异常也称为未受检异常
5.4 异常处理
Java中对异常的处理包括两种方式:
- 第一种方式:在方法声明时使用
trows
关键字,抛给上一级。 - 第二种方式:使用
try ... catch
语句对异常进行捕捉。
上报和捕捉怎么选择?
如果希望调用者处理,选择**上报方式,其余情况使用捕捉**。
六、集合框架
5.1 主要集合概述
所有的集合类和集合的接口,都在 java.util.*
包下面。
集合有两大接口:java.util.Collection
与 java.util.Map
。
5.1 List
List
接口继承于 Collection
,定义了一个有序集合(ordered collection)。可以采用两种方式访问元素:
- 使用迭代器访问(顺序访问);
- 使用整数索引访问(随机访问);
List
接口定义了多种随机访问的方法
void add(int index, E element);
void remove(int index);
E get(int index);
E set(int index, E element);
5.1.1 ArrayList
ArrayList底层采用了数组这种数据结构,并且封装了一个动态再分配的对象数组。