名称规范
1 名词
ex:java.lang.String
2 双名词
ex:java.util.ArrayList
3 形容词 + 名词
ex:java.util.LinkedList
访问性设计
public(都可以访问) protected(继承 + 同包) default(同包) private(当前类)
private和protected 不能用于修饰类(这个类是最外层的内,内置类可以使用)
public 和default 可以修饰类(这个类是最外层的内,内置类可以使用)
可继承性
以String源码为例:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
}
我们看到String使用了final关键字进行修饰,里面的value也是final进行了修饰。也就是说String是不被允许继承的,里面的值也不允许修改。
final 不具备继续性,与所以不能用于抽象类因为抽象类一定是要被继承实现的。final保证了类的完整性,保证类的行为不被破坏。
关于字符串的拓展,对象都是new出来的,只是String提供了可以直接写成常量的写法,相当于变量常量化。
// 对象类型常量化 字符串常量池 底层的实现是一个Hash表
String s1 = "hello";
// 合法写法
String s2 = new String("hello");
字符串被定义为final,但是其实也是可以被修改的,我们可以通过反射机制来修改:
public class T {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
String v1 = "s1";
Field field = String.class.getDeclaredField("value");
field.setAccessible(true);
field.set(v1, "s2".toCharArray());
System.out.println(v1);
}
}
接口设计规范
接口实现名称前缀:Default Generic Common Basic
接口实现名称后缀:Impl
接口的应用场景:
API 契约 也就是说我们向外提供一组规范或约定 提供给他人使用。
RPC 依赖于序列化,其本质也是一组规范
抽象类的设计
抽象类介于类和接口之间,其实在1.8之后接口也能有默认的实现所以和抽象类差别不是很大了,但是抽象类可以有自己的成员。
抽象类通常以abstract 和base为前缀进行命名。
抽象类的应用场景:
1 提供接口的通用实现(模板方法模式)
2 状态行为继承
3 工具类
内置类
常见使用场景:
1 临时存储数据 比如ThreadLocalMap
ThreadLocalMap是ThreadLocal的一个内置类,里面定义了软引用数组来存储共享变量
2 特殊API 例如Collections中的UnmodifiableMap等
其实就是一个装饰器模式,将这集合的方法全部重写重写为UnsupportedOperationException
3 Builder模式 构造器模式
例如Java Stream 中的Builder
枚举设计
1 类的方式
final class Counting {
private Counting() {
}
public static final Counting ONE = new Counting();
public static final Counting TWO = new Counting();
public static final Counting THREE = new Counting();
public static final Counting FOUR = new Counting();
public static final Counting FIVE = new Counting();
}
2 枚举
会继承Java.lang.Eum类,编译以后也是一个final类
public enum Counting {
ONE,
TWO,
THREE,
FOUR,
FIVE
}
- Three是第几个定义的?
继承了Enum ordinal就是它的位置 - 能否输出所有的成员?
Counting[] values = Counting.values();
- 枚举类型为什么可以输出字面量?
// 定义了name
String name
方法设计
1 方法返回值
原则一: 返回类型需要抽象,除Object
因为抽象的返回更通用,调用方更容易接收和处理。
// 返回的是接口 方法采用 动词 + 形容词 + 名词
public SortedSet<String> getSortedValues() {
return new TreeSet<>();
}
原则二: 尽可能的返回Java集合框架内的接口,尽量避免数组
因为Collection 比较[] 而言,拥有更多的操作方法,比如add()
Collection 接口返回时,可以限制只读,而[] 不行。
原则三:确保返回的集合为只读
public class TT {
private final List<Map<String, List<Object>>> list = new ArrayList<>();
public static void main(String[] args) throws NoSuchFieldException {
List<Integer> numbers = getNumbers();
// Aarrays.asList 并不是只读的
numbers.set(3, 9);
numbers.forEach(System.out::println);
List<Integer> unModifyNumbers = getUnModifyNumbers();
unModifyNumbers.set(3, 9);
unModifyNumbers.forEach(System.out::println);
}
public static List<Integer> getNumbers() {
return Arrays.asList(1, 2, 3, 4);
}
public static List<Integer> getUnModifyNumbers() {
return Collections.unmodifiableList(Arrays.asList(1, 2, 3, 4));
}
}
原则四:如果需要集合是可以修改的确保返回的是快照,尽可能返回ArrayList(如果确定的话,如果不确定可以返回LinkedList 但是效率会慢一点)
public static List<Integer> getSnapshotNumbers() {
return new ArrayList<>(Arrays.asList(1, 2, 3, 4));
}
2 参数设计
arguments 通常形容方法参数
parameters 通常是值外部媒介传递过来,请求参数
参数名称:
一些例子
public boolean equals(Object that) {
return this == that;
}
public int compareTo(Bar another) {
return 1;
}
// 参数类型对等方式单项传输
public void copy(Object source, Object target) {
}
// 参数类型非对等单项传输
public void add(Collection<Object> collection, Object element) {
collection.add(element);
}
// 多项参数非对等
/**
*
* @param collection collection
* @param elements zero or more elements(0..n)
*/
public void add(Collection<Object> collection, Object ...elements) {
}
/**
*
* @param collection collection
* @param one one element
* @param others zero or more elements(0..n)
*/
public void add(Collection<Object> collection, Object one, Object ...others) {
}
// 多项对等
public void addAll(Collection<Object> source, Collection<Object> target) {
target.addAll(source);
}
参数个数:参数的个数最好不要超过3个