"효과적인 자바"(C) - 3 분 속도는 원래 읽기

21. 정책을 표현하기 위해 사용하는 함수 객체

즉, 정책을 나타내는 함수 오브젝트라고 다른 전략을 달성하기 위해 다른 인터페이스를 달성하도록 구현 될 전략적 접근을 정의하기 위해 다음의 특정 카테고리의 인터페이스를 사용하여

22. 우선 고정 부재 클래스

1. 중첩 클래스는 정적 부재 클래스를 제외한 네, 다음과 다른 클래스는 내부로 지칭 될 수있다

  • 1.1 정적 부재 클래스 액세스가 외부 클래스의 인스턴스를 필요로하지 않는 경우 클래스, 보조 외부 액세스 할 수있다,
  • 1.2 비 정적 부재 내부 클래스이 클래스가 인스턴스화되는 클래스는 외부 설계 반복들의 세트 중에서, 예를 들어, 구현되는 동작 내측 일부 필드 종종 필요 사용될 수 후에 만 ​​필요하다.
  • 1.3 익명의 내부 클래스는, 그 본질은 외부 클래스의 멤버가 아닌, 명령문의 다른 회원들과 함께 노래를 부르는 수는 없지만, 사용시에만 선언 및 인스턴스화. 일반적인 이러한 비교기의 인스턴스를 생성, 우리는 필요 그것을 실현하기 위해 내부 비교 함수의 방법을 포함
  • 지역 변수와 비슷한 1.4 지방 클래스는, 일반적으로 개발에 이러한 사용이 없습니다. 어떤 지역 변수 선언과 방법을 동시에 사용 로컬 변수의 범위 내에서 초기화 할 수 있습니다 것입니다

23. 새로운 코드 사이에 원래의 생태 유형을 사용하지 마십시오

이 사람이 우리에게 이야기하고 싶어에서 원본 일반 문이 잘못된 제네릭에게 더러운 데이터를 삭제로 이어질 것입니다, 다음 코드 샘플

public class Test {

    public static void main(String[] args) {
        List<String> strings = new ArrayList<>();
        StackDemo stackDemo = new StackDemo();
        unsafeAdd(strings,stackDemo);
        unsafeAdd(strings,new Integer(1));
        System.out.println(strings);
    }
    //该方法会导致泛型被擦除,导致脏数据的产生
    private static void unsafeAdd(List strings, StackDemo stackDemo) {
        strings.add(stackDemo);
    }
    //该方法就会限制对应的参数操作也必须是对应的String类型,所以会编译报错不通过
    private static void unsafeAdd(List<String> strings, Integer stackDemo) {
        strings.add(stackDemo);
    }
    
    //综上所述:需要采用第二种方式来声明和使用泛型才是合理的
}

경고 비 과목 (24)을 제거

개발에있는 등 이전 JDK1.8 컴파일러에서 경고 많은 컴파일러 경고를 발생합니다 다음 코드가

//JDK1.8之前的编译器要求我们必须要在实例当中声明泛型类型,否则会有编译警告
Set<String> strings = new HashSet();
//如果编译器比较早的,采用下面这个方式即可解决
Set<String> strings = new HashSet<String>();

일부 경고는 당신이 우리가 신뢰 불필요한 경고를 제거하기 위해 ( "선택 해제") 주석 @SuppressWarings을 사용할 수 제거되지 않습니다

어레이 (25)에 설정된 우선 순위

배열을 사용하여 비교 문제는 컴파일시에 발견되지 않지만 더 쉬운 일반적인 세트의 사용과 문제도 다음과 같은 코드를 찾을 수 있습니다.

public class GenericsTest {

    public static void main(String[] args) {
        //使用这种方式需要运行时才能发现它的错误
        Object[] objects = new Long[1];
        objects[0] = "不要这样操作";
        
        //使用这种方式,编译本身就不通过,异常比较容易发现
        List<Object> objectList = new ArrayList<Long>();
        objectList.add("可以这样做");
    }
}

