《码出高效:Java开发手册》学习笔记2
作者:互联网
一、面向对象相关概念
面向对象四大特性:抽象、封装、继承、多态。
本书将“抽象"作为面向对象的特性之一,支持面向对象“四大特性"的说法。
在面向对象的思维中,抽象分为归纳和演绎。 前者是从具体到本质, 从个性到共性,将一类对象的共同特征进行归一化的逻辑思维过程;**后者则是从本质到具体,从共性到个性,逐步形象化的过程。**在归纳的过程中,需要抽象出对象的属性和行为的共性,难度大于演绎。演绎是在已有问题解决方案的基础上,正确地找到合适的使用场景。
Java中的Object类是一切的父类,是对所有物体的抽象。
(1) 我是谁?getCIass()说明本质上是谁,而toString()是当前职位的名片。
(2) 我从哪三来?Object()构造方法是生产对象的基本步骤,clone()是繁殖对象的另一种方式。
(3) 我到哪里去? finalize()是在对象销毁时触发的方法。
(4) 世界是否因你而不同?hashCode()和equals()就是判断与其他元素是否相同的一组方法。
(5) 与他人如何协调?wait()和notify()是对象间通信与协作的一组方法。
PS: Object中的clone()方法分为深拷贝和浅拷贝,可具体参考以下文章
https://www.cnblogs.com/nickhan/p/8569329.html
https://www.cnblogs.com/ysocean/p/8482979.html
二、初始Java
jdk和jre的概念及区别
JRE是Java Runtime Environment的缩写,顾名思义是java运行时环境,包含了java虚拟机,java基础类库。 是使用java语言编写的程序运行所需要的软件环境,是提供给想运行java程序的用户使用的,还有所有的Java类库的class文件,都在lib目录下,并且都打包成了jar。
JDK是Java Development Kit的缩写,顾名思义是java开发工具包,是程序员使用java语言编写java程序所需的开发工具包,是提供给程序员使用的。JDK包含了JRE,同时还包含了编译java源码的编译器javac,还包含了很多java程序调试和分析的工具: jconsole,jvisualvm等工具软件,还包含了java程序编写所需的文档和demo例子程序。如果需要运行java程序,只需安装JRE就可以了。如果你需要编写java程序,需要安装JDK。
三、类相关
1、接口与抽象类的区别
抽象类在继承时体现的是is-a的关系,而接口在被实现时体现的是can-do的关系。
2、内部类
关于内部类的理解:
1、关于成员内部类和静态内部类,public, protected, 默认, public对他们修饰是起相同作用的。
2、可以用静态内部类作为线程的启动类,实现Runnable接口。
3、访问权限控制
在对成员变量或者方法限定权限时主要注意以下几点:
- 如果不充许外部直接通过new创建对象,构造方法必须是privateo
- 工具类不允许有public或default构造方法。
- 类非static成员变量并且与子类共享,必须是protectedo。
- 类非static成员变量并且仅在本类使用,必须是private。
- 类static成员变量如果仅在本类使用,必须是privateo
- 若是static成员变量,必须考虑是否为final。
- 类成员方法只供类内部调用,必须是private。
- 类成员方法只对继承类公开,那么限制为protected。
4、this与super
this与super的异同点
5、类与类之间的关系
类与类之间主要有以下几种关系: - 继承–extends (is-a)
- 实现–implements (can-do)
- 组合–类是成员变量(contains-a)
- 聚合–类是成员变量(has-a)
- 依赖–import类(use-a)
组合与聚合之间的区别:组合体现的的是一种非常强的整体与部分的关系,是一种完全绑定的关系。比如说头与身体之间的关系。而聚合是一种可以拆分的整体与部分的关系,是非常松散的暂时组合,部分可以独立成为另一个整体。
类与类之间只要import了,那就是依赖关系。
在类图中,一般将有形状的图形符号放在权力强的这一侧。
以下为类图的相关展示。
6、序列化
内存中的数据对象只有转换为二进制流才可以进行数据持久化和网络传输。将数据对象转换为二进制流的过程称为对象的序列化(Serialization)。反之,将二进制流恢复为数据对象的过程称为反序列化(Deserialization)。
常见的序列化方式主要有三种:
(1)Java原生序列化:Java类通过实现Serializable接口来实现该类对象的序列化,这个接口非常特殊,没有任何方法,只起标识作用。
**实现Serializable接口的类建议设置serialVersionUID字段值,如果不设置,那么每次运行时,编译器会根据类的内部实现,包括类名、接口名、方法和属性等来自动生成serialVersionUID。****如果类的源代码有修改,那么重新编译后serialVersionUID 的取值可能会发生变化。**因此实现Serializable接口的类一定要显式地定义 serialVersionUID属性值。修改类时需要根据兼容性决定是否修改serialVersionUID值:.
如果是兼容升级,请不要修改serialVersionUID字段,避免反序列化失败。
如果是不兼容升级,需要修改serialVersionUID值,避免反序列化混乱。
使用Java原生序列化需注意,Java反序列化时不会调用类的无参构造方法,而是调用native方法将成员变量赋值为对应类型的初始值。基于性能及兼容性考虑,不推荐使用Java原生序列化。
(2)Hessian序列化。
(3)JSON序列化。JSON是一种轻量级的数据交换格式。JSON序列化就是将数据对象转换为JSON字符串。在序列化过程中抛弃了类型信息,所以反序列化时只有提供类型信息才能准确地反序列化。相比前两种方式, JSON可读性比较好,方便调试。
四、类方法相关
在JVM中方法名称和参数列表是标识方法的唯一索引。不包括返回值。
在JDK5之后,java中出现了可变参数列表,**在使用时,尽量不要使用这种可变参数编程。如果要使用的话,则只有相同参数类型,相同业务含义的参数才可以,**并且一个方法中只能有一个可变参数,且这个可变参数必须是该方法的最后一个参数。
如下的警示代码:
在方法中对参数进行预处理时,主要包括以下两种:
入参保护:实质上是对服务提供方的保护(也就是接收参数,进行处理的一方)。常见于批量接口。虽然批量接口能处理一批数据,但其处理能力并不是无限的,因此需要对入参的数据量进行判断和控制,如果超出处理能力,可以直接返回错误给客户端。
参数校验:基于防御式编程理念,在方法内,无论是对方法调用方传入参数的理性不信任,还是对参数有效值的检测都是非常有必要的。但是,由于方法间交互是非常频繁的,如果所有方法都进行参数校验,就会导致重复代码及不必要的检查影响代码性能。 综合两个方面考虑,汇总需要进行参数校验和无须处理的场景。
需要进行参数校验的场景: - 调用频度低的方法。
- 执行时间开销很大的方法。此情形中,参数校验时间几乎可以忽略不计,但如果因为参数错误导致中间执行回退或者错误,则得不偿失。
- 需要极高稳定性和可用性的方法。
- 对外提供的开放接口。 ·
- 敏感权限入口。
不需要进行参数校验的场景 - 极有可能被循环调用的方法。但在方法说明里必须注明外部参数检查。 ·
- 底层调用频度较高的方法。参数错误不太可能到底层才会暴露问题。
- 一般DAO层与service层都在同一个应用中,部署在同一台服务器中,所以可以省略DAO的参数校验。
- 声明成private只会被自己代码调用的方法。如果能够确定调用方法的代码传入参数已经做过检查或者肯定不会有问题,此时可以不校验参数。
五、构造方法
类中的构造函数与静态代码块之间的执行顺序:
首先执行父类中的静态代码块,在执行子类中的静态代码块,再执行父类构造方法,子类构造方法。静态代码块只会执行一次。
静态方法的使用注意事项:
- 静态方法中不能使用实例成员变量和实例方法(静态方法的分配早于类的实例化,所以不能使用)。
- 静态方法不能使用super和this关键字,这两个关键字指代的都是需要被创建出来的对象。
getter与setter相关注意方法 - getter与setter中不要添加业务逻辑
- 同时定义isxxx()和getXxx()0在类定义中,两者同时存在会在iBATIS、JSON序列化等场景下引起冲突。比如,iBATIS通过反射机制解析加载属性的getter 方法时,首先会获取对象所有的方法,然后筛选出以get和is开头的方法,并存储到类型为HashM叩的getMethods变量中。其中key为属性名称,value为getter方法。因此isxxx()和getXxx()方法只能保留一个,哪个方法被后存储到getMethods变量中,就会保留哪个方法,具有一定的随机性。所以当两者定义不同时,会导致误用,进而产生问题。
- 相同的属性名容易带来歧义。在编程过程中,应该尽量避免在子父类的成员变量之间、不同代码块的局部变量之间采用完全相同的命名。
重写的注意事项(一大两小两同):
一大: 子类的方法访问权限控制符只能相同或变大。
两小: 抛出异常和返回值只能变小,能够转型成父类对象。子类的返回值、抛出异常类型必须与父类的返回值、抛出异常类型存在继承关系。
两同: 方法名和参数必须完全相同。
重载参数匹配的解析顺序: - 精确匹配。
- 如果是基本教啹类型,自动转唤成更大表示节围的基本类型。
- 通过自动扒箱与装筘。
- 通过子类向上转型些承路线依次匹配。
- 通过可变参数匹配。
六、泛型
泛型可以定义在类、接口、方法中,编译器通过识别尖括号和尖括号内的字母来解析泛型,在进行泛型定义时,约定俗成的符号包括:E代表Element,用于集合中的元素,T代表type of object表示某个类,K代表key,V代表value,用于键值对元素。
泛型在使用时的几点注意地方:
1、尖括号里的每一种元素都代表一种未知类型。比如说如果String出现在泛型中,那么他就不再是java.lang.String,而仅仅是一种代号,代表了一种类型约定。类名后方的泛型和方法中使用的泛型是两个指代,可以完全不同,不受影响。
2、尖括号的位置必须在类名之后或方法返回值之前。
3、泛型在编译之后仍然是Object类型,泛型只是一种语法规定。所以在使用泛型时,他只能调用Object类中的方法,同时最后会进行强制类型转换。
七、数据类型
标签:码出,Java,手册,参数,泛型,java,序列化,方法 来源: https://blog.csdn.net/u_ranfa/article/details/99937211