• Post Reply Bookmark Topic Watch Topic
  • New Topic

Parameterized collections types holding subtypes aka generic polymorphism - how does it work?  RSS feed

 
Scott Shipp
Ranch Hand
Posts: 223
12
Eclipse IDE IntelliJ IDE Java Scala Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I've become curious about something. After a question in my local java users group email list, I have been playing about a bit with parameterized collections types (e.g. List<Number>) that hold subtypes. I blogged some findings about this at http://code.scottshipp.com/2013/07/23/collections-of-objects-of-different-types-and-the-bounded-wildcard/, but I want to know what is happening "under the hood."

Here is the specific question.

You can define a list that holds a supertype, like Number, and then add objects of a subtype, like Integer, to the list:



This both compiles and runs just fine. But if you try anything like the following two examples, a compile-time error results.



This produces: Type mismatch: cannot convert from List<Integer> to List<Number>



This produces: Type mismatch: cannot convert from ArrayList<Integer> to List<Number>

This is all explained very well in Effective Java, Item 28 which notes that parameterized types are not considered to be subtypes of each other even if their parameter is.

But I am curious if there is some kind of explanation somewhere about generic polymorphism like in the above example that does work (where I added Integer, Float, Long to an ArrayList<Number>). Obviously the ArrayList implementation in Java uses a generic type, and obviously something within the JVM understands polymorphism of generic types. Otherwise adding Integer, Float, Long etc. to an ArrayList<Number> wouldn't work.

Any points of reference or quick explanation someone can provide about how this works or how it is accomplished?
 
Ivan Jozsef Balazs
Rancher
Posts: 999
5
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Generics are implemented with erasure.

At compile time the compiler sees that

is simply an ArrayList of Numbers: Numbers can be put into it Numbers can be obtained from there, and Integer, Float, Long are Numbers.

Akin to

 
Henry Wong
author
Sheriff
Posts: 23295
125
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Scott Shipp wrote:
Here is the specific question.

You can define a list that holds a supertype, like Number, and then add objects of a subtype, like Integer, to the list:



This both compiles and runs just fine.


A List<Number> is an instance of List that can contains Numbers. An Integer IS-A Number. A Float IS-A Number. And a Long IS-A Number. Hence, all three can be added to a List of Numbers.

Henry
 
Henry Wong
author
Sheriff
Posts: 23295
125
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Scott Shipp wrote:
But if you try anything like the following two examples, a compile-time error results.



This produces: Type mismatch: cannot convert from List<Integer> to List<Number>



This produces: Type mismatch: cannot convert from ArrayList<Integer> to List<Number>




Well, A List<Number> is NOT IS-A List<Integer>. And a List<Integer> is NOT IS-A List<Number>. So, assigning this (in either direction) is not allowed.

Just think about it a bit....



If it was allowed, then the listOfNumber reference would be pointing to the same object as the listOfInteger reference. And then, you would be able to add a Float object into the listOfNumber instance (because a Float IS-A number), which is also the same instance as the listOfInteger instance. Hence, you would be able to put a Float into a List<Integer>.

Henry
 
Scott Shipp
Ranch Hand
Posts: 223
12
Eclipse IDE IntelliJ IDE Java Scala Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sorry but what I am asking hasn't been addressed. I am wondering about the how, not the what. In other words, how does the compiler determine what is allowed to be added to the list, and when is it determined. I was reading Learning Java, Fourth Edition (O'Reilly publishing) which seems to indicate that the compiler merely referees the code during compilation, throwing errors when an unsafe operation is attempted, and if not, then it translates the code to an ArrayList of Object but casts when necessary in the translated code. But I sure would like more specifics, and the title and page of a book where to find it.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Scott Shipp wrote:Sorry but what I am asking hasn't been addressed. I am wondering about the how, not the what. In other words, how does the compiler determine what is allowed to be added to the list, and when is it determined. I was reading Learning Java, Fourth Edition (O'Reilly publishing) which seems to indicate that the compiler merely referees the code during compilation, throwing errors when an unsafe operation is attempted, and if not, then it translates the code to an ArrayList of Object but casts when necessary in the translated code. But I sure would like more specifics, and the title and page of a book where to find it.

