方法

笔记:

method:
    1、检查参数的有效性
        考虑方法参数的限制,并将这些限制写到文档中,并在方法开头出,通过显式的检查来实施限制。私有方法使用assert断言实施限制。
    2、必要时进行保护性拷贝
        假设类的客户端会尽其所能来破坏这个类的约束条件,因此你必须保护性地设计程序。
            对于构造器的每个可变参数进行保护性拷贝是必要的;
            保护性拷贝是在检查参数的有效性之前进行的,并且有效性检查是针对拷贝之后的对象,而不是针对原始的对象;
            对于参数类型可以不被信任方子类化的参数,请不要使用clone方法进行保护性拷贝
            使它返回内部域的保护性拷贝即可
        参数的保护性拷贝并不仅仅针对不可变类。每当编写方法或者构造器时,如果它要允许客户提供的对象进入到内部数据结构中,则有必要考虑一下,客户提供的对象是否有可能是可变的。如果是,就要考虑你的类是否能够容忍对象进入数据结构之后发生变化。如果答案是否定的,就必须对该对象进行保护性拷贝,并且让拷贝之后的对象而不是原始对象进入到数据结构中。
        只要有可能,都应该使用不可变的对象作为对象内部的组件,这样就不必再为保护性拷贝而操心。
    3、谨慎设计方法签名
        谨慎地选择方法的名称
        不要过于追求提供便利的方法
        避免过长的参数列表。目标是四个参数,或者更少。
            缩短过长参数列表方法:
                将方法分解成多个方法,每个方法只需要这些参数的一个子集;
                创建辅助类,用来保存参数的分组;
                从对象创建到方法调用都采用builder模式
        对于参数类型,要优先使用接口而不是类
        对于boolean参数,要优先使用两个元素的枚举类型
    4、慎用重载
        要调用哪个重载方法是在编译时做出决定的
        对于被覆盖的方法的选择是动态的,依据是被调用方法所在对象的运行时类型
        避免胡乱使用重载机制
        安全而保守的策略是,永远不要导出两个具有相同参数数目的重载方法,参考ObjectOutputStream的writeBoolean(boolean)等方法
    5、慎用可变参数
        可变参数接受0个或者多个指定类型的参数。可变参数机制通过先创建一个数组,数组的大小为在调用位置所传递的参数数量,然后将参数值传到数组中,最后将数组传递给方法
         不必改造具有final数组参数的每个方法,只当确实是在数量不定的值上执行调用时才使用可变参数
    6、返回零长度的数组或者集合,而不是null
        返回类型为数组或集合的方法没理由返回null,而不是返回一个零长度的数组或者集合
    7、为所有导出的API元素编写文档注释
        为了正确地编写API文档,必须在每个被导出的类、接口、构造器、方法和域声明之前增加一个文档注解
        方法的文档注释应该简洁地描述出它和客户端之间的约定

  有关代码:

package chapter6;

import java.math.BigInteger;
import java.util.*;

/**
 * @author zhen
 * @Date 2018/10/8 10:12
 */
public class CollectionClassifier {

//    public static String classify(Set<?> s) {
//        return "Set";
//    }
//
//    public static String classify(List<?> s) {
//        return "List";
//    }
//
//    public static String classify(Collection<?> s) {
//        return "UnKnow Collection";
//    }

    public static String classify(Collection<?> c) {
        return c instanceof Set ? "Set" :
            c instanceof List ? "List" : "UnKnow Collection";
    }

    public static void main(String[] args) {
        Collection<?>[] collections = {
            new HashSet<String>(),
            new ArrayList<BigInteger>(),
            new HashMap<String, String>().values()
        };

        for(Collection<?> c : collections){
            System.out.println(classify(c));
        }
    }
}
CollectionClassifier
package chapter6;

import java.math.BigInteger;

/**
 * @author zhen
 * @Date 2018/10/8 9:15
 */
public class Demo {

    /**
     *
     * @param m the modulus, which must be positive
     * @return this mod m
     * @throws ArithmeticException if m is less than or equal to 0
     */
    public BigInteger mod(BigInteger m) {
        if (m.signum() <= 0) {
            throw new ArithmeticException("Modulus <= 0:" + m);
        }
        return null;
    }

    private static void sort(long a[], int offset, int length) {
        assert a != null;
        assert offset >= 0 && offset <= a.length;
        assert length >= 0 && length <= a.length - offset;
        // Do the computation
    }

    static int sum(int ... args) {
        int sum = 0;
        for(int arg : args) {
            sum += arg;
        }
        return sum;
    }

    //如果客户端调用这个方法时,并没有传递参数进去,它就会再运行时而不是编译时失败。
    //这段代码很不美观,你必须在args中包含显式的有效性检查,除非将min初始化为Integer.MAX_VALUE,否则将无法使用for-each循环,这样的代码也不美观
    static int min(int ... args) {
        if (args.length == 0) {
            throw new IllegalArgumentException("Too few arguments");
        }
        int min = args[0];
        for(int i = 1; i < args.length; i++){
            if (args[i] < min) {
                min = args[i];
            }
        }
        return min;
    }
}
Demo
package chapter6;

import java.util.Date;

/**
 * @author zhen
 * @Date 2018/10/8 9:31
 */
public final class Period {

    private final Date start;
    private final Date end;

    /**
     *
     * @param start
     * @param end
     * @throws IllegalArgumentException if start is after end
     * @throws NullPointerException if start or end is null
     */
    public Period(Date start, Date end) {
        if (start.compareTo(end) > 0) {
            throw new IllegalArgumentException(start + " after " + end);
        }
        this.start = new Date(start.getTime());
        this.end = new Date(end.getTime());
    }

    public Date start() {
        return new Date(start.getTime());
    }

    public Date end() {
        return new Date(end.getTime());
    }

    // Remainder omitted
}
Period
package chapter6;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

/**
 * @author zhen
 * @Date 2018/10/8 15:52
 */
public class SetList {
    public static void main(String[] args) {
        Set<Integer> set = new TreeSet<>();
        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);
        }

        System.out.println(set + " " + list);
    }
}
SetList

 

posted @ 2018-10-09 17:06  guodaxia  阅读(107)  评论(0)    收藏  举报