• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Ron McLeod
  • Paul Clapham
  • Bear Bibeault
  • Junilu Lacar
Sheriffs:
  • Jeanne Boyarsky
  • Tim Cooke
  • Henry Wong
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • salvin francis
  • Frits Walraven
Bartenders:
  • Scott Selikoff
  • Piet Souris
  • Carey Brown

Potential Error on Page 136 of OCA Java SE 8 Programmer I by Boyarsky and Selikoff

 
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
As the subject says, I think I may have spotted an error in this book. I checked the current listing of errors on https://www.selikoff.net/java-oca-8-programmer-i-study-guide/ and can't find it mentioned there. So following the instructions on that page, it told me to create a new thread here. I've never been here before though, so my apologies if I ended up doing this incorrectly.

The concern I have is that for the example given concerning Integer autoboxing when using an ArrayList of type Integer, the solution they list doesn't seem to match the problem. To explain, I have to reference a snippet from the book:

I understand what the book is describing the problem to be. The remove method expects int input to be the INDEX of the item to remove, so instead of removing the 1 from the array, it removes the 2 instead.
The sentence detailing the solution to this says:

"If you want to remove the 2, you can write numbers.remove(new Integer(2)) to force wrapper class use."

And while that statement is indeed true, it's not solving the original problem. both the original code and the suggested solution result in the 'numbers' array being [1], having the entry for the 2 removed. It's just that the original code removed it by index, and the 'solution' removed it by equality of the Integer instance. I think what the book means to say, to completely get the point across, would be to replace the '2's in the solution sentence with '1's, like so:

"If you want to remove the 1, you can write numbers.remove(new Integer(1)) to force wrapper class use."

This would result in the 'numbers' array having a final value of [2], which I believe was the original intent of the example.
 
Marshal
Posts: 70318
283
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch
Yes, this is the right place to report errata.
It is both right and wrong. You can either remove the 2 by using ....remove(1) which removes the element at index  or ....remove(new Integer(2)) to remove the value 2. It might be preferable to write ....remove(Integer.valueOf(2)) because that constructor is potentially inefficient.
So what the book says is technically correct. But it might have been easier to understand, as you say, had it used ....remove(Integer.valueOf(1)). Remember that ....remove(2) will cause that List to throw an exception. You can get even stranger confusion with other integer types because widening conversion seems to take precedence over boxing.
 
author & internet detective
Posts: 40211
816
Eclipse IDE VI Editor Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Aleici,
Welcome to CodeRanch! You definitely created a thread right. I also appreciate the "potential error" language!

As Campbell said, it is correct. Integer.valueOf() would have been more obvious. We were trying to show the subtle trick.
 
Aleicia Forsberg
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you for the warm welcome and responses!

However my question still stands. I thought of a better term for it, 'misleading'. It seems misleading to me the way it currently is in the book, even though it's technically correct, since both the 'wrong way' and the 'right way' result in the same behavior. In both cases, the '2' is removed from the array. What seems misleading to me is that the scenario seemed to set up that the first way, `...remove(1)` would, at first glance, want to remove the '1' element from the 0th index, when in fact it removes the '2' element from the 1st index. It just seems like it would be clearer and less misleading to say that the 'right way' would be to either use `...remove(new Integer(1))` or `...remove(Integer.valueOf("1"))` when you want to pass an Integer instance of '1' to the remove method to effectively remove the '1' element from the 0th index, rather than suggesting that you remove the '2' element a different way.

But I think I see where the misunderstanding might be. I was approaching the problem from the standpoint that using `...remove(1)` was a bad idea because the programmer wanted to remove the element of '1' from the array. However I think perhaps the intended approach was that the programmer wanted to remove the '2' by index intentionally, but this is misleading to future programmers who read the code later. In this latter approach then yes, I agree that the programmer should eliminate ambiguity by always removing Integers from array by their Integer value instead of their index. However the way the situation was led up to, by first explaining that "It (`...remove(1); ...println(numbers);`) actually outputs [1]" would naturally lead readers to the assumption that the former approach is the one to view the question from, which is why seeing a solution of `...remove(new Integer(2))`, while being a valid statement, is misleading and jarring.

edit: emphasis added
 
Campbell Ritchie
Marshal
Posts: 70318
283
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Aleicia Forsberg wrote:Thank you for the warm welcome . . .

That's a pleasure

I see where the misunderstanding might be. . . .

The problem is that you have an overloaded method, and you need to know which version of it is called in which circumstances. You can also try a cast:- numbers.remove((Object)1); See if you can't work out what that does
 
Aleicia Forsberg
Greenhorn
Posts: 4
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:The problem is that you have an overloaded method, and you need to know which version of it is called in which circumstances. You can also try a cast:- numbers.remove((Object)1); See if you can't work out what that does



My problem was not that I don't understand the code (I understand many ways of removing whichever entry I want in this scenario), it's a matter of how the problem and solution is presented.

The problem: "It (`...remove(1); ...println(numbers);`) actually outputs [1]"