I think your basic misconception is that this has anything to do with generics. It doesn't. Nor does anything you've shown us have anything to do with polymorphism; it is simple type checking.

A Number, even a single one, can be assigned any subtype that is compatible, so:
Number n = new Integer(0);
is perfectly legal. That's all the compiler does when it checks what you're trying to add: "is it a Number?".

Personally, I find the easiest way to think about generics - at least the basic stuff - is to imagine that the compiler (and only the compiler) is dealing with a piece of source code where every instance of 'E' has been replaced with whatever we supplied as a type (in your case 'Number'), and then try to work out what that method will allow me to do. What's actually run, though, is a class where every instance of 'E' has been replaced with Object.

It's not precisely what happens, and the analogy breaks down when wildcards get involved; but I generally find it close enough to work out the basic stuff.

HIH

Winston

PS: I haven't checked, but I think you'll find that (paraphrased from your code):
ArrayList<Integer> listOfIntegers = new ArrayList<Integer>();
// code to add some Integers
List<Number> listOfIntegersAsNumbers = new ArrayList<Number>(listOfIntegers);

will work just fine. What you can't do is assign between Lists of different types.
 
Scott Shipp
Ranch Hand
Posts: 223
12
Eclipse IDE IntelliJ IDE Java Scala Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston, it is clear you completely misunderstand what is being asked. I have no problem understanding that subtypes can be assigned to a super type. That is basic OO development. But you should go look at the add method in ArrayList's source and you will see the use of generics there. So I don't know how you think it has nothing to do with generics. Also your code snippet you posted, which is not paraphrased from my post, but rather modified into something different, will not compile because a parameterized type is not a subtype of another just because the supplied parameter is a subtype. A List<Number> would be a subtype of Collection<Number> but a List<Integer> would not be a subtype of List<Number>. If it does compile, it is because of very clever use of generics in the underlying implementation, in the constructor. And that gets at my question of how it all works.
 
Henry Wong
author
Sheriff
Posts: 23295
125
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Scott Shipp wrote:Winston, it is clear you completely misunderstand what is being asked. I have no problem understanding that subtypes can be assigned to a super type. That is basic OO development. But you should go look at the add method in ArrayList's source and you will see the use of generics there. So I don't know how you think it has nothing to do with generics. Also your code snippet you posted, which is not paraphrased from my post, but rather modified into something different, will not compile because a parameterized type is not a subtype of another just because the supplied parameter is a subtype. A List<Number> would be a subtype of Collection<Number> but a List<Integer> would not be a subtype of List<Number>. If it does compile, it is because of very clever use of generics in the underlying implementation, in the constructor. And that gets at my question of how it all works.


I think the issue here is that you are asking for a comparison of three things that have little relationship to each other -- or more likely, have a interplay between different sets of rules, that you are trying to consolidate into one. Let me try to answer your question for each example separately... which may not answer your question, but may help you understand your question better.

1. In the case of adding Integer, Float, etc. into a List<Number>, Winston is correct. This is basic type checking rules. The List<Number> takes Number instances, so as long as what is being added IS-A Number, it will be allowed.

2. In the case of List<Number> being a subclass of Collection<Number>, that is standard subtype rules too. Granted there is generics in the mix, but the generics are the same type, so it doesn't apply here (well, it does apply, but there is nothing that will forbid it).

3. In the case of List<Number> and List<Integer>, this one is affected by the generic rules. And the rule is simple, if the generic type is different, it will not be allowed. This is explained with the simple example that I provided earlier.

4. The complexity of generic actually occurs when wildcards are used -- which is not the subject of this topic here. I am only mentioning it here because it may come up. Regardless, the complexity increases with wildcards, so I recommend understanding the simple case (case 3), and how it works with the standard subclassing rules first.


