以下主要针对方法参数,返回值,方法签名等细节的优化,以提高程序的健壮性和灵活性。值得大家阅读
private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
/**
* 构造器或公用方法 第一先检查参数有效性,防止错误深入蔓延,不便问题查找
*/
public void f1(Object o) {
if (o == null) {
throw new IllegalArgumentException("o not to be null");
}
//... other codes
}
/**
* 私有方法 使用断言 调试时出错快速中断程序 必须开启断言 配置 VM -ea 开启
*/
private void f2(Object o) {
assert (o != null) : "o is not null";
// ... other codes
}
/**
* 必要时进行保护性拷贝
*/
private void f3() throws Exception {
Date startDate = simpleDateFormat.parse("2020-01-01");
Date endDate = simpleDateFormat.parse("2020-01-05");
Period period = new Period(startDate, endDate);
System.out.println(period); //Period{startDate=2020-01-01, endDate=2020-01-05}
endDate.setYear(0); // 在引用参数的外部改动时,破坏了对象内部限制
System.out.println(period); //Period{startDate=2020-01-01, endDate=1900-01-05}
period.getEndDate().setYear(1); // 对对象的操作,破坏了对象内部的限制
System.out.println(period); //Period{startDate=2020-01-01, endDate=1901-01-05}
}
/**
* 避免过长参数列表 参数数量最好不要超过4个 减少参数个数 有3种方法
* 1.把一个方法分成多个方法
* 2.增加辅助类 把参数放到辅助类内 通过辅助类来传递参数
* 3.使用构建器 先把参数传入构建器 然后通过构建器生成对象
* 4.对于参数类型优先使用接口而非类
* 5.对于boolean参数 优先使用枚举类型
*/
public void f4() {
Student.Builder studentBuilder = new Student.Builder()
.setName("张三")
.setAge(25)
.setHeight(1.8);
Student student = studentBuilder.builder();
System.out.println(student); // Student{name='张三', age=25, height=1.8}
}
/**
* 慎用重载
* 1.重载 在编译器时选择相对应方法执行 选择是静态的
* 2.重写(Override) 在运行期选择相对应的方法执行 选择是动态的
* 3.可以使用更改签名来替代重载 例如 ObjectOutputStream 里的 writeInt(Int n), writeBoolean(boolean b) ...
*/
private void f5() {
Collection<?>[] collections = {
new HashSet<String>(),
new ArrayList<String>(),
new HashMap<String, String>().values()};
for (Collection<?> collection : collections) {
printCollections(collection);
// 结果是 collection collection collection
// 编译器 类型都是 Collection<?> 所以选择的 printCollections(Collection<?> collection)
}
Animal[] animals = {new Animal(), new Dog(), new Cat()};
for (Animal animal : animals) {
animal.printName();
// 结果是 Animal, Dog, Cat
}
Set<Integer> set = new HashSet<>();
List<Integer> list = new ArrayList<>();
for (int i = -3; i < 3; i++) {
set.add(i);
list.add(i);
}
for (int i = 0; i < 3; i++) {
set.remove(i); //
list.remove(i); // List 里有两个重载方法 remove(int) remove(Object) 这里实际调用的是前者
// list.remove(Integer.valueOf(i)); // 需要强制转化下
}
System.out.println(set + " " + list); // [-1, -2, -3] [-2, 0, 2]
}
private void printCollections(Set<?> set) {
System.out.println("set");
}
private void printCollections(List<?> list) {
System.out.println("list");
}
private void printCollections(Collection<?> collection) {
System.out.println("collection");
}
/**
* 慎用可变参数
* 1.可变参数 允许一个参数都不传
* 2.当至少需要一个参数时 我们可以指定一个参数 而不是对可变参数进行数量判断
*/
public void f6() {
int sum = sum();
System.out.println(sum); // 0
int min = min(2, 4, 4, 6, 7, 8);
System.out.println(min); // 2
List<String> list = Arrays.asList("sfa", "sf", "sadf");
System.out.println(list); // [sfa, sf, sadf]
int[] nArr = {1,2,3,4,5};
System.out.println(Arrays.asList(nArr)); // [[I@a09ee92]
System.out.println(Arrays.asList(1, 0, 2 ,3 ,4 )); // [1, 0, 2, 3, 4]
System.out.println(Arrays.toString(nArr)); // [1, 2, 3, 4, 5]
}
private int sum(int... args) {
int sum = 0;
for (int n : args) {
sum += n;
}
return sum;
}
private int min(int first, int... args) {
// if (args.length == 0) {throw new Exception("至少传入一个参数")}
int min = first;
for (int n : args) {
min = Math.min(min, n);
}
return min;
}
/**
* 返回0长度的数组或集合而非null
* 1.返回null 调用的地方就需要对 null进行判断 稍不注意就会出现空指针异常
* 2.如果觉得返回空数组或空集合 浪费内存空间 可以预选定义一个空集合或数组
*/
private final String[] EMPTY_ARR = {};
private final List<String> EMPTY_LIST = new ArrayList<>();
public String[] getArr() {
return EMPTY_ARR;
}
public List<String> getList() {
return EMPTY_LIST;
}
/**
* 为所有的Export的API编写文档注释
*/
/**
* 获取指定id的学生姓名
* @param id 学生id
* @return 学生姓名
* @see String
*/
public String getName(int id) {
return "张三";
}
public class Period {
private Date startDate;
private Date endDate;
public Period(Date startDate, Date endDate) {
if (startDate.compareTo(endDate) > 0) {
throw new IllegalArgumentException("开始时间不能大于结束时间");
}
this.startDate = startDate;
this.endDate = endDate;
// 必要时进行保护性拷贝
// this.startDate = new Date(startDate.getTime());
// this.endDate = new Date(endDate.getTime());
}
@Override
public String toString() {
return "Period{" +
"startDate=" + simpleDateFormat.format(startDate) +
", endDate=" + simpleDateFormat.format(endDate) +
'}';
}
public Date getStartDate() {
return this.startDate;
// 防止对象外部的修改,破坏对象内部的限制
//return new Date(this.startDate.getTime());
}
public Date getEndDate() {
return endDate;
// 防止对象外部的修改,破坏对象内部的限制
//return new Date(this.endDate.getTime());
}
}
public class Student {
private String name;
private int age;
private double height;
Student(Builder builder) {
this.name = builder.name;
this.age = builder.age;
this.height = builder.height;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", height=" + height +
'}';
}
public class Builder {
private String name;
private int age;
private double height;
public Builder() {
}
;
public Builder setName(String name) {
this.name = name;
return this;
}
public Builder setAge(int age) {
this.age = age;
return this;
}
public Builder setHeight(double height) {
this.height = height;
return this;
}
public Student builder() {
if (StringUtils.isEmpty(name)) {
throw new IllegalArgumentException("请设置name");
}
if (age == 0) {
throw new IllegalArgumentException("请设置age");
}
if (height == 0) {
throw new IllegalArgumentException("请设置height");
}
return new Student(this);
}
}
}
public class Animal {
public void printName() {
System.out.println("Animal");
}
}
public class Dog extends Animal {
@Override
public void printName() {
System.out.println("Dog");
}
}
public class Cat extends Animal {
@Override
public void printName() {
System.out.println("Cat");
}
}