장 VI 인터페이스, 람다 표현식과 내부 클래스 | 연구 노트

자바 핵심 기술 볼륨

6.1 인터페이스

  • 인터페이스 개념

자바 프로그래밍 언어에서, 인터페이스는 클래스가 아니라 클래스의 설명에 대한 일련의 요구 사항은,이 클래스는 인터페이스 설명을 따라 통일 된 형식을 정의한다.

例如:
    public interface Comparable
    {
        int compareTo(Object other);
    }

필적하는 클래스 구현 compareTo 메소드에있어서의 인터페이스, 및이 방법의 파라미터는 객체 객체 복귀 정수 배열이어야.
자동으로 대중에게 속한다 인터페이스 방법. 인터페이스 메서드에 선언 할 때 따라서, 키워드 대중을 제공하지 않습니다.
클래스가 구현하는 인터페이스를 만들려면 다음과 같은 두 단계가 필요합니다 :
1. 클래스 구현이 지정된 인터페이스를 선언합니다.
2. 인터페이스 메소드를 정의한다.

例如:
    public int compareTo(Object otherObject)
    {
        Employee other = (Employee) otherObject;
        return Double ,compare(sal ary, other,sal ary);
    }
  • 인터페이스의 특성

인터페이스는 특히, 그러나, 오브젝트 인터페이스 변수를 선언 할 수 인터페이스에도 불구하고 구축 할 수 없었던 새로운 오퍼레이터 인터페이스를 인스턴스화 할 수는 클래스 아니다.

Comparable x; // OK

인터페이스 변수를 구현하는 객체의 인터페이스이 클래스를 참조해야합니다 :

x = new Employee(. . .); // OK provided Employee implements Comparable

인터페이스도 확장 할 수 있습니다 :

例如:假设有一个称为Moveable的接口
    public interface Moveable
    {
        void move(double x, double y);
    }
然而,可以以它为基础拓展一个叫做Powered的接口:
    public interface Powered extends Moveable
    {
        double milesPerCallon();
    }
虽然在接口中不能包含实例域或静态方法,但却可以包含常量。
    public interface Powered extends Moveable
    {
        double milesPerCallon();
        double SPEED. LIHIT = 95; // a public static final constant
    }

인터페이스 메소드 자동 공개로 설정되어, 상기 인터페이스 영역이 자동으로 공개 정적 최종 설정된다.

  • 인터페이스와 추상 클래스
  • static 메소드

지금까지 집 퇴치를위한 일반적인 방법은 정적 메서드 클래스와 함께.

例如:
    public interface Path//Path.get("jdk1.8.0", "jre", "bin")
    {
        public static Path get(String first, String... more) {
            return Fi1eSystems.getDefault().getPath(first, more);
        }
        ...
    }
  • 기본 방법

이 인터페이스 방법에 대한 기본 구현을 제공 할 수 있습니다. 당신은 기본 수식을 사용해야합니다.

例如:
    public interface Comparable<T>
    {
        default int compareTo(T other) { return 0; }
        // B y default, all elements are the same
    }

때로는 기본 방법은 유용하다. 마우스 클릭은 시간이 발생할 때 알림을하려는 경우 예를 들어, 우리는 다섯 인터페이스가 포함되어 깨달아야한다 :

  public interface MouseListener
    {
        void mousedieked(MouseEvent event);
        void mousePressed(MouseEvent event);
        void mouseReleased(MouseEvent event);
        void mouseEntered(MouseEvent event);
        void mouseExited(MouseEvent event);
    }
    可以把所有方法声明为默认方法,这些默认方法什么也不做:
    public interface MouseListener
    {
        default void mousedieked(MouseEvent event) {}
        default void mousePressed(MouseEvent event) {}
        default void mouseReleased(MouseEvent event) {}
        default void mouseEntered(MouseEvent event) {}
        default void mouseExited(MouseEvent event) {}
    }

기본 방법은 다른 방법을 호출 할 수 있습니다.

例如,Collection接口可以定义一个便利方法:
    public interface Collection
    {
        int size(); // An abstract method
        default boolean isEmpty()
        {
            return size() == 0;
        } 
        ...
    }

달성하기 위해이 컬렉션 IsEmpty 함수 프로그래머는 방법의 실현에 대해 걱정할 필요가 없습니다.

  • 해결 충돌에 대한 기본 방법