범용의 사용 우선 순위 (26)

아래 우리 사이에 제 코드 수있는 더 나은 확장하고 불필요한 경고를 줄일 수 있도록 일반 수정

public class StackDemo<E> {
    private E[] elements;
    private int size = 0;
    private final int DEFAULT_INITIAL_CAPACITY = 16;

    /**
     * 功能描述:
     * 〈初始化栈〉
     *
     * @params : []
     * @return :
     * @author : cwl
     * @date : 2019/5/5 16:59
     */
    public StackDemo(){
        elements = (E[])new Object[DEFAULT_INITIAL_CAPACITY];
    }

    /**
     * 功能描述:
     * 〈压栈〉
     *
     * @params : [o]
     * @return : void
     * @author : cwl
     * @date : 2019/5/5 16:58
     */
    public void push(E o){
        ensureCapacity();
        elements[size++] = o;
    }

    /**
     * 功能描述:
     * 〈出栈〉
     *
     * @params : []
     * @return : java.lang.Object
     * @author : cwl
     * @date : 2019/5/5 16:59
     */
    public E pop(){
        if (size == 0){
            throw new EmptyStackException();
        }
        return elements[size--];
    }

    /**
     * 功能描述:
     * 〈自动扩容〉
     *
     * @params : []
     * @return : void
     * @author : cwl
     * @date : 2019/5/5 16:59
     */
    private void ensureCapacity() {
        if(elements.length == size){
            elements = Arrays.copyOf(elements,2*size+1);
        }
    }
}

한마디로 : 한 시간이 허락으로, 더 나은 것 코드의 확장 성, 제네릭의 최대한을 할 수

27. 우선 순위 일반적인 방법

오류의 예 : 일반 S1과 S2가 함께 추가됩니다 현재 컬렉션의 두 가지 유형이있는 경우에도 사용하지 않을.

    private static Set union(Set s1, Set s2) {
        s1.addAll(s2);
        return s1;
    }

오른쪽 : 한 세트 모음을 추가 할 때이 방법에 따라,이를 기반으로합니다 형식 유추, 요구 사항은 E의 동일한 유형, 그래서 더러워지고 않고, 정확한 데이터이의 수집을 제한 할 수있다이다

public class Test {

    public static void main(String[] args) {
        Set<String> s1 = new HashSet<>();
        s1.addAll(Arrays.asList("1","2","3"));
        Set<String> s2 = new HashSet<>();
        s2.addAll(Arrays.asList("4","5","6"));
        Set<String> s3 = union(s1, s2);
        System.out.println(s3);
    }
    private static <E> Set<E> union(Set<E> s1, Set<E> s2) {
        s1.addAll(s2);
        return s1;
    }
}

(28) 제네릭 유연성 상한과 하한의 사용은 API를 개선하기 위해

우리는 이전에 코드 예제로 : 난 그냥 방법이 코드 예제처럼의 오퍼레이션과 addAll하는 과정에 있다면, 내가 추가 할 유형이 설정 될 수있다 <정수> 또는 설정 <문자열> 너무 예에 의해 컴파일한다. 무리, 그래서 우리는 같은 클래스에 속한 상한은 추가의 유형을 보장하기 위해, 현재 제네릭 형식 T입니다 설정해야합니다

public class ChildHashSet<T> extends HashSet<T> {

    private int count = 0;

    public ChildHashSet() {
    }

    public ChildHashSet(int initCap , int loadFactory) {
        super(initCap,loadFactory);
    }

    @Override
    public boolean add(T t) {
        count++;
        return super.add(t);
    }
    
    @Override
    public boolean addAll(Collection<? extends T> c) {
        count = c.size();
        return super.addAll(c);
    }

    public int getCount() {
        return count;
    }
}

코드 예제 2 :

    //错误做法
    @Override
    public boolean addAll(Collection<T> c) {
        count = c.size();
        return super.addAll(c);
    }

