关于面向对象
- 里氏代换原则
LSP:任何父类能够出现的地方,子类都能够出现 - 谨慎使用方法继承
方法继承带来的危害性:- 方法污染:父类具备的行为通过继承传递给子类,子类不具备执行此行为的能力
- 方法爆炸:指继承树不断扩大
- JDK进化史
- JDK8:Lambda表达式、函数式接口、Stream流等
- JDK9:模块化、进程改善和锁机制优化、代码分段缓存等
- JDK10:改进GC和内存管理等
- JDK11:提供实验性质的可扩展的低延迟垃圾收集器ZGC等
- JDK12 :Switch表达式功能增强、G1收集器优化
类
- java类的组成部分:成员、方法
- 接口是顶级的类
- 内部类加载和外部类通常不在同一个阶段进行
原因:
1. 作用域不会扩散到包外
2. 可以通过“外部类.内部类”的方式直接访问
3. 内部类可以访问外部类中的所有静态属性和方法 - 修饰符总结:
- public任何地方都能访问
- protected同一包内都可以,包外只能子类可以
- default只能同一包内
- private只能同一类内
序列化
对象只有序列化后成为二进制流才可以进行数据持久化和网络传输。
序列化方式
- java原生序列化
通过实现Serializable接口实现序列化,改接口只起标识作用,不支持跨语言、性能一般。 - Hessian序列化
Hessian会把复杂对象的所有属性都存储在一个map中进行序列化;当父类子类存在同名变量时,会先序列化子类,然后序列化父类,这样反序列化时会导致子类同名变量被父类的值覆盖。 - JSON序列化
将数据对象转换为JSON字符串。
参数
- 无论是对于基本数据类型还是引用变量,java中的参数传递都是值复制的传递过程。对于引用变量,复制指向对象的首地址,则双方都可以通过自己的引用变量修改指向对象的相关属性。
- 批量接口进行批量操作时,要对入参数据量进行判断和控制,防止超出处理能力
- 执行顺序
- 父类静态代码块
- 子类静态代码块
- 父类构造方法
- 子类构造方法
覆写
- 动态绑定
由于有些子类是延迟加载的,甚至是网络加载的,所以最终的实现需要再运行期进行判断,这就是动态绑定。
动态绑定是多态性得以实现的重要因素,元空间有一个方发表保存着每个可以实例化类的方法信息,jvm可以通过方法表快速的激活实例方法。 - 向上转型
如果某个类覆写了父类的某个方法,则方法表中的方法指向引用会指向子类的实现处。
注意:- 无法调用到子类中存在而父类本身不存在的方法
- 可以调用到子类中覆写了父类的方法,这是一种多态实现
- 覆写条件(一大两小两同)
- 访问权限不能变小(一大:子类访问权限只能相同或变大)
- 返回类型能够向上转型成为父类的返回类型
- 异常也要能向上转型成为父类的异常(两小)
- 方法名、参数类型及个数必须保持严格一致(两同)
重载
定义:方法名相同、参数类型不同、参数个数不同、参数顺序不同。(又称为静态绑定)
- 重载匹配顺序
- 精确匹配
- 如果是基本数据类型,自动转换成更大表示范围的基本类型
- 通过自动拆箱与装箱
- 通过子类向上转型继承路线依次匹配
- 通过可变参数匹配
包装类
Integer类型数据在-128~127之间会进行缓存,在IntegerCache.cache中,会复用对象,在这个范围内的数据可以直接使用==进行判断,这个区域之外的数据要在堆上产生,并不会复用。
修改这个范围的大小可以通过修改VM options参数 -XX:AutoBoxCacheMax=777(这样修改缓存的最大值为777)只对Integer类型数据有效
字符串
字符串相关类型:
- String
只读字符串,任何改动都是创建一个新对象然后把引用指向该对象 - StringBuilder
非线程安全的,效率比StringBuffer高 - StringBuffer
可以在原对象上进行修改,是线程安全的