Henry

 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Scott Shipp wrote:Winston, it is clear you completely misunderstand what is being asked. I have no problem understanding that subtypes can be assigned to a super type. That is basic OO development. But you should go look at the add method in ArrayList's source and you will see the use of generics there. So I don't know how you think it has nothing to do with generics. Also your code snippet you posted, which is not paraphrased from my post, but rather modified into something different, will not compile because a parameterized type is not a subtype of another just because the supplied parameter is a subtype. A List<Number> would be a subtype of Collection<Number> but a List<Integer> would not be a subtype of List<Number>. If it does compile, it is because of very clever use of generics in the underlying implementation, in the constructor. And that gets at my question of how it all works.

I beg to differ. I understood your initial post (or at least - I suspect- the questions that led to it) precisely - because they were exactly the same ones that I had when I started using generics.

If your question is simply a "why" question, then you need to ask the authors of the enhancement - anything you get here will be mere conjecture.

However, in simple terms, how would you allow assignment of different generically typed objects to each other, even if the types are hierarchically linked? It's certainly possible that a compiler could be made to understand that an ArrayList<Number> is a supertype of ArrayList<Integer> - but what about when you then decide to add a BigInteger to that "assigned" List? - which seems to be the main point of your post.

And imagine the reverse, ie:
List<Integer> intList = someNumberList;

I suspect you've already thought that one through - what if someNumberList doesn't contain only Integers? Throw an exception? How would we possibly know? This is an assignment of a reference, not a function.

HIH

Winston
 
Ulf Lindqvist
Ranch Hand
Posts: 36
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Scott Shipp wrote:
If it does compile, it is because of very clever use of generics in the underlying implementation, in the constructor. And that gets at my question of how it all works.


It's the Java Language Specification that determines what compiles and what doesn't, not the "cleverness" of the compiler.
 
Scott Shipp
Ranch Hand
Posts: 223
12
Eclipse IDE IntelliJ IDE Java Scala Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Henry Wong wrote:
1. In the case of adding Integer, Float, etc. into a List<Number>, Winston is correct. This is basic type checking rules. The List<Number> takes Number instances, so as long as what is being added IS-A Number, it will be allowed.


No doubt, man! Keep in mind that I am the one that wrote the code example in order to demonstrate the point that it is allowed. I don't know why you're repeating it back to me? :-)

Henry Wong wrote:
2. In the case of List<Number> being a subclass of Collection<Number>, that is standard subtype rules too. Granted there is generics in the mix, but the generics are the same type, so it doesn't apply here (well, it does apply, but there is nothing that will forbid it).

3. In the case of List<Number> and List<Integer>, this one is affected by the generic rules. And the rule is simple, if the generic type is different, it will not be allowed. This is explained with the simple example that I provided earlier.


