Java 基础知识
一、概念
特点:
- 书写一次,到处运行
- 垃圾收集
解释执行: Java 源代码编译 -> 字节码 -> 运行时 JVM 解释器解释成机器码
** 编译执行:_ _**JIT 能够在运行时将热点代码编译成机器码,这种情况下部分热点代码就属于编译执行
二、基本类型
缓存池:
new Integer (123) 与 Integer.valueOf (123) 的区别在于:
- new Integer (123) 每次都会新建一个对象
- Integer.valueOf (123) 会使用缓存池中的对象,多次调用会取得同一个对象的引用。
Integer 缓存池的大小默认为 -128~127。
三、类型转换
float f = 3.4; 是否正确?
不正确。3.4 是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型(down-casting,也称为窄化)会造成精度损失,因此需要强制类型转换 float f =(float) 3.4; 或者写成 float f =3.4F;
short s1 = 1; s1 = s1 + 1; 有错吗?short s1 = 1; s1 += 1; 有错吗?
对于 short s1 = 1; s1 = s1 + 1; 由于 1 是 int 类型,因此 s1+1 运算结果也是 int 型,需要强制转换类型才能赋值给 short 型。
而 short s1 = 1; s1 += 1; 可以正确编译,因为 s1+= 1; 相当于 s1 = (short)(s1 + 1); 其中有隐含的强制类型转换。
计算:
Java 中的 byte,short,char 进行计算时都会提升为 int 类型。
常量则不会
1 | final byte a = 1, b = 2; |
四、字符串
Java 中 的 String,StringBuilder,StringBuffer 三者的区别:
- 线程安全: StringBuilder 是 ** 线程不安全 ** 的,而 StringBuffer 是线程安全的
- 运行速度:StringBuilder > StringBuffer > String
- 常量: String 为字符串常量,而后两者的对象是变量,是可以更改的。
String 不可变好处:
- hash 缓存: 可以缓存 hash 值。不可变的特性可以使得 hash 值也不可变,因此只需要进行一次计算。
- 常量池: String Pool 的需要。如果一个 String 对象已经被创建过了,那么就会从 String Pool 中取得引用。只有 String 是不可变的,才可能使用 String Pool。
- 安全性
- 线程安全
1. 代码点与代码单元
代码点:
指可用于编码字符集的数字,即 u+0000 等。
代码点可以分成 17 个代码级别,第一个代码级别称为 基本的多语言级别(U+0000 到 U+FFFF),其余的 16 个级别码点从 U+10000 到 U+10FFFF , 其中包括一些辅助字符。
代码单元:
char 类型用于存储代码单元,其使用 uft-16 编码来表示所有代码点。
对于 ** 基本的多语言级别 ** 的代码点用一个代码单元来表示,对于辅助字符用 ** 一对连续的代码单元 ** 来表示。
String 的 length () 方法返回的是 代码单元的数量,codePointCount () 方法返回的是代码点的数量
所以尽量不要使用 char
2. 常量池
过程:
- 直接使用 双引号声明 出来的 String 对象会直接存储在常量池中。
- 如果不是用双引号声明的 String 对象,可以使用 String 提供的 intern 方法。intern 方法会从字符串常量池中查询当前字符串是否存在,若不存在就会将当前字符串放入常量池中
例 1:String str = new String("abc");
首先查看池中是否有相同的字符串
- 如果有则拷贝一份放到堆中
- 如果池中没有则在堆中和常量池中都创建对象
- 然后返回堆中的地址,最后用栈中的引用 str 指向堆中的对象
例 2:
1 | String s3 = new String("1") + new String("1"); |
- 生成常量池中的 “1” 和堆中的对象 “11”(由于没有声明 “11”,所以常量池中并没有”11”)
- intern () 将 s3 放入常量池中
- jdk6 中常量池在持久代(Perm)中,所以常量池中会创建一个 “11” 的对象
- jdk7 中常量池不在持久代中而在堆中,所以常量池中 不需要再存储一份对象了,而是直接存储堆中的引用,即指向 s3 指向的对象
- s4 获得常量池中的 “11”
- jdk6 中为新的 “11” 对象
- jdk7 中 s4 就是指向 s3 指向的对象
- 结论:jdk7 中 String#intern 方法时,如果存在堆中的对象,会直接保存对象的引用,而不会重新创建对象
例 3:
JVM 确实对形如 String str = “javablog”; 的对象放在常量池中,但是它是在编译时做的。而 String s = str1 + str2; 是在 运行时候才能知道的,也就是说 str1 + str2 是在堆里创建的,所以结果为 false 了。str1 + “b” 等类似,在运行时才能知道,所以在堆中创建
深入解析 String#intern
五、数组
int[] a1 = {1, 2, 3};
int[] a2 = new int[5];
长度:a1.length
Arrays.copyOf:int[] copiedLuckyNumbers = Arrays.copyOf(luckyNumbers , luckyNumbers .length);
Arrays.sort (a):使用了优化的归并排序算法
一个 Object 数组不能转换成自定义数组:
即创建数组时 new 表达式中使用的元素类型。将一个 Employee [] 临时地转换成 Object [] 数组, 然后再把它转换回来是可以的,但一个从开始就是 Object [ ] 的数组却永远不能转换成 Employe [ ] 数组。
自定义排序:
1 | class LengthComparator implements Comparator<String> { |
六、java 中的包
java.util 工具包
java.sql 数据库包
java.io 输入输出流包
java.net 网络包
java.lang 基础包
七、Object 通用方法
1 | public native int hashCode() |
八、日期
1 | public class DateTimeTest { |
九、运算符
1. ==
- 对于引用类型,判断引用是否相同
- equals () 判断引用类型值是否相同。但是 equals () 方法的默认行为是比较引用,因此自定义的类中需覆盖 equals () 方法
2. && 与 ||
短路与 和 短路或
3. 移位运算符
运算符用符号位填充高位,>>> 运算符用 0 填充高位
- 1 << 35 == 1 << 3 == 8(int 类型只有 32 位)
十、输入输出
1. 输入
1 | //1.Scanner |
2. 文件输入输出
1 | //读 |