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












18















This question already has an answer here:




  • Java nested generic type mismatch

    5 answers



  • What is PECS (Producer Extends Consumer Super)?

    12 answers




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.











marked as duplicate by Lino, aminography, Andy Turner java
Users with the  java badge can single-handedly close java questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
1 hour ago


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.















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






  • 2




    @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
    4 hours ago


















18















This question already has an answer here:




  • Java nested generic type mismatch

    5 answers



  • What is PECS (Producer Extends Consumer Super)?

    12 answers




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.











marked as duplicate by Lino, aminography, Andy Turner java
Users with the  java badge can single-handedly close java questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
1 hour ago


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.















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






  • 2




    @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
    4 hours ago
















18












18








18


6






This question already has an answer here:




  • Java nested generic type mismatch

    5 answers



  • What is PECS (Producer Extends Consumer Super)?

    12 answers




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.












This question already has an answer here:




  • Java nested generic type mismatch

    5 answers



  • What is PECS (Producer Extends Consumer Super)?

    12 answers




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> {}




This question already has an answer here:




  • Java nested generic type mismatch

    5 answers



  • What is PECS (Producer Extends Consumer Super)?

    12 answers








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 4 hours 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 7 hours ago









Stoyan RadnevStoyan Radnev

944




944




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.




marked as duplicate by Lino, aminography, Andy Turner java
Users with the  java badge can single-handedly close java questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
1 hour ago


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.






marked as duplicate by Lino, aminography, Andy Turner java
Users with the  java badge can single-handedly close java questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
1 hour ago


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.














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






  • 2




    @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
    4 hours ago




















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






  • 2




    @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
    4 hours ago


















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




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




2




2




@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
4 hours 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
4 hours ago














4 Answers
4






active

oldest

votes


















6














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 otherwise I could for example put a Foo<Integer> into set1 via 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. For example, the compiler will refuse a write operation like set3.add(new Foo<Integer>()), but accept a read operation like set3.iterator().



Iterator<Foo<String>> fooIterator = set3.iterator(); // OK
set3.add(new Foo<String>()); // 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
    5 hours ago










  • Oops thank you @matt, I fixed my answer.
    – kagmole
    5 hours ago





















4














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



















  • 1




    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
    6 hours ago






  • 1




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








  • 1




    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
    5 hours 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














    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






























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      6














      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 otherwise I could for example put a Foo<Integer> into set1 via 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. For example, the compiler will refuse a write operation like set3.add(new Foo<Integer>()), but accept a read operation like set3.iterator().



      Iterator<Foo<String>> fooIterator = set3.iterator(); // OK
      set3.add(new Foo<String>()); // 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
        5 hours ago










      • Oops thank you @matt, I fixed my answer.
        – kagmole
        5 hours ago


















      6














      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 otherwise I could for example put a Foo<Integer> into set1 via 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. For example, the compiler will refuse a write operation like set3.add(new Foo<Integer>()), but accept a read operation like set3.iterator().



      Iterator<Foo<String>> fooIterator = set3.iterator(); // OK
      set3.add(new Foo<String>()); // 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
        5 hours ago










      • Oops thank you @matt, I fixed my answer.
        – kagmole
        5 hours ago
















      6












      6








      6






      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 otherwise I could for example put a Foo<Integer> into set1 via 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. For example, the compiler will refuse a write operation like set3.add(new Foo<Integer>()), but accept a read operation like set3.iterator().



      Iterator<Foo<String>> fooIterator = set3.iterator(); // OK
      set3.add(new Foo<String>()); // 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 otherwise I could for example put a Foo<Integer> into set1 via 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. For example, the compiler will refuse a write operation like set3.add(new Foo<Integer>()), but accept a read operation like set3.iterator().



      Iterator<Foo<String>> fooIterator = set3.iterator(); // OK
      set3.add(new Foo<String>()); // 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 3 hours ago









      JimmyB

      9,20411537




      9,20411537










      answered 6 hours ago









      kagmolekagmole

      1,032317




      1,032317








      • 3




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










      • Oops thank you @matt, I fixed my answer.
        – kagmole
        5 hours ago
















      • 3




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










      • Oops thank you @matt, I fixed my answer.
        – kagmole
        5 hours ago










      3




      3




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




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












      Oops thank you @matt, I fixed my answer.
      – kagmole
      5 hours ago






      Oops thank you @matt, I fixed my answer.
      – kagmole
      5 hours ago















      4














      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



















      • 1




        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
        6 hours ago






      • 1




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








      • 1




        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
        5 hours ago
















      4














      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



















      • 1




        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
        6 hours ago






      • 1




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








      • 1




        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
        5 hours ago














      4












      4








      4






      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 6 hours ago

























      answered 7 hours ago









      leftbitleftbit

      539414




      539414








      • 1




        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
        6 hours ago






      • 1




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








      • 1




        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
        5 hours ago














      • 1




        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
        6 hours ago






      • 1




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








      • 1




        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
        5 hours ago








      1




      1




      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
      6 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
      6 hours ago




      1




      1




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






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






      1




      1




      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
      5 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
      5 hours 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 5 hours ago

























          answered 5 hours ago









          St.AntarioSt.Antario

          9,4061551138




          9,4061551138























              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 4 hours ago

























                  answered 5 hours ago









                  M Fauzan AbdiM Fauzan Abdi

                  25417




                  25417















                      Popular posts from this blog

                      Liste der Baudenkmale in Friedland (Mecklenburg)

                      Single-Malt-Whisky

                      Czorneboh