규칙 :
1. 슈퍼 클래스의 우선 순위. 슈퍼 클래스는 같은 이름의 특정 방법을 제공하고 기본 방법을 반환하는 동일한 유형의 매개 변수가있는 경우 무시됩니다.
2. 인터페이스 충돌합니다. 슈퍼 인터페이스가 기본 방법을 제공하는 경우, 다른 인터페이스가 같은 이름과 같은 방법의 파라미터 화 된 형태를 제공합니다, 당신은 충돌을 해결하기 위해이 방법을 재정의해야합니다.

인터페이스 예 6.2

  • 인터페이스 및 콜백

콜백은 일반적인 프로그래밍 모델이다. 특정 이벤트가 취해 져야한다 발생할 때 모드에서 작업을 가리킬 수 있습니다.

  • 비교기 인터페이스
  • 개체 복제

복제 가능한 인터페이스는 복제에 안전한 방법을 제공한다.
그림 삽입 설명 여기
각 클래스에 대해 결정한다 :
1. 기본 복제 방법은 요구 사항을 충족;
; 변수 하위 객체의 기본 복제 수리 방법 여부 2. 전화 복제
3. 여부 복제를 사용해야
실제로 세 번째 옵션은 기본 옵션입니다. 선택한 항목 1 또는 2, 클래스해야이 경우
Cloneable를 인터페이스를 구현하는 1,
2 클론 방식을 재정의하고 액세스 한정자 공개를 지정합니다.

6.3 람다 표현식

  • 왜 람다 식의 도입

람다 표현식은 하나 이상의 시간 후에 수행 할 수있는 경우 코드 블록이 전송 될 수있다.
의 actionPerformed 방법은 작업이 지정된 간격으로 수행됩니다 어떻게 된 ActionListener에있는 것이 작품을 이해하기 :

   class Worker implements ActionListener
    {
        public void actionPerformed(ActionEvent event)
        {
            // do some work
        }
    }

원하는 곡이 반복하여 실행하고 코드 위상되면, 작업자 클래스 인스턴스하도록 구성 될 수있다. 그런 다음이 예는 Timer 객체에 제출했다.
당신이 길이로하려면 기본 사전 순서로 정렬 문자열 정렬 방법 비교기 객체에 전달 될 수보다는 :

 class LengthComparator implements Comparator<String>
    {
        public int compare(String first, String second)
        {
            return first.lengthQ - second.length();
        }
    }
    . .
    Arrays.sort(strings, new LengthComparator());

비교 즉시 호출되지 않습니다. 사실, 배열을 정렬의 완료 전에, 정렬 방법은 항상 긴 요소를 재 배열 잘못된 순서로 요소로, 비교 방법을 호출됩니다.

  • 문법 람다 표현식
例如:
    (String first, String second)
        -> first.length() - second.length()

람다 식은 코드 블록이며,이 코드는 가변 명세서에 전달되어야한다.

(제 문자열, 문자열 초) ->
{
경우 (first.length () <second.length ()) -1을 리턴;
다른 경우 (first.length ()> second.length ()) 창 1;
그렇지 않은 경우 0;
}

어떤 매개 변수 람다 식이없는 경우에도, 여전히 매개 변수없이 동일한 방법으로, 빈 괄호를 제공합니다 :

   () -> { for (int i = 100;i >= 0;i ) System.out.println(i); }
  • 기능 인터페이스

이러한 인터페이스를 필요로하는 람다 식을 제공 할 수있는 추상적 방식 인터페이스 하나만 들어. 이 인터페이스는 함수 인터페이스라고합니다.