Have you read Effective Java, specifically item 28? I mean, once again you are repeating back to me something that I have posted. Also did you happen to read (my blog post that this thread is based on?

Henry Wong wrote:
4. The complexity of generic actually occurs when wildcards are used -- which is not the subject of this topic here. I am only mentioning it here because it may come up. Regardless, the complexity increases with wildcards, so I recommend understanding the simple case (case 3), and how it works with the standard subclassing rules first.


I think it already came up because Winston posted this example that uses the ArrayList constructor which accepts a Collection object as a parameter, which uses the bounded wildcard to function.
 
Scott Shipp
Ranch Hand
Posts: 223
12
Eclipse IDE IntelliJ IDE Java Scala Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ulf Lindqvist wrote:
Scott Shipp wrote:
If it does compile, it is because of very clever use of generics in the underlying implementation, in the constructor. And that gets at my question of how it all works.


It's the Java Language Specification that determines what compiles and what doesn't, not the "cleverness" of the compiler.


Hi Ulf! I didn't say cleverness of the compiler, I said underlying implementation and I was referring to the source code of ArrayList's constructor which looks like this (OpenJDK 7-b147):

 
Scott Shipp
Ranch Hand
Posts: 223
12
Eclipse IDE IntelliJ IDE Java Scala Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Scott Shipp wrote:Winston, it is clear you completely misunderstand what is being asked.


Winston Gutkowski wrote:I beg to differ. I understood your initial post (or at least - I suspect- the questions that led to it) precisely - because they were exactly the same ones that I had when I started using generics.


LOL...Winston I have to say I really appreciate your posts around here but this is a case where I am pretty confused. I guess you're going to dictate to me what questions I am asking from now on? Also I did not start using generics just now; I'm no "spring chicken" as they say.
 
Paul Clapham
Sheriff
Posts: 22823
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Scott Shipp wrote:Hi Ulf! I didn't say cleverness of the compiler, I said underlying implementation and I was referring to the source code of ArrayList's constructor which looks like this (OpenJDK 7-b147)...


Okay, that's what's in one implementation's version of the constructor for ArrayList. But wasn't your question about how the compiler does something? Because the compiler knows nothing and cares nothing about how any constructor or method is implemented. All it knows and cares about is the signatures of those things.

(I apologize, there's been a lot of obfuscation in this thread and I'm now not sure what your question was, exactly. Perhaps a recap of what you understand and don't understand at this point would be helpful?)
 
Scott Shipp
Ranch Hand
Posts: 223
12
Eclipse IDE IntelliJ IDE Java Scala Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Paul Clapham wrote:
Scott Shipp wrote:Hi Ulf! I didn't say cleverness of the compiler, I said underlying implementation and I was referring to the source code of ArrayList's constructor which looks like this (OpenJDK 7-b147)...


Okay, that's what's in one implementation's version of the constructor for ArrayList. But wasn't your question about how the compiler does something? Because the compiler knows nothing and cares nothing about how any constructor or method is implemented. All it knows and cares about is the signatures of those things.

(I apologize, there's been a lot of obfuscation in this thread and I'm now not sure what your question was, exactly. Perhaps a recap of what you understand and don't understand at this point would be helpful?)


I agree about the obfuscation. I am not following you on the compiler not caring about how things are implemented. But the reason it was about a particular implementation was because in the exchange that took place, Winston referenced this constructor. If I get a moment, I will come back and try to recap and clarify but I'm headed out the door. Thanks Paul!
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Let me de-obfuscate some. The initial question from the first post was this:
Scott Shipp wrote:But I am curious if there is some kind of explanation somewhere about generic polymorphism like in the above example that does work (where I added Integer, Float, Long to an ArrayList<Number>). Obviously the ArrayList implementation in Java uses a generic type, and obviously something within the JVM understands polymorphism of generic types. Otherwise adding Integer, Float, Long etc. to an ArrayList<Number> wouldn't work.

Any points of reference or quick explanation someone can provide about how this works or how it is accomplished?


Ivan was first to correctly answer the question.

Ivan Jozsef Balazs wrote:
is simply an ArrayList of Numbers: Numbers can be put into it Numbers can be obtained from there, and Integer, Float, Long are Numbers.

Akin to



But you ignored him.

Scott Shipp wrote:Sorry but what I am asking hasn't been addressed.


Then you give a description of what a book told you that pretty much covered the topic:

Scott Shipp wrote:the compiler merely referees the code during compilation, throwing errors when an unsafe operation is attempted, and if not, then it translates the code to an ArrayList of Object but casts when necessary in the translated code. But I sure would like more specifics, and the title and page of a book where to find it.


But then you ignored it, asking for another book to tell you what that book told you. If you really want some specifics, I suggest:
http://docs.oracle.com/javase/specs/jls/se7/html/index.html

To narrow your search, start here:
http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.5
http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.5
http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2

There are a lot more places, but I suspect you already are ignoring me at this point. So the links won't help. Why do I guess you will be ignoring me? Because here is the summary of the rest of this thread:

Remember, you said:
Scott Shipp wrote:Sorry but what I am asking hasn't been addressed.


as you ignored Ivan's response. To which Winston responded:

Winston Gutkowski wrote:I think your basic misconception is that this has anything to do with generics. It doesn't. Nor does anything you've shown us have anything to do with polymorphism; it is simple type checking.


You respond with

Scott Shipp wrote:Winston, it is clear you completely misunderstand what is being asked.


When it is probably closer to the truth that you don't understand what is being said. Ivan, Winston, Henry understand your question. The answer is... well no point being the fourth to say it. Read their posts if you want the answer.

Having ignored the important part of Winston's post (how what he talks applies to your question) you dwell only on subtype assignment:
Scott Shipp wrote:I have no problem understanding that subtypes can be assigned to a super type. That is basic OO development.


Henry is next to reiterate what you have been told three times in this post and at least once in a book:

Henry Wong wrote:1. In the case of adding Integer, Float, etc. into a List<Number>, Winston is correct. This is basic type checking rules. The List<Number> takes Number instances, so as long as what is being added IS-A Number, it will be allowed.


Again, you ignore how what he says applies to your question, and instead reply (rather sarcastically in my reading):

Scott Shipp wrote:No doubt, man! Keep in mind that I am the one that wrote the code example in order to demonstrate the point that it is allowed. I don't know why you're repeating it back to me?


Umm. No. You asked a question. Ivan, Henry, and Windston gave you answers. You have ignored the answers. Do you understand that Henry isn't saying "You can put an Integer into a List<Number>" he is saying ... never mind, I won't repeat it again. Re-read if you want the answer.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
And just to add to Steve's excellent post:

Scott Shipp wrote:Also your code snippet you posted, which is not paraphrased from my post, but rather modified into something different, will not compile...

It most certainly will. And what's more, it does exactly what I said it would, which is effectively (and hence the word "paraphrased") what your original assignment does.

If it does compile, it is because of very clever use of generics in the underlying implementation, in the constructor. And that gets at my question of how it all works.

Not at all. It behaves precisely as it is specified to; and to understand that, you only need to look at the definition of the constructor. I highly doubt that anything in the implementation source would enlighten you any further.

Winston
 
Scott Shipp
Ranch Hand
Posts: 223
12
Eclipse IDE IntelliJ IDE Java Scala Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Steve Luke wrote:Let me de-obfuscate some. The initial question from the first post was this:
Scott Shipp wrote:But I am curious if there is some kind of explanation somewhere about generic polymorphism like in the above example that does work (where I added Integer, Float, Long to an ArrayList<Number>). Obviously the ArrayList implementation in Java uses a generic type, and obviously something within the JVM understands polymorphism of generic types. Otherwise adding Integer, Float, Long etc. to an ArrayList<Number> wouldn't work.

Any points of reference or quick explanation someone can provide about how this works or how it is accomplished?


Ivan was first to correctly answer the question.

Ivan Jozsef Balazs wrote:
is simply an ArrayList of Numbers: Numbers can be put into it Numbers can be obtained from there, and Integer, Float, Long are Numbers.

Akin to



But you ignored him.


Please understand: I am not ignoring Ivan's post. Again to reiterate what I posted above, "I am wondering about the how, not the what." It's pretty easy to go around programming in generics and thinking to yourself, "this is what I do to get this result." And I would say that so far most of this discussion falls into that mode of thought. But to know how it works "under the hood" is another story. I'd like to get down to a lower level in the system. My idea here is to use the particular example in the context of a more general question.

What is really being ignored is any depth here. The simple fact that most of this discussion ignores the source code for ArrayList (it doesn't refer to it) is ample evidence that we aren't getting into the question. I already know from experience what happens when I take a particular action, but I'd like to know how we get from the action to the result. I don't know how many ways I should say this...if it is not making it any clearer than I am reticent to continue beating my head against this wall.


Steve Luke wrote:
Scott Shipp wrote:Sorry but what I am asking hasn't been addressed.


Then you give a description of what a book told you that pretty much covered the topic:

Scott Shipp wrote:the compiler merely referees the code during compilation, throwing errors when an unsafe operation is attempted, and if not, then it translates the code to an ArrayList of Object but casts when necessary in the translated code. But I sure would like more specifics, and the title and page of a book where to find it.


But then you ignored it, asking for another book to tell you what that book told you.


I feel that is unfair. I wasn't asking for another book to tell me the same thing. I wrote here that "I sure would like more specifics..." and that is exactly what I meant. The subsequent posts didn't go into more specifics on that process. I don't want reiteration.

So I am not just going along ignoring posts here. I am merely saying what I already knew and attempting to set the discussion on course to somewhere that would be helpful for anyone else with similar goals...but I am getting the impression that no matter how many times I say this, though, it's a losing battle?



Yes, that is very helpful and exactly along the lines of what I am looking for / thinking of. In addition, I am looking for the code that is produced by the compiler when the particular example runs.


Steve Luke wrote:
There are a lot more places, but I suspect you already are ignoring me at this point. So the links won't help. Why do I guess you will be ignoring me?


Because here is the summary of the rest of this thread:

Remember, you said:
Scott Shipp wrote:Sorry but what I am asking hasn't been addressed.


as you ignored Ivan's response. To which Winston responded:

Winston Gutkowski wrote:I think your basic misconception is that this has anything to do with generics. It doesn't. Nor does anything you've shown us have anything to do with polymorphism; it is simple type checking.


You respond with

Scott Shipp wrote:Winston, it is clear you completely misunderstand what is being asked.


When it is probably closer to the truth that you don't understand what is being said. Ivan, Winston, Henry understand your question. The answer is... well no point being the fourth to say it. Read their posts if you want the answer.


Why do you say that, "it is probably closer to the truth that you don't understand what is being said?"

Steve Luke wrote:
Having ignored the important part of Winston's post (how what he talks applies to your question) you dwell only on subtype assignment:
Scott Shipp wrote:I have no problem understanding that subtypes can be assigned to a super type. That is basic OO development.


Henry is next to reiterate what you have been told three times in this post and at least once in a book:

Henry Wong wrote:1. In the case of adding Integer, Float, etc. into a List<Number>, Winston is correct. This is basic type checking rules. The List<Number> takes Number instances, so as long as what is being added IS-A Number, it will be allowed.


Again, you ignore how what he says applies to your question, and instead reply (rather sarcastically in my reading):

Scott Shipp wrote:No doubt, man! Keep in mind that I am the one that wrote the code example in order to demonstrate the point that it is allowed. I don't know why you're repeating it back to me?


Umm. No. You asked a question. Ivan, Henry, and Windston gave you answers. You have ignored the answers. Do you understand that Henry isn't saying "You can put an Integer into a List<Number>" he is saying ... never mind, I won't repeat it again. Re-read if you want the answer.


And you say I am sarcastic?

You can edit the discussion down in all kinds of different ways to make it look like it says what you want, but Henry is the one who wrote: "A List<Number> is an instance of List that can contains Numbers. An Integer IS-A Number. A Float IS-A Number. And a Long IS-A Number. Hence, all three can be added to a List of Numbers. "

Contrast this with the blog post I authored, which I posted on July 23, before I came here and posted this thread, where I wrote: "In this code, since Integer, Long, and Float are all subtypes of Number, they can be added to a List<Number> (list of number)."
 
Scott Shipp
Ranch Hand
Posts: 223
12
Eclipse IDE IntelliJ IDE Java Scala Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:And just to add to Steve's excellent post:

Scott Shipp wrote:Also your code snippet you posted, which is not paraphrased from my post, but rather modified into something different, will not compile...

It most certainly will. And what's more, it does exactly what I said it would, which is effectively (and hence the word "paraphrased") what your original assignment does.

If it does compile, it is because of very clever use of generics in the underlying implementation, in the constructor. And that gets at my question of how it all works.

Not at all. It behaves precisely as it is specified to; and to understand that, you only need to look at the definition of the constructor. I highly doubt that anything in the implementation source would enlighten you any further.

Winston


I posted the source of this constructor above. By the way, the "definition of the constructor" is part of the source. But setting that aside, do you agree that it compiles because there is a constructor provided with a bounded wildcard? Without this constructor in the ArrayList source, it would not compile. That's what I was getting at here:

Scott Shipp wrote:
If it does compile, it is because of very clever use of generics in the underlying implementation, in the constructor. And that gets at my question of how it all works.



At the time, I had not looked at the source for ArrayList yet but I knew that without such a constructor accepting a bounded wildcard (because I do understand generics no matter how many times other board posters here want to say otherwise) it would not compile. I consider that "clever use of generics in the underlying implementation" because obviously Bloch and the other author (his name is slipping my mind right now) anticipated this kind of thing. If this also is what you meant all along, good, then we are just talking past each other. But some of the things you said made it seem like you thought it would just work with the normal constructor.
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Simple questions then:
Do you understand what type checking is, where it happens, and how it works?
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!