Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебное пособие Java.doc
Скачиваний:
17
Добавлен:
07.09.2019
Размер:
569.34 Кб
Скачать

Инициализирование полей в интерфейсах

Поля определенные в интерфейсах автоматически становятся static и final. Они не могут быть пустыми (чистыми) final переменными, но они могут быть инициализированы не постоянными выражениями. К примеру:

// Инициализирование полей интерфейса

// не постоянными инициализаторами.

import java.util.*;

public interface RandVals {

int rint = (int)(Math.random() * 10);

long rlong = (long)(Math.random() * 10);

float rfloat = (float)(Math.random() * 10);

double rdouble = Math.random() * 10;

} ///:~

Поскольку все поля static, то они инициализируются при первой загрузке класса, что происходит при первом доступе к любой переменной. Вот пример:

public class TestRandVals {

public static void main(String[] args) {

System.out.println(RandVals.rint);

System.out.println(RandVals.rlong);

System.out.println(RandVals.rfloat);

System.out.println(RandVals.rdouble);

}

} ///:~

Эти поля, естественно, не являются частью интерфейса, вместо этого они размещены в static хранилище этого интерфейса.

Вложенные интерфейсы

Интерфейсы могут быть вложены внутрь классов и других интерфейсов. Такая возможность выявляет несколько очень интересных возможностей:

class A {

interface B {

void f();

}

public class BImp implements B {

public void f() {}

}

private class BImp2 implements B {

public void f() {}

}

public interface C {

void f();

}

class CImp implements C {

public void f() {}

}

private class CImp2 implements C {

public void f() {}

}

private interface D {

void f();

}

private class DImp implements D {

public void f() {}

}

public class DImp2 implements D {

public void f() {}

}

public D getD() { return new DImp2(); }

private D dRef;

public void receiveD(D d) {

dRef = d;

dRef.f();

}

}

interface E {

interface G {

void f();

}

// избыточный "public":

public interface H {

void f();

}

void g();

// Не может быть private внутри интерфейса:

//! private interface I {}

}

public class NestingInterfaces {

public class BImp implements A.B {

public void f() {}

}

class CImp implements A.C {

public void f() {}

}

// Не может быть реализован private interface без

// внутреннего определения класса:

//! class DImp implements A.D {

//! public void f() {}

//! }

class EImp implements E {

public void g() {}

}

class EGImp implements E.G {

public void f() {}

}

class EImp2 implements E {

public void g() {}

class EG implements E.G {

public void f() {}

}

}

public static void main(String[] args) {

A a = new A();

// Нет доступа A.D:

//! A.D ad = a.getD();

// Ничего не возвращается, кроме A.D:

//! A.DImp2 di2 = a.getD();

// Нельзя получить доступ к участнику интерфейса:

//! a.getD().f();

// Только другой A может что-то делать с getD():

A a2 = new A();

a2.receiveD(a.getD());

}

} ///:~

Синтаксис внутреннего интерфейса внутри класса очевиден и похож на не внутренние интерфейсы, которые могут быть public или friendly. Вы так же видите, что оба внутренних интерфейса public и friendly могут быть реализованы как public, friendly и private внутренние классы.

С этой новой особенностью интерфейсы могут так же быть private, как видно из A.D (тот же самый синтаксис используется для внутренний интерфейсов и для внутренних классов). Что же хорошего в private внутреннем интерфейсе? Как Вы можете догадаться, он может быть реализован только как private внутренний класс, как, например в DImp, но в A.DImp2 видно, что он так же может быть реализован и как public класс. Но все равно, A.DImp2 может быть использован только как сам. Однако не следует пропустить упоминание о том, что реализация private интерфейса это всего лишь путь для принудительного определения методов в этом интерфейсе, без добавления любой информации о типе (это так и есть, без возможности любого приведения к базовому типу).

Метод getD( ) вызывает дальнейшие затруднения связанные с private интерфейсом: это public метод, который возвращает ссылку на private интерфейс. И что Вы будете делать с этим возвращенным значением? В main( ), Вы можете видеть несколько провалившихся попыток что-либо поделать с ним. Единственная вещь способная работать с ним - это может быть объект имеющий на него права, в нашем случае другой объект A, посредством метода received( ).

Интерфейс E показывает, что интерфейсы могут быть вложены друг в друга. Но все равно, правила насчет интерфейсов следующие, все элементы интерфейса должны быть public, но в случае внутреннего интерфейса внутри другого интерфейса они все и так становятся public автоматически и не могут быть сделаны private.

NestingInterfaces показывает различные пути реализации внутренних интерфейсов. В частности заметьте, что когда Вы реализуете интерфейс, вам не нужно так же реализовывать внутренние интерфейсы, находящиеся в нем. Так же, private интерфейсы не могут быть реализованы снаружи класса, в котором они определены.