系列:《Java核心技术 卷1》笔记

系列:《Java核心技术 卷1》笔记

一)简介

1. 语言特点

  • 面向对象
  • 健壮性
  • 安全性
  • 可移植性
  • 解释型

2. 数据类型

类型存储字节取值范围
int4[-2^31, 2^31-1]
short2[-2^15, 2^15-1]
long8[-2^63, 2^63-1]
byte1[-2^7, 2^7-1]
float4(有效位6-7位)
double8(有效位15位)
char2[0, 2^16-1]
boolean参考JVM规范

3. 枚举类型

enum Size {
    SMALL, MIDDLE, LARGE
}

Size size = Size.SMALL;

4. 位运算符之移位

运算符说明
<<左移,低位补0
>>右移,高位填充符号位
>>>无符号右移,高位填充0

5. 直接输出数组

System.out.println(Arrays.toString(arr))

6. 新的日期时间

LocalDateTime系列。

7. Java的传参方式

按值引用。

  • 对于基本类型,传的值(int等,值)
  • 对于引用类型,传的值(Java引用,值即为指向对象的地址)

二)OOP

1. 封装

定义:将数据和行为组合在一个包中,对对象的使用者隐藏具体的实现方式。

意义:重用性和可靠性

访问权限
  • public
  • protected
  • 默认
  • private

2. 继承

定义:通过扩展一个类来建立另外一个类的过程

3. 多态

定义:一个对象变量,可指向多种实际类型的现象

动态绑定:在运行时能够自动选择适当的方法

4. 类之间的关系

  • 依赖:user-a。方法参数
  • 聚合:has-a。成员属性
  • 继承:is-a。父子类

5. 关键字

  • this
  • super
  • static
  • final

6. 初始化顺序

1. 父类的【静态】:属性,代码块
2. 子类的【静态】:属性,代码块
3. 父类的【成员】:属性,代码块
4. 父类的构造方法
5. 子类的【成员】:属性,代码块
6. 子类的构造方法

说明:
	【静态】:静态属性,静态代码块。按定义的先后顺序
	【成员】:成员属性,构造代码块

7. 抽象类和接口

主要理解Java的单继承即可。具体的区别其实意义不大,这个更多的看设计时抽象出来的结构。

具体见: 深入理解Java的接口和抽象类

8. lambda表达式

熟悉语法,使用场景。

语法:(parameters) -> expression,或(paras) -> { statements; }

使用案例:菜鸟教程

9. 内部类

类型:成员内部类,局部内部类,静态内部类,匿名内部类。

10. 函数式接口

有且仅有一个抽象方法的接口。

同类型:方法引用,lambda,函数式接口

自定义一个接口:

@FunctionInterface
interface GreetingService {
    void sayMsg(String msg);
}

GreetingService gS = msg -> System.out.println(msg);
gS.sayMsg("hello");

API提供的函数式接口:见源码包java.util.function

三)反射和代理

参考:Java动态代理

1. 什么是反射

运行时

2. 相关API

Class, Method

3. 静态代理

角色:委托类、代理类。

实现解耦,可以在代理类进行过滤增强等处理,而无需修改委托类代码。例如对学生五折销售,对商人八折销售等。

/*
场景:销售。生产,商店。
*/
interface Sell {
    void sell();
}

// 委托类
class Product implements Sell {
    @Override
    public void sell() {
        System.out.println("生产商");
    }
}

// 静态代理类
class Shop implements Sell {
    private Product product;
    // ToDo 构造器
    @Override
    public void sell() {
        this.product.sell();
    }
}

4. 动态代理

代理类,在运行时被创建的代理方式,即动态代理。

优点:对代理类的函数进行统一的处理。而不用修改每个静态代理类的代码。

假设场景:在上述静态代理类的sell方法内,执行product.sell前后都需要输出日志信息。如果只有一个方法sell,很简单,如果有很多方法呢?每个方法都需要添加日志,较为繁琐。

角色

接口:Sell

委托类:Product

中介类:class SellProxy implements InvocationHandler

Object invoke(Object proxy, Method method, Object[] args);

说明:InvocationHandler只有一个方法需要实现,即invoke

解释:调用代理类对象时,这个调用会转送到invoke方法中,代理类对象作为proxy参数传进去,参数method标识了我们具体调用的代理类的方法,args位方法的参数。如此,可在invoke中添加统一的处理

// 接口:Sell
// 委托类:Product
// 终结类
class ProductProxy implements InvocationHandler {
    private Object obj;
    // ToDo 构造器(Object obj)
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) {
        // 调用前处理..
        // 调用:实际是反射
        Object res = method.invoke(obj, args);
        // 调用后处理
        return res;
    }
}
实现机制

需要实现接口,如Sell。JDK动态代理

常见的还有CGLib,利用ASM开源包,通过修改其字节码生成子类来实现。

四)异常体系

1. 异常层次结构

在这里插入图片描述

2. 非检查型异常

Error和RuntimeException

RuntimeException,是可以通过编码避免的异常。

3. 检查型异常

Exception中除RuntimeException

编译器要求必须处理的异常,要么捕获,要么抛出。

4. 如何处理

创建异常类
class MyException  extends Exception {..}
class MyException2 extends RuntimeException {..}
抛出异常
void func(T arg) throws Exception {..}

void func2(T arg) {
	if (arg == null) {
		throw Exception();
	}
}
捕获异常
void func() {
    try {
        ...
    } catch (Exception e) {
        ...
        // 可抛出:throw Exception;
    }
}

5. finally

常用于释放资源。

6. 断言

一种调试程序的方式,建议使用单元测试。

五)泛型

1. 作用

  • 省去强制类型转换
  • 将运行时错误转到编译期。编译检查

