Why is Set<? extends Foo> allowed, but Set<Foo> is not












17














I want to know how generics work in this kind of situation and why
Set<? extends Foo<?>> set3 = set1; is allowed but Set<Foo<?>> set2 = set1; is not?



import java.util.HashSet;
import java.util.Set;

public class TestGenerics {
public static <T> void test() {
Set<T> set1 = new HashSet<>();
Set<?> set2 = set1; // OK
}

public static <T> void test2() {
Set<Foo<T>> set1 = new HashSet<>();
Set<Foo<?>> set2 = set1; // COMPILATION ERROR
Set<? extends Foo<?>> set3 = set1; // OK
}
}

class Foo<T> {}









share|improve this question









New contributor




Stoyan Radnev is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




















  • An interesting reading about this "issue": stackoverflow.com/a/4343547/7709086
    – kagmole
    2 hours ago






  • 3




    Possible duplicate of What is PECS (Producer Extends Consumer Super)?
    – Lino
    1 hour ago






  • 1




    @Lino: This question is similar to and related to "What is PECS", but not exactly the same. This question is about PECS, but specifically applied to the case when the type arguments themselves are types which have type parameters. That makes this a particularly tricky special case, which warrants its own question. (But I'd be surprised if there is no other exactly duplicate question some where.)
    – Lii
    36 mins ago


















17














I want to know how generics work in this kind of situation and why
Set<? extends Foo<?>> set3 = set1; is allowed but Set<Foo<?>> set2 = set1; is not?



import java.util.HashSet;
import java.util.Set;

public class TestGenerics {
public static <T> void test() {
Set<T> set1 = new HashSet<>();
Set<?> set2 = set1; // OK
}

public static <T> void test2() {
Set<Foo<T>> set1 = new HashSet<>();
Set<Foo<?>> set2 = set1; // COMPILATION ERROR
Set<? extends Foo<?>> set3 = set1; // OK
}
}

class Foo<T> {}









share|improve this question









New contributor




Stoyan Radnev is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




















  • An interesting reading about this "issue": stackoverflow.com/a/4343547/7709086
    – kagmole
    2 hours ago






  • 3




    Possible duplicate of What is PECS (Producer Extends Consumer Super)?
    – Lino
    1 hour ago






  • 1




    @Lino: This question is similar to and related to "What is PECS", but not exactly the same. This question is about PECS, but specifically applied to the case when the type arguments themselves are types which have type parameters. That makes this a particularly tricky special case, which warrants its own question. (But I'd be surprised if there is no other exactly duplicate question some where.)
    – Lii
    36 mins ago
















17












17








17


5





I want to know how generics work in this kind of situation and why
Set<? extends Foo<?>> set3 = set1; is allowed but Set<Foo<?>> set2 = set1; is not?



import java.util.HashSet;
import java.util.Set;

public class TestGenerics {
public static <T> void test() {
Set<T> set1 = new HashSet<>();
Set<?> set2 = set1; // OK
}

public static <T> void test2() {
Set<Foo<T>> set1 = new HashSet<>();
Set<Foo<?>> set2 = set1; // COMPILATION ERROR
Set<? extends Foo<?>> set3 = set1; // OK
}
}

class Foo<T> {}









share|improve this question









New contributor




Stoyan Radnev is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











I want to know how generics work in this kind of situation and why
Set<? extends Foo<?>> set3 = set1; is allowed but Set<Foo<?>> set2 = set1; is not?



import java.util.HashSet;
import java.util.Set;

public class TestGenerics {
public static <T> void test() {
Set<T> set1 = new HashSet<>();
Set<?> set2 = set1; // OK
}

public static <T> void test2() {
Set<Foo<T>> set1 = new HashSet<>();
Set<Foo<?>> set2 = set1; // COMPILATION ERROR
Set<? extends Foo<?>> set3 = set1; // OK
}
}

class Foo<T> {}






java generics






share|improve this question









New contributor




Stoyan Radnev is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question









New contributor




Stoyan Radnev is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited 32 mins ago









Lii

6,87044159




6,87044159






New contributor




Stoyan Radnev is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked 3 hours ago









Stoyan RadnevStoyan Radnev

864




864




New contributor




Stoyan Radnev is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





Stoyan Radnev is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






Stoyan Radnev is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.












  • An interesting reading about this "issue": stackoverflow.com/a/4343547/7709086
    – kagmole
    2 hours ago






  • 3




    Possible duplicate of What is PECS (Producer Extends Consumer Super)?
    – Lino
    1 hour ago






  • 1




    @Lino: This question is similar to and related to "What is PECS", but not exactly the same. This question is about PECS, but specifically applied to the case when the type arguments themselves are types which have type parameters. That makes this a particularly tricky special case, which warrants its own question. (But I'd be surprised if there is no other exactly duplicate question some where.)
    – Lii
    36 mins ago




















  • An interesting reading about this "issue": stackoverflow.com/a/4343547/7709086
    – kagmole
    2 hours ago






  • 3




    Possible duplicate of What is PECS (Producer Extends Consumer Super)?
    – Lino
    1 hour ago






  • 1




    @Lino: This question is similar to and related to "What is PECS", but not exactly the same. This question is about PECS, but specifically applied to the case when the type arguments themselves are types which have type parameters. That makes this a particularly tricky special case, which warrants its own question. (But I'd be surprised if there is no other exactly duplicate question some where.)
    – Lii
    36 mins ago


















An interesting reading about this "issue": stackoverflow.com/a/4343547/7709086
– kagmole
2 hours ago




An interesting reading about this "issue": stackoverflow.com/a/4343547/7709086
– kagmole
2 hours ago




3




3




Possible duplicate of What is PECS (Producer Extends Consumer Super)?
– Lino
1 hour ago




Possible duplicate of What is PECS (Producer Extends Consumer Super)?
– Lino
1 hour ago




1




1




@Lino: This question is similar to and related to "What is PECS", but not exactly the same. This question is about PECS, but specifically applied to the case when the type arguments themselves are types which have type parameters. That makes this a particularly tricky special case, which warrants its own question. (But I'd be surprised if there is no other exactly duplicate question some where.)
– Lii
36 mins ago






@Lino: This question is similar to and related to "What is PECS", but not exactly the same. This question is about PECS, but specifically applied to the case when the type arguments themselves are types which have type parameters. That makes this a particularly tricky special case, which warrants its own question. (But I'd be surprised if there is no other exactly duplicate question some where.)
– Lii
36 mins ago














5 Answers
5






active

oldest

votes


















5














Perhaps the issue becomes clearer if you leave the generic parameter of Foo out of the equation.



Consider



final Set<Foo> set1 = new HashSet<>();
Set<Object> set2 = set1;


This makes the compile error more obvious. If this was valid, it would be possible to insert an object into set2, thus into set1 violating the type constraint.



Set<? extends Foo> set3 = set1;


This is perfectly valid because set1 would also accept types derived from Foo.






share|improve this answer























  • why did you transform Set<Foo<?>> to Set<Object> after type erasure? I guess wildcard will be replaced by Object since it is closest bound?
    – Sergey Prokofiev
    2 hours ago










  • Foo<?> is not Object, it is Foo "of something". What allows the assignment to set3 is the covariance.
    – kagmole
    2 hours ago












  • Also you answer implies that set3 is writable, which is not the case. See more about covariance and contravariance here : stackoverflow.com/a/4343547/7709086
    – kagmole
    2 hours ago



















4














Simply said, this is because Set<? extends Foo<?>> is covariant (with the extends keyword). Covariant types are read-only and the compiler will refuse any write action, like Set.add(..).



Set<Foo<?>> is not covariant. It does not block write or read actions.



This...



Set<Foo<String>> set1 = new HashSet<>();
Set<Foo<?>> set2 = set1; // KO by compiler


... is illegal because I could for example write an Integer in set1 with set2.



set2.add(new Foo<Integer>()); // Whoopsie


But...



Set<Foo<String>> set1 = new HashSet<>();
Set<? extends Foo<?>> set3 = set1; // OK


... is covariant (extends keyword), so it is legal. The compiler will refuse a set3.add(42). You can only read from set3, not write.



set3.add(new Foo<Integer>()); // KO by compiler


See these posts for a better explanation:




  • https://stackoverflow.com/a/4343547/7709086

  • https://medium.freecodecamp.org/understanding-java-generic-types-covariance-and-contravariance-88f4c19763d2






share|improve this answer



















  • 3




    Did you mean Foo<Integer> foo; set2.add(foo); because set2.add(42) 42 isn't a Foo<?>.
    – matt
    1 hour ago










  • Oops thank you @matt, I fixed my answer.
    – kagmole
    1 hour ago





















1














Additionally to the answers given already I'll add some formal explanation.



Given by 4.10.2 (emp. mine)




Given a generic type declaration C (n > 0), the direct
supertypes of the parameterized type C, where Ti (1 ≤ i ≤
n) is a type, are all of the following:



D < U1 θ,...,Uk θ>, where D is a generic type which is a
direct supertype of the generic type C and θ is the
substitution [F1:=T1,...,Fn:=Tn].



C < S1,...,Sn> , where Si contains Ti (1 ≤ i ≤ n) (§4.5.1).



The type Object, if C is a generic interface type with no
direct superinterfaces.



The raw type C.




Rule for contains are specified at 4.5.1:




A type argument T1 is said to contain another type argument T2,
written T2 <= T1, if the set of types denoted by T2 is provably a
subset of the set of types denoted by T1 under the reflexive and
transitive closure of the following rules (where <: denotes subtyping
(§4.10)):



? extends T <= ? extends S if T <: S



? extends T <= ?



? super T <= ? super S if S <: T



? super T <= ?



? super T <= ? extends Object



T <= T



T <= ? extends T



T <= ? super T




Since T <= ? super T <= ? extends Object = ? so applying 4.10.2 Foo<T> <: Foo<?> we have ? extends Foo<T> <= ? extends Foo<?>. But Foo<T> <= ? extends Foo<T> so we have Foo<T> <= ? extends Foo<?>.



Applying 4.10.2 we have that Set<? extends Foo<?>> is a direct supertype of Set<Foo<T>>.



The formal answer to why your first example does not compile may be got by assuming a contradiction. Percisely:



If Set<Foo<T>> <: Set<Foo<?>> we have that Foo<T> <= Foo<?> which is not possible to prove applying reflexive or transitive relations to rules from 4.5.1.






share|improve this answer































    0














    That's because Foo<?> does not extend Foo<T>



    Even in the case where ? is replaced by a class that actually extends T.



    Example : Integer extends Number, but Foo<Integer> does not extend Foo<Number>






    share|improve this answer





























      0














      I think simply because the Set element Datatype is different while it must be the same except for Generic Datatype.

      the first set Set<Foo<T>> datatype is Foo<T>,

      then second set Set<Foo<?>> is Foo<?>,

      As I can see the element datatype is different Foo<T> != Foo<?> and not generic type because it use Foo, so then would cause compilation error.

      It is same as below invalid different datatype example :



      Set<List<T>> set3 = new HashSet<>();
      Set<List<?>> set4 = set3; // compilation error due to different element datatype List<T> != List<?>


      Set<? extends Foo<?>> set3 = set1; can because it have ? datatype which is generic and have purpose can accept any datatype.

      ex :



      Set<List<T>> set4 = new HashSet<>();
      Set<?> set5 = set4; // would be Ok





      share|improve this answer























        Your Answer






        StackExchange.ifUsing("editor", function () {
        StackExchange.using("externalEditor", function () {
        StackExchange.using("snippets", function () {
        StackExchange.snippets.init();
        });
        });
        }, "code-snippets");

        StackExchange.ready(function() {
        var channelOptions = {
        tags: "".split(" "),
        id: "1"
        };
        initTagRenderer("".split(" "), "".split(" "), channelOptions);

        StackExchange.using("externalEditor", function() {
        // Have to fire editor after snippets, if snippets enabled
        if (StackExchange.settings.snippets.snippetsEnabled) {
        StackExchange.using("snippets", function() {
        createEditor();
        });
        }
        else {
        createEditor();
        }
        });

        function createEditor() {
        StackExchange.prepareEditor({
        heartbeatType: 'answer',
        autoActivateHeartbeat: false,
        convertImagesToLinks: true,
        noModals: true,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: 10,
        bindNavPrevention: true,
        postfix: "",
        imageUploader: {
        brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
        contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
        allowUrls: true
        },
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        });


        }
        });






        Stoyan Radnev is a new contributor. Be nice, and check out our Code of Conduct.










        draft saved

        draft discarded


















        StackExchange.ready(
        function () {
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54105832%2fwhy-is-set-extends-foo-allowed-but-setfoo-is-not%23new-answer', 'question_page');
        }
        );

        Post as a guest















        Required, but never shown

























        5 Answers
        5






        active

        oldest

        votes








        5 Answers
        5






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes









        5














        Perhaps the issue becomes clearer if you leave the generic parameter of Foo out of the equation.



        Consider



        final Set<Foo> set1 = new HashSet<>();
        Set<Object> set2 = set1;


        This makes the compile error more obvious. If this was valid, it would be possible to insert an object into set2, thus into set1 violating the type constraint.



        Set<? extends Foo> set3 = set1;


        This is perfectly valid because set1 would also accept types derived from Foo.






        share|improve this answer























        • why did you transform Set<Foo<?>> to Set<Object> after type erasure? I guess wildcard will be replaced by Object since it is closest bound?
          – Sergey Prokofiev
          2 hours ago










        • Foo<?> is not Object, it is Foo "of something". What allows the assignment to set3 is the covariance.
          – kagmole
          2 hours ago












        • Also you answer implies that set3 is writable, which is not the case. See more about covariance and contravariance here : stackoverflow.com/a/4343547/7709086
          – kagmole
          2 hours ago
















        5














        Perhaps the issue becomes clearer if you leave the generic parameter of Foo out of the equation.



        Consider



        final Set<Foo> set1 = new HashSet<>();
        Set<Object> set2 = set1;


        This makes the compile error more obvious. If this was valid, it would be possible to insert an object into set2, thus into set1 violating the type constraint.



        Set<? extends Foo> set3 = set1;


        This is perfectly valid because set1 would also accept types derived from Foo.






        share|improve this answer























        • why did you transform Set<Foo<?>> to Set<Object> after type erasure? I guess wildcard will be replaced by Object since it is closest bound?
          – Sergey Prokofiev
          2 hours ago










        • Foo<?> is not Object, it is Foo "of something". What allows the assignment to set3 is the covariance.
          – kagmole
          2 hours ago












        • Also you answer implies that set3 is writable, which is not the case. See more about covariance and contravariance here : stackoverflow.com/a/4343547/7709086
          – kagmole
          2 hours ago














        5












        5








        5






        Perhaps the issue becomes clearer if you leave the generic parameter of Foo out of the equation.



        Consider



        final Set<Foo> set1 = new HashSet<>();
        Set<Object> set2 = set1;


        This makes the compile error more obvious. If this was valid, it would be possible to insert an object into set2, thus into set1 violating the type constraint.



        Set<? extends Foo> set3 = set1;


        This is perfectly valid because set1 would also accept types derived from Foo.






        share|improve this answer














        Perhaps the issue becomes clearer if you leave the generic parameter of Foo out of the equation.



        Consider



        final Set<Foo> set1 = new HashSet<>();
        Set<Object> set2 = set1;


        This makes the compile error more obvious. If this was valid, it would be possible to insert an object into set2, thus into set1 violating the type constraint.



        Set<? extends Foo> set3 = set1;


        This is perfectly valid because set1 would also accept types derived from Foo.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 2 hours ago

























        answered 3 hours ago









        leftbitleftbit

        541414




        541414












        • why did you transform Set<Foo<?>> to Set<Object> after type erasure? I guess wildcard will be replaced by Object since it is closest bound?
          – Sergey Prokofiev
          2 hours ago










        • Foo<?> is not Object, it is Foo "of something". What allows the assignment to set3 is the covariance.
          – kagmole
          2 hours ago












        • Also you answer implies that set3 is writable, which is not the case. See more about covariance and contravariance here : stackoverflow.com/a/4343547/7709086
          – kagmole
          2 hours ago


















        • why did you transform Set<Foo<?>> to Set<Object> after type erasure? I guess wildcard will be replaced by Object since it is closest bound?
          – Sergey Prokofiev
          2 hours ago










        • Foo<?> is not Object, it is Foo "of something". What allows the assignment to set3 is the covariance.
          – kagmole
          2 hours ago












        • Also you answer implies that set3 is writable, which is not the case. See more about covariance and contravariance here : stackoverflow.com/a/4343547/7709086
          – kagmole
          2 hours ago
















        why did you transform Set<Foo<?>> to Set<Object> after type erasure? I guess wildcard will be replaced by Object since it is closest bound?
        – Sergey Prokofiev
        2 hours ago




        why did you transform Set<Foo<?>> to Set<Object> after type erasure? I guess wildcard will be replaced by Object since it is closest bound?
        – Sergey Prokofiev
        2 hours ago












        Foo<?> is not Object, it is Foo "of something". What allows the assignment to set3 is the covariance.
        – kagmole
        2 hours ago






        Foo<?> is not Object, it is Foo "of something". What allows the assignment to set3 is the covariance.
        – kagmole
        2 hours ago














        Also you answer implies that set3 is writable, which is not the case. See more about covariance and contravariance here : stackoverflow.com/a/4343547/7709086
        – kagmole
        2 hours ago




        Also you answer implies that set3 is writable, which is not the case. See more about covariance and contravariance here : stackoverflow.com/a/4343547/7709086
        – kagmole
        2 hours ago













        4














        Simply said, this is because Set<? extends Foo<?>> is covariant (with the extends keyword). Covariant types are read-only and the compiler will refuse any write action, like Set.add(..).



        Set<Foo<?>> is not covariant. It does not block write or read actions.



        This...



        Set<Foo<String>> set1 = new HashSet<>();
        Set<Foo<?>> set2 = set1; // KO by compiler


        ... is illegal because I could for example write an Integer in set1 with set2.



        set2.add(new Foo<Integer>()); // Whoopsie


        But...



        Set<Foo<String>> set1 = new HashSet<>();
        Set<? extends Foo<?>> set3 = set1; // OK


        ... is covariant (extends keyword), so it is legal. The compiler will refuse a set3.add(42). You can only read from set3, not write.



        set3.add(new Foo<Integer>()); // KO by compiler


        See these posts for a better explanation:




        • https://stackoverflow.com/a/4343547/7709086

        • https://medium.freecodecamp.org/understanding-java-generic-types-covariance-and-contravariance-88f4c19763d2






        share|improve this answer



















        • 3




          Did you mean Foo<Integer> foo; set2.add(foo); because set2.add(42) 42 isn't a Foo<?>.
          – matt
          1 hour ago










        • Oops thank you @matt, I fixed my answer.
          – kagmole
          1 hour ago


















        4














        Simply said, this is because Set<? extends Foo<?>> is covariant (with the extends keyword). Covariant types are read-only and the compiler will refuse any write action, like Set.add(..).



        Set<Foo<?>> is not covariant. It does not block write or read actions.



        This...



        Set<Foo<String>> set1 = new HashSet<>();
        Set<Foo<?>> set2 = set1; // KO by compiler


        ... is illegal because I could for example write an Integer in set1 with set2.



        set2.add(new Foo<Integer>()); // Whoopsie


        But...



        Set<Foo<String>> set1 = new HashSet<>();
        Set<? extends Foo<?>> set3 = set1; // OK


        ... is covariant (extends keyword), so it is legal. The compiler will refuse a set3.add(42). You can only read from set3, not write.



        set3.add(new Foo<Integer>()); // KO by compiler


        See these posts for a better explanation:




        • https://stackoverflow.com/a/4343547/7709086

        • https://medium.freecodecamp.org/understanding-java-generic-types-covariance-and-contravariance-88f4c19763d2






        share|improve this answer



















        • 3




          Did you mean Foo<Integer> foo; set2.add(foo); because set2.add(42) 42 isn't a Foo<?>.
          – matt
          1 hour ago










        • Oops thank you @matt, I fixed my answer.
          – kagmole
          1 hour ago
















        4












        4








        4






        Simply said, this is because Set<? extends Foo<?>> is covariant (with the extends keyword). Covariant types are read-only and the compiler will refuse any write action, like Set.add(..).



        Set<Foo<?>> is not covariant. It does not block write or read actions.



        This...



        Set<Foo<String>> set1 = new HashSet<>();
        Set<Foo<?>> set2 = set1; // KO by compiler


        ... is illegal because I could for example write an Integer in set1 with set2.



        set2.add(new Foo<Integer>()); // Whoopsie


        But...



        Set<Foo<String>> set1 = new HashSet<>();
        Set<? extends Foo<?>> set3 = set1; // OK


        ... is covariant (extends keyword), so it is legal. The compiler will refuse a set3.add(42). You can only read from set3, not write.



        set3.add(new Foo<Integer>()); // KO by compiler


        See these posts for a better explanation:




        • https://stackoverflow.com/a/4343547/7709086

        • https://medium.freecodecamp.org/understanding-java-generic-types-covariance-and-contravariance-88f4c19763d2






        share|improve this answer














        Simply said, this is because Set<? extends Foo<?>> is covariant (with the extends keyword). Covariant types are read-only and the compiler will refuse any write action, like Set.add(..).



        Set<Foo<?>> is not covariant. It does not block write or read actions.



        This...



        Set<Foo<String>> set1 = new HashSet<>();
        Set<Foo<?>> set2 = set1; // KO by compiler


        ... is illegal because I could for example write an Integer in set1 with set2.



        set2.add(new Foo<Integer>()); // Whoopsie


        But...



        Set<Foo<String>> set1 = new HashSet<>();
        Set<? extends Foo<?>> set3 = set1; // OK


        ... is covariant (extends keyword), so it is legal. The compiler will refuse a set3.add(42). You can only read from set3, not write.



        set3.add(new Foo<Integer>()); // KO by compiler


        See these posts for a better explanation:




        • https://stackoverflow.com/a/4343547/7709086

        • https://medium.freecodecamp.org/understanding-java-generic-types-covariance-and-contravariance-88f4c19763d2







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 1 hour ago

























        answered 2 hours ago









        kagmolekagmole

        1,012317




        1,012317








        • 3




          Did you mean Foo<Integer> foo; set2.add(foo); because set2.add(42) 42 isn't a Foo<?>.
          – matt
          1 hour ago










        • Oops thank you @matt, I fixed my answer.
          – kagmole
          1 hour ago
















        • 3




          Did you mean Foo<Integer> foo; set2.add(foo); because set2.add(42) 42 isn't a Foo<?>.
          – matt
          1 hour ago










        • Oops thank you @matt, I fixed my answer.
          – kagmole
          1 hour ago










        3




        3




        Did you mean Foo<Integer> foo; set2.add(foo); because set2.add(42) 42 isn't a Foo<?>.
        – matt
        1 hour ago




        Did you mean Foo<Integer> foo; set2.add(foo); because set2.add(42) 42 isn't a Foo<?>.
        – matt
        1 hour ago












        Oops thank you @matt, I fixed my answer.
        – kagmole
        1 hour ago






        Oops thank you @matt, I fixed my answer.
        – kagmole
        1 hour ago













        1














        Additionally to the answers given already I'll add some formal explanation.



        Given by 4.10.2 (emp. mine)




        Given a generic type declaration C (n > 0), the direct
        supertypes of the parameterized type C, where Ti (1 ≤ i ≤
        n) is a type, are all of the following:



        D < U1 θ,...,Uk θ>, where D is a generic type which is a
        direct supertype of the generic type C and θ is the
        substitution [F1:=T1,...,Fn:=Tn].



        C < S1,...,Sn> , where Si contains Ti (1 ≤ i ≤ n) (§4.5.1).



        The type Object, if C is a generic interface type with no
        direct superinterfaces.



        The raw type C.




        Rule for contains are specified at 4.5.1:




        A type argument T1 is said to contain another type argument T2,
        written T2 <= T1, if the set of types denoted by T2 is provably a
        subset of the set of types denoted by T1 under the reflexive and
        transitive closure of the following rules (where <: denotes subtyping
        (§4.10)):



        ? extends T <= ? extends S if T <: S



        ? extends T <= ?



        ? super T <= ? super S if S <: T



        ? super T <= ?



        ? super T <= ? extends Object



        T <= T



        T <= ? extends T



        T <= ? super T




        Since T <= ? super T <= ? extends Object = ? so applying 4.10.2 Foo<T> <: Foo<?> we have ? extends Foo<T> <= ? extends Foo<?>. But Foo<T> <= ? extends Foo<T> so we have Foo<T> <= ? extends Foo<?>.



        Applying 4.10.2 we have that Set<? extends Foo<?>> is a direct supertype of Set<Foo<T>>.



        The formal answer to why your first example does not compile may be got by assuming a contradiction. Percisely:



        If Set<Foo<T>> <: Set<Foo<?>> we have that Foo<T> <= Foo<?> which is not possible to prove applying reflexive or transitive relations to rules from 4.5.1.






        share|improve this answer




























          1














          Additionally to the answers given already I'll add some formal explanation.



          Given by 4.10.2 (emp. mine)




          Given a generic type declaration C (n > 0), the direct
          supertypes of the parameterized type C, where Ti (1 ≤ i ≤
          n) is a type, are all of the following:



          D < U1 θ,...,Uk θ>, where D is a generic type which is a
          direct supertype of the generic type C and θ is the
          substitution [F1:=T1,...,Fn:=Tn].



          C < S1,...,Sn> , where Si contains Ti (1 ≤ i ≤ n) (§4.5.1).



          The type Object, if C is a generic interface type with no
          direct superinterfaces.



          The raw type C.




          Rule for contains are specified at 4.5.1:




          A type argument T1 is said to contain another type argument T2,
          written T2 <= T1, if the set of types denoted by T2 is provably a
          subset of the set of types denoted by T1 under the reflexive and
          transitive closure of the following rules (where <: denotes subtyping
          (§4.10)):



          ? extends T <= ? extends S if T <: S



          ? extends T <= ?



          ? super T <= ? super S if S <: T



          ? super T <= ?



          ? super T <= ? extends Object



          T <= T



          T <= ? extends T



          T <= ? super T




          Since T <= ? super T <= ? extends Object = ? so applying 4.10.2 Foo<T> <: Foo<?> we have ? extends Foo<T> <= ? extends Foo<?>. But Foo<T> <= ? extends Foo<T> so we have Foo<T> <= ? extends Foo<?>.



          Applying 4.10.2 we have that Set<? extends Foo<?>> is a direct supertype of Set<Foo<T>>.



          The formal answer to why your first example does not compile may be got by assuming a contradiction. Percisely:



          If Set<Foo<T>> <: Set<Foo<?>> we have that Foo<T> <= Foo<?> which is not possible to prove applying reflexive or transitive relations to rules from 4.5.1.






          share|improve this answer


























            1












            1








            1






            Additionally to the answers given already I'll add some formal explanation.



            Given by 4.10.2 (emp. mine)




            Given a generic type declaration C (n > 0), the direct
            supertypes of the parameterized type C, where Ti (1 ≤ i ≤
            n) is a type, are all of the following:



            D < U1 θ,...,Uk θ>, where D is a generic type which is a
            direct supertype of the generic type C and θ is the
            substitution [F1:=T1,...,Fn:=Tn].



            C < S1,...,Sn> , where Si contains Ti (1 ≤ i ≤ n) (§4.5.1).



            The type Object, if C is a generic interface type with no
            direct superinterfaces.



            The raw type C.




            Rule for contains are specified at 4.5.1:




            A type argument T1 is said to contain another type argument T2,
            written T2 <= T1, if the set of types denoted by T2 is provably a
            subset of the set of types denoted by T1 under the reflexive and
            transitive closure of the following rules (where <: denotes subtyping
            (§4.10)):



            ? extends T <= ? extends S if T <: S



            ? extends T <= ?



            ? super T <= ? super S if S <: T



            ? super T <= ?



            ? super T <= ? extends Object



            T <= T



            T <= ? extends T



            T <= ? super T




            Since T <= ? super T <= ? extends Object = ? so applying 4.10.2 Foo<T> <: Foo<?> we have ? extends Foo<T> <= ? extends Foo<?>. But Foo<T> <= ? extends Foo<T> so we have Foo<T> <= ? extends Foo<?>.



            Applying 4.10.2 we have that Set<? extends Foo<?>> is a direct supertype of Set<Foo<T>>.



            The formal answer to why your first example does not compile may be got by assuming a contradiction. Percisely:



            If Set<Foo<T>> <: Set<Foo<?>> we have that Foo<T> <= Foo<?> which is not possible to prove applying reflexive or transitive relations to rules from 4.5.1.






            share|improve this answer














            Additionally to the answers given already I'll add some formal explanation.



            Given by 4.10.2 (emp. mine)




            Given a generic type declaration C (n > 0), the direct
            supertypes of the parameterized type C, where Ti (1 ≤ i ≤
            n) is a type, are all of the following:



            D < U1 θ,...,Uk θ>, where D is a generic type which is a
            direct supertype of the generic type C and θ is the
            substitution [F1:=T1,...,Fn:=Tn].



            C < S1,...,Sn> , where Si contains Ti (1 ≤ i ≤ n) (§4.5.1).



            The type Object, if C is a generic interface type with no
            direct superinterfaces.



            The raw type C.




            Rule for contains are specified at 4.5.1:




            A type argument T1 is said to contain another type argument T2,
            written T2 <= T1, if the set of types denoted by T2 is provably a
            subset of the set of types denoted by T1 under the reflexive and
            transitive closure of the following rules (where <: denotes subtyping
            (§4.10)):



            ? extends T <= ? extends S if T <: S



            ? extends T <= ?



            ? super T <= ? super S if S <: T



            ? super T <= ?



            ? super T <= ? extends Object



            T <= T



            T <= ? extends T



            T <= ? super T




            Since T <= ? super T <= ? extends Object = ? so applying 4.10.2 Foo<T> <: Foo<?> we have ? extends Foo<T> <= ? extends Foo<?>. But Foo<T> <= ? extends Foo<T> so we have Foo<T> <= ? extends Foo<?>.



            Applying 4.10.2 we have that Set<? extends Foo<?>> is a direct supertype of Set<Foo<T>>.



            The formal answer to why your first example does not compile may be got by assuming a contradiction. Percisely:



            If Set<Foo<T>> <: Set<Foo<?>> we have that Foo<T> <= Foo<?> which is not possible to prove applying reflexive or transitive relations to rules from 4.5.1.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 1 hour ago

























            answered 1 hour ago









            St.AntarioSt.Antario

            9,4061551138




            9,4061551138























                0














                That's because Foo<?> does not extend Foo<T>



                Even in the case where ? is replaced by a class that actually extends T.



                Example : Integer extends Number, but Foo<Integer> does not extend Foo<Number>






                share|improve this answer


























                  0














                  That's because Foo<?> does not extend Foo<T>



                  Even in the case where ? is replaced by a class that actually extends T.



                  Example : Integer extends Number, but Foo<Integer> does not extend Foo<Number>






                  share|improve this answer
























                    0












                    0








                    0






                    That's because Foo<?> does not extend Foo<T>



                    Even in the case where ? is replaced by a class that actually extends T.



                    Example : Integer extends Number, but Foo<Integer> does not extend Foo<Number>






                    share|improve this answer












                    That's because Foo<?> does not extend Foo<T>



                    Even in the case where ? is replaced by a class that actually extends T.



                    Example : Integer extends Number, but Foo<Integer> does not extend Foo<Number>







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered 2 hours ago









                    Florian NicolasFlorian Nicolas

                    113




                    113























                        0














                        I think simply because the Set element Datatype is different while it must be the same except for Generic Datatype.

                        the first set Set<Foo<T>> datatype is Foo<T>,

                        then second set Set<Foo<?>> is Foo<?>,

                        As I can see the element datatype is different Foo<T> != Foo<?> and not generic type because it use Foo, so then would cause compilation error.

                        It is same as below invalid different datatype example :



                        Set<List<T>> set3 = new HashSet<>();
                        Set<List<?>> set4 = set3; // compilation error due to different element datatype List<T> != List<?>


                        Set<? extends Foo<?>> set3 = set1; can because it have ? datatype which is generic and have purpose can accept any datatype.

                        ex :



                        Set<List<T>> set4 = new HashSet<>();
                        Set<?> set5 = set4; // would be Ok





                        share|improve this answer




























                          0














                          I think simply because the Set element Datatype is different while it must be the same except for Generic Datatype.

                          the first set Set<Foo<T>> datatype is Foo<T>,

                          then second set Set<Foo<?>> is Foo<?>,

                          As I can see the element datatype is different Foo<T> != Foo<?> and not generic type because it use Foo, so then would cause compilation error.

                          It is same as below invalid different datatype example :



                          Set<List<T>> set3 = new HashSet<>();
                          Set<List<?>> set4 = set3; // compilation error due to different element datatype List<T> != List<?>


                          Set<? extends Foo<?>> set3 = set1; can because it have ? datatype which is generic and have purpose can accept any datatype.

                          ex :



                          Set<List<T>> set4 = new HashSet<>();
                          Set<?> set5 = set4; // would be Ok





                          share|improve this answer


























                            0












                            0








                            0






                            I think simply because the Set element Datatype is different while it must be the same except for Generic Datatype.

                            the first set Set<Foo<T>> datatype is Foo<T>,

                            then second set Set<Foo<?>> is Foo<?>,

                            As I can see the element datatype is different Foo<T> != Foo<?> and not generic type because it use Foo, so then would cause compilation error.

                            It is same as below invalid different datatype example :



                            Set<List<T>> set3 = new HashSet<>();
                            Set<List<?>> set4 = set3; // compilation error due to different element datatype List<T> != List<?>


                            Set<? extends Foo<?>> set3 = set1; can because it have ? datatype which is generic and have purpose can accept any datatype.

                            ex :



                            Set<List<T>> set4 = new HashSet<>();
                            Set<?> set5 = set4; // would be Ok





                            share|improve this answer














                            I think simply because the Set element Datatype is different while it must be the same except for Generic Datatype.

                            the first set Set<Foo<T>> datatype is Foo<T>,

                            then second set Set<Foo<?>> is Foo<?>,

                            As I can see the element datatype is different Foo<T> != Foo<?> and not generic type because it use Foo, so then would cause compilation error.

                            It is same as below invalid different datatype example :



                            Set<List<T>> set3 = new HashSet<>();
                            Set<List<?>> set4 = set3; // compilation error due to different element datatype List<T> != List<?>


                            Set<? extends Foo<?>> set3 = set1; can because it have ? datatype which is generic and have purpose can accept any datatype.

                            ex :



                            Set<List<T>> set4 = new HashSet<>();
                            Set<?> set5 = set4; // would be Ok






                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited 52 mins ago

























                            answered 1 hour ago









                            M Fauzan AbdiM Fauzan Abdi

                            24617




                            24617






















                                Stoyan Radnev is a new contributor. Be nice, and check out our Code of Conduct.










                                draft saved

                                draft discarded


















                                Stoyan Radnev is a new contributor. Be nice, and check out our Code of Conduct.













                                Stoyan Radnev is a new contributor. Be nice, and check out our Code of Conduct.












                                Stoyan Radnev is a new contributor. Be nice, and check out our Code of Conduct.
















                                Thanks for contributing an answer to Stack Overflow!


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.





                                Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                                Please pay close attention to the following guidance:


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function () {
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54105832%2fwhy-is-set-extends-foo-allowed-but-setfoo-is-not%23new-answer', 'question_page');
                                }
                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown







                                Popular posts from this blog

                                What visual should I use to simply compare current year value vs last year in Power BI desktop

                                Alexandru Averescu

                                Trompette piccolo