Dan Doyle

Greenhorn
+ Follow
since Oct 02, 2006
Merit badge: grant badges
For More
Cows and Likes
Cows
Total received
0
In last 30 days
0
Total given
0
Likes
Total received
0
Received in last 30 days
0
Total given
0
Given in last 30 days
0
Forums and Threads
Scavenger Hunt
expand Ranch Hand Scavenger Hunt
expand Greenhorn Scavenger Hunt

Recent posts by Dan Doyle

Ok, it is time for a little self-deprecation, I must be dense. I understand that we are not doing harm if we are adding back the same elements to the list when they are being reversed, but one of the points from K&B about the wildcard is that it doesn't allow you to modfiy a list. Well, changing the order is a modification unless I am interpretting modification incorrectly. For one, wildcards and generics are a compile time check and are removed completely from runtime bytecode, so at runtime, everything is treated as an object. So, at runtime, the bytecode is not going to know whether it is adding a Cat or a Dog. Two, the code from the book on pg 595 is taking any List, but specifically adding a Dog to the list. That doesn't seem right as it is not guaranteeing that only objects of a certain type are added to the list. What is a List<Cat> is passed in to the doInsert. Then, the code is adding a Dog to it and that is a no-no.

But to the syntax of the the reverse method, where did you find this code for the reverse method? I don't see it in the javadocs. So, when a reverse is done, it is modifying the list with the swap method. And swapping indexes in a list must not be considered a modification as far as the compiler is concerned since it is not adding new Objects to the list, and rather it is swapping the elements that are already in the list. I guess when I read modifying in the text of K&B, my modifying has a wider scope and they really mean only adding to the list as a modification. Losing information like original order as lists maintain seems like a modification as information is lost. This makes sense.

So, it seems that if I want to maintain original order and not lose that information, I either extract this information into an Object that will maintain the original order information, or I create a new List with the contents of the original List and sort the new List. So, to continue with binarySearch, does the list have to be sorted before or can I hand in the sort as an argument with the binarySearch and everything will be taken care of? It seems that I need to hand in a pre-sorted list and the sort that was used to sort the list into binarySearch in order for it to work. Which means that I might as well sort the original List as keeping two lists is a pain in the butt. Hmmm, I think I read somewhere about some sort of indirection I can keep by creating a Row object that resolves to the list items. Then, I sort the Row objects which use the values from the original list they are tied to and use this sorted Row list. This will allow my original list to stay unmolested by methods like reverse =P.

Thanks for all the help. I think I better understand generics, I am still a little confused but it seems to be constained to add and probably insert, and I know how I will want to use lists with regards to the Collections API.
So, I take it that the static reverse method is considered an unbounded wildcard since it is not qualified with super or extends. But I don't understand the tie in with what the reverse method is doing? Is it modifying the list that is passed in to the reverse()?

In the K&B book on pg 595, there is a code example as follows:


The explanation below says,