타이머 t = 새로운 타이머 (1000 이벤트 ->
{에서 System.out.println는 (+ 새 날짜 "톤에서 thetime는"())
. Toolkit.getDefaultToolkit () 비프 ();
};

BiFunction<String, String, Integer> comp
    = (first, second) -> first.length() - second.length();
  • 방법 참조

예를 들어,이 타이머 이벤트 객체를 인쇄하는 데 시간이 오래 표시 할 가정, 당신은 호출 할 수 있습니다 :

타이머 t = 새로운 타이머 (1000 이벤트 ->에서 System.out.println (이벤트)) :

인쇄 방법 타이머 생성자 더 나은에 전달.

타이머 t = 새로운 타이머 (1000 Systey.out ::에 println);

표현 Systey.out는 ::에 println는 방법 참조입니다. 람다 식 x>에서 System.out.println (X)에 상당
없이 문자 사건의 정렬 스트링 원하는 것으로 가정한다.

  Arrays.sort(strings,String::conpareToIgnoreCase)

:: 파티션 방법 이름 또는 객체 클래스 이름을 사용하여 연산자. 삼가지 경우가 있습니다 :

• 개체 :: instanceMethod
• 클래스 : StaticMethod를
• 클래스 :: instanceMethod

이 매개 변수는 참조의 방법으로 사용될 수있다. > this.equals (x)를 - 예를 들어,이 :: 등호는 x와 동일.
슈퍼 :: instanceMethod : 사용 슈퍼 법적

例如:
    class Greeter
    {
        public void greet()
        {
            System.out.println("Hello, world!");
        }
        }
     class TimedCreeter extends Greeter
        {
            public void greet()
        {
        Timer t = new Timer(1000, super::greet);
        t.start();
        }
    }
  • 생성자 참조

생성자는 참조 방법과 매우 유사하지만, 방법은 새로운했다. 예를 들어, 사람 : 새로운 생성자 참조의 사람입니다.
, 호출이 같은 다음 생성자는 각 문자열에 호출 할 수있는 개체의 사람 배열로 변환 할 수 있습니다, 당신은 문자열 목록이 있다고 가정 :

  ArrayList<String> names = . . .;
        Stream<Person> stream = names.stream().map(Person::new);
        List<Person> people = stream.collect(Collectors.toList());

당신은 배열 참조 생성자 유형을 만들 수 있습니다. 어레이의 길이 예를 들어, INT [] :: 새로운 생성자는 기준, 그것은 하나 개의 파라미터를 갖는다. > 새로운 INT [X] -이 람다 식 X와 동일하다 .
Java는 한계가있다, 당신은 제네릭 형식 T.의 배열을 만들 수 없습니다

  • 변수 범위

: 람다 발현은 세 부분으로 구성되어
, 1 코드 블록
2 파라미터;
3. 비모수 변수를 참조하여 코드에서 정의되지 않은 자유 변수의 값.

  • 람다 표현식 처리

람다 표현식의 사용에 초점 지연 실행하는 것입니다. 즉시 코드를 실행하려는 경우에는 람다 표현식에서 포장 할 필요없이 바로 실행할 수 있습니다.
이유 :
; 1. 코드에서 별도의 스레드 허용
2. 실행 코드를 여러 번,
3. 알고리즘의 장소에 코드를 허용,
상황 코드 실행 4. 발생,
5. 코드를 실행하기 만 의미합니다.
당신이 작업을 n 번 반복한다고 가정. 이 작업을 반복 번 반복 방법으로 전송 될 것입니다 :

repeat(10, () -> System.out.println("Hello, World!"));

그림 삽입 설명 여기
그림 삽입 설명 여기

6.4 내부 클래스

다른 클래스 카테고리 내부 클래스에 의해 정의된다.
사용 이유 :
1. 클래스의 클래스 내의 데이터 액세스 방법은 고유의 데이터를 포함하여 범위를 정의 하였다.
2. 내부 클래스는 같은 패키지의 다른 클래스에 숨길 수 있습니다.
3. 콜백 함수를 정의 할 익명 내부 클래스보다 편리하게 사용하여 코드를 많이 쓰고 싶지 않습니다.
클래스 사이보다는 개체 사이의 관계에 의해 중첩 관계. 명명 제어 및 액세스 제어 : 중첩 클래스는 두 가지 이점이있다.

  • 내부 클래스는 객체 상태에 액세스하는 데 사용

TimerTest 예, 그리고 TalkingClock 추상 클래스에서. 릴리스 스위치 플래그 광고 간격과 벨소리 : 매개 변수 연설의 두 클럭 설정을 제공 할 필요가있다.

  public class TalkingClock
    {
        private int interval:
        private boolean beep;
        
        public TalkingClock(int interval, boolean beep) { . . . }
        public void start() { . . . }
        
        public class TimePrinter implements ActionListener
        // an inner class
        {
            ...
        }
    }

TimePrinter TalkingClock 클래스 카테고리 내에 위치한 주목된다.
비프 음이 발생하기 전에 검사 방법을 플래그의 actionPerformed.

  public class TimePrinter implements ActionListener
    {
        public void actionPerformed(ActionEvent event)
        {
            System.out.println("At the tone, thetimeis" + new Date());
            if (beep) Toolkit.getDefaultToolkit().beep();
        }
    }

TimePrinter 클래스에는 인스턴스 필드 또는 변수 경고음 이름 및 경고음 인용 도메인 생성 TalkingClock에 의해 TimePrinter의 객체 교체가 없습니다.
그림 삽입 설명 여기

클래스 내부의 특수 구문 규칙
OuterClass.this : 둘러싸는 클래스 참조 형식 문법

例如:
    public void actionPerformed(ActionEvent event)
    {
            ...
        if (TalkingClock.this.beep) Toolkit.getDefaultToolkitO.beep();
    }
    采用下列语法格式更明确地编写内部对象的构造器:
        outerObject.new InnerClass(construction parameters)
    例如:
        ActionListener listener = this.new TimerPrinter();
    TalkingClock jabberer = new TalkingClock(1000, true);
    TalkingOock.TiiePrinter listener= jabberer.newTimePrinter();

内部类中声明的所有静态域都必须是final。
内部类不能用static方法。

  • 内部类是否有用、必要和安全
  • 局部内部类
  • 由外部方法访问变量

局部类不仅能够访问包含他们的内部类,还可以访问局部变量。

例如:将TalkingClock 构造器的参数 interval和 beep 移至 start方法中。
    public void start(int interval, boolean beep)
    {
        class TimePrinter implements ActionListener
        {
            public void actionPerformed(ActionEvent event)
            {
                System.out.println("At the tone, the time is" +new Date());
                if (beep) Toolkit.getDefaultToolkit().beep();
            }
        }
        ActionListener listener = new TimePrinter();
        Timer t = new Timer(interval, listener);
        t.start();
    }

    流程:
        1.调用start方法
        2.调用内部类TimePrinter的构造器,一边初始化对象变量listener
        3.将listener引用传递给Timer构造器,定时器开始计数时,start方法结束。
        4.然后actionPerformed方法执行if
  • 匿名内部类

只创建这个类的一个对象,就不必命名,这种类被称之为匿名内部类。

   public void start(int interval, boolean beep)
    {
        ActionListener listener = new ActionListener()
        {
            public void actionPerformed(ActionEvent event)
            {
                System.out.println("At the tone, the time is" + new Date());
                if (beep) Toolkit.getDefaultToolkit().beep();
            }
        };
        Timer t = new Timer(interval, listener);
        t.start();
    }

含义:创建一个实现ActionListener接口的类的新对象,需要实现的方法actionPerformed定义在括号{}内。

语法格式:
    new SuperType(construction parameters)
    {
        inner class methods and data
    }
  • 静态内部类

将内部类声明为static。
考虑一下计算数组中的最小值和最大值的问题。同时计算出最小值和最大值。

double min = Double.POSITIVE_INFINITY;
double max = Double.NECATIVE_INFINITY;
for (double v : values)
{
if (min > v) min = v;
if (max < v) max = v;
}

클래스 ArrayAlg
{
공공 정적 쌍 MINMAX (이중선] 값)
{
...
새로운 쌍 (최대 분) 리턴;
}
}
使用方法:
페어 p = ArrayAlg.minmax (d);
시스템 out.println ( "분 ="+ p.getFirst ());
시스템 out.println ( "MAX ="+ p.getSecond ());

6.5 프록시

에이전트는 런타임에 인터페이스를 제공 새로운 클래스 세트의 구현을 만드는 데 사용할 수 있습니다.

  • 때 프록시를 사용하는 방법

다음 방법으로 에이전트
일 모든 방법 지정된 인터페이스가 필요합니다.
모든 방법의 2.Object 클래스입니다.

  • 프록시 객체를 생성

우리는 프록시 개체, 프록시 클래스의 사용 newProxyInstance 방법을 만들려고합니다. 매개 변수는 다음과 같습니다
1. 클래스 로더.
객체의 2. 클래스의 배열은 각 요소가 구현해야합니다.
3. 통화 프로세서.

게시 14 개 원래 기사 · 원의 찬양 (22) · 조회수 558

추천

출처blog.csdn.net/qq_41550921/article/details/103999206