The pages of this web site are not formatted to conserve paper, but my new book (ISBN: 0-9745862-0-X) is formatted to save paper, save your printer cartridge, save a loose-leaf binder, and save money. If you prefer to work my exams from printed pages, then give your printer a rest and buy my new book.
Today, you can find my book at amazon.com.
| No. | Answer | Remark | |
|---|---|---|---|
| 1 | a | Prints: float,float | A method invocation conversion can widen an argument of type float to match a method parameter of type double, so any argument that can be passed to m(float i) can also be passed to m(double i) without generating a compile-time type error. For that reason, we can say that m(float i) is more specific than m(double i). Since both methods are applicable, the more specific of the two, m(float i), is chosen over the less specific, m(double i). The arguments of the method invocation expressions, m(a1) and m(b1), are of types int and long respectively. A method invocation conversion can widen an argument of type int or long to match either of the two method parameter types float or double; so both methods, m(float i) and m(double i), are applicable to the two method invocation expressions. Since both methods are applicable, the more specific of the two, m(float i) is chosen rather than the less specific, m(double i). |
| 2 | a | Prints: float,float | A method invocation conversion can widen an argument of type float to match a method parameter of type double, so any argument that can be passed to m(float i) without generating a compile-time type error can also be passed to m(double i). For that reason, we can say that m(float i) is more specific than m(double i). The arguments of the method invocation expressions, m(a1) and m(b1), are of types char and long respectively. A method invocation conversion can widen an argument of type char or long to match either of the two method parameter types float or double; so both methods, m(float i) and m(double i), are applicable to the two method invocation expressions. Since both methods are applicable, the more specific of the two, m(float i) is chosen rather than the less specific, m(double i). |
| 3 | e | Compile-time error | The method invocation expression, m(b1), contains an argument of type double. A method invocation conversion will not implicitly narrow the argument to match the parameter type of the method, m(float i). The method invocation expression, m(a1), contains an argument of type long. A method invocation conversion will widen the argument to match the parameter type of the the method, m(float i). |
| 4 | b | Prints: String | A method invocation conversion can widen an argument of type String to match a method parameter of type Object, so any argument that can be passed to m(String x) without generating a compile-time type error can also be passed to m(Object x). For that reason, we can say that m(String x) is more specific than m(Object x). The argument of the method invocation expression, m(null), is of type null and can be converted to either type String or Object by method invocation conversion, so both methods, m(String x) and m(Object x), are applicable. The more specific of the two, m(String x), is chosen over the less specific, m(Object x). |
| 5 | d | Compile-time error | The type of the argument is null and could be converted to any of the types Object, String or GFC200, by method invocation conversion. All three methods are applicable, but none of the three is more specific than both of the other two. The ambiguity results in a compile-time type error. If type GFC200 were a subclass of type String; then any argument that could be pass to m(GFC200 x) could also be passed to m(String x) without causing a compile-time type error, and we could say that m(GFC200 x) is more specific than m(String x). Since GFC200 is not a subclass of type String, a method invocation conversion is not able to widen an argument of type GFC200 to match a method parameter of type String, so m(GFC200 x) is not more specific than m(String x). |
| 6 | b | Prints: GFC203 | The type of the argument is null and could be converted to either type GFC202 or GFC203 by method invocation conversion; so both methods are applicable. The more specific of the two, m(GFC203 x), is chosen. Type GFC203 is a subclass of type GFC202; so any argument that can be passed to m(GFC203 x) can also be passed to method m(GFC202 x) without causing a compile-time type error; therefore, we can say that method m(GFC203 x) is more specific than m(GFC202 x). |
| 7 | d | Prints: GFC206,GFC206 | Type GFC207 is a subclass of types GFC206 and GFC205, so any of the four methods are applicable to the method invocation expression, m(gfc207, gfc207). The most specific of the four, m(GFC206 x, GFC206 y), is chosen. Type GFC206 is a subclass of type GFC205, and method m(GFC206 x, GFC206 y) is more specific than the other three, because any invocation of m(GFC206 x, GFC206 y) could also be handled by any of the other three without causing a compile-time type error. |
| 8 | f | Compile-time error | The method invocation expression, m(gfc213, gfc213), is ambiguous; because, no applicable method is more specific than all of the others. Method m(GFC212 x, GFC212 y) is more specific than m(GFC212 x, GFC211 y), because any invocation of m(GFC212 x, GFC212 y) could also be handled by m(GFC212 x, GFC211 y) without causing a compile-time type error. However, some invocations of m(GFC212 x, GFC212 y) can not be handled by m(GFC211 x, GFC213 y), so m(GFC212 x, GFC212 y) is not more specific than m(GFC211 x, GFC213 y). Furthermore, not all invocations of m(GFC211 x, GFC213 y) could be handled by m(GFC212 x, GFC212 y). |
| 9 | b | Prints: byte byte boolean | Variable b1 was initialized by the first method invocation statement, so the second method invocation statement does not result in a compile-time error. The assignment expression, b1 = 1, initializes variable b1 with the value 1, and the same value is passed as an argument to method m1(byte b1). The method invocation expression, m1(b1), invokes the same method, m1(byte b1). The argument of the third method invocation expression, m1(b1 == 1), is the result of the equality expression, b1 == 1. The type of the result and the argument is boolean, so the invoked method is m1(boolean b1). |
| 10 | b | Prints: BBABBA | Type B is a subclass of type A, and method m(B x, B y) is more specific than the other three; because any invocation of it could be handled by any of the other three without causing a compile-time type error. All four methods are applicable to the first method invocation expression, m(null,null). The most specific method, m(B x, B y), is chosen; and both arguments are converted to type B. In the second method invocation expression, m(a1=null,b1=null), simple assignment expressions initialize the local variables a1 and b1 with null references of types A and B respectively. The invoked method is m(A x, B y). In the third method invocation expression, the positions of the arguments are reversed relative to the previous invocation: The type of the first argument is now B and the second is A. The invoked method is m(B x, A y). |
| 11 | c | Prints: m3Cm2Bm1A | The method invocation expression, m3(new C()), invokes method m3(C x), because the argument type matches the parameter type of the method declaration exactly. Method m3 uses the parameter as the argument of the next invocation expression, m2(x). Of the two overloaded versions of m2, the most specific is invoked, m2(B x). Type B is a subclass of A, so any invocation of m2(B x) could be handled by m2(A x) without causing a compile-time type error. For that reason, m2(B x) is more specific than m2(A x). |