The solution should focus on 'actually' removing the '1' since the problem seems to present that the '1' shouldn't have stuck around, but rather the '2' should have. The problem I have is with the phrasing of the problem not being consistent with the presented solution. The solution in the book and what's been discussed here are all perfectly valid ways of removing the '2', it's just that problem suggests that the intent is to remove the '1', not the '2'. "ACTUALLY outputs [1]" indicates that the INTENDED output was [2]. The solution presented still results in an output of [1] and THAT'S why this is confusing to the reader. I hope I'm getting my point across clearly, as again, it's not the code itself per se, but that the way it's laid out is confusing and could benefit from a rephrasing.
 
Campbell Ritchie
Marshal
Posts: 70318
283
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I no longer understand the problem. I think you are saying that the text isn't clear. Otherwise, what is wrong? Everything the text says is correct, even though you would prefer it to say numbers.remove(Integer.valueOf(1));
Unlike a website, a book is restricted by its page size and count, so there isn't unlimited spae to discuss all possibilities.

But that is the sort of thing that comes up in the exams; you need to know which element of the List is removed by numbers.remove(1); or numbers.remove(Integer.valueOf(2)); or numbers.remove((Object)2);
 
Greenhorn
Posts: 4
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

The OP of this thread is right. There is a mistake at page 136 on the last example of autoboxing. I'll try to put it in simpler terms:

From the book:


What do you think this code outputs?


It actually outputs 1. After adding the two values, the List contains [1, 2]. We then request
the element with index 1 be removed. That’s right: index 1. Because there’s already a remove()
method that takes an int parameter, Java calls that method rather than autoboxing. If you
want to remove the 2, you can write numbers.remove(new Integer(2)) to force wrapper
class use.



The bold and underlined part is the "mistake", because WE ALREADY REMOVED VALUE 2 WHEN WE USED BECAUSE VALUE 2 IS AT INDEX 1!
So the correct statement would have been If you want to remove the 1, you can write numbers.remove(new Integer(1)) to force wrapper
class use.


sorry for CapsLock
Cheers!






 
Campbell Ritchie
Marshal
Posts: 70318
283
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch

No, the book is correct. It is written like that to show the subtle difference between 2 as an int and 2 as an Integer. The underlined sentence is written as an alternative to what it said earlier. It might have been easier to understand if it told you how to remove the 1. There are good reasons for writing like that; the exam questions depend on your knowing the subtle nuances of the behaviour of the remove() method. What would have happened if the List had been declared with type List<Long> instead?

There is a possible imprecision when it says the program outputs 1; it actually displays “[1]” including [].
 
Stefan Doe
Greenhorn
Posts: 4
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

I get your point. But then, for clarity's sake, the above underlined phrase should start with sth like "Another way to remove value 2....".  
Because as is, makes you think you want to remove value 2 again after you already removed it. Which you cannot do, because there is no value 2 left.


LATER EDIT:
An even better way of putting this:

I think the book tries to present this from the point of an unexperienced programmer who had the intentions to remove value 1 by writing numbers.remove(1); (which is obviously a mistake), and then advises that person by wrongly stating: If you want to remove the 2, you can write numbers.remove(new Integer(2)) to force wrapper class use.
So even with this interpretation we have the same lack of clarity because the book should have said sth like this:
"Hello there unexperienced programmer, If you actually want to remove the value 1 (because this was the original intention of the programmer), you can then write numbers.remove(new Integer(1)) to force wrapper class use." (or use the above numbers.remove() method for index 0 like this: numbers.remove(0)).

hope this helps!

Thanks for the warm welcome!
Cheers!

 
Greenhorn
Posts: 13
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Such a lively thread! Just thought I'd throw my two-cents in because, you know, I've been doing this for a couple months so I'm an expert

But in all serious, I understand both the OP's point that the verbiage here requires a bit of grappling, but I also take the point made by several of the other posters that there is value in illustrating the subtlety. I, for one, needed to write the code myself and then come here and read a few posts before I felt like I really grasped the point and, in the process, felt I gained not only a better understanding of the specific nuance being addressed in this passage, but also of autoboxing and unboxing in general. As I'm working through the book, I'm also creating some flash cards for myself, in addition to those provided by the author (thank you), and have found that it helps me to try to reformulate concepts I struggle with into a question or two resembling the structure and format I've seen used on examples from the exam itself. I also feel like this is helping me adopt a mindset that's less likely to get duped by the little tricks the test creators like to sneak in there  .

So, all that said, in the event that another traveler should this way pass, I thought I'd share the flashcard I wrote for myself to help me understand this:

Which line of code, inserted at //1, will remove 1 from the list (choose all that apply):

A. numbers.remove(1);
B. number.remove(0);
C. numbers.remove(new Integer(1));
D. numbers.remove(Integer.valueOf(1));
E. numbers.remove(Integer.parseInt("1"));
F. None of the above.
 
Campbell Ritchie
Marshal
Posts: 70318
283
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There is a reason why you can't box 1 into an Integer in that sort of code. The remove() method was written for Java1.2. and boxing conversion wasn't introduced until Java5.
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
    Bookmark Topic Watch Topic
  • New Topic