简体   繁体   中英

Java Generics: wildcards again

I'm trying to create a container that would accept specific classes only. Using generics as follows:

    static class Test1<C extends Test1> {
            C field = null;
            public C getField() {
                return field;
            }
            public void setField(C field) {
                this.field = field;
            }
        }
        static class Test2 extends Test1{
        }

class MainTest {
            public static void main(String[] args) throws Exception {
                List<Test1<? extends Test1>> list = new ArrayList<Test1<? extends Test1>>();
                Test1<Test2> newInstance = new Test1<Test2>();
                list.add(newInstance);
                Test1<Test2> value = list.get(1);
    }
}

Just want to understand why this List> would accept a newInstance object, but compilation time error occurs while I'm fetching "Test1 value" back? Is there any chance to workaround the problem?

Thanks in advance.

UPDATE Many noticed that " Test1<? extends Test1> , where ? MAY NOT be equal to Test2." I totally agree but as far as I understand in this case I need to type cast the extracted value to Test1<Test2> and that means that the whole point of generics is lost in this case... Please correct me if I'm wrong.

Because when you list.get(1) returns Test1<? extends Test1> Test1<? extends Test1> , where ? MAY NOT be equal to Test2 .

On the onther hand list.add(...) accepts Test1<? extends Test1> Test1<? extends Test1> , ie Test1 with ANY generics parameter which is inheritor of Test1.

This is because you can store a Test1<> with every object that is a child of Test1 as a typed parameter. Let's say you have class Test3 extends Test1 then you would have

Test1<Test2> value = list.get(1);

but how the list would be sure that the element with index 1 has a generic type Test2 but not Test3 as it accepts every subtype of Test1 ().

The proper way to fetch the element is using

Test1<? extends Test1> test1 = list.get(1);

You could solve the problem by writing

Test1<? extends Test1> value = list.get(1);

instead of

Test1<Test2> value = list.get(1);

or by making a cast to Test1.

List<Test1<? extends Test1>> list = new ArrayList<Test1<? extends Test1>>();

this is a read only list, you can only insert null to this list, nothing else

instead use below:

List<Test1<? extends Test1>> list = new ArrayList<Test1<XXX>>();  where XXX extends Test1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM