Find and explain the errors in the following code. Warning: this is a challengin
ID: 3620459 • Letter: F
Question
Find and explain the errors in the following code. Warning: this is a challenging and hard problem!In particular, for each line with a numbered comment (1 through 11), you should be eventually able to explain why the line is OK, or that the problem with the line is in the context of the classes and declarations in the rest of the code. I think because of the generic declarations, all errors that exist are caught by the compiler.
public class GenericTestOneA {
public static void main (String args []) {
GenericStack < MyGenA > sga = new GenericStack < MyGenA > ();
GenericStack < MyGenB > sgb = new GenericStack < MyGenB > ();
GenericStack < MyGenC > sgc = new GenericStack < MyGenC > ();
addN (sga, sga); // 1
addE (sga, sgb); // 2
addS (sgb, sga); // 3
addS (sga, sgb); // 4
addE (sgb, sga); // 5
addN (sgb, sga); // 6
addN (sga, sgb); // 7
} // end main
public static < T > void addN (GenericStack < T > stack1, GenericStack < T > stack2) {
while (!stack1.isEmpty ()) stack2.push(stack1.pop()); // 8
} // end addN
public static < T > void addS (GenericStack < T > stack1, GenericStack < ? super T > stack2) {
while (!stack1.isEmpty ()) stack2.push(stack1.pop()); // 9
} // end addS
public static < T > void addE (GenericStack < T > stack1, GenericStack < ? extends T > stack2) {
while (!stack1.isEmpty ()) stack2.push(stack1.pop()); // 10
while (!stack2.isEmpty ()) stack1.push(stack2.pop()); // 11
} // end addE
} // end GenericTestOne
class GenericStack < E > {
private java.util.ArrayList < E > list = new java.util.ArrayList < E > ();
public int getSize () {return list.size();}
public E peek () {return list.get(getSize() - 1);}
public E push (E o) {list.add (o); return o;}
public E pop () {E o = peek (); list.remove (getSize() - 1); return o;}
public boolean isEmpty () {return list.isEmpty();}
} // end class GenericStack
class MyGenA {}
class MyGenB extends MyGenA {}
class MyGenC extends MyGenB {}
Explanation / Answer
First, let's look at the addN method. It works by removing items from stack1 and adding them to stack2 until stack1 is empty. In line //1, we are going to be removing items from stack1 and adding items to stack1 until stack1 is empty. This will never happen! Thus, //1 results in an infinite loop. //6 and //7 will not work because the addN method takes two parameters of the same type, and we are passing in two parameters with different types. Line //8 is fine. Now let's look at the addS method. This method takes in a stack of objects, and another stack of objects that are the same or a superclass of the type of objects in the first stack. The behavior is otherwise the same as addN. Line //9 is fine. In //3, we are taking items of type MyGenB and putting them onto a stack of type MyGenA. Since MyGenB extends MyGenA, this is allowed (because all MyGenB objects are also MyGenA objects). Therefore, //3 is fine. On the other hand, in //4, we are trying to convert objects of type MyGenA to MyGenB. However, not all instances of MyGenA are also instances of MyGenB. Therefore, the type conversion might fail (you might see a compile error like "incompatible types"). What's going on in the last method, addE? We're taking items that extend type T (off stack2) and putting them onto our stack (stack1) of type T. This will work because we're making the items more generic. Then we are taking those generic items of type T and putting them back onto the stack of the more specific type (that extends T). There's a trick here. We **know** that those items can be converted back to the original type! Thus, we could add a cast to line //11. There is no syntax error on line //5. The basic idea is that you can make a specific type (S extends T) into a more generic type (T), but you cannot always make a more generic type (T) more specific (S extends T). If you **know** you casted down from a more specific type, you can explicitly cast back to the specific type. The compiler will always let you do this, but if you make a mistake and you cast something you're not supposed to, you'll get a runtime error. That's it! Make sense? Feel free to follow up if you have any more questions. Good luck!
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.