(1)单一职责原则:一个类应该有且只有一个去改变它的理由,这意味着一个类应该只有一项工作。
(2)开放封闭原则:对象或实体应该对扩展开放,对修改封闭。
(3)里氏替换原则:在对象 x 为类型 T 时 q(x) 成立,那么当 S 是 T 的子类时,对象 y 为类型 S 时 q(y) 也应成立。(即对父类的调用同样适用于子类)
(4)接口隔离原则:不应强迫客户端实现一个它用不上的接口,或是说客户端不应该被迫依赖它们不使用的方法。
(5)依赖反转原则:实体必须依靠抽象而不是具体实现。它表示高层次的模块不应该依赖于低层次的模块,它们都应该依赖于抽象。
(1)继承的根本原因是因为要复用,而实现的根本原因是定义一个标准。
(2)多继承会出现菱形继承问题,C++引入虚继承解决。
(3)组合与继承:继承是is-a的关系,组合是has-a的关系。同样可行的情况下建议用组合。
在没有重写equals方法的情况下,使用equals做比较,判断的是两个对象的引用是否相等。如果想判断两个对象的内容是否相等,则需要重写equals和hashCode方法。
在java中,==比较的是对象的引用,而equals比较的是值。
clone方法在不重写的情况下是浅拷贝,想要实现深拷贝需要重写clone方法,还有一种实现深拷贝的方式是序列化技术
拼接过程中是将String转换成StringBuilder后,使用其append方法进行处理的。
有五种,分别是’+'、concat、StringBuilder、StringBuffer和StringUtils.join。
如果不是在循环体中进行字符串的拼接用’+'。
如果在并发中使用字符串拼接则要使用StringBuffer代替StringBuilder。
如果是通过一个List进行字符串拼接,则使用StringJoiner(java8中提供的StringJoiner,与Stream流有关)。
java11中的strip()方法要比trim()方法更强大,它可以删除很多不在ASCLL中的空白字符,但是删除的是字符串前导和末尾的空格。
**replaceAll()**与适当的正则表达式一起使用可以删除字符串中的空格。
switch只能使用整型,比如byte、short、char和int,其它数据类型都是转成整型之后再使用switch的。
类加载的过程要经历加载、链接、初始化等几个步骤,在链接的步骤中又分为验证、准备和解析。
自己明确知道如何处理的,就要处理,不知道如何处理的,就要向上抛出,交给调用者处理。
try是必须的,catch和finally至少有一个。
finally是在什么时候执行的?
如果try中有return,先执行finally再执行try中的return,如果try和finally中都有return,则finally中的return最后执行。
(1)集合的遍历:for、foreach、迭代器Iterator、迭代器Enumeration、Stream流
(2)ArrayList 的扩容是之前的1.5倍,Vector扩容是之前的2倍,vector是线程安全的。
(3)Collections的synchronizedList方法可以把任意一个List转换成一个线程安全的List。
(4)synchronizedList和Vector建议使用synchronizedList。因为可以定义一个线程安全的LinkList。
(5)HashMap最多允许存储一个null键和多个null值,然而TreeMap不允许空键,但可能有多个空值。
(6)HashTable是线程安全的,但是在普通和get方法上都增加了synchronized,因此有了concurrentHashMap,在1.7之前使用分段(segment)锁,1.8之后改为node结点锁,锁粒度更小。
(7)同步容器(Vector和HashTable)中复合方法也不是线程安全的。
(8)HashMap扩容是之前的2倍,扩容时还要进行rehash,初始化容量要设成expectedSize/0.75+1,而且将hash()方法生成的整型值转换成数组下标时使用位运算代替取模增加效率(还能解决负数的问题),HashMap运用扰动降低Hash冲突,,
(9)HashTable 默认的初始大小是11,每次扩充2n+1,
Stream的创建:(1)通过已有的集合创建流:集合.stream()(2)通过Stream.of()创建流
Stream的中间操作:filter、map、limit、sorted、distinct。
Stream的最终操作:forEach、count、collect。
通过以下三种方式可以获取一个class对象
(1)调用对象的getClass()方法获取Class对象
(2)根据类名.class获取Class对象
(3)根据Class中的静态方法Class.forName()获取Class对象
反射破坏了单例模式,序列化也可以破坏单例模式
我们创建的java对象都是存在于JVM的堆内存中(不考虑JIT优化)的。
序列化是将对象装换为可存储或传输的形式的过程,一般是以字节码或XML格式传输对象的。而将字节码或XML编码格式的对象还原为对象的过程称为反序列化。
序列化会通过反射调用无参的构造方法创建一个新的对象进而破坏单例模式。
使用枚举可以实现单例模式,且是线程安全的。
输入流:inputStream(字节流)和Reader(字符流)
输出流:OutputStream(字节流)和Write(字符流)
OutputStreamWrite是Write的子类,是字符流通向字节流的桥梁
InputStreamReader是Reader的子类,是字节流通向字符流的桥梁
阻塞和非阻塞描述的是调用方,同步和异步描述的是被调用方。
Linux的五种I/O模型:阻塞I/O、非阻塞I/O、I/O复用模型、信号驱动式I/O和异步I/O模型。
BIO(同步阻塞)、NIO(同步非阻塞)、AIO(异步非阻塞)
动态代理的几种实现方式:JDK动态代理、CGLib动态代理。
实现动态代理主要涉及哪几个类:Proxy(生成代理的主类)和InvocationHandler(调用处理器)
注解分为元注解和自定义注解
日常开发中常用注解:
(1)使用自自定义注解做日志记录
(2)使用自定义注解做前置检查
编程式事物和声明式事物
泛型不支持基本数据类型
如何使用 extends T>和 super T>
SimpleDateFormat是线程不安全的类,一般不要定义为static变量,也不要当成共享变量使用。
SimpleDateFormat中format将一个Date类型转换为String,parse方法将一个String转换为Date类型。
Java8中的时间处理:LocalTime和LocalDate
日期格式要用y表示年,而不能用Y(涉及跨年时间段的问题)。
语法糖让程序更加简单,有更高的可读性。
使用BigDecimal(double)创建一个BigDecimal是损失了精度的,要使用BigDecimal(String)创建BigDecimal。
BigDecimal的等值比较使用compareTo()方法,而不是equals()方法。
Apache Commons
常用的有BeanUtils、Collections、IO、Long、Logging和OGNL
Commons Long中提供很多好用的工具类:StringUtils、ArrayUtils、DateUtils。
Commons IO中常用的有:IOUtils、FileUtils、FilenameUtils。
Commons BeanUtils中有:BeanUtils和propertyUtils,BeanUtils在进行属性拷贝时本质上是浅拷贝
MapStruct字段映射工具
Guava
常用的有:Optional、Guava Cache
Lombok
java8:函数式编程,有且只有一个抽象方法的接口被称为函数式接口,函数式接口适用于函数式编程的场景。
java9:模块化技术
java10:本地变量类型推断
java11:增强var
java12:Switch表达式
java13:text block
java14:更有价值的NullPointException、record类型
java15:封闭类
java16:instanceof模式匹配
java17:Switch模式匹配