Это работает:
public class TestList {
interface Record {}
interface SubRecord extends Record {}
public static void main(String[] args) {
List<? extends Record> l = new ArrayList<Record>();
List<SubRecord> l2 = new ArrayList<SubRecord>();
Record i = new Record(){};
SubRecord j = new SubRecord(){};
l = l2;
Record a = l.get( 0 );
((List<Record>)l).add( i ); //<--will fail at run time,see below
((List<SubRecord>)l).add( j ); //<--will be ok at run time
}
}
Я имею в виду, что оно компилируется, но вам придется разыграть свой List<? extends Record>
, прежде чем добавлять что-либо внутрь.Java разрешит приведение, если тип, который вы хотите привести, является подклассом Record
, но он не может угадать, какой это будет тип, вы должны указать его.
A List<Record>
может толькосодержат Records
(включая subRecords
), A List<SubRecord>
может содержать только SubRecords
.
Но A List<SubRecord
> не является List<Record>
, если он не может содержать Records
, и подклассы всегда должны делать то, что могут делать суперклассы.Это важно , поскольку наследование является спецификацией, если List<SubRecords>
будет подклассом List<Record>
, он должен содержать `но это не так.
A List<Record>
иList<SubRecord>
оба List<? extends Record>
.Но в List<? extends Record>
вы ничего не можете добавить, так как java не может знать, какого именно типа List
является контейнером.Представьте, что вы могли бы, тогда вы могли бы иметь следующие утверждения:
List<? extends Record> l = l2;
l.add( new Record() );
Как мы только что видели, это возможно только для List<Record>
, но не для любых List<Something that extends Record>
, таких как List<SubRecord>
.
С уважением, Стефан