이종 컨테이너 보안 29 순위 타입

이기종 용기 :과 같은 다양한 종류의 수용 할 수 있지만, 이러한 컨테이너 바이트 객체를 사용하여 데이터베이스 행으로 저장되는 객체가 같은 종류와 같은 여러 종류의 항목이 포함되도록 같이 법적으로 사용될 수있다. 구체적으로는 아래와 같이 코드를 구현한다 :

public class Hobbies {

    private Map<Class<?>,Object> hobbies = new HashMap<>();

    /**
     * 功能描述:
     * 〈添加爱好〉
     *
     * @params : [type, instance]
     * @return : void
     * @author : cwl
     * @date : 2019/5/6 17:51
     */
    public <T> void putHobbies(Class<T> type,T instance){
        if(type == null){
            throw new NullPointerException("type is null");
        }
        hobbies.put(type,instance);
    }
    
    /**
     * 功能描述: 
     * 〈查询爱好〉
     *
     * @params : [type]
     * @return : T
     * @author : cwl
     * @date : 2019/5/6 17:52
     */
    public <T> T getHobbies(Class<T> type){
        return type.cast(hobbies.get(type));
    }

}

우리는 광고 항목 중 데이터베이스를 나타내는 클래스를 사용할 수있는 경우 기본적으로, 당신이 원하는 패키지에 대한 정보 등의 수집을하지 말고, 우리는 객체 지향 프로그래밍을하려고 할 오히려 설정 지향 프로그래밍에 비해

대신 INT 상수 (30)를 사용하여 열거

열거 형의 경우, 범위는 INT 상수보다 상대적으로 더 광범위한 사용할 수 있습니다, 여기에 통합 사용 열거 클래스입니다. 수요가 근무일을 구분하고 일을 휴식하는 것입니다, 다른 근로 시간은 환율이 다른 작업에 해당하는 계산

public enum PayrollyDay {
    MONDAY(PayType.WEEKDAY),
    TUESDAY(PayType.WEEKDAY),
    WENDESDAY(PayType.WEEKDAY),
    THURSDAY(PayType.WEEKDAY),
    FRIDAY(PayType.WEEKDAY),
    SATURDAY(PayType.WEEKEND),
    SUNDAY(PayType.WEEKEND);

    private final PayType payType;
    //当创建一个枚举对象的时候,有多少个枚举字段就会调用多少次构造器,可以通过人肉打印测试
    PayrollyDay(PayType payType){
        //System.out.println("调用构造器");
        this.payType = payType;
    }
    double pay(double hoursWorked,double payRate){
       return payType.pay(hoursWorked,payRate);
    }
    private enum PayType{

        WEEKDAY{
            double overTimePay(double hours,double payRate){
                return hours <= HOURS_PER_SHIFT ? 0 : (hours - HOURS_PER_SHIFT) * payRate / 2;
            }

        },
        WEEKEND{
            double overTimePay(double hours,double payRate){
                return hours = payRate / 2;
            }
        };
        //枚举类当中的固定写法,具体实现时会找到上面两个枚举当中的任意一个
        abstract double overTimePay(double hours,double payRate);

        private static final int HOURS_PER_SHIFT = 8;
        double pay(double hoursWorked,double payRate){
            double basePay = hoursWorked * payRate;
            return basePay + overTimePay(hoursWorked,payRate);
        }
    }
}

테스트 케이스

    public static void main(String[] args) {
        //参数1:时薪
        //参数2:工作时间
        //参数3:加班工资计算汇率
        //此处double精度不够,有兴趣的可以自行转换成Bigdecmail计算
        double pay = PayrollyDay.MONDAY.pay(50,10, 0.8);
        System.out.println(pay);
    }

HTTPS : //www.jianshu.com/p/85bf695b6f45 재현

추천

출처blog.csdn.net/weixin_33859665/article/details/91103707