The problem is in the list.add() method within doInsert( . The <?> wildcard allows a list of ANY type to be passed to the method, but the add( method is not valid, for the reasons we explored earlier...

And previous to this text something similar is mentioned about List<?> and modification because the compiler can't guarantee an object of the correct type will be added to the list.

Essentially, what I want to know is if the original list is modified in any way when you sort it? It seems like this must be the case, but I want to know so I can put my collection in a new List whenever I sort. What is the best practice when it comes to sorting? My gut tells me that I would prefer to leave an original list unmodified and get a new sorted list in return. But I am not sure why I wouldn't just resort it with a new Comparator. However, there might be value in keeping the original order and that is what my gut does not feel good about since this information will be lost after I sort a list. This is in addition to knowing what the reverse() is doing under the covers as well as some of the other Collections static methods.

Regards,
Dan
From reading the K&B SCJP 5.0 cert book, the wildcard syntax is used to declare that a method can take a list of a generic type and its subtypes or supertypes, but it signifies that the list will not be modified. For instance,

is legal as long as inspectList() is not modifying the list. I think my statement is backed up by the summary in K&B on page 610 where it states that, "When using a wildcard, List<? extends Dog>, the collection can be accessed but not modified."

However, I am confused when I am looking at the Collections API. For instance, it declares reverse() located at: Class Collections,

reverse

public static void reverse(List<?> list)

Reverses the order of the elements in the specified list.



So, my confusion lies in the fact that this static method is not returning a new list. So, in order for it to reverse, isn't it modifying the original list? In other words, is it more accurate to say that the wildcard prevents adding and removing from a list? Or is reverse() modifying the iterator that would be returned so that it will iterate over the reverse order thus leaving the original list alone and unmodified?

Regards,
Dan

p.s. it was a pain in the butt to change all the (, <, ), and >. This makes it real difficult to post a question about generics. I felt like giving up =( as I revisited my post 7 times to find the bad syntax.

Note that in upgrade exam the topics are the same, only number of questions and passing score differ.

1.5 changes includes generic types, metadata, autoboxing, an enhanced for loop, enumerated types, static import, C style formatted input/output, variable arguments, concurrency utilities, and simpler RMI interface generation.



This concerns me as I am also going to take the upgrade exam. The K&B book doesn't cover several of these topics like the simplified RMI interface and metadata. Are these topics on the upgrade exam or not?

Thank you,
Dan
Just to add a little more info:

But, Boxing first, then Widening is no problem.

int --> Integer --> Object (correct)
int --> Integer --> Long (illegal)



The reason it is illegal to go from Integer to Long isn't because it is widening from Integer to Long, it is because Long and Integer are not in the same inheiritance tree. Both Long and Integer inheirit from java.lang.Number, so trying to widen an Integer to a Long is not widening at all.

Regards,
Dan
So, I have a question: can you have the hashmap rehash itself? In other words, if you know it is possible the keys may have updated their state, like when the name property is changed, can you ask the hashmap to recalculate the hashes? Or is it possible to create a new hashmap with the old hashmap as an argument? If not, it seems that the best strategy for keys is to have them be immutable. Is this a correct conclusion? The other conclusion I get from this is that the hash is calculated when the object is placed in the map, not dynamically whenever get is used. This makes sense as you wouldn't want a million object map to recalculate itself everytime you wanted to retrieve an object.

Regards,
Dan
Thanks for the tip.

I am curious if there are other special cases when an enum value can be used without specifying the enum type. I thought this was strange when I stumbled across it. I am reading the Sun Certified Programmer for Java 5 by Kathy Sierra and I didn't see anywhere in the book that highlights this instance and I picked up incorrectly that enums need to be qualified with their type. I suspect this is because switches are smart, which I didn't guess at. I would have thought that the switch would do a .equals() with the cases if they are enums, which should return false if the types being compared are different. I didn't know if someone might have a better explanation or could confirm my hunch about the switch statement.

Dan
17 years ago
I am trying to figure out how to use enum values in a switch as cases. I am a little confused as I thought I had to prefix or qualify the enum value with the enum type. Here is an example I found from Joshua Bloch in 2003 (http://java.sun.com/features/2003/05/bloch_qa.html) which is rather old so I didn't necessarily expect it to work as the spec was finalized, but since I couldn't get my own code to work, I figured I would try this as it is what I thought I needed to do.

public enum Coin {
penny(1), nickel(5), dime(10), quarter(25);

Coin(int value) { this.value = value; }

private final int value;

public int value() { return value; }
}

public class CoinTest {
public static void main(String[] args) {
for (Coin c : Coin.VALUES)
System.out.println(c + ": \t"
+ c.value() +"� \t" + color(c));
}
private enum CoinColor { copper, nickel, silver }
private static CoinColor color(Coin c) {
switch(c) {
case Coin.penny: return CoinColor.copper;
case Coin.nickel: return CoinColor.nickel;
case Coin.dime:
case Coin.quarter: return CoinColor.silver;
default: throw new AssertionError("Unknown coin: " + c);
}
}
}

But this does not work. The compiler throws these errors for the syntax for each case statement:
CoinTest.java:11: an enum switch case label must be the unqualified name of an enumeration constant
case Coin.nickel: return CoinColor.nickel;
^
CoinTest.java:11: duplicate case label
case Coin.nickel: return CoinColor.nickel;
^
If I remove the qualifier/prefix(i.e. Coin), then the code compiles and runs. Well, almost, VALUES needs to be changed to values() in he main method.

So, I am a little confused. Why does the switch get to buck the trend of having to qualify the enum value with the enum type? Are there other instances in which this occurs? Is this a case of Java not being consistant or is it that switches are smart? In other words, once you use a variable reference to be switched on, the switch knows the type and only allows values of that type in the case statements. I didn't expect this since it seems everywhere else I use enums in my code, I have to do the full qualification. It made me think that the values were static, but I tested that and that is not the case either.

Any comments?

Dan
17 years ago