Именованные группы захвата могут быстро перейти на JavaScript. Предложение для него уже на этапе 3.
Группе захвата может быть присвоено имя с использованием синтаксиса (? ...) для любого имени идентификатора. Регулярное выражение для даты тогда может быть записано как / (? \ D {4}) - (? \ D {2}) - (? \ D {2}) / u. Каждое имя должно быть уникальным и следовать грамматике имени ECMAScript IdentifierName.
Доступ к именованным группам можно получить из свойств свойства групп результата регулярного выражения. Также создаются нумерованные ссылки на группы, как и для неименованных групп. Например:
let re = / (& lt; year & gt; \ d {4}) - (& lt; month & gt; \ d {2}) - (& lt; day & gt; \ д {2}) / U; let result = re.exec ('2015-01-02'); // result.groups.year === '2015'; // result.groups.month === '01'; // result.groups.day === '02'; // result [0] === '2015-01-02'; // result [1] === '2015'; // result [2] === '01'; // result [3] === '02';
Используйте это вместо:
1 public List<? extends Foo> getFoos()
2 {
3 List<Foo> foos = new ArrayList<Foo>(); /* Or List<SubFoo> */
4 foos.add(new SubFoo());
5 return foos;
6 }
Как только вы объявляете foos как List<? extends Foo>
, компилятор не знает, что безопасно добавлять SubFoo. Что, если ArrayList<AltFoo>
было присвоено foos
? Это будет действительное назначение, но добавление SubFoo будет загрязнять коллекцию.
Следующие будут работать нормально:
public List<? extends Foo> getFoos() {
List<Foo> foos = new ArrayList<Foo>();
foos.add(new SubFoo());
return foos;
}
Просто подумал, что я бы добавил к этому старому потоку, суммируя свойства параметров List, созданных с помощью типов или подстановочных знаков ....
Когда у метода есть параметр / результат, который является List, использование типа экземпляра или подстановочных знаков определяет
List< Foo>
List< Foo>
List< Foo>
List< ? super Foo>
List< ? super SubFoo>
List< ? extends Foo>
List< ? extends SuperFoo>
Foo
& amp; подтипы Foo
& amp; супертипы (до Object
) List< ? extends Foo>
List< Foo>
List< Subfoo>
List< SubSubFoo>
List< ? extends Foo>
List< ? extends SubFoo>
List< ? extends SubSubFoo>
List< ? extends Foo>
List< ? extends SuperFoo>
List< ? extends SuperSuperFoo>
Foo
& amp; супертипы (до Object
) List<? super Foo>
List< Foo>
List< Superfoo>
List< SuperSuperFoo>
List< ? super Foo>
List< ? super SuperFoo>
List< ? super SuperSuperFoo>
List< ? super Foo>
List< ? super SubFoo>
List< ? super SubSubFoo>
Foo
& amp; супертипы Foo
& amp; супертипы (до Object
) List<Foo>
, если код вызывающего абонента всегда сфокусирован при манипулировании классом Foo, поскольку он максимизирует гибкость как для чтения, так и для записи List<? extends UpperMostFoo>
, если может быть много разных типов абонентов, ориентированных на управление другим классом (не всегда Foo), и есть один самый верхний класс в иерархии типов Foo, и если этот метод предназначен для внутренней записи в список, а чтение списка вызывающих абонентов читается. Здесь метод может внутренне использовать List< UpperMostFoo>
и добавлять к нему элементы, прежде чем возвращать List< ? extends UpperMostFoo>
List< ? super LowerMostFoo>
List<? super Foo>
ошибочны. Это должно быть «Foo & amp; Подтипы & Quot; и "Объект" соответственно.
– FuegoFro
22 August 2016 в 18:36
Попробуйте:
public List<Foo> getFoos() {
List<Foo> foos = new ArrayList<Foo>();
foos.add(new SubFoo());
return foos;
}
Генерирующий конструктор ArrayList должен иметь определенный тип для параметризации, вы не можете использовать '?' wildcard там. Изменение экземпляра «new ArrayList & lt; Foo & gt; ()» разрешило бы первую ошибку компиляции.
Объявление переменной foos может иметь подстановочные знаки, но поскольку вы знаете точный тип, он делает больше чтобы ссылаться на информацию о том же типе. Что вы теперь говорите, что foos содержит определенный подтип Foo, но мы не знаем, что. Добавление SubFoo может быть запрещено, поскольку SubFoo не является «всеми подтипами Foo», Изменение декларации в «List & lt; Foo & gt; foos =» решает вторую ошибку компиляции.
Наконец, я бы изменил тип возвращаемого значения на «List & lt; Foo & gt;»; поскольку клиенты этого метода не смогут многое сделать с возвращаемым значением, как определено в настоящее время. Вы должны редко использовать подстановочные знаки в типах возврата. При необходимости используйте сигнатуру с параметризованным методом, но предпочитайте ограниченные типы только в аргументах метода, так как который оставляет его до вызывающего абонента, который может передавать конкретные типы и работать и соответственно.
Чтобы понять, как работают дженерики, посмотрите этот пример:
List<SubFoo> sfoo = new ArrayList<SubFoo>();
List<Foo> foo;
List<? extends Foo> tmp;
tmp = sfoo;
foo = (List<Foo>) tmp;
Дело в том, что это не было предназначено для локальных / членных переменных, а для сигнатур функций, вот почему это так осел в обратном направлении.