2. 泛型类和泛型方法

3. 限制

List<?> list = null;
List<? extends Number> list2 = null;
List<? super Manager> list3 = null;
..

? super Manager

4. 泛型擦除

虚拟机没有泛型。

了解桥方法(保持多态)。

六)集合

1. 迭代器

作用:遍历。

说明:remove和next的搭配

2. List

实现说明
ArrayList默认容量10,扩容1.5倍
LinkedList

3. Queue & Deque

实现说明
PriorityQueue默认容量11,扩容(2倍+2)或(1.5倍)
ArrayQueue容量=(tail-head+cap)%cap
ArrayDeque默认容量16,扩容2倍
LinkedList

4. Set

实现说明
HashSet允许一个null
LinkedHashSet
TreeSet

5. Map

实现说明
HashMap默认容量16,扩容2倍,允许null键和值
桶由链表和红黑树实现
LinkedHashMapNode添加前后指针,记录插入顺序
TreeMap红黑树。节点key+value+left+right+parent+color
WeakHashMap
IdentityHashMap

6. Collections

常见API的使用。

七)IO

1. 控制台

System.out.println();
Scanner sc = new Scanner(System.in);

2. 文件IO

File file = new File(path);
FileOutputStream fos = ..;

3. 序列化

  • 基本类型:DataInputStream
  • 对象:ObjectInputStream

接口:Serializable

transient:序列化跳过当前关键字修饰的属性。

说明:可通过重载readObject和writeObject方法实现序列化

4. 设计模式:装饰模式,适配模式

具体:java的IO之适配器模式和装饰模式

字符流Reader/Writer,适配器: InputStreamReaderOutputStreamWriter

字节流InputStream/OutputStream,装饰器:FilterInputStreamFilterOutputStream

5. 网络IO

  • ServerSocket
  • Socket

6. Java中的IO类型

常见的BIO,阻塞IO。

然后是NIO,非阻塞IO,基础:IO多路复用

详情见:Java NIO浅析 美团技术团队

最后是AIO,异步IO。

八)并发

1. 什么是线程

进程中一个单一顺序的控制流。

2. 实现

  • Thread

  • Runnable

  • Callable

3. 线程状态

新建:new Thread®

可运行:start

阻塞:试图获取内部的对象锁,失败,线程被阻塞(synchronized)

等待:线程等待另一个线程通知调度器出现一个方法时,线程进入等待(wait或join,或j.u.c的Lock或Condition

计时等待:Thread.sleep、Object.wait、Thread.join、Lock.tryLock以及Condition.await

终止:run方法正常退出,或一个没有捕获的异常

4. 线程属性

优先级

中断标志位:静态的Thread.interrupted(),检查当前线程是否被中断,回清除中断状态;成员方法isInterrupted()

说明:线程被阻塞,其他线程调用interrupt()中断当前线程,会抛出异常

守护线程

5. 同步

通过同步,实现存取的顺序访问

6. 锁

  • synchronized
  • ReentrantLock
条件对象:Condition

7. 深入

监视器和synchronized

monitor,略。

volatile

JMM模型:略

  • 保证可见性,原理见JMM模型

三大特性:原子性,可见性,有序性

  • 内存屏障:禁止指令重排
死锁

情形描述:多个线程同时被阻塞,它们中的一个或全部都在等待某个资源释放。

死锁产生的四个必要条件:

  1. 互斥:资源被线程占用,别的线程不能使用
  2. 非抢占:资源只能由占用者释放
  3. 请求和保持:占用资源的线程同时请求资源
  4. 循环等待:存在一个等待队列,P1占用P2需要的资源,P2占用P3的资源,…形成环路

如何解决死锁:synchronized,或Lock。

产生死锁的样例:可使用信号量,避免死锁(具体)

线程1
syn(A) {
	syn(B) {
		..
	}
}

线程2
syn(B) {
	syn(A) {
		..
	}
}
线程局部变量

ThreadLocal

方法:void set(T t)和T get()

场景一:管理数据库连接Connection,保证当前线程操作的都是同一个Connection,保证事务

8. 线程安全的集合

阻塞队列:BlockingQueue

  • ArrayBlockingQueue:必须指定容量

  • LinkedBlockingQueue:可指定容量,默认Integer.MAX_VALUE

  • DelayQueue:无上限阻塞队列

  • PriorityBlockingQueue:无上限

  • TransferQueue

高效的映射、有序集和队列:ConcurrentHashMapConcurrentSkipListMapConcurrentSkipListSetConcurrentLinkedQueue

写数组:CopyOnWriteArrayList

9. 线程池

Executors

newCachedThreadPool: 核心线程=1,最大线程=Integer.MAX_VALUE,存活时间60s,同步队列(线程间同步移交任务)
	new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
newFixedThreadPool: 核心线程=最大线程,LinkedBlockingQueue(容量Integer.MAX_VALUE)
	new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
newScheduledThreadPool: 核心线程=core,最大线程=Integer.MAX_VALUE
	new ScheduledThreadPoolExecutor(corePoolSize);
newSingleThreadExecutor: 核心线程=最大线程=1LinkedBlockingQueue(容量int.max)
	new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));

ThreadPoolExecutor

  • 核心线程

  • 工作队列:阻塞队列BlockingQueue

  • 最大线程数量 & 工作线程

  • 工作线程存活时间

  • 饱和策略

    AbortPolicy:默认。不执行任务,直接抛出运行时异常
    DiscardPolicy:抛弃任务
    DiscardOldestPolicy:抛弃head的任务,即最先入队的任务
    CallerRunsPolicy:在调用execute的线程执行此任务,会阻塞入口
    用户自定义策略:需实现RejectedExecutionHandler
    
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值