![]() |
Spec-Zone .ru
спецификации, руководства, описания, API
|
Содержание | Предыдущий | Следующий | Индекс | Спецификация языка Java Третий Выпуск |
ГЛАВА 9
Интерфейсное объявление представляет новый ссылочный тип, элементы которого являются классами, интерфейсами, константами и абстрактными методами. У этого типа нет никакой реализации, но иначе несвязанные классы могут реализовать его, обеспечивая реализации для ее абстрактных методов.
Вложенный интерфейс является любым интерфейсом, объявление которого происходит в пределах тела другого класса или интерфейса. Высокоуровневый интерфейс является интерфейсом, который не является вложенным интерфейсом.
Мы различаем два вида интерфейсов - нормальные интерфейсы и типы аннотации.
Эта глава обсуждает общую семантику всех нормальных интерфейсами интерфейсов и типов аннотации (§9.6), верхний уровень (§7.6) и вложенный (§8.5, §9.5). Детали, которые являются определенными для определенных видов интерфейсов, обсуждаются в разделах, выделенных этим конструкциям.
Программы могут использовать интерфейсы, чтобы сделать это ненужным для связанных классов, чтобы совместно использовать общий абстрактный суперкласс или добавить методы к Object
.
Класс, как могут объявлять, непосредственно реализует один или более интерфейсов, означая, что любой экземпляр класса реализует все абстрактные методы, определенные интерфейсом или интерфейсами. Класс обязательно реализует все интерфейсы, которые делают его прямые суперклассы и прямые суперинтерфейсы. Это (многократное) интерфейсное наследование позволяет объектам поддерживать (многократные) общие поведения, не совместно используя реализации.
Переменная, чья объявленный типом интерфейсный тип, может иметь как его значение ссылка на любой экземпляр класса, который реализует указанный интерфейс. Не достаточно, что класс, оказывается, реализует все абстрактные методы интерфейса; класс или один из его суперклассов, как должны фактически объявлять, реализуют интерфейс, или иначе класс, как полагают, не реализует интерфейс.
InterfaceDeclaration: NormalInterfaceDeclaration AnnotationTypeDeclaration
Типы аннотации описываются далее в §9.6.
Идентификатор в интерфейсном объявлении определяет имя интерфейса. Ошибка времени компиляции происходит, если у интерфейса есть то же самое простое имя как какой-либо из его классов включения или интерфейсов.NormalInterfaceDeclaration: InterfaceModifiersopt interface Identifier TypeParametersopt ExtendsInterfacesopt InterfaceBody
Модификатор доступаInterfaceModifiers: InterfaceModifier InterfaceModifiers InterfaceModifier InterfaceModifier: one of Annotation public protected private abstract static strictfp
public
обсуждается в §6.6. Не все модификаторы применимы ко всем видам интерфейсных объявлений. Модификаторы доступа protected
и private
принадлежите только задействованным интерфейсам в пределах непосредственно объявления класса включения (§8.5), и обсуждаются в §8.5.1. Модификатор доступа static
принадлежит только задействованным интерфейсам (§8.5, §9.5). Ошибка времени компиляции происходит, если тот же самый модификатор появляется не раз в интерфейсном объявлении. Если аннотация на интерфейсном объявлении соответствует типу T аннотации, и T имеет (мета-) аннотация м., который соответствует annotation.Target
, тогда у м. должен быть элемент, значение которого annotation.ElementType.TYPE
, или ошибка времени компиляции происходит. Модификаторы аннотации описываются далее в §9.7.abstract
. Этот модификатор является устаревшим и не должен использоваться в новых программах.strictfp
модификатор должен сделать все float
или double
выражения в пределах интерфейсного объявления быть явно строгим FP (§15.4).
Это подразумевает, что все вложенные типы, объявленные в интерфейсе, неявно strictfp
.
Контекст параметра типа интерфейса является всем объявлением интерфейса включая раздел параметра типа непосредственно. Поэтому, введите параметры, может появиться как части их собственных границ, или как границы других параметров типа, объявленных в том же самом разделе.
Это - ошибка времени компиляции, чтобы обратиться к параметру типа интерфейса I где угодно в объявлении поля или элементе типа меня.
extends
пункт обеспечивается, тогда объявляемый интерфейс расширяет каждый из других именованных интерфейсов и поэтому наследовал типы элемента, методы, и константы каждого из других именованных интерфейсов. Эти другие именованные интерфейсы являются прямыми суперинтерфейсами объявляемого интерфейса. Любой класс это implements
объявленный интерфейс, как также полагают, реализует все интерфейсы что этот интерфейс extends
.
Следующее повторяется от §4.3, чтобы сделать представление здесь более четким:ExtendsInterfaces: extends InterfaceType ExtendsInterfaces , InterfaceType
Данный (возможно универсальный) соединяют интерфейсом с объявлением, поскольку я <F1..., Fn>, n0InterfaceType: TypeDeclSpecifier TypeArgumentsopt
Позвольте мне <F1..., Fn>, n> 0, быть универсальным интерфейсным объявлением. Прямые суперинтерфейсы параметризованного интерфейсного типа I <T1..., Tn>, где Ti, 1 дюйм
, является типом, являются всеми типами J <тета U1..., Британская тета>, где J <U1..., Великобритания> являются прямым суперинтерфейсом меня <F1..., Fn>, и тета является заменой [F1: = T1..., Fn: = Tn].
Каждый InterfaceType в extends
пункт интерфейсного объявления должен назвать доступный интерфейсный тип; иначе ошибка времени компиляции происходит.
Интерфейс I непосредственно зависит от типа T, если T упоминается в extends
пункт я или как суперинтерфейс или как спецификатор в пределах суперинтерфейсного имени. Интерфейс I зависит от ссылочного типа T, если какое-либо из следующих условий содержит:
В то время как каждый класс является расширением класса Object
, нет никакого единственного интерфейса, которого все интерфейсы являются расширениями.
Суперинтерфейсное отношение является переходным закрытием прямого суперинтерфейсного отношения. Интерфейсный K является суперинтерфейсом интерфейса I, если любое из следующего является истиной:
Контекст объявления элемента м. объявил в или наследовался интерфейсным типом, я - все тело меня, включая любые объявления вложенного типа.InterfaceBody: { InterfaceMemberDeclarationsopt } InterfaceMemberDeclarations: InterfaceMemberDeclaration InterfaceMemberDeclarations InterfaceMemberDeclaration InterfaceMemberDeclaration: ConstantDeclaration AbstractMethodDeclaration ClassDeclaration InterfaceDeclaration;
public
. Они доступны вне пакета, где интерфейс объявляется, если интерфейс также объявляется public
или protected
, в соответствии с правилами §6.6.
throws
пункт t, соответствующий каждому общедоступному методу экземпляра м. с подписью s, возвратите тип r, и throws
пункт t, объявленный в Object
, если метод с той же самой подписью, тем же самым типом возврата, и совместимым throws
пункт явно объявляется интерфейсом. Это - ошибка времени компиляции, если интерфейс явно объявляет такой метод м. в случае, где м., как объявляют, находится final
в Object
. Object
, но имеет различный тип возврата или несовместимый throws
пункт.Интерфейс наследовался от интерфейсов, которые он расширяет, все элементы тех интерфейсов, за исключением полей, классов, и интерфейсов, которые он скрывает и методы, которые он переопределяет.
Каждое полевое объявление в теле интерфейса неявноConstantDeclaration: ConstantModifiersopt Type VariableDeclarators ; ConstantModifiers: ConstantModifier ConstantModifier ConstantModifers ConstantModifier: one of Annotation public static final
public
, static
, и final
. Разрешается избыточно определить любые из этих модификаторов для таких полей.
Если аннотация на полевом объявлении соответствует типу T аннотации, и T имеет (мета-) аннотация м., который соответствует annotation.Target
, тогда у м. должен быть элемент, значение которого annotation.ElementType.FIELD
, или ошибка времени компиляции происходит. Модификаторы аннотации описываются далее в §9.7.
Если интерфейс объявляет поле с определенным именем, то объявление того поля, как говорят, скрывает любого и все доступные объявления полей с тем же самым именем в суперинтерфейсах интерфейса.
Это - ошибка времени компиляции для тела интерфейсного объявления, чтобы объявить два поля с тем же самым именем.
Для интерфейса возможно наследовать больше чем одно поле с тем же самым именем (§8.3.3.3). Такая ситуация сам по себе не вызывает ошибку времени компиляции. Однако, любая попытка в пределах тела интерфейса, чтобы обратиться к любому полю его простым именем приведет к ошибке времени компиляции, потому что такая ссылка неоднозначна.
Могло бы быть несколько путей, которыми то же самое полевое объявление могло бы быть наследовано от интерфейса. В такой ситуации поле, как полагают, наследовано только однажды, и это может быть упомянуто его простым именем без неоднозначности.
Ошибка времени компиляции происходит, если выражение инициализации для интерфейсного поля содержит ссылку простым именем к тому же самому полю или к другому полю, объявление которого происходит дословно позже в том же самом интерфейсе.
Таким образом:
причины две ошибки времени компиляции, потому чтоinterface Test { float f = j; int j = 1; int k = k+1; }
j
упоминается в инициализации f
прежде j
объявляется и потому что инициализация k
обращается к k
непосредственно.Одна тонкость здесь - то, что во время выполнения поля, которые инициализируются с постоянными величинами времени компиляции, инициализируются сначала. Это применяется также к static
final
поля в классах (§8.3.2.1). Это означает, в частности что у этих полей, как никогда будут наблюдать, не будет своих начальных значений по умолчанию (§4.12.5), даже окольными программами. См. §12.4.2 и §13.4.9 для большего количества обсуждения.
this
(§15.8.3) или ключевое слово super
(15.11.2, 15.12), происходит в выражении инициализации для поля интерфейса, затем если возникновение не в пределах тела анонимного класса (§15.9.5), ошибка времени компиляции происходит.
интерфейсinterface BaseColors { int RED = 1, GREEN = 2, BLUE = 4; } interface RainbowColors extends BaseColors { int YELLOW = 3, ORANGE = 5, INDIGO = 6, VIOLET = 7; } interface PrintColors extends BaseColors { int YELLOW = 8, CYAN = 16, MAGENTA = 32; } interface LotsOfColors extends RainbowColors, PrintColors { int FUCHSIA = 17, VERMILION = 43, CHARTREUSE = RED+90; }
LotsOfColors
наследовал два названные поля YELLOW
. Это в порядке, пока интерфейс не содержит ссылки простым именем к полю YELLOW
. (Такая ссылка могла произойти в пределах переменного инициализатора для поля.)Даже если интерфейс PrintColors
должны были дать значение 3
к YELLOW
вместо значения 8
, ссылка на поле YELLOW
в пределах интерфейса LotsOfColors
все еще считался бы неоднозначным.
В примере в предыдущем разделе, полях RED
, GREEN
, и BLUE
наследованы интерфейсом LotsOfColors
больше чем одним способом, через интерфейс RainbowColors
и также через интерфейс PrintColors
, но ссылка на поле RED
в интерфейсе LotsOfColors
не считается неоднозначным потому что только одно фактическое объявление поля RED
включается.
Модификатор доступаAbstractMethodDeclaration: AbstractMethodModifiersopt TypeParametersopt ResultType MethodDeclarator Throwsopt ; AbstractMethodModifiers: AbstractMethodModifier AbstractMethodModifiers AbstractMethodModifier AbstractMethodModifier: one of Annotation public abstract
public
обсуждается в §6.6. Ошибка времени компиляции происходит, если тот же самый модификатор появляется не раз в абстрактном объявлении метода.
Каждое объявление метода в теле интерфейса неявно abstract
, таким образом, его тело всегда представляется точкой с запятой, не блоком.
Каждое объявление метода в теле интерфейса неявно public
.
Для совместимости с более старыми версиями платформы Java это разрешается, но обескураживается, как стиль, чтобы избыточно определить abstract
модификатор для методов объявляется в интерфейсах.
Это разрешается, но строго обескураживается как стиль, чтобы избыточно определить public
модификатор для интерфейсных методов.
static
, или ошибка времени компиляции происходит, потому что static
методы не могут быть abstract
.
Отметьте, что метод, объявленный в интерфейсе, не должен быть объявлен strictfp
или native
или synchronized
, или ошибка времени компиляции происходит, потому что те ключевые слова описывают свойства реализации, а не интерфейсные свойства. Однако, метод, объявленный в интерфейсе, может быть реализован методом, который объявляется strictfp
или native
или synchronized
в классе, который реализует интерфейс.
Если аннотация на объявлении метода соответствует типу T аннотации, и T имеет (мета-) аннотация м., который соответствует annotation.Target
, тогда у м. должен быть элемент, значение которого annotation.ElementType.METHOD
, или ошибка времени компиляции происходит. Модификаторы аннотации описываются далее в §9.7.
Это - ошибка времени компиляции для тела интерфейса, чтобы объявить, явно или неявно, два метода с эквивалентными переопределению подписями (§8.4.2). Однако, интерфейс может наследовать несколько методов с такими подписями (§9.4.1).
Отметьте, что метод, объявленный в интерфейсе, не должен быть объявлен final
или ошибка времени компиляции происходит. Однако, метод, объявленный в интерфейсе, может быть реализован методом, который объявляется final
в классе, который реализует интерфейс.
Метод в интерфейсе может быть универсальным. Правила для формальных параметров типа универсального метода в интерфейсе являются тем же самым что касается универсального метода в классе (§8.4.4).
Кроме того у объявления метода не должно быть a throws
пункт, который конфликтует (§8.4.6) с тем из любого метода, который это переопределяет; иначе, ошибка времени компиляции происходит.
Это - ошибка времени компиляции, если описание типа T имеет задействованный метод m1 и там существует метод m2, объявленный в T или супертипе T так, что, все следующие условия содержат:
Методы переопределяются на основе подписи подписью. Если, например, интерфейс объявляет два public
методы с тем же самым именем, и подынтерфейс переопределяют одного из них, подынтерфейс все еще наследовал другой метод.
Интерфейс наследовал от его прямых суперинтерфейсов все методы суперинтерфейсов, которые не переопределяются объявлением в интерфейсе.
Для интерфейса возможно наследовать несколько методов с эквивалентными переопределению подписями (§8.4.2). Такая ситуация сам по себе не вызывает ошибку времени компиляции. Интерфейс, как полагают, наследовал все методы. Однако, один из наследованных методов должен, должен быть тип возврата substitutable для любого другого наследованного метода; иначе, ошибка времени компиляции происходит ( throws
пункты не вызывают ошибки в этом случае.)
Могло бы быть несколько путей, которыми то же самое объявление метода наследовано от интерфейса. Этот факт не вызывает трудности и никогда себя результаты в ошибке времени компиляции.
throws
пункты двух методов с тем же самым именем, но различными подписями, которые не эквивалентны переопределению.abstract
и таким образом не содержите реализацию. Обо все, что может быть выполнено объявлением метода переопределения, кроме подтвердить сигнатуру метода, должно совершенствовать тип возврата или ограничить исключения, которые могли бы быть выданы реализацией метода. Вот изменение примера, показанного в (§8.4.3.1):
class BufferEmpty extends Exception { BufferEmpty() { super(); } BufferEmpty(String s) { super(s); } } class BufferException extends Exception { BufferException() { super(); } BufferException(String s) { super(s); } } public interface Buffer { char get() throws BufferEmpty, BufferException; } public interface InfiniteBuffer extends Buffer { char get() throws BufferException; // override }
имя методаinterface PointInterface { void move(int dx, int dy); } interface RealPointInterface extends PointInterface { void move(float dx, float dy); void move(double dx, double dy); }
move
перегружается в интерфейсе RealPointInterface
с тремя различными подписями, двумя из них объявленный и один наследованный. Любой не -abstract
класс, который реализует интерфейс RealPointInterface
должен обеспечить реализации всех трех сигнатур методов.static
и общественность.Если тип элемента, объявленный с простым именем C, непосредственно включается в пределах объявления интерфейса с полностью определенным именем N, то у типа элемента есть полностью определенное имя Северная Каролина.
Если интерфейс объявляет тип элемента с определенным именем, то объявление того поля, как говорят, скрывает любого и все доступные объявления типов элемента с тем же самым именем в суперинтерфейсах интерфейса.
Интерфейс наследовал от его прямых суперинтерфейсов все типы нечлена парламента, не занимающего официального поста суперинтерфейсов, которые и доступны, чтобы кодировать в интерфейсе и не скрытые объявлением в интерфейсе.
Интерфейс может наследовать два или больше описания типа с тем же самым именем. Ошибка времени компиляции происходит на любой попытке обратиться к любому двусмысленно наследованному классу или интерфейсу его простым именем. Если то же самое описание типа наследовано от интерфейса разнообразными путями, класс или интерфейс, как полагают, наследованы только однажды; это может быть упомянуто его простым именем без неоднозначности.
interface
предшествуется знаком at sign (@
).
Обсуждение
Отметьте что знак at sign (@
) и ключевое слово interface
два отличных маркера; технически возможно разделить их пробелом, но этому строго обескураживают как стиль.
AnnotationTypeDeclaration: InterfaceModifiersopt @ interface Identifier AnnotationTypeBody AnnotationTypeBody: { AnnotationTypeElementDeclarationsopt } AnnotationTypeElementDeclarations: AnnotationTypeElementDeclaration AnnotationTypeElementDeclarations AnnotationTypeElementDeclaration AnnotationTypeElementDeclaration: AbstractMethodModifiersopt Type Identifier ( ) DefaultValueopt ; ConstantDeclaration ClassDeclaration InterfaceDeclaration EnumDeclaration AnnotationTypeDeclaration ; DefaultValue: default ElementValue
Обсуждение
Следующие ограничения вводятся для описаний типа аннотации на основании их контекста свободный синтаксис:
annotation.Annotation
.)
throws
пункт
Если явно не изменено здесь, все правила, которые применяются к обычным интерфейсным объявлениям, применяются к описаниям типа аннотации.
Обсуждение
Например, типы аннотации совместно используют то же самое пространство имен как обычный класс и интерфейсные типы.
Описания типа аннотации являются законными везде, где интерфейсные объявления являются законными, и имеют тот же самый контекст и доступность.
Идентификатор в описании типа аннотации определяет имя типа аннотации. Ошибка времени компиляции происходит, если у типа аннотации есть то же самое простое имя как какой-либо из его классов включения или интерфейсов.
Если аннотация на описании типа аннотации соответствует типу T аннотации, и T имеет (мета-) аннотация м., который соответствует annotation.Target
, тогда у м. должен быть любой элемент, значение которого annotation.ElementType.ANNOTATION_TYPE
, или элемент, значение которого annotation.ElementType.TYPE
, или ошибка времени компиляции происходит.
Обсуждение
Условно, никакой AbstractMethodModifiers не должен присутствовать за исключением аннотаций.
Прямой суперинтерфейс типа аннотации всегда annotation.Annotation
.
Обсуждение
Последствие факта, что тип аннотации не может явно объявить суперкласс или суперинтерфейс, - то, что подкласс или подынтерфейс типа аннотации никогда не являются самостоятельно типом аннотации. Точно так же annotation.Annotation
не самостоятельно тип аннотации.
Это - ошибка времени компиляции, если тип возврата метода, объявленного в типе аннотации, является каким-либо типом кроме одного из следующего: одни из типов примитивов, String
, Class
и любой вызов Class
, перечислимый тип (§8.9), тип аннотации, или массив (§10) одного из предыдущих типов. Это - также ошибка времени компиляции, если у какого-либо метода, объявленного в типе аннотации, есть подпись, которая эквивалентна переопределению тому из любого public
или protected
метод объявляется в классе Object
или в интерфейсе annotation.Annotation
.
Обсуждение
Отметьте, что это не конфликтует с запретом на универсальные методы, поскольку подстановочные знаки избавляют от необходимости явный параметр типа.
Каждое объявление метода в описании типа аннотации определяет элемент типа аннотации. У типов аннотации могут быть нуль или больше элементов. У типа аннотации нет никаких элементов кроме определенных методами, которые он явно объявляет.
Обсуждение
Таким образом описание типа аннотации наследовало несколько элементов от annotation.Annotation
, включая неявно объявленные методы, соответствующие методам экземпляра в Object
, все же эти методы не определяют элементы типа аннотации, и это недопустимо, чтобы использовать их в аннотациях.
Без этого правила мы не могли гарантировать, что элементы имели типы, представимые в аннотациях, или что методы доступа для них будут доступны.
Это - ошибка времени компиляции, если тип T аннотации содержит элемент типа T, любой прямо или косвенно.
Обсуждение
и так это:// Illegal self-reference!! @interface SelfRef { SelfRef value(); }
Отметьте также, что эта спецификация устраняет элементы, типы которых вкладываются массивы. Например, это описание типа аннотации недопустимо:// Illegal circularity!! @interface Ping { Pong value(); } @interface Pong { Ping value(); }
// Illegal nested array!! @interface Verboten { String[][] value(); }
Элементу типа аннотации можно было определить значение по умолчанию для этого. Это делается следующим его (пустой) список параметров с ключевым словом default
и значение по умолчанию элемента.
Значения по умолчанию применяются динамически в то время, когда аннотации читаются; значения по умолчанию не компилируются в аннотации. Таким образом изменение значения по умолчанию влияет на аннотации даже в классах, которые были скомпилированы прежде, чем изменение было произведено (предположение, что эти аннотации испытывают недостаток в явном значении принятого значение по умолчанию элемента).
ElementValue используется, чтобы определить значение по умолчанию. Это - ошибка времени компиляции, если тип элемента не соразмерен (§9.7) с определенным значением по умолчанию. ElementValue всегда строг FP (§15.4).
Обсуждение
Следующее описание типа аннотации определяет тип аннотации с помощью нескольких элементов:
Следующее описание типа аннотации определяет тип аннотации без элементов, назвал тип аннотации маркера:// Normal annotation type declaration with several elements /** * Describes the "request-for-enhancement" (RFE) * that led to the presence of * the annotated API element. */ public @interface RequestForEnhancement { int id(); // Unique ID number associated with RFE String synopsis(); // Synopsis of RFE String engineer(); // Name of engineer who implemented RFE String date(); // Date RFE was implemented }
// Marker annotation type declaration /** * Annotation with this type indicates that the specification of the * annotated API element is preliminary and subject to change. */ public @interface Preliminary { }
Условно, имя единственного элемента в одноэлементном типе аннотации value
.
Обсуждение
Лингвистическое обеспечение этого соглашения обеспечивается единственной конструкцией аннотации элемента (§9.7); нужно повиноваться соглашению, чтобы использовать в своих интересах конструкцию.
Обсуждение
Соглашение иллюстрируется в следующем описании типа аннотации:
Следующее описание типа аннотации определяет одноэлементный тип аннотации, единственный элемент которого сделал, чтобы массив ввел:// Single-element annotation type declaration /** * Associates a copyright notice with the annotated API element. */ public @interface Copyright { String value(); }
Вот пример сложных типов аннотации, типы аннотации, которые содержат один или более элементов, типы которых являются также типами аннотации.// Single-element annotation type declaration with array-typed // element /** * Associates a list of endorsers with the annotated class. */ public @interface Endorsers { String[] value(); }
Следующее описание типа аннотации обеспечивает значения по умолчанию для двух из его четырех элементов:// Complex Annotation Type /** * A person's name. This annotation type is not designed to be used * directly to annotate program elements, but to define elements * of other annotation types. */ public @interface Name { String first(); String last(); } /** * Indicates the author of the annotated program element. */ public @interface Author { Name value(); } /** * Indicates the reviewer of the annotated program element. */ public @interface Reviewer { Name value(); }
Следующее описание типа аннотации показывает a// Annotation type declaration with defaults on some elements public @interface RequestForEnhancement { int id(); // No default - must be specified in // each annotation String synopsis(); // No default - must be specified in // each annotation String engineer() default "[unassigned]"; String date() default "[unimplemented]"; }
Class
аннотация, значение которой ограничивается ограниченным подстановочным знаком.
Отметьте, что грамматика для описаний типа аннотации разрешает другие объявления элемента помимо объявлений метода. Например, можно было бы хотеть объявлять вложенное перечисление для использования в соединении с типом аннотации:// Annotation type declaration with bounded wildcard to // restrictClass
annotation // The annotation type declaration below presumes the existence // of this interface, which describes a formatter for Java // programming language source code public interface Formatter { ... } // Designates a formatter to pretty-print the annotated class. public @interface PrettyPrinter { Class<? extends Formatter> value(); }
// Annotation type declaration with nested enum type declaration public @interface Quality { enum Level { BAD, INDIFFERENT, GOOD } Level value(); }
annotation.Target
предназначается, чтобы использоваться в метааннотациях, которые указывают на вид элемента программы, к которому тип аннотации применим. Target
имеет один элемент, типа annotation.ElementType[]
. Это - ошибка времени компиляции, если данная перечислимая константа появляется не раз в аннотации, соответствующий тип которой annotation.Target
. См. разделы §7.4.1, §8.1.1, §8.3.1, §8.4.1, §8.4.3, §8.8.3, §8.9, §9.1.1, §9.3, §9.4, §9.6 и §14.4 для других эффектов @annotation.Target
аннотации.
Тип аннотации annotation.Retention
используется, чтобы выбрать среди вышеупомянутых возможностей. Если аннотация, которую соответствование типу T, и T имеют (мета-) аннотация м., который соответствует annotation.Retention
, тогда:
annotation.RetentionPolicy.SOURCE
, тогда компилятор Java должен гарантировать что присутствование в двоичном представлении класса или интерфейса в который появляться.
annotation.RetentionPolicy.CLASS
, или annotation.RetentionPolicy.RUNTIME
компилятор Java, должен гарантировать, что то, представленного в двоичном представлении класса или интерфейса, в который появляться, если м. не аннотирует объявление локальной переменной. Аннотация на объявление локальной переменной никогда не сохраняется в двоичном представлении. annotation.Retention
, тогда компилятор Java должен обработать T, как будто у этого действительно есть такая метааннотация м. с элементом, значение которого annotation.RetentionPolicy.CLASS
.
Обсуждение
Если у м. есть элемент, значение которого annotation.RetentionPolicy.RUNTIME
, отражающие библиотеки платформы Java сделают доступное во время выполнения также.
annotation.Inherited
используется, чтобы указать, что аннотации на класс C, соответствующий данному типу аннотации, наследованы подклассами C.
Обсуждение
Классический пример касается, равняется методу. Программисты пишут следующее:
когда они означают писать:public boolean equals(Foo that) { ... }
Это является совершенно законным, но классpublic boolean equals(Object that) { ... }
Foo
наследовался equals
реализация от Object
, который может вызвать некоторые очень тонкие ошибки.
Тип аннотации Override
поддерживает раннее обнаружение таких проблем. Если объявление метода аннотируется аннотацией @Override
, но метод фактически не переопределяет метода, объявленного в суперклассе, ошибка времени компиляции произойдет.
Обсуждение
Отметьте это, если метод переопределяет метод от суперинтерфейса, но не от суперкласса, используя @Override
вызовет ошибку времени компиляции.
Объяснение для этого - то, что реальный класс, который реализует интерфейс, обязательно переопределит методы всего интерфейса независимо от @Override
аннотация, и таким образом, сбило бы с толку иметь семантику этой аннотации, взаимодействует с правилами для того, чтобы реализовать интерфейсы.
Продуктом этого правила то, что никогда не возможно использовать @Override
аннотация в интерфейсном объявлении.
SuppressWarnings
поддерживает управление программиста предупреждениями, иначе выпущенными компилятором Java. Это содержит единственный элемент, который является массивом String
. Если объявление программы аннотируется аннотацией @SuppressWarnings(value = {
S1..., Sk}), затем компилятор Java не должен сообщить ни о каком предупреждении, идентифицированном одним из S1..., Sk, если то предупреждение было бы сгенерировано в результате аннотируемого объявления или какой-либо из его частей.
Предупреждения непроверенные идентифицируются строкой "unchecked"
.
Обсуждение
Недавние компиляторы Java выпускают больше предупреждений, чем предыдущие сделали, и эти "подобные линту" предупреждения очень полезны. Вероятно, что больше таких предупреждений будет добавлено в течение долгого времени. Чтобы поощрить их использование, должен быть некоторый способ отключить предупреждение в определенной части программы, когда программист знает, что предупреждение является несоответствующим.
Обсуждение
Поставщики компилятора должны задокументировать имена предупреждения, которые они поддерживают в соединении с этим типом аннотации. Они поощряются сотрудничать, чтобы гарантировать, что те же самые имена работают через многократные компиляторы.
@Deprecated
тот, который программисты отговариваются использовать, обычно потому что это опасно, или потому что существует лучшая альтернатива. Компилятор Java должен произвести предупреждение, когда осуждаемый тип, метод, поле, или конструктор используются (переопределенный, вызванный, или ссылался по имени), если:
@Deprecated
; или
@SuppressWarnings("deprecation")
@Deprecated
на объявлении локальной переменной или на объявлении параметра не имеет никакого эффекта.Аннотации должны содержать пару значения элемента для каждого элемента соответствующего типа аннотации, за исключением тех элементов со значениями по умолчанию, или ошибка времени компиляции происходит. Аннотации, но не обязаны, может содержать пар значения элемента для элементов со значениями по умолчанию.
Аннотации могут использоваться в качестве модификаторов в любом объявлении, ли пакет (§7.4), класс (§8), интерфейс, поле (§8.3, §9.3), метод (§8.4, §9.4), параметр, конструктор (§8.8), или локальная переменная (§14.4).
Обсуждение
Отметьте, что классы включают перечисления (§8.9), и интерфейсы включают типы аннотации (§9.6)
Аннотации могут также использоваться на перечислимых константах. Такие аннотации сразу помещаются перед перечислимой константой они аннотируют.
Это - ошибка времени компиляции, если объявление аннотируется больше чем одной аннотацией для данного типа аннотации.
Обсуждение
Аннотации традиционно помещаются перед всеми другими модификаторами, но это не требование; они могут быть свободно смешаны с другими модификаторами.
Есть три вида аннотаций. Первое (нормальная аннотация) является полностью общим. Другие (аннотация маркера и одноэлементная аннотация) являются просто сокращениями.
Нормальная аннотация используется, чтобы аннотировать элемент программы:Annotations: Annotation Annotations Annotation Annotation: NormalAnnotation MarkerAnnotation SingleElementAnnotation
NormalAnnotation: @ TypeName ( ElementValuePairsopt ) ElementValuePairs: ElementValuePair ElementValuePairs , ElementValuePair ElementValuePair: Identifier = ElementValue ElementValue: ConditionalExpression Annotation ElementValueArrayInitializer ElementValueArrayInitializer: { ElementValuesopt ,opt } ElementValues: ElementValue ElementValues , ElementValue
Обсуждение
Отметьте, что знак at-sign является маркером к себе. Технически возможно поместить пробел промежуточный знак at-sign и TypeName, но этому обескураживают.
TypeName называет тип аннотации, соответствующий аннотации. Это - ошибка времени компиляции, если TypeName не называет тип аннотации. Тип аннотации, названный аннотацией, должен быть доступным (§6.6) в точке, где аннотация используется, или ошибка времени компиляции происходит.
Идентификатор в ElementValuePair должен быть простым именем одного из элементов типа аннотации, идентифицированного TypeName в содержании аннотации. Иначе, ошибка времени компиляции происходит. (Другими словами идентификатор в паре значения элемента должен также быть именем метода в интерфейсе, идентифицированном TypeName.)
Тип возврата этого метода определяет тип элемента пары значения элемента. ElementValueArrayInitializer подобен нормальному инициализатору массива (§10.6), за исключением того, что аннотации разрешаются вместо выражений.
Тип T элемента соразмерен со значением элемента V, если и только если одно из следующих условий является истиной:
Если тип элемента не является типом аннотации или типом массива, ElementValue должен быть ConditionalExpression (§15.25).
Обсуждение
Отметьте это null
не юридическое значение элемента для любого типа элемента.
Если тип элемента является типом массива, и соответствующим ElementValue не является ElementValueArrayInitializer, значение массива, единственный элемент которого является значением, представленным ElementValue, связывается с элементом. Иначе, значение, представленное ElementValue, связывается с элементом.
Обсуждение
Другими словами допустимо опустить изогнутые фигурные скобки, когда одноэлементный массив должен быть связан с оцененным массивом элементом типа аннотации.
Отметьте, что тип элемента массива не может быть типом массива, то есть, вложенные типы массива не разрешаются как типы элемента. (В то время как синтаксис аннотации разрешил бы это, синтаксис описания типа аннотации не будет.)
Аннотация на описание типа аннотации известна как метааннотация. Тип аннотации может использоваться, чтобы аннотировать его собственное объявление. Более широко зацикливания в переходном закрытии "аннотируют" отношение, разрешаются. Например, законно аннотировать описание типа аннотации другим типом аннотации, и аннотировать объявление последнего типа прежним типом. (Предопределенные типы метааннотации содержат несколько таких зацикливаний.)
Обсуждение
Вот пример нормальной аннотации:
// Normal annotation @RequestForEnhancement( id = 2868724, synopsis = "Provide time-travel functionality", engineer = "Mr. Peabody", date = "4/1/2004" ) public static void travelThroughTime(Date destination) { ... }
Отметьте, что типы аннотаций в примерах в этом разделе являются типами аннотации, определенными в примерах в §9.6. Отметьте также, что элементы находятся в вышеупомянутой аннотации, находятся в том же самом порядке как в соответствующем описании типа аннотации. Это не требуется, но если определенные обстоятельства диктуют иначе, это - разумное соглашение следовать.
Вторая форма аннотации, аннотации маркера, является сокращением, разработанным для использования с типами аннотации маркера:
Это - просто сокращение для нормальной аннотации:MarkerAnnotation: @ TypeName
@TypeName()
Обсуждение
// Marker annotation @Preliminary public class TimeTravel { ... }
Отметьте, что законно использовать аннотации маркера для типов аннотации с элементами, пока у всех элементов есть значения по умолчанию.
Третья форма аннотации, одноэлементной аннотации, является сокращением, разработанным для использования с одноэлементными типами аннотации:
Это - сокращение для нормальной аннотации:SingleElementAnnotation: @ TypeName ( ElementValue )
@TypeName ( value = ElementValue )
Обсуждение
Пример с оцененной массивом одноэлементной аннотацией:// Single-element annotation @Copyright("2002 Yoyodyne Propulsion Systems, Inc., All rights reserved.") public class OscillationOverthruster { ... }
Пример с одноэлементной оцененной массивом одноэлементной аннотацией (отмечают, что изогнутые фигурные скобки опускаются):// Array-valued single-element annotation @Endorsers({"Children", "Unscrupulous dentists"}) public class Lollipop { ... }
Пример со сложной аннотацией:// Single-element array-valued single-element annotation @Endorsers("Epicurus") public class Pleasure { ... }
// Single-element complex annotation @Author(@Name(first = "Joe", last = "Hacker")) public class BitTwiddle { ... }
Отметьте, что законно использовать одноэлементные аннотации для типов аннотации с многократными элементами, пока один элемент называют значением, и у всех других элементов есть значения по умолчанию.
Вот пример аннотации, которая использует в своих интересах значения по умолчанию:
Вот пример аннотации с элементом Класса, значение которого ограничивается при помощи ограниченного подстановочного знака.// Normal annotation with default values @RequestForEnhancement( id = 4561414, synopsis = "Balance the federal budget" ) public static void balanceFederalBudget() { throw new UnsupportedOperationException("Not implemented"); }
Вот пример аннотации, используя перечислимый тип, определенный в типе аннотации:// Single-element annotation with Class element restricted by bounded wildcard // The annotation presumes the existence of this class. class GorgeousFormatter implements Formatter { ... } @PrettyPrinter(GorgeousFormatter.class) public class Petunia {...} // This annotation is illegal, as String is not a subtype of Formatter!! @PrettyPrinter(String.class) public class Begonia { ... }
// Annotation using enum type declared inside the annotation type @Quality(Quality.Level.GOOD) public class Karma { ... }
Содержание | Предыдущий | Следующий | Индекс | Спецификация языка Java Третий Выпуск |
Авторское право © 1996-2005 Sun Microsystems, Inc. Все права защищены
Пожалуйста, отправьте любые комментарии или исправления через нашу