基础语法
基本类型(8种)
byte,short,int,long,float,double
char,boolean
基本类型的字面值规则
- 整数字面值是 int 类型
- byte,short,char 比 int 小的整数,可以直接使用范围内的字面值
- 浮点数字面值是 double 类型
- 字面值后缀
- F float
- L long
- D double
- 字面值前缀
- 0x 16进制
- 0 8进制
- 0b 2进制
- \u char类型16进制 ‘\u0061’
基本类型的运算规则
- 整数运算溢出
- 运算结果的类型,和运算项中最大的类型一致
- byte,short,char 比int范围小的整数,先自动转成int再运算
- 浮点数运算不精确,如果做精确运算需要使用 BigDecimal 对象
2-1.9 ----> 0.10000000000009
4.35*100 ----> 434.99999999999994 - 浮点数的特殊值
- Infinity 无穷: 3.14/0, Double.MAX_VALUE*2
- NaN — Not a Number: Math.sqrt(-4)
- 判断一个浮点数是否是 Infinity 或 NaN:
- Double.isInfinite(d1)
- Double.isNaN(d1)
运算符
±*/%
> >= < <=
== !=
&&
||
!
& 位与,两个都是1结果才是1
| 位或,两个都是0结果才是0
^ 相同是0, 不同是1
~ 求反,1变0, 0变1
>> 带符号右移位
>>> 不带符号右移位,不管符号位是1还是0,左边都补0
<< 左移位
=
+= -= /=
()
? :
方法
方法递归 — 方法中调用自身
递归是一步一步的简化问题,把问题简化成最简问题,再倒推求出结果
求阶乘
f(5);
5 * f(4)
4 * f(3)
3 * f(2)
2 * f(1)
1 * f(0)
void f(int n) {
if(n == 0) return 1;
return n * f(n-1);
}
流程控制
if
switch
只能判断byte,short,char,int 这几种整数和 String
break
- 如果没有break,会穿透执行
- 遇到 break 跳出 switch
for
for(int i=1; i<=3; i++) {
for(char j='a'; j<='c'; j++) {
打印 i,j
}
}
1, a
1, b
1, c
2, a
2, b
2, c
3, a
3, b
3, c
while 先判断后执行
do-while 先执行后判断,至少执行1次
break 跳出循环
continue 跳到下一轮循环
循环的命名
在内层循环中,控制外层循环
outer:
for() {
for() {
break outer;
continue outer;
}
}
数组
创建数组的三种语法:
int[] a = new int[5];
int[] a = {2,1,5,7};
a = new int[]{3,2,6};
- 数组长度不可变
- a.length
- 数组遍历
二维数组
数组中保存数组
int[][] a = {{2,3,4}, {2,1}, {3,4,2,6}};
数组的工具类
Arrays.toString()
Arrays.sort()
Arrays.binarySearch()
Arrays.copyOf()
面向对象(*)
封装
类
对象(实例)
引用
构造方法
重载
this
- this.xxx, this.xxx() 调用当前实例的成员,this是特殊引用,引用自己的地址
- this() 调用重载的构造方法
隐藏 ---- 方便代码的维护和修改,私有成员可以随便修改,对其他代码无影响
继承
集成的作用: 代码重用
创建子类实例:
- 先创建父类实例
- 再创建子类实例
- 两个实例绑定在一起整体作为一个实例
调用成员时:
- 先找子类
- 再找父类
方法重写
- 在子类中重新定义继承的方法
super
- super.xxx 调用父类成员
- super() 调用父类的构造方法
多态
多态的作用: 一致的类型
所有子类型的实例,都可以被当做父类型来处理
类型转换
- 向上转型
- 向下转型
instanceof
- 判断一个对象的真实类型
- 对真实类型和父类型判断,都是true
B 继承 A
A a = new B()
a instanceof B --- true
a instanceof A --- true
a instanceof Object --- true
抽象类
- 包含抽象方法的类必须是抽象类
- 抽象类中不一定有抽象方法
abstract class A {
void a() {
…
}
abstract void b();
}
抽象方法的作用:
- 作用通用方法在父类中定义
- 要求子类必须实现这个方法
final,static,访问控制符
final
- 修饰类: 不能被继承
- 修饰方法: 不能在子类中重写
- 修饰常量: 变量的值不可变,即常量
static
- 属于类,而不属于实例
- 静态初始化块
class A {
static {
}
}
private 类
[default] 包
protected 任意子类
public 任意
接口
作用: 结构设计工具, 用来解耦合
内部类
- 非静态内部类
- 静态内部类
- 局部内部类
- 匿名内部类
基础API
-
Object
-
String
- 字符串字面值 “ger4t3” 在“字符串常量池”分配内存
- 常量池中的字符串可以重复使用,不会重复创建
- 字符串连接效率低
String s1 = “aa”;
String s2 = “bb”;
String s3 = “cc”;
String s = s1 + s2 + s3;String s = "aa" + "bb" + "cc"; // 编译器直接优化为 String s = "aabbcc";
-
StringBuilder / StringBuffer
- 一般用来代替字符串做高效率连接运算
- appen()
-
Integer 、Double …
-
BigDecimal
-
Date
-
SimpleDateFormat
集合(*)
-
ArrayList
- 数组存放数据
- 访问效率高
- 增删数据效率可能降低 -
LinkedList
- 双向链表
- 两端效率高
- 如果只在两端操作数据,用双向链表 -
HashMap
- 哈希表
- HashMap 使用 Entry[] 数组存放数据
- 初始长度 16
- 翻倍增长
- 存放数据的运算过程:
- key.hashCode() 获得键的哈希值计算下标 i
- 新建 Entry 实例封装键值对
- 把 Entry 实例放入 i 位置
- 如果是空位置直接方法
- 如果已经有数据,依次用 equals() 比较键是否相等
- 有相等的键,覆盖值
- 没有相等的键,用链表连接在一起
- 加载因子、负载率到 0.75
- 容量翻倍
- 所有数据重新执行哈希运算放入新数组
- jdk1.8
- 链表长度到8,转成红黑树
- 树上的数据减少到6,转回链表 -
LinkedHashMap
- 结合双向链表的哈希表
- 有序的哈希表
-
ConcurrentHashMap
- 多线程并发访问安全的哈希表
- 实现了分段锁
-
Iterator
-
Collections
IO
-
File
-
InputStream / OuputStream 字节流父类
-
FileInputStream / FileOutputStream 读写文件
-
BufferedInputStream / BufferedOutputStream 缓冲流
-
ObjectInputStream / ObjectOutputStream 序列化流
-
Reader / Writer 字符流父类
-
InputStreamReader / OutputStreamWriter 字符编码转换流
-
BufferedReader readLine()方法可以一次读取一行字符
-
PrintWriter / PrintStream print()、println()
Serializable 接口
只有实现这个接口的对象才允许被序列化
线程(*)
-
创建线程
- 继承 Thread
- 实现 Runnable
-
线程常用方法
- start()
- join()
- interrupt()
- sleep()
- yield()
- …
-
synchronized
- synchronized(对象) {
}
争夺执行对象的锁 - synchronized void f() {
}
争夺当前实例(this)的锁 - static synchronized void f() {
}
争夺“类对象”的锁
- synchronized(对象) {
-
生产者消费者模型
- 线程间数据传递的方式
- 线程之间使用一个数据集合来传递数据
- 生产者放入数据
- 消费者取出数据
-
等待和通知
- 没有数据时消费者等待
- 生产者放入数据时发送通知
- wait()
- notify()
- notifyAll()
- 等待和通知方法必须在 synchroznied 内调用
- 等待和通知的对象必须是同一个对象
-
线程工具
-
线程池
- ExecutorService - 线程池
- Executors - 辅助创建线程池的工具类
- newFixedThreadPool(5) 最多5个线程的线程池
- newCachedThreadPool() 创建足够多的线程,使执行的任务不会等待
- newSingleThreadExecutor() 单线程线程池
- 执行任务的方法
- execute(Runnable) 向线程池丢任务
- submit(Runnable) 返回一个 Future 对象,可以等待任务结束
- submit(Callable) 返回一个 Future 对象,可以异步的获得任务执行结果
- Callable / Future
- callable 任务有返回值,可以抛出异常
- future 是取餐条,当需要执行结果时,使用取餐条获取结果
-
ThreadLocal
- 线程数据绑定
- set()
- get()
- remove()
-
-
Lock
- ReentrantLock - 可重入锁
- ReadWriteLock - 读写锁
- 对读锁优化,读锁是共享锁
-
volatile
- 多线程环境下,频繁修改的数据应该添加这个关键字
- 可见性
- 不同cpu之间监听数据的修改,对数据修改可见
- 禁用指令重拍
- cpu可能会对代码执行进行优化,对代码顺序重新排序
- 加 volatile 可以禁用指令重排优化
网络
Socket
ServerSocket
反射
框架底层的实现方式,
如果不做框架开发,很少会使用反射
- 获取类对象
- A.class
- a1.getClass()
- Class.forName(“aa.bb.cc.DD”)
- 获取类的定义信息
- 获得包名类型
- 获得成员变量的定义信息
- 获得构造方法的定义信息
- 获得方法的定义信息
- 反射创建实例
- c.newInstance() - 创建实例,并执行无参构造
- 反射调用成员
- 反射调用成员变量
- 反射调用方法