# 牛客刷题知识点 **Repository Path**: ME_WE/nowcoder-practice ## Basic Information - **Project Name**: 牛客刷题知识点 - **Description**: 记录在牛客遇到的一些知识点,持续更新 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2021-01-31 - **Last Updated**: 2023-04-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 牛客刷题知识点 记录在牛客遇到的一些知识点,持续更新 ## Java 基础 1. is-a,like-a,has-a,uses-a + is-a,理解为是一个,代表继承关系。如果 A is-a B,那么 B 就是 A 的父类。 + like-a,理解为像一个,代表组合关系。如果 A like a B,那么 B 就是 A 的接口。 + has-a,理解为有一个,代表从属关系。如果 A has a B,那么 B 就是 A 的组成部分。 + uses-a,依赖关系 2. **内部类**(也叫成员内部类)可以有 4 种访问权限:private、protected、public 以及默认。 3. 面向对象三大特征:封装,继承,多态。 非要说四大特征的话,那就是:抽象,封装,继承,多态。 4. `==` 比较的是地址值,没有重写的 `equals` 方法默认也是直接调用 `==` 5. Java 体系结构 + Java 编程语言 + Java class 文件格式 + Java API + Java 虚拟机(JVM) 6. 两个数值进行二元操作时,会有如下的转换操作: + 如果两个操作数其中有一个是 `double` 类型,另一个操作就会转换为 `double` 类型; + 否则,如果其中一个操作数是 `float` 类型,另一个将会转换为 `float` 类型; + 否则,如果其中一个操作数是 `long` 类型,另一个会转换为 `long` 类型; + 否则,两个操作数都转换为 `int` 类型。 + 被 `fianl` 修饰的变量不会自动改变类型,当两个 `final` 修饰相操作时,结果会根据左边变量的类型而转化。 7. 类的成员变量包括实例变量和类变量(静态变量),成员方法包括实例方法和类方法(静态方法)。 类变量(静态变量)和类方法(静态方法)用关键字 static 声明。 8. Java 内部类 ![Java 内部类](https://gitee.com/ME_WE/my-picture-repository/raw/master/%E7%89%9B%E5%AE%A2%E5%88%B7%E9%A2%98/Java%20%E5%86%85%E9%83%A8%E7%B1%BB.png) 9. Java 8 的 String 底层是 char 数组,Java 9 之后的 String 底层是 byte 数组。 10. 一个 .java 文件中,可以有多个类,包括内部类和外部类。考虑到内部类的原因,一个 .java 文件中可以有多个 public 类。但是对于外部类而言,一个 .java 文件必须只能有一个 public 类,同时这个类的类名必须和 .java 的文件名一致(包括大小写)。 11. 构造函数不能被继承,构造方法只能被显式或隐式的调用。 12. 多态的作用:提高可重用性,扩展代码模块 13. Java 关键字,共 50 个 > [Java Language Keywords](https://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html) > > Here is a list of keywords in the Java programming language. You cannot use any of the following as identifiers in your programs. The keywords `const` and `goto` are reserved, even though they are not currently used. `true`, `false`, and `null` might seem like keywords, but they are actually literals; you cannot use them as identifiers in your programs. > > 下面是 Java 编程语言中的关键字列表。您不能在程序中使用以下任何一项作为标识符。关键字 `const` 和 `goto` 是保留的,即使它们当前未被使用。`true` 、`false` 和 `null` 可能看起来像关键字,但实际上它们是字面量;您不能在程序中将它们用作标识符。 > > | | | | | | > | -------- | -------- | ---------- | --------- | ------------ | > | abstract | continue | for | new | switch | > | assert | default | goto | package | synchronized | > | boolean | do | if | 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 | 14. `final` 不能修饰接口和抽象(abstract)类 因为接口需要类去实现,抽象类需要类去继承,都需要重写其中的方法;但是 final 是不可继承的,相矛盾。 15. 访问权限从大到小依次为:public,protected,默认(包访问),private。 16. Java 实现了真数组,避免了覆盖数据的可能,而不是覆盖数据类型。 真数组:数组元素在内存中是一个接一个线性存放的。 17. 接口可以继承一个或多个接口 18. 类的成员变量会自动进行初始化,引用数据类型默认为 `null`,基本数据类型默认对应值; 局部变量不会自动进行初始化。 19. for 循环结束的判断条件必须是 `boolean` 类型 for 循环执行流程: ``` for (1; 2; 4) { 3 } ``` 20. 管道通信为半双工模式,且只能在具有亲缘关系的进程间使用。 21. `static` 不能修饰类,除非该类是内部类 22. Object 类中的方法(Java SE 11) ![Object 类中的方法](https://gitee.com/ME_WE/my-picture-repository/raw/master/%E7%89%9B%E5%AE%A2%E5%88%B7%E9%A2%98/Java%2011%20Object%20%E4%B8%AD%E7%9A%84%E6%96%B9%E6%B3%95.png) 23. 数组直接调用 `equals()` 方法,调用的是 `Object.equals()`,比较的是地址值;如果要比较数组元素,应该调用 `Arrays.equals()`。 24. 执行顺序:父类静态代码块 -> 子类静态代码块 -> 父类非静态代码块 -> 父类构造函数 -> 子类非静态代码块 -> 子类构造函数。 25. Java 多态有两种情况:重载和覆写 在覆写中,运用的是动态单分配,是根据 new 的类型确定对象,从而确定调用的方法; 在重载中,运用的是静态多分派,即根据静态类型确定对象,因此不是根据new的类型确定调用的方法。 + 成员变量:编译和运行都参考左边; + 成员函数(非静态):编译看左边,运行看右边; + 静态函数:编译和运行都看左边。 26. 关于 Java 构造函数 1. 构造方法可以被重载,一个构造方法可以通过 `this` 关键字调用另一个构造方法,`this` 语句必须位于构造方法的第一行; 2. 当一个类中没有定义任何构造方法,Java 将自动提供一个缺省构造方法; 3. 子类通过 `super` 关键字调用父类的一个构造方法; 4. 当子类的某个构造方法没有通过 `super` 关键字调用父类的构造方法,通过这个构造方法创建子类对象时,会自动先调用父类的缺省构造方法; 5. 构造方法不能被 static、final、synchronized、abstract、native 修饰,但可以被 public、private、protected 修饰; 6. 构造方法不是类的成员方法; 7. 构造方法不能被继承。 27. 不能用来修饰 interface 的有(`private`、`protected`、`static`)(仅限外部接口) 28. `<<` 表示左移;`>>` 表示带符号右移;`>>>` 表示无符号右移;没有 `<<<`,因为 `<<` 后右边总是补 0。 29. 在调用子类构造器之前,会先调用父类构造器,当子类构造器中没有使用 `super` 指定调用父类构造器时,是默认调用父类的无参构造器,如果父类中包含有参构造器,却没有无参构造器,则在子类构造器中一定要使用 `super(参数)` 指定调用父类的有参构造器,不然就会报错。 30. Java 运算符优先级 ![Java 运算符优先级](https://uploadfiles.nowcoder.com/images/20200115/943949859_1579095580482_4B515A30E58F292D4E0C7907955D4283) 31. Java IO 流 字符流:以 Reader / Writer 结尾 字节流:以 Stream 结尾 ![IO 流](https://gitee.com/ME_WE/my-picture-repository/raw/master/%E7%89%9B%E5%AE%A2%E5%88%B7%E9%A2%98/IO%20%E6%B5%81.png) 32. javac 命令 ![javac 命令](https://gitee.com/ME_WE/my-picture-repository/raw/master/%E7%89%9B%E5%AE%A2%E5%88%B7%E9%A2%98/javac%20%E5%91%BD%E4%BB%A4.png) 33. InputStreanReader 可以指定字符集 34. 关于 Java 编译 + Java 编译成的是字节码,再被各系统的 JVM 翻译成本系统可以识别的机器码,这就是 Java 一次编程多平台应用的跨平台性 + Java 源文件生成的是 class 文件,与系统无关 + 注意字节码和机器码不是一回事,Java 程序在运行时字节码才会被 JVM 翻译成机器码,所以说 Java 是解释性语言 + JVM 有版本之别,Java 编译出来的目标文件,并不能运行在任意 JVM 上 35. `finally` 语句块是在 `try-catch` 语句块中的 `return` 语句**之后**执行的。流程如下: 1. 如果有返回值,就把返回值保存到局部变量中 2. 执行 jsr 指令跳到 `finally` 语句里执行 3. 执行完 `finally` 语句后,返回之前保存在局部变量表里的值 **如果 `try` ,`finally` 语句里均有 `return`,忽略 `try` 的 `return`,而使用 `finally` 的 `return` 。** 36. `equals()` 与 `hashCode()` + `equals()` 相等的两个对象他们的 `hashCode()` 肯定相等,也就是用 `equals()` 对比是绝对可靠的 + `hashCode()` 相等的两个对象他们的 `equals()` 不一定相等,也就是 `hashCode()` 不是绝对可靠的 因此每当需要对比的时候,首先用 `hashCode()` 去对比,如果 `hashCode()` 不一样,则表示这两个对象肯定不相等,也就是不必再用 `equal()` 去再对比了;如果 `hashCode()` 相同,此时再对比他们的 `equals()` ,如果 `equals()` 也相同,则表示这两个对象是真的相同了。这样兼顾效率与正确性。 37. `transient` 关键字,只需要实现 Serializable 接口,将不需要序列化的属性前添加关键字 `transient`,序列化对象的时候,这个属性就不会序列化到指定的目的地中。 38. 抽象方法不可以有方法体 39. `final` + `final` 修饰的类不可被继承 + `final` 修饰的方法不可被重写 + `final` 修饰的基本数据类型的值一旦初始化,不能被修改 + `final` 修饰的引用类型对象,初始化后该引用不能再指向其他对象,但所指对象的内容可变 40. `super()` 和 `this()` 都必须位于构造器的第一行,而且不能同时使用,这是因为会造成初始化两次,`this()` 用于调用重载的构造器,`super() ` 用于调用父类被子类重写的方法 41. 面向对象五大基本原则 1. 单一职责原则(Single-Resposibility Principle) 一个类,最好只做一件事,只有一个引起它的变化。单一职责原则可以看做是低耦合、高内聚在面向对象原则上的引申,将职责定义为引起变化的原因,以提高内聚性来减少引起变化的原因。 2. 开放封闭原则(Open-Closed principle) 软件实体应该是可扩展的,而不可修改的。也就是,对扩展开放,对修改封闭的。 3. 里氏替换原则(Liskov-Substituion Principle) 子类必须能够替换其基类。这一思想体现为对继承机制的约束规范,只有子类能够替换基类时,才能保证系统在运行期内识别子类,这是保证继承复用的基础。 4. 接口隔离原则(Interface-Segregation Principle) 使用多个小的专门的接口,而不要使用一个大的总接口 5. 依赖倒置原则(Dependecy-Inversion Principle) 依赖于抽象。具体而言就是高层模块不依赖于底层模块,二者都同依赖于抽象;抽象不依赖于具体,具体依赖于抽象。 便于记忆:SOLID 固体 42. 流 按照流是否直接与特定的地方(如磁盘、内存、设备等)相连,分为节点流和处理流两类: + 节点流:可以从或向一个特定的地方(节点)读写数据 + 处理流:是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写 常用节点流: + 文件 + 字符串 + 数组 + 管道 常用处理流: + 缓冲流 + 转换流 + 数据流 43. Java 的基本编程单位是类,基本存储单元是变量 44. Java 有 5 种方式创建对象 1. 使用 `new` 关键字 2. 反射:java.lang.Class 类的 `newInstance()` 方法 ``` ObjectName obj = ObjectName.class.newInstance(); ``` 3. 反射:java.lang.reflect.Constructor 类的 `newInstance()` 方法 ``` ObjectName obj = ObjectName.class.getConstructor.newInstance(); ``` 4. 对象 `clone()` 方法 ``` ObjectName obj = obj.clone(); ``` 5. 反序列化,调用 java.io.ObjectInputStream 对象的 `readObject()` 方法 ``` try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(FILE_NAME))) { ObjectName obj = ois.readObject(); } ``` 45. --- ## Java 集合 1. HashMap 实现的接口有:`Map`,`Cloneable`,`Serializable`。没有 `Collection` 接口。 2. `Iterator.remove()` 支持从源集合中安全地删除对象。 3. HashMap 1. HashMap 的基类是 AbstractMap,基接口是 Map 2. 初始容量 16,装载因子 0.75。扩容机制:2 * 旧表长度。 Capacity 和 LoadFactor 是影响其性能的两个参数。 3. 扩容条件:HashMap.size >= Capacity * LoadFactor 4. 线程不安全 5. 迭代方法:迭代器 6. HashMap 的 K 和 V 都可以是 `null` ,但 `null` 键最多只能有一个 在 HashMap 中不能由 `get()` 方法来判断 HashMap 中是否存在某个键, 而应该用 `containsKey()` 方法来判断。因为当 `get()` 方法返回 `null` 时,既可以表示 HashMap 中没有该键,也可以表示该键为 null 。 7. 取消了 `contains` 方法,使用 `containsKey` 和 `containsValue` 8. 解决哈希冲突:拉链法 > 解决冲突主要有三种方法: > > 1. 开放定址法 > 2. 链地址法(拉链法) > 3. 再哈希法(再散列法) 9. 4. Hashtable 1. Hashtable 的基类是 Dictionary,基接口是 Map 2. 初始容量 11,装载因子 0.75。扩容机制:2 * 旧表长度 + 1。 3. 线程安全,所有方法使用 synchronized 4. 迭代方法:迭代器,枚举 5. K 和 V 都不能是 `null` 6. 三个方法都有:`contains` , `containsKey` , `containsValue` 5. 常用集合线程安全 ![常用集合线程安全](https://gitee.com/ME_WE/my-picture-repository/raw/master/%E7%89%9B%E5%AE%A2%E5%88%B7%E9%A2%98/%E5%B8%B8%E7%94%A8%E9%9B%86%E5%90%88%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8.png) 6. java.util.PriorityQueue > An unbounded priority [queue](https://docs.oracle.com/javase/8/docs/api/java/util/Queue.html) based on a priority heap. The elements of the priority queue are ordered according to their [natural ordering](https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html), or by a [`Comparator`](https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html) provided at queue construction time, depending on which constructor is used. A priority queue does not permit `null` elements. A priority queue relying on natural ordering also does not permit insertion of non-comparable objects (doing so may result in `ClassCastException`). > > The *head* of this queue is the *least* element with respect to the specified ordering. If multiple elements are tied for least value, the head is one of those elements -- ties are broken arbitrarily. The queue retrieval operations `poll`, `remove`, `peek`, and `element` access the element at the head of the queue. > > A priority queue is unbounded, but has an internal *capacity* governing the size of an array used to store the elements on the queue. It is always at least as large as the queue size. As elements are added to a priority queue, its capacity grows automatically. The details of the growth policy are not specified. > > This class and its iterator implement all of the *optional* methods of the [`Collection`](https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html) and [`Iterator`](https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html) interfaces. The Iterator provided in method [`iterator()`](https://docs.oracle.com/javase/8/docs/api/java/util/PriorityQueue.html#iterator--) is *not* guaranteed to traverse the elements of the priority queue in any particular order. If you need ordered traversal, consider using `Arrays.sort(pq.toArray())`. > > **Note that this implementation is not synchronized.** Multiple threads should not access a `PriorityQueue` instance concurrently if any of the threads modifies the queue. Instead, use the thread-safe [`PriorityBlockingQueue`](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/PriorityBlockingQueue.html) class. > > Implementation note: this implementation provides O(log(n)) time for the enqueuing and dequeuing methods (`offer`, `poll`, `remove()` and `add`); linear time for the `remove(Object)` and `contains(Object)` methods; and constant time for the retrieval methods (`peek`, `element`, and `size`). > > This class is a member of the [Java Collections Framework](https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html). > > 基于优先堆的无界 priority queue。priority queue 的元素根据其自然顺序排列,或者由队列构造时提供的 `Comparator` 排列,具体取决于使用的构造函数。**priority queue 不允许 `null` 元素**。依赖于自然排序的 priority queue 也不允许插入不可比较的对象(这样做可能会导致 `ClassCastException`)。 > > 队列的头是相对于指定顺序最少的元素。如果多个元素以最小值绑定,则头部就是其中一个元素—绑定被任意断开。队列检索操作 `poll`、`remove`、`peek` 和 `element` 访问队列头部的元素。 > > **priority queue 是无界的**,但其内部容量控制用于存储队列中元素的数组的大小。它总是至少和队列大小一样大。当元素被添加到优先级队列时,其容量会自动增长。增长策略的详细信息没有具体说明。 > > 这个类及其迭代器实现了 `Collection` 和 `Iterator` 接口的所有可选方法。方法 `iterator()` 中提供的迭代器不能保证以任何特定顺序遍历 priority queue 的元素。如果需要有序遍历,请考虑使用 `Arrays.sort(pq.toArray())`。 > > **请注意,此实现不是同步的。**如果任何线程修改队列,则多个线程不应同时访问 `PriorityQueue` 实例。相反,请使用线程安全的 `PriorityBlockingQueue` 类。 > > 实现说明:入队和出队方法(`offer`、`poll`、`remove()` 和 `add`)时间复杂度 O(log(n) ;为 `remove(Object)` 和 `contains(Object)` 方法线性时间复杂度;检索方法(`peek`、`element` 和 `size`)常数时间。 > > 此类是 Java 集合框架的成员。 7. java.util.concurrent.LinkedBlockingQueue > An optionally-bounded [blocking queue](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/BlockingQueue.html) based on linked nodes. This queue orders elements FIFO (first-in-first-out). The *head* of the queue is that element that has been on the queue the longest time. The *tail* of the queue is that element that has been on the queue the shortest time. New elements are inserted at the tail of the queue, and the queue retrieval operations obtain elements at the head of the queue. Linked queues typically have higher throughput than array-based queues but less predictable performance in most concurrent applications. > > The optional capacity bound constructor argument serves as a way to prevent excessive queue expansion. The capacity, if unspecified, is equal to [`Integer.MAX_VALUE`](https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html#MAX_VALUE). Linked nodes are dynamically created upon each insertion unless this would bring the queue above capacity. > > This class and its iterator implement all of the *optional* methods of the [`Collection`](https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html) and [`Iterator`](https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html) interfaces. > > This class is a member of the [Java Collections Framework](https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html). > > 基于链表的**可选有界**阻塞队列。这个队列命令元素 **FIFO**(先进先出)。队列的头是在队列中出现时间最长的元素。队列的尾部是在队列中出现时间最短的元素。新元素被插入到队列的尾部,队列检索操作获得队列头部的元素。链表队列通常比基于数组的队列具有更高的吞吐量,但在大多数并发应用程序中性能不太可预测。 > > 可选的指定 capacity 的构造函数用作防止队列过度扩展。如果未指定 capacity,等于 `Integer.MAX_VALUE`。链表节点在每次插入时动态创建,除非这样会使队列超过容量。 > > 这个类及其迭代器实现了 `Collection` 和 `Iterator` 接口的所有可选方法。 > > 此类是 Java 集合框架的成员。 8. java.util.concurrent.ConcurrentLinkedQueue > An unbounded thread-safe [queue](https://docs.oracle.com/javase/8/docs/api/java/util/Queue.html) based on linked nodes. This queue orders elements FIFO (first-in-first-out). The *head* of the queue is that element that has been on the queue the longest time. The *tail* of the queue is that element that has been on the queue the shortest time. New elements are inserted at the tail of the queue, and the queue retrieval operations obtain elements at the head of the queue. A `ConcurrentLinkedQueue` is an appropriate choice when many threads will share access to a common collection. Like most other concurrent collection implementations, this class does not permit the use of `null` elements. > > This implementation employs an efficient *non-blocking* algorithm based on one described in [Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms](http://www.cs.rochester.edu/u/michael/PODC96.html) by Maged M. Michael and Michael L. Scott. > > Iterators are *weakly consistent*, returning elements reflecting the state of the queue at some point at or since the creation of the iterator. They do *not* throw [`ConcurrentModificationException`](https://docs.oracle.com/javase/8/docs/api/java/util/ConcurrentModificationException.html), and may proceed concurrently with other operations. Elements contained in the queue since the creation of the iterator will be returned exactly once. > > Beware that, unlike in most collections, the `size` method is *NOT* a constant-time operation. Because of the asynchronous nature of these queues, determining the current number of elements requires a traversal of the elements, and so may report inaccurate results if this collection is modified during traversal. Additionally, the bulk operations `addAll`, `removeAll`, `retainAll`, `containsAll`, `equals`, and `toArray` are *not* guaranteed to be performed atomically. For example, an iterator operating concurrently with an `addAll` operation might view only some of the added elements. > > This class and its iterator implement all of the *optional* methods of the [`Queue`](https://docs.oracle.com/javase/8/docs/api/java/util/Queue.html) and [`Iterator`](https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html) interfaces. > > Memory consistency effects: As with other concurrent collections, actions in a thread prior to placing an object into a `ConcurrentLinkedQueue` [*happen-before*](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility) actions subsequent to the access or removal of that element from the `ConcurrentLinkedQueue` in another thread. > > This class is a member of the [Java Collections Framework](https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html). > > **基于链表的无界线程安全队列**。这个队列命令元素 **FIFO**(先进先出)。队列的头是在队列中出现时间最长的元素。队列的尾部是在队列中出现时间最短的元素。新元素被插入到队列的尾部,队列检索操作获得队列头部的元素。当许多线程将共享对公共集合的访问权限时,`ConcurrentLinkedQueue` 是一个合适的选择。与大多数其他并发集合实现一样,此类**不允许使用 `null` 元素**。 > > 该实现基于 Maged M.Michael 和 Michael L.Scott 提出的简单、快速、实用的非阻塞和阻塞并发队列算法,采用了一种**高效的非阻塞算法**。 > > 迭代器是弱一致的,返回的元素反映了在迭代器创建时或创建之后某个时刻的队列状态。它们不会抛出 `ConcurrentModificationException`,并且可以与其他操作同时进行。创建迭代器后队列中包含的元素将只返回一次。 > > 注意,与大多数集合不同,**`size` 方法不是一个常量时间操作**。由于这些队列的异步性质,确定当前元素数需要遍历元素,因此如果在遍历期间修改此集合,则可能会报告不准确的结果。此外,批量操作 `addAll`、`removeAll`、`retainAll`、`containsAll`、`equals` 和 `toArray` 不能保证以原子方式执行。例如,与 `addAll` 操作并发操作的迭代器可能只查看一些添加的元素。 > > 这个类及其迭代器实现了 `Queue` 和 `Iterator` 接口的所有可选方法。 > > 内存一致性影响:与其他并发集合一样,在将对象放入 `ConcurrentLinkedQueue` 之前,线程中的操作发生在另一个线程中从 `ConcurrentLinkedQueue` 访问或删除该元素之后的操作之前。 > > 此类是 Java 集合框架的成员。 9. --- ## 异常 1. 运行时异常,可以通过 Java 虚拟机来自行处理; 非运行时异常,应该捕获或者抛出。 2. 常见异常继承关系 ![常见异常继承关系](https://gitee.com/ME_WE/my-picture-repository/raw/master/%E7%89%9B%E5%AE%A2%E5%88%B7%E9%A2%98/Throwable.png) 3. InterruptedException > Thrown when a thread is waiting, sleeping, or otherwise occupied, and the thread is interrupted, either before or during the activity. > > 当线程正在等待、睡眠或被占用,并且线程在活动之前或活动期间被中断时抛出。 打断会抛出 InterruptedException 的常见方法有: + java.lang.Object.wait() + java.lang.Thread.sleep() + java.lang.Thread.join() 4. --- ## 多线程 1. 线程安全的 Map + `java.util.Hashtable` 通过 synchronized 来保证线程安全。即:多线程通过同一个“对象的同步锁”来实现并发控制。Hashtable 在线程竞争激烈时,效率比较低(此时建议使用 ConcurrentHashMap)。当一个线程访问Hashtable 的同步方法时,其他线程如果也在访问 Hashtable 的同步方法,可能会进入阻塞状态。 + `java.util.concurrent.ConcurrentHashMap` 在 Java 7 中它是通过“分段锁”来保证线程安全的,本质上也是一个“可重入的互斥锁”(ReentrantLock)。多线程对同一个片段的访问,是互斥的;但是,对于不同片段的访问,却是可以同步进行的。 在 Java 8 中是通过使用 CAS 原子更新、volatile 关键字、synchronized 可重入锁实现的。 + `java.util.Collections.synchronizedMap(Map m)` 这是 Collections 工具类中的一个方法,可以把 Map 同步,本质就是给每一个方法加上 synchronized 关键字进行同步 2. `SimpleDateFormat` 对象是线程不安全的 3. Java 多线程实现方式主要有四种: 1. 继承 `Thread` 类 2. 实现 `Runnable` 接口 3. 实现 `Callable` 接口通过 `FutureTask` 包装器来创建 `Thread` 线程 4. 使用 `ExecutorService`、`Callable`、`Future` 实现有返回结果的多线程 4. Java 线程状态转换 ![Java 线程状态转换](https://gitee.com/ME_WE/my-picture-repository/raw/master/%E7%89%9B%E5%AE%A2%E5%88%B7%E9%A2%98/Java%E7%BA%BF%E7%A8%8B%E7%8A%B6%E6%80%81%E8%BD%AC%E6%8D%A2.png) 5. 使线程释放锁资源:`wait()` `join()` 。 `sleep()` 在指定时间内让当前正在执行的线程暂停执行,但不会释放“锁标志”。 6. 直接调用 Thread 对象的 `run` 方法不会报异常,但是会直接在主线程中运行,起不到多线程的效果。 应该调用 `start` 方法启动一个新线程。 7. volatile 与 synchronized ![volatile 与 synchronized](https://gitee.com/ME_WE/my-picture-repository/raw/master/%E7%89%9B%E5%AE%A2%E5%88%B7%E9%A2%98/volatile%20%E4%B8%8E%20synchronized.png) 8. ThreadLocal + ThreadLocal 并没有继承任何类,也没有实现任何接口 + ThreadLocal 类为每一个线程都维护了自己独有的变量拷贝。每个线程都拥有了自己独立的一个变量。所以 ThreadLocal 重要作用并不在于多线程间的数据共享,而是**数据的独立** + ThreadLocal 保证各个线程间数据安全,每个线程的数据不会被另外线程访问和破坏。每个线程在访问该变量时,读取和修改的,都是自己独有的那一份变量拷贝,不会被其他线程访问,变量被彻底封闭在每个访问的线程中 + ThreadLocal 中定义了一个哈希表用于为每个线程都提供一个变量的副本 + ThreadLocal 解决哈希冲突所使用的是**开放寻址法** 9. `suspend` 与 `resume` 配套使用 `suspend` 用于将线程挂起,`resume` 用于恢复被 `suspend` 挂起的线程。 注意:因为容易引起死锁,这两个方法从 1.2 起就已经被弃用了 10. synchronized 保证原子性、有序性、可见性; volatile 保证有序性、可见性,不能保证原子性。 11. --- ## JVM 1. 关于 OOM(Out Of Memory,内存溢出) + `java.lang.OutOfMemoryError: PermGen space` “永久代”内存不足。“永久代”的解释应该为 JVM 中的方法区,主要用于存储类信息、常量、静态变量、即时编译器编译后代码等。本错误仅限于 Hotspot 虚拟机,本区进行垃圾回收很少,不够直接加大。增加 `-XX:MaxPermSize` 这个参数的值的话,这个问题通常会得到解决。 Java 8 没有 Permanent Generation,取而代之的是元空间(MetaSpace)。 + `java.lang.OutOfMemoryError: Requested array size exceeds VM limit` 数组过长导致堆内存溢出,加大堆内存或者减少数组长度。 + `java.lang.OutOfMemoryError: Java heap space` 堆内存不足。可通过 `-Xmx` 参数来增加堆的大小 + `java.lang.OutOfMemoryError: nativeGetNewTLA` 当虚拟机不能分配新的线程本地空间(Thread Local Area)的时候错误信息,此错误是线程申请一个新的 TLA 时产生的,这个异常一般发生在 JRockit 虚拟机,只有过于绝对。 2. 一些 JVM 命令 + jps:查看本机 java 进程信息 + jstack:打印线程的**栈**信息,制作线程 dump 文件。 + jmap:打印内存映射,制作**堆** dump 文件 + jstat:性能监控工具 + jhat:内存分析工具 + jconsole:简易的可视化控制台 + jvisualvm:功能强大的控制台 3. 垃圾回收在 JVM 中优先级很低; 程序开发者只能推荐 JVM 进行垃圾回收,但何时回收、回收哪些,开发人员不能控制; 垃圾回收机制只是回收不再使用的 JVM 内存,并不能保证程序不会出现内存溢出,如果程序有严重 BUG,依旧会内存溢出。 4. JVM 默认提供的三个 ClassLoader:启动类加载器 BootStrap ClassLoader,扩展类加载器 Extension ClassLoader,应用类加载器 App ClassLoader + BootStrap ClassLoader:负责加载 Java 基础类,主要是 %JRE_HOME/lib/ 目录下的 rt.jar、resources.jar、charsets.jar 和 class 等。 + Extension ClassLoader:负责加载 Java 扩展类,主要是 %JRE_HOME/lib/ext 目录下的 jar 和 class。 + App ClassLoader:负责加载当前 Java 应用的 classpath 中的所有类。 5. ClassLoader 使用的是**双亲委托模型**来搜索类的 6. JVM 在判定两个 class 是否相同时,不仅要判断两个类名是否相同,而且要判断是否由同一个类加载器实例加载的。 7. JVM 内存管理 ![JVM 内存管理](https://uploadfiles.nowcoder.com/images/20181226/242025553_1545835787199_11CD8DF4C9693369E94F5F84238EBBC6) 8. JVM 内存管理 ![JVM 内存管理](https://gitee.com/ME_WE/my-picture-repository/raw/master/%E7%89%9B%E5%AE%A2%E5%88%B7%E9%A2%98/JVM%20%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.png) 9. off-heap,堆外内存。堆外内存意味着把内存对象分配在 Java 虚拟机的堆以外的内存,这些内存直接受操作系统管理(而不是虚拟机)。不属于老年代和新生代。 10. JVM 内存可简单分为三个区: + 堆区(heap):用于存放所有对象,是线程共享的(注:数组也属于对象) + 栈区(stack):用于存放基本数据类型的数据和对象的引用,是线程私有的(分为:虚拟机栈和本地方法栈) + 方法区(method):用于存放类信息、常量、静态变量、编译后的字节码等,是线程共享的(也被称为非堆,即 None-Heap) **Java 的垃圾回收器(GC)主要针对堆区** 11. 关于运行时常量池 + 运行时常量池大小受方法区大小的影响 + 存放编译时期生成的各种字面量 + 存放编译时期生成的符号引用 12. 泛型与 JVM + 创建泛型对象的时候,一定要指出类型变量 T 的具体类型。争取让编译器检查出错误,而不是留给JVM运行的时候抛出类不匹配的异常。 + 虚拟机中没有泛型,只有普通类和方法 + 类型擦除:在编译阶段,所有泛型类的类型参数都会被 Object 或者它们的限定边界来替换 + 在继承泛型类型的时候,桥方法的合成是为了避免类型变量擦除所带来的多态灾难。 无论我们如何定义一个泛型类型,相应的都会有一个原始类型被自动提供。原始类型的名字就是擦除类型参数的泛型类型的名字。 + 虽然有类型擦除机制,但是依旧能够在运行时动态获取 T 的实际类型 13. 一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其 finalize() 方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。 14. --- ## Java 新特性 ### Java 8 接口默认方法 1. `default` 修饰的方法,是普通实例方法,可以用 `this` 调用,可以被子类继承、重写。 2. `static` 修饰的方法,使用上和一般类静态方法一样。但它不能被子类继承,只能用 `Interface` 调用。 Lambda 表达式 函数式接口 Optional Stream API + Filter(过滤) + Sorted(排序) + Map(映射) + Match(匹配) + Count(计数) + Reduce(规约) + Parallel Stream(并行流) Date API 可重复注解 `@Repeatable` ### Java 9 Java 平台模块系统 Jshell 集合、Stream 和 Optional 调整 进程 API --- ## 数据库 1. 加载驱动方法 1. `Class.forName("com.mysql.jdbc.Driver");` 2. `DriverManager.registerDriver(new com.mysql.jdbc.Driver());` 3. `System.setProperty("jdbc.drivers", "com.mysql.jdbc.Driver");` 2. 创建 Statement 是不传参的,创建 PreparedStatement 需要传入 SQL 语句。 3. Java 数据库连接库 JDBC 用到哪种设计模式?桥接模式 4. java.sql.Statement 接口继承树 ![java.sql.Statement 接口继承树](https://gitee.com/ME_WE/my-picture-repository/raw/master/%E7%89%9B%E5%AE%A2%E5%88%B7%E9%A2%98/java.sql.Statement%20%E6%8E%A5%E5%8F%A3%E7%BB%A7%E6%89%BF%E6%A0%91.png) 5. 事务隔离级别 | 隔离级别 | 脏读 | 不可重复读 | 幻读 | | -------------------------------------- | ---- | ---------- | ---- | | READ_UNCOMMITTED(读未提交) | 有 | 有 | 有 | | READ_COMMITTED(读已提交) | 无 | 有 | 有 | | REPEATABLE_READ(可重复读,MySQL默认) | 无 | 无 | 有 | | SERIALIZABLE(串行化) | 无 | 无 | 无 | 6. --- ## Java Web 1. JSP 九大内置对象 `request`,`response`,`session`,`application`,`page`,`pageContext`,`out`,`exception`,`config`。 2. 获取 http 请求中的 cookie 值 + `request.getHeader` + `request.getCookies` 3. `doGet()` / `doPost()` 是在 javax.servlet.http.HttpServlet 中实现的 4. `service()` 是在 javax.servlet.Servlet 接口中定义的 5. 不管是 post 还是 get 方法提交过来的连接,都会在 service 中处理,service 判断请求类型,决定是调用 doGet 还是 doPost 方法 6. BOM 中 History 属性和方法 BOM,Browser Object Model,浏览器内置对象管理模型 History 的属性和方法: + `length` :返回浏览器历史列表中的 URL 数量 + `back()` :加载 history列表中的前一个 URL + `forward()` :加载 history 列表中的下一个 URL + `go()` :加载 history 列表中的某个具体页面 7. Servlet 生命周期 ![Servlet 生命周期](https://gitee.com/ME_WE/my-picture-repository/raw/master/%E7%89%9B%E5%AE%A2%E5%88%B7%E9%A2%98/Servlet%20%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.png) 8. 在 Web 应用程序中,(Web 容器)负责将 HTTP 请求转换为 HttpServletRequest 对象 9. WebService + Webservice 是跨平台,跨语言的远程调用技术 + Webservice 通信机制实质就是 XML 数据交换 + Webservice 采用了 SOAP 协议(简单对象访问协议)进行通信 + WSDL (Web Service Description Language) 是用于描述 Web Services 以及如何对它们进行访问 10. 在 WEB 开发中实现会话跟踪的方法 + session + Cookie + URL 重写 + 表单隐藏域 11. 关于 Socket 通信编程 客户端:通过 `new Socket()` 创建通信的 Socket 对象 服务端:服务端通过 `new ServerSocket()` 创建 TCP 连接对象,`accept` 接纳客户端请求 12. servlet 处于服务器进程中,它通过**多线程**方式运行其 service 方法,一个实例可以服务于多个请求,并且其实例一般不会销毁;而 CGI 对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于 servlet。 13. --- ## 数据结构与算法 1. 排序算法 ![排序算法](https://gitee.com/ME_WE/my-picture-repository/raw/master/%E7%89%9B%E5%AE%A2%E5%88%B7%E9%A2%98/%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95.png) 2. 几种常见数据结构的操作性能 | | 查找 | 插入 | 删除 | 遍历 | | ---------------------------- | ----------- | ----------- | ----------- | ------ | | 数组 | $O(n)$ | $O(1)$ | $O(n)$ | — | | 有序数组 | $O(\log n)$ | $O(n)$ | $O(n)$ | $O(n)$ | | 链表 | $O(n)$ | $O(1)$ | $O(n)$ | — | | 有序链表 | $O(n)$ | $O(n)$ | $O(n)$ | $O(n)$ | | 二叉树(一般情况) | $O(\log n)$ | $O(\log n)$ | $O(\log n)$ | $O(n)$ | | 二叉树(最坏情况) | $O(n)$ | $O(n)$ | $O(n)$ | $O(n)$ | | 平衡树(一般情况和最坏情况) | $O(\log n)$ | $O(\log n)$ | $O(\log n)$ | $O(n)$ | | 哈希表 | $O(1)$ | $O(1)$ | $O(1)$ | — | 3. --- ## 框架 1. 优化 Hibernate 所鼓励的 7 种措施 1. 尽量使用多对一,避免使用单项一对多 2. 灵活使用单向一对多 3. 不用一对一,使用多对一代替一对一 4. 配置对象缓存,不使用集合缓存 5. 一对多使用 Bag ,多对一使用 Set 6. 继承使用显示多态 HQL : from object polymorphism="exlicit" 避免查处所有对象 7. 消除大表,使用二级缓存 2. 事务的传播行为可以由传播类型指定,Spring 定义了 7 种传播类型 | 传播类型 | 描述 | | :------------ | ------------------------------------------------------------ | | REQUIRED | 如果有事务在运行,当前的方法就在这个事务内运行;否则,就启动一个新的事务,并在自己的事务内运行 | | REQUIRES_NEW | 当前的方法必须启动新事务,并在它自己的事务内运行;如果有事务正在运行,应该将它挂起 | | SUPPORTS | 如果有事务在运行,当前的方法就在这个事务内运行,否则它可以不运行在事务中 | | NOT_SUPPORTED | 当前的方法不应该运行在事务中,如果有运行的事务,将它挂起 | | MANDATORY | 当前的方法必须运行在事务内部,如果没有正在运行的事务,就抛出异常 | | NEVER | 当前的方法不应该运行在事务中,如果有运行的事务,就抛出异常 | | NESTED | 如果有事务在运行,当前的方法就应该在这个事务的嵌套事务内运行;否则,就启动一个新的事务,并在它自己的事务内运行 | 3. Hibernate 中,`get()` 是非延迟加载,`load()` 是延迟加载 4. Hibernate 使用 Java 反射机制实现透明性 5. --- ## 其他 1. Ant 与 Maven Ant 和 Maven 都是基于 Java 的构建(build)工具。理论上来说,有些类似于(Unix)C 中的 make,但没有 make 的缺陷。Ant 是软件构建工具,Maven 的定位是软件项目管理和理解工具。 Ant 特点: + 没有一个约定的目录结构 + 必须明确让 Ant 做什么,什么时候做,然后编译,打包 + 没有生命周期,必须定义目标及其实现的任务序列 + 没有集成依赖管理 Maven 特点: + 拥有约定,知道你的代码在哪里,放到哪里去 + 拥有一个生命周期,例如执行 `mvn install` 就可以自动执行编译,测试,打包等构建过程 + 只需要定义一个 pom.xml,然后把源码放到默认的目录,Maven 帮你处理其他事情 + 拥有依赖管理,仓库管理 2. 原码,反码,补码 1. 正数的原码、反码、补码都相同; 2. 负数的原码:最高位为1,其余位为真值的绝对值; 3. 负数的反码:在原码的基础上,符号位不变,其余位按位取反; 4. 负数的补码:在原码的基础上,符号位不变,其余位取反,最后加1;也就是在反码的基础上加1。 3. 常见循环优化方法 + 强度削弱 + 删除归纳变量 + 代码外提 4. --- ## Java GUI(不建议看) 1. Panel 和 Applet 的默认布局管理器是 `FlowLayout`。 2. Swing 是在 AWT 的基础上构建的一套新的图形界面系统,它提供了 AWT 所能够提供的所有功能,并且用纯粹的 Java 代码对 AWT 的功能进行了大幅度的扩充。 AWT 是基于本地方法的 C/C++ 程序,其运行速度比较快;Swing 是基于 AWT 的 Java 程序,其运行速度比较慢。 3. 关于 Applet 的一些说法 + Applet 可以在带有 Java 解释器的浏览器中运行 + Applet 类必须继承 java.applet.Applet + Applet 可以访问本地文件 + Applet 是 Object 类的子类 4. Swing 提供三个顶层容器类:JFrame,JDialog 和 JApplet。 5.