SUN CERTIFIED PROGRAMMER FOR THE JAVA 2
PLATFORM 1.4
Available at: Authorized Prometric testing centres
Exam number: CX-310-035
Prerequisites: None
Exam type: Multiple choice and short answer
Number of questions: 61
Pass score: 52% (32 of 61 questions)
Time limit: 120 minutes
Cost: US$150, or as priced in the country where the exam is taken
Exam Objectives
1
DECLARATIONS AND ACCESS CONTROL
1.1 Write code that declares, constructs and initialises arrays of any base type using any of the permitted forms both for declaration and for initialisation.
1.2 Declare classes, nested classes, methods, instance variables, static variables and automatic (method local) variables making appropriate use of all permitted modifiers (such as public, final, static, abstract, etc.). State the significance of each of these modifiers both singly and in combination and state the effect of package relationships on declared items qualified by these modifiers.
1.3 For a given class, determine if a default constructor will be created and if so state the prototype of that constructor.
1.4 Identify legal return types for any method given the declarations of all related methods in this or parent classes.
2
FLOW CONTROL, ASSERTIONS, AND EXCEPTION HANDLING
2.1 Write code using if and switch statements and identify legal argument types for these statements.
2.2 Write code using all forms of loops including labeled and unlabeled, use of break and continue, and state the values taken by loop counter variables during and after loop execution.
2.3 Write code that makes proper use of exceptions and exception handling clauses (try, catch, finally) and declares methods and overriding methods that throw exceptions.
2.4 Recognize the effect of an exception arising at a specified point in a code fragment. Note: The exception may be a runtime exception, a checked exception, or an error (the code may include try, catch, or finally clauses in any legitimate combination).
2.5 Write code that makes proper use of assertions, and distinguish appropriate from inappropriate uses of assertions.
2.6 Identify correct statements about the assertion mechanism.
3 GARBAGE
COLLECTION
3.1 State the behaviour that is guaranteed by the garbage collection system.
3.2 Write code that explicitly makes objects eligible for garbage collection.
3.3 Recognize the point in a piece of source code at which an object becomes eligible for garbage collection.
4 LANGUAGE
FUNDAMENTALS
4.1 Identify correctly constructed package declarations, import statements, class declarations (of all forms including inner classes) interface
declarations, method declarations (including the main method that is used to start execution of a class), variable declarations, and identifiers.
4.2 Identify classes that correctly implement an interface where that interface is either java.lang.Runnable or a fully specified interface in the question.
4.3 State the correspondence between index values in the argument array passed to a main method and command line arguments.
4.4 Identify all Java programming language keywords. Note: There will not be any questions regarding esoteric distinctions between keywords and manifest constants.
4.5 State the effect of using a variable or array element of any kind when no explicit assignment has been made to it.
4.6 State the range of all primitive formats, data types and declare literal values for String and all primitive types using all permitted formats bases and representations.
5
OPERATORS AND ASSIGNMENTS
5.1 Determine the result of applying any operator (including assignment operators and instance of) to operands of any type class scope or accessibility or any combination of these.
5.2 Determine the result of applying the boolean equals (Object) method to objects of any combination of the classes java.lang.String,
java.lang.Boolean and java.lang.Object.
5.3 In an expression involving the operators &, |, &&, || and variables of known values state which operands are evaluated and the value of the expression.
5.4 Determine the effect upon objects and primitive values of passing variables into methods and performing assignments or other modifying operations in that method.
6
OVERLOADING, OVERRIDING, RUNTIME TYPE AND OBJECT
ORIENTATION
6.1 State the benefits of encapsulation in object oriented design and write code that implements tightly encapsulated classes and the relationships "is a" and "has a".
6.2 Write code to invoke overridden or overloaded methods and parental or overloaded constructors; and describe the effect of invoking these methods.
6.3 Write code to construct instances of any concrete class including normal top level classes and nested classes.
7 THREADS
7.1 Write code to define, instantiate and start new threads using both java.lang.Thread and java.lang.Runnable.
7.2 Recognize conditions that might prevent a thread from executing.
7.3 Write code using synchronized wait, notify and notifyAll to protect against concurrent access problems and to communicate between threads. 7.4 Define the interaction among threads and object locks when executing
synchronized wait, notify or notifyAll.
8
FUNDAMENTAL CLASSES IN THE JAVA.LANG PACKAGE
8.1 Write code using the following methods of the java.lang.Math class: abs, ceil, floor, max, min, random, round, sin, cos, tan, sqrt.
8.2 Describe the significance of the immutability of String objects.
8.3 Describe the significance of wrapper classes, including making appropriate selections in the wrapper classes to suit specified behavior requirements, stating the result of executing a fragment of code that includes an instance of one of the wrapper classes, and writing code using the following methods of the wrapper classes (e.g., Integer, Double, etc.):
doubleValue floatValue intValue longValue parseXxx getXxx toString toHexString
9
THE COLLECTIONS FRAMEWORK
9.1 Make appropriate selection of collection classes/interfaces to suit specified behaviour requirements.
9.2 Distinguish between correct and incorrect implementations of hashcode methods.
1. Which two create an instance of an array? (Choose two.) A. int[ ] ia = new int[15];
B. float fa = new float[20]; C. char[ ] ca = "Some String"; D. Object oa = new float[20]; E. int ia[ ] [ ] = { 4, 5, 6 }, { 1,2,3 }; Answer: AD
Explanation: An array must be declared and constructed before it can be used. An array variable declaration has either the following syntax:
<elementType>[ ] <arrayName>; or
<elementType> <arrayName>[ ];
Once an array has been declared it can be constructed for a specific number of elements of the element data type, using the new operator. The resulting array can be assigned to a variable of the corresponding type:
<arrayName> = new <elementType>[<noOfElements>];
The minimum value of <noOfElements> is 0, i.e. arrays with zero elements can be constructed in Java.
The array declaration and construction can be combined:
<elementType1> <arrayName>[ ] = new <elementType2>[<noOfElements>]; However, here array type <elementType2> must be assignable to array type
<elementType1>. When the array is constructed, all its elements are initialised to the default value for <elementType2>. This is true for both member and local arrays when they are constructed.
Java provides the means of declaring, constructing and explicitly initialising an array in one language construct:
<elementType>[ ] <arrayName> = { <arrayInitializerCode> };
This form of initialisation applies to both members as well as local arrays. The
initialisation code in the block results in the construction and initialisation of the array. For example the following array, anIntArray, is declared as an array of ints. It is constructed to hold 10 elements (equal to the number of items in the comma-separated list in the block), where the first element is initialised to 1, the second element to 3, and so on.
int[ ] anIntArray = {1, 3, 49, 2, 6, 7, 15, 2, 1, 5};
In summary, an array type is written as the name of an element type followed by some number of empty pairs of square brackets [ ]. The number of bracket pairs indicates the depth of array nesting. An array's length is not part of its type. The element type of an array may be any type, whether primitive or reference.
A is correct. It uses correct array declaration and correct array construction.
B is incorrect. It generates a compiler error: incompatible types because the array variable declaration is not correct. The array construction expects a reference type, but it is supplied with a primitive type in the declaration. This is why B doesn’t work and why D does work. It would compile if it was changed to any of the following:
(i) float fa[ ] = new float[20]; (ii) float fa[];
…
fa = new float[20];
(iii) float[] fa = new float[20]; (iv) float[] fa;
…
fa = new float[20];
C is incorrect. It generates a compiler error: incompatible types because a string literal is not assignable to a character type variable.
The following is a suggested solution that compiles correctly (if an array of characters was required):
char[ ] ca = {'S','o','m','e',' ','S','t','r','i','n','g'}; The following is a suggested solution that compiles correctly (if an array of strings was required):
String[ ] ca = {"Some String"};
In both of the above, the data type returned by the array construction are of the correct data type to initialise the elements of array ca.
D is correct. All classes directly or indirectly extend the Object class. The Object class is the root of every inheritance hierarchy. The Object class defines the basic functionality that all objects exhibit and which all classes inherit. This also applies for array, since arrays are genuine objects in Java. My opinion is that this is allowed because the rule of thumb for converting reference values is that conversions up the inheritance hierarchy are allowed (upcasting), but conversions down the hierarchy require explicit casting (downcasting). That is, conversions that preserve the inheritance is-a relationship (an array is-a object) are allowed.
E is wrong, it generates a compiler error <identifier> expected. The compiler thinks that you are trying to create two arrays because there are two array initialisers to the right of the equals, whereas your intention was to create a 3 x 3 two-dimensional array. To correct the problem and make E compile you need to add an extra pair of curly brackets:
int ia[ ] [ ] = { { 4, 5, 6 }, { 1,2,3 } }; Source code file: ArrayTest01.java
2. Given:
01. public class ArrayTest {
02. public static void main(String[ ] args){
03. float f1[ ], f2[ ]; 04. f1 = new float[10]; 05. f2 = f1; 06. System.out.println("f2[0] = " + f2[0]); 07. } 08. }
What is the result? A. It prints f2[0] = 0.0 B. It prints f2[0] = NaN
C. An error at line 5 causes compile to fail. D. An error at line 6 causes compile to fail.
E. An error at line 6 causes an exception at runtime. Answer: A
Explanation:
When you create an array (line 04) the elements are initialises to the default values for the primitive data type (float in this case - 0.0), so f1 will contain 10 elements each with a value of 0.0. f2 has been declared but has not been initialised, it has the ability to reference or point to an array but as yet does not point to any array. Line 05 copies the reference (pointer/memory address) of f1 into f2 so now f2 points at the array pointed to by f1. This means that the values returned by f2 are the values returned by f1. Changes to f1 are also changes to f2 because both f1 and f2 point to the same array. The following code illustrates this point: 01 public class ArrayTest02d {
02 public static void main(String[] args){
03 float f1[], f2[];
04 f1 = new float[10];
05 for(int i = 0; i < 10; i++) f1[i] = i + 5; // init the array
06 f2 = f1; 07 System.out.println("f2[0] = " + f2[0]); // outputs 5.0 08 f1[0] = 99.99f; 09 System.out.println("f2[0] = " + f2[0]); // outputs 99.99 10 } 11 }
The following is a discussion on Not-a-Number (NaN). The Java Language Specification 2
The floating-point types are float and double, which are conceptually associated with the single-precision 32-bit and double-single-precision 64-bit format IEEE 754 values and operations.
The IEEE 754 standard includes not only positive and negative numbers that consist of a sign and magnitude, but also positive and negative zeros, positive and negative infinities, and special Not-a-Number values (also abbreviated as NaN). A NaN value is used to represent the result of certain invalid operations such as dividing zero by zero. NaN constants of both float and double type are predefined as Float.NaN and Double.NaN.
For the most part, the Java platform treats NaN values of a given type as though
collapsed into a single canonical value (and hence this specification normally refers to an arbitrary NaN as though to a canonical value). However, version 1.3 the Java platform introduced methods enabling the programmer to distinguish between NaN values: the Float.floatToRawIntBits and Double.doubleToRawLongBits methods. Refer to the
specifications for the Float and Double classes for more information. In English
the two floating-point types are float and double, they conform to the IEEE 754
specification. Many mathematical operations can yield results that have no expression in numbers (infinity, for example). To describe such non-numerical situations, both doubles and floats can take on values that are bit patterns that do not represent numbers. Rather, these patterns represent non-numerical values. The patterns are defined in the Float and Double classes and may be referenced as follows (NaN stands for Not a Number):
Float.NaN Float.NEGATIVE_INFINITY Float.POSITIVE_INFINITY Double.NaN Double.NEGATIVE_INFINITY Double.POSITIVE_INFINITY The code below shows the use of these constants: 01 public class ArrayTest02a {
02 public static void main(String[] args) {
03 double d = -10.0 / 0.0;
04 if (d == Double.NEGATIVE_INFINITY) {
05 System.out.println( "d just exploded: " + d);
06 }
07 }
08 }
In this code fragment, the test on line 04 passes, so line 05 is executed.
There is a significance associated with the NaN values. NaN values are used to indicate that a calculation has no result in ordinary arithmetic, such as some calculations involving infinity or the square root of a negative number.
Two Nan values are defined in the java.lang package (Float.Nan and Double.Nan) and are considered non-ordinal for comparisons. This means that for any value of x, including NaN itself, all of the following comparisons will return false:
x < Float.NaN x <= Float.NaN x == Float.NaN x > Float.NaN x >= Float.NaN In fact, the test
Float.NaN != Float.NaN
and the equivalent with Double.NaN return true, as you might deduce from the item above indicating that x == Float.NaN gives false even if x contains Float.NaN. The most appropriate way to test for a NaN result from a calculation is to use the Float.isNaN(float) or Double.isNaN(double) static methods provided in the java.lang package.
Source code files: ArrayTest02.java ArrayTest02a.java ArrayTest02b.java ArrayTest02c.java ArrayTest02d.java
3. Which two cause a compiler error? (Choose two.) A. int[ ] scores = {3, 5, 7};
B. int [ ][ ] scores = {2,7,6}, {9,3,45}; C. String cats[ ] = {"Fluffy", "Spot", "Zeus"};
D. boolean results[ ] = new boolean [3] {true, false, true};
E. Integer results[ ] = {new Integer(3), new Integer(5), new Integer(8)};
F. String[ ] dogs = new String[ ] {new String("Fido"), new String("Spike"), new String("Aiko")}; Answer: BD
Explanation: Read the explanations below in conjunction with those given for question 1.
A does not cause a compiler error. Java provides the means of declaring, constructing and explicitly initialising an array in one language construct:
<elementType>[ ] <arrayName> = { <arrayInitializerCode> };
This form of initialisation applies to both members as well as local arrays. The
initialisation code in the block results in the construction and initialisation of the array. For example the following array, anIntArray, is declared as an array of ints. It is constructed to hold 10 elements (equal to the number of items in the comma-separated list in the block), where the first element is initialised to 1, the second element to 3, and so on.
int[ ] anIntArray = {1, 3, 49, 2, 6, 7, 15, 2, 1, 5};
B generates a compiler error: <identifier> expected. The compiler thinks you are trying to create two arrays because there are two array initialisers to the right of the equals, whereas your intention was to create one 3 x 3 two-dimensional array. To correct the problem and make B compile you need to add an extra pair of curly brackets:
int [ ] [ ] scores = { {2,7,6}, {9,3,45} };
C does not cause a compiler error. See the explanation above for A.
D generates a compiler error: ';' expected. You cannot initialise an array in this manner because you are declaring the number of elements in two different places, between the brackets [3] and in the block {true, false, true}. Rewrite the line as follows to make it compile:
boolean results[ ] = {true, false, true}; or
boolean results[ ] = new boolean [ ] {true, false, true}; also works. Also see the explanation above for A.
E compiles correctly. This code creates an array of arrays - it creates a one-dimensional array and initialises each element of this array according to the code in the block. See the explanation above for A.
F compiles correctly. This code creates an array of string objects - it creates a one-dimensional array and initialises each element of this array according to the code in the block. See the explanation above for both A and D.
Source code file: ArrayTest03.java
4. Which three form part of correct array declarations? (Choose three.) A. public int a [ ] B. static int [ ] a C. public [ ] int a D. private int a [3] E. private int [3] a [ ] F. public final int [ ] a Answer: A, B, F
Explanation:
An array declaration tells the compiler the array’s name and what type its elements will be not the number of elements in the array.
A, B and F are valid array declarations.
C is not a correct array declaration. The compiler complains with: illegal start of type. The brackets are in the wrong place. The following would work:
public int[ ] a
D is not a correct array declaration. The compiler complains with: ']' expected. A closing bracket is expected in place of the 3. The following works:
private int a []
An array declaration tells the compiler the array’s name and what type its elements will be not the number of elements in the array.
E is not a correct array declaration. The compiler complains with 2 errors: ']' expected
A closing bracket is expected in place of the 3 and
<identifier> expected
A variable name is expected after a[ ]
An array declaration tells the compiler the array’s name and what type its elements will be not the number of elements in the array. The following would work:
private int[ ][ ] a
Source code file: ArrayTest04.java
5. Which two cause a compiler error? (Choose two.) A. float[ ] f = new float(3);
B. float f2[ ] = new float[ ]; C. float[ ]f1 = new float[3]; D. float f3[ ] = new float[3]; E. float f5[ ] = {1.0f, 2.0f, 2.0f};
F. float f4[ ] = new float[ ] {1.0f, 2.0f, 3.0f}; Answer: AB
Explanation:
A causes two compiler errors ( '[' expected and illegal start of
expression) because the wrong type of bracket is used, ( ) instead of [ ]. The following is the correct syntax:
float[ ] f = new float[3];
B causes a compiler error ( '{' expected ) because the array constructor does not specify the number of elements in the array. The following is the correct syntax: float f2[ ] = new float[3];
C, D, E and F compile without error.
Source code file: ArrayTest04.java
6. Given:
12. float f[ ][ ][ ] = new float[3][][]; 13. float f0 = 1.0f;
14. float[ ][ ] farray = new float[1][1]; Which is valid? A. f[0] = f0; B. f[0] = farray; C. f[0] = farray[0]; D. f[0] = farray[0][0]; Answer: B Explanation:
A is incorrect. It results in the compiler error: incompatible types found float required float[][]. This means that f[0] is not the same data type as f0, and, they are not. f[0] is an array element that stores a reference to another array and you cannot assign a primitive value (the float f0) to a reference value.
B is correct. You can assign one reference type to another. f[0] is a reference to a two dimensional array, farray is also a reference to a two dimensional array therefore farray can be assigned to f[0].
C is incorrect. It results in the compiler error: incompatible types found float[] required[][].You can assign one reference type to another. f[0] is a reference to a two dimensional array, farray[0] is reference to a one dimensional array therefore farray[0] cannot be assigned to f[0].
D is incorrect. It results in the compiler error: incompatible types found float required float[][].You can assign one reference type to another. f[0] is a reference to a two dimensional array, farray[0][0] is not a reference - it is a float therefore the float value stored in farray[0][0] cannot be assigned to the reference f[0].
Source code file: ArrayTest06.java
7. Given:
01. public abstract class Test {
02. public abstract void methodA(); 03.
04. public abstract void methodB()
05. {
06. System.out.println("Hello");
07. }
08. }
Which two changes, independently applied, allow this code to compile? (Choose two.) A. add a method body to methodA
B. replace lines 5 -7 with a semicolon (";")
C. remove the abstract qualifier from the declaration of Test D. remove the abstract qualifier from the declaration of methodA E. remove the abstract qualifier from the declaration of methodB Answer: BE
Explanation: Read this question carefully. How would you interpret the question if it had stated “simultaneously applied” rather than “independently applied”?
I read this question as five different/separate/independent questions:
1). “If A is applied to the code as given will it allow the code to compile. 2). “If B is applied to the code as given will it allow the code to compile. 3). “If C is applied to the code as given will it allow the code to compile. 4). “If D is applied to the code as given will it allow the code to compile. 5). “If E is applied to the code as given will it allow the code to compile. Now which two of the above will allow the code to compile.
To business, compiling the code as supplied generates a compiler error: abstract methods cannot have a body
A is incorrect. If you add a method body to methodA you just get the compiler error message given above for both methodA and methodB.
B is correct. This turns methodB into an abstract method and eliminates all compiler errors.
C is incorrect. An abstract class is a class that has one or more abstract methods and methodA is an abstract method.
D is incorrect. This causes the compiler error: missing method body, or declare abstract. This is self-explanatory.
E is correct. This makes methodB into an ordinary method.
Source code file: ArrayTest06.java
8. You want subclasses in any package to have access to members of a superclass. Which is the most restrictive access that accomplishes this objective?
A. public B. private C. protected D. transient E. default access Answer: C
Explanation: Access modifiers dictate which classes, not which instances, may access features.
Methods and variables are collectively known as members. Method and variable members are given access control in exactly the same way.
private makes a member accessible only from within its own class
protected makes a member accessible only to classes in the same package or subclass of the class
default access is very similar to protected (make sure you spot the difference) default access makes a member accessible only to classes in the same package
public means that all other classes regardless of the package that they belong to, can access the member (assuming the class itself is visible)
final makes it impossible to extend a class, when applied to a method it prevents a method from being overridden in a subclass, when applied to a variable it makes it impossible to reinitialise a variable once it has been initialised
abstract declares a method that has not been implemented
transient indicates that a variable is not part of the persistent state of an object volatile indicates that a thread must reconcile its working copy of the field with the master copy every time it accesses the variable
After examining the above it should be obvious that the access modifier that provides the most restrictions for methods to be accessed from the subclasses of the class from another package is C – protected. A is also a contender but C is more restrictive, B would be the answer if the constraint was the “same package” instead of “any package” in other words the subclasses clause in the question eliminates default.
Source code file:
9. You want a class to have access to members of another class in the same package. Which is the most restrictive access that accomplishes this objective?
A. public B. private C. protected D. transient E. default access Answer: E
Explanation: The only two real contenders are C and E. Protected access (C) makes a member accessible only to classes in the same package or subclass of the class. While default access (E) makes a member accessible only to classes in the same package. Review the explanation for question 8 for more information.
Source code file:
10. You want to limit access to a method of a public class to members of the same class. Which access accomplishes this objective?
A. public B. private C. protected D. transient E. default access Answer: B
Explanation: Review the explanations for questions 8 and 9 for more information. Source code file:
11. Given:
01. public class Test {
02. public static void main(String args[]) {
03. class Foo {
04. public int i = 3;
05. }
06. Object o = (Object)new Foo();
07. Foo foo = (Foo)o;
08. System.out.println("i = " + foo.i);
09. }
10. }
What is the result? A. i =3
B. Compilation fails.
C. A ClassCastException is thrown at line 6. D. A ClassCastException is thrown at line 7. Answer: A
Explanation:
B is not correct because the code compiles and runs ok.
C is not correct because you can always cast up the hierarchy tree.
D is not correct because o is a reference of type Object that points to a Foo object therefore Foo can be cast to a reference type of Foo.
Source code file: Test11.java and Test11a.java
12. Given:
01. abstract class AbstractIt { 02. abstract float getFloat(); 03. }
04. public class AbstractTest extends AbstractIt { 05. private float f1 = 1.0f;
06. private float getFloat() { return f1; } 07. }
What is the result?
A. Compilation succeeds B. An exception is thrown
C. Compilation fails because of an error at line 2 D. Compilation fails because of an error at line 6 Answer: D
Explanation:
I got errors at line 4 – Class AbstractTest is public, should be declared in a file named Abstract Test.java
And at line 6 – Abstract Test cannot override getFloat() in AbstractIt, attempting to assign weaker access privileges. This is probably the point of the question. The private on line 06 is more restrictive than the default access on line 02.
Compilation fails so that rules out answers A and B. Line 2 compiles OK, ruling out answer C. So, by default the answer must be D.
Source code file:
13 Given:
01. public class OuterClass { 02. private double d1 = 1.0; 03. // insert code here 04. }
Which two are valid if inserted at line 3 (Choose two) A. static class InnerOne {
public double methoda() { return d1; } }
B. static class InnerOne {
static double methoda() { return d1; } }
C. private class InnerOne {
public double methoda() { return d1; } }
D. protected class InnerOne {
static double methoda() { return d1; } }
E. public abstract class InnerOne { public abstract double methoda(); }
Answer: C, E
Explanation:
A, B and D are incorrect because the non-static variable d1 cannot be referenced from a static context. Static inner classes do not have any reference to an enclosing instance, therefore you cannot use the this keyword, either implied or explicit.
Source code file: OuterClass13.java
14. Click on the Exhibit button 01. public class Test {
02. public int aMethod() {
03. static int i = 0;
04. i++;
05. return i;
06. }
07. public static void main(String args[]) {
08. Test test = new Test();
09. test.aMethod();
10. int j = test.aMethod();
11. System.out.println(j);
12 }
13. }
What is the result? A. 0
B. 1 C. 2
D. Compilation fails Answer: D
Explanation: Compilation failed because static was an illegal start of expression - method variables do not have a modifier (they are always considered local). Two more errors followed on from this saying on both occasions cannot resolve symbol.
Now, if the line 03 from the code was moved from the method to the class (see code below) then C would be the correct answer.
public class Test14a {
static int i = 0;
public int aMethod() {
i++;
return i;
}
public static void main(String args[]) {
Test14a test = new Test14a();
test.aMethod();
int j = test.aMethod();
System.out.println(j);
}
}
Source code file: Test14.java Test14a.java
15. Click on the Exhibit button ClassOne.java:
01. package com.abc.pkg1; 02. public class ClassOne { 03. private char var = 'a';
04. char getVar() { return var; } 05. }
ClassTest.java:
01. package com.abc.pkg2;
02. import com.abc.pkg1.ClassOne;
03. public class ClassTest extends ClassOne { 04. public static void main(String[] args) {
05. char a = new ClassOne.getVar();
06. char b = new ClassOne.getVar();
07. }
08. } What is the result?
A. Compilation fails
B. Compilation succeeds and no exceptions are thrown C. An exception is thrown at line 5 in ClassTest.java D. An exception is thrown at line 6 in ClassTest.java Answer: A
Explanation:
It wouldn’t compile giving two errors:
Cannot resolve symbol in line 5 char a = new ClassOne.getVar(); Cannot resolve symbol in line 6 char b = new ClassOne.getVar(); If lines 5 and 6 are amended:
line 5: char a = new ClassOne().getVar(); line 6: char b = new ClassOne().getVar();
then the compilation still fails because getVar() has default access and not public or protected. Default allows package access but does not allow access from a sub-class while protected and public do. In this case, this is the reason that compilation fails. Another clue is that the package details are given.
Source code file:
16. Given:
01. package test1; 02. public class Test1 { 03. static int x = 42; 04. }
01. package test2;
02. public class Test2 extends test1.Test1 { 03. public static void main(String[] args) { 04. System.out.println("x = "+x);
05. }
06. }
What is the result? A. x = 0
B. x = 42
C. Compilation fails because of an error in line 2 of class Test2 D. Compilation fails because of an error in line 3 of class Test1 E. Compilation fails because of an error in line 4 of class Test2 Answer: E
Explanation: I got an error in line 4 saying, x is not public in Test1. Test1 cannot be accessed from outside package System.out.println(“x = ” + x);
Think it through:
► What access modifier is needed to access a class member in another package? (Answer: public / protected.)
► What is the access modifier for x? (Answer: default.)
► What is the scope of default? (Answer: current package and not including sub classes.)
From the compile error, in this case, it must be public/protected. However if you make the variable x in Test1 public static, then all the code compiles and the number 42 is output.
Source code file: Test16.java Test16a.java
17. Given
01. public class Outer {
02. public void someOuterMethod() {
03. //Line 3
04. }
05. public class Inner { }
06. public static void main(String[] argv) {
07. Outer o = new Outer();
08. //Line 8
09. }
10. }
Which instantiates an instance of inner? A. new Inner(); //At line 3
B. new Inner(); //At line 8 C. new o.Inner(); //At line 8 D. new Outer.Inner(); //At line 8 Answer: A
Explanation:
A compiles without problem
B gives error – non-static variable cannot be referenced from a static context C package o does not exist
D gives error – non-static variable cannot be referenced from a static context Source code file: Outer.java
18. Click the Exhibit button 01. class Super{
02. public int i = 0; 03.
04. public Super(String text){
05. i = 1;
06. }
07. } 08.
09. class Sub extends Super{ 10. public Sub(String text){
11. i = 2;
12. }
13.
14. public static void main(String args[]){ 15. Sub sub = new Sub("Hello");
16. System.out.println(sub.i);
17. }
18. }
What is the result? A. 0
B. 1 C. 2
D. Compilation fails. Answer: D
Explanation: A default no-args constructor is not created because there is a constructor
supplied that has an argument, line 04. Therefore the sub-class constructor must explicitly make a call to the super class constructor:
10. public Sub(String text){
11. super(text); // this must be the first line constructor
12. i = 2;
13. }
Source code file: Super18.java
19. Which three statements are true? (Choose three.) A. The default constructor initialises method variables. B. The default constructor has the same access as its class.
C. The default constructor invokes the no-arg constructor of the superclass.
D. If a class lacks a no-arg constructor, the compiler always creates a default constructor. E. The compiler creates a default constructor only when there are no other constructors for
the class. Answer: B, C, E
Explanation:
A is the wrong answer because the default constructor does not initialise method
variables. If you want to perform some initialisation you will have to write some constructors for your class.
B sounds correct as in the example below
class CoffeeCup {
private int innerCoffee; public CoffeeCup() {
}
public void add(int amount) {
innerCoffee += amount;
}
//...
}
The compiler gives default constructors the same access level as their class. In the example above, class CoffeeCup is public, so the default constructor is public. If CoffeeCup had been given package access, the default constructor would be given package access as well.
C is correct. The Java compiler generates at least one instance initialisation method for
every class it compiles. In the Java class file, the instance initialisation method is named "<init>." For each constructor in the source code of a class, the Java compiler generates one <init>() method. If the class declares no constructors explicitly, the compiler
generates a default no-arg constructor that just invokes the superclass's no-arg
constructor. As with any other constructor, the compiler creates an <init>() method in the class file that corresponds to this default constructor.
D is wrong because the compiler does not always create a default constructor the main reason being that the compiler will not do so if a constructor is already declared by the programmer.
E is correct. The compiler creates a default constructor if you do not declare any
constructors in your class. Source code file:
20. Given
01. class TestSuper{
02. TestSuper(int i) {} 03. }
04. class TestSub extends TestSuper{} 05. class TestAll{
06. public static void main(String[] args){
07. new TestSub();
08. }
09. }
A. Compilation fails
B. The code runs without exception C. An exception is thrown at line 7 D. An exception is thrown at line 2 Answer: A
Explanation: The code does not compile therefore the correct answer is A (the compiler cannot resolve the constructor TestSuper())
TestSub doesn’t have a constructor therefore the default constructor for TestSub calls the no-args constructor of the superclass(TestSuper), but TestSuper doesn’t have a no-args constructor because it already has a constructor with arguments
The code will compile and run if you do something like the following: class TestSuper{
TestSuper(int i) {} }
class TestSub extends TestSuper{ TestSub() { super(12); } }
class TestAll{
public static void main(String[] args){
new TestSub();
}
}
Source code file:
21. Given
01. class Base{
02. Base(){System.out.print("Base");} 03. }
04. public class Alpha extends Base{
05. public static void main(String[] args){
06. new Alpha();
07. new Base();
08. }
09. }
What is the result? A. Base B. BaseBase C. Compilation fails
D. The code runs with no output E. An exception is thrown at runtime Answer: B
Explanation:
A is wrong. It would be correct if either the main class or the subclass had not been
instantiated.
B is correct. It would be correct if the code had compiled, and the subclass Alpha had
been saved in its own file. In this case Java supplies an implicit call from the sub-class constructor to the no-args constructor of the super-class therefore line 06 causes Base to be output. Line 07 also causes Base to be output
C is wrong. The code compiles. D is wrong. There is output output.
E is wrong. Because there are no errors in the code. Source code file: Alpha.java
22. Which two allow the class Thing to be instantiated using new Thing( )? (Choose two.) A. public class Thing {
}
B. public class Thing { public Thing() {} }
C. public class Thing { public Thing(void) {} }
D. public class Thing {
public Thing(String s) {} }
E. public class Thing { public void Thing() {} public Thing(String s) {} }
Answer: AB
Explanation:
A is correct because the compiler will add its own default constructor.
public class Thing{
}
class NextThing{
public static void main(String [] args){
new Thing();
}
}
B is correct because the programmer has added a constructor to the code. C is not correct. The compiler generates an error: illegal start of type.
D is not correct. The code compiles when a string is added to the parameter.
public class Thing{
public Thing(String s){}
}
class NextThing{
public static void main(String [] args){ Thing c1 = new Thing("hello");
}
}
But the question specifies new Thing( ) not new Thing(“Some king of string”), so this is wrong.
E is not correct. This code compiles correctly, but, any code that tries to use the public void Thing() {} constructor will generate a compiler error (cannot resolve symbol) because of the void keyword. Constructors do not have a return type, we are dealing here with a method and not a constructor.
Source code files: Thing22a.java, NextThing22a.java Thing22b.java, NextThing22b.java Thing22c.java
Thing22d.java, NextThing22d.java Thing22e.java, NextThing22e.java
23. Given: 01. class A { 02. A( ) { } 03. } 04. 05. class B extends A { 06. }
Which two statements are true? (Choose two.) A. Class B'S constructor is public.
B. Class B'S constructor has no arguments. C. Class B'S constructor includes a call to this( ). D. Class B'S constructor includes a call to super( ). Answer: B, D
Explanation:
A is wrong. Class B inherits Class A’s constructor which uses default access. B is correct. Class B inherits Class A’s constructor which has no arguments. C is wrong. There is just no implicit call to this( ).
D is correct. There is an implicit call to super( ) added by the compiler.
class A{ A() { System.out.println("Constructing A. "); } } class B extends A { B() { System.out.println("Constructing B. "); } } class OrderOfConstruction {
public static void main(String args[]) { B b = new B();
} }
This code compiles and runs whether B( ) is included or not. Source code files:
The following is a summary of the key points about constructors: 1) The constructor name must match the name of the class. 2) Constructors must not have a return type.
3) It’s legal (but stupid) to have a method with the same name as the class, but that doesn’t make it a constructor. If you see a return type, it’s a method rather than a constructor.
4) Constructors are not inherited in the same way as normal methods. You can only create an object if the class defines a constructor with an argument list that matches the one your new call provides.
5) If you define no constructor in a class, then the compiler provides a default that takes no arguments. If you define even a single constructor, this default is not provided. The default constructor is always a no-arg constructor. If you want a no-arg constructor and you’ve typed any other constructor(s) into your class code, the compiler won’t provide the no-arg constructor (or any other constructor) for you. In other words, if you’ve typed in a constructor with arguments, you won’t have a no-arg constructor unless you type it in yourself !
6) The default constructor:
Has the same access modifier as the class. Has no arguments.
Includes a no-arg call to the super constructor (super()).
7) It is common to provide multiple overloaded constructors – that is, constructors with different argument lists. One constructor can call another using the syntax
this(arguments).
8) A constructor delays running its body until the parent parts of the class have been initialised. This commonly happens because of an implicit call to super( ) (no-arg) added by the compiler. You can provide your own call to super(arguments) to control the way the parent parts are initialised. If you do so, it must be the first statement of the constructor. You cannot make a call to an instance method, or access an instance variable, until after the super constructor runs.
9) A constructor can use overloaded constructor versions to support its work. These are invoked using the syntax this(arguments) and if supplied, this call must be the first statement of the constructor. In such conditions, the initialization of the parent class is performed in the overloaded constructor.
10) The only way a constructor can be invoked is from within another constructor. In other words, you can’t write code that actually calls a constructor as follows:
class Horse {
Horse() { } // constructor
void doStuff() {
Horse(); // calling the constructor - illegal!
}
}
11) Every constructor must have as its first statement either a call to an overloaded constructor (this()) or a call to the superclass constructor (super()).
12) A no-arg constructor is not necessarily the default constructor, although the default constructor is always a no-arg constructor. The default constructor is the one the compiler provides! While the default constructor is always a no-arg constructor, you’re free to put in your own no-arg constructor.
13) You can access static variables and methods, although you can use them only as part of the call to super() or this(). (Example: super(Animal.DoThings()))
14) Abstract classes have constructors, and those constructors are always called when a concrete subclass is instantiated.
15) Interfaces do not have constructors. Interfaces are not part of an object’s inheritance tree.
16) The following modifiers are the only ones that can be applied to constructors: public
protected
(default) – not a modifier but the name of the access if no modifier is specified private - means only code within the class itself can instantiate an object of that type, so if the private-constructor class wants to allow an instance of the class to be used, the class must provide a static method or variable that allows access to an instance created from within the class.
24. Given:
1. public class Test { }
What is the prototype of the default constructor? A. Test( )
B. Test(void) C. public Test( ) D. public Test(void) E. public void Test( ) Answer: C
Explanation:
A and B are wrong because they use the default access modifier and the access
modifier for the class is public (remember, the default constructor has the same access modifier as the class).
C is correct. Just because it is.
D is wrong. The void makes the compiler think that this is a method specification – in fact
if it were a method specification the compiler would spit it out.
E is wrong because this is a method prototype (specification) with the method name the
same as the class name – stupid. You know it is a method because it specifies a return type and constructors do not return anything – not even void.
Source code files: Test24.java, Tester24.java
25. In which two cases does the compiler supply a default constructor for class A? (Choose two.) A. class A { } B. class A { public A( ) { } } C. class A { public A(int x) { } } D. class Z { } class A extends Z { void A( ) { } } Answer: A, D
Explanation: If you define no constructor in a class, then the compiler provides a default no-args constructor. If you define even a single constructor, this default is not provided.
A is correct. No constructor is programmed so the compiler supplies the default.
B is wrong. The default constructor is not supplied because the programmer has defined
a constructor.
C is wrong. The default constructor is not supplied because the programmer has defined
a constructor.
D is correct. No constructor is programmed so the compiler supplies the default
(void A( ) { } is a method specification). Source code files: A.java, B.java, C.java, Z.java
26. What produces a compiler error? A. class A { public A(int x) { } } B. class A { } class B extends A { B( ) {} } C. class A { A( ) { } } class B { public B( ) {} } D. class Z { public Z(int) {} } class A extends Z { } Answer: D Explanation:
A is wrong because it compiles correctly. Class A has a constructor supplied – that’s
fine.
B is wrong because it compiles correctly. Class A has no constructor so the compiler will
supply a default no-arg constructor. Class B extends class A and it has a constructor, now, the compiler will automatically supply the constructor in B with an implicit call to super( ) (no-arg) and this will call the default constructor for A.
C is wrong because it compiles correctly. Both classes have constructors. They don’t
interfere with each other in any way, that’s OK.
D is correct. It does not compile. Class Z has a constructor supplied therefore it has no
default constructor. Class A extends Z and has no constructor supplied therefore the compiler will supply a default constructor. Now, the default constructor: includes a no-arg call to the super constructor (super( )), but because class Z has no default constructor we get a compiler error. Equally you could argue that the compiler error is generated
because the class Z constructor specification does not supply an identifier, if corrected it could look like this: public Z(int xyz) {}.
Source code file: Zd26.java
27. Given:
01. public class A{
02. void A() {
03. System.out.println("Class A");
04. }
05. public static void main(String[] args) {
06. new A();
07. }
08. }
What is the result? A. Class A
B. Compilation fails.
C. An exception is thrown at line 2. D. An exception is thrown at line 6. E. The code executes with no output. Answer: E
Explanation: A is wrong. B is wrong.
C is wrong. The code runs without exception. D is wrong. The code runs without exception.
E is correct. The specification at line 2 is for a method and not a constructor and this method is never called therefore there is no output. The constructor that is called is the default constructor.
Source code file: A27.java
28. Given:
01. public class ReturnIt {
02. returnType methodA(byte x, double y) {
03. return (long)x / y * 2;
04. }
05. }
What is the narrowest valid returnType for methodA in line 2? A. int B. byte C. long D. short E. float F. double Answer: F
Explanation: However A, B, C, D and E are all wrong. Each of these would result in a narrowing conversion. Whereas we want a widening conversion, therefore the only correct answer is F. Don’t be put off by the long cast, this applies only to the variable x and not the rest of the expression. It is the variable y (of type double) that forces the widening conversion to double.
Java’s widening conversions are:
- From a byte to a short, an int, a long, a float, or a double. - From a short, an int, a long, a float, or a double.
- From a char to an int, a long, a float, or a double. - From an int to a long, a float, or a double. - From a long to a float, or a double. - From a float to a double.
Source code file: ReturnIT28.java
29. Given:
01. public class ReturnIt {
02. returnType methodA(byte x, double y) {
03. return (short)x / y * 2;
04. }
05. }
What is the narrowest valid returnType for methodA in line 2? A. int B. byte C. long D. short E. float F. double Answer: F
Explanation: See the explanation for question 28. Source code file: ReturnIt29.java
30. Given:
01. class Super {
02. public float getNum( ) { return 3.0f; } 03. }
04.
05. public class Sub extends Super { 06.
07. }
Which method, placed at line 6, causes compilation to fail? A. public void getNum( ) { }
B. public void getNum(double d) { } C. public float getNum( ) { return 4.0f; }
D. public double getNum(float d) { return 4.0d; } Answer: A
Explanation:
The signature of a method consists of the name of the method and the number and types of formal parameters to the method. A class may not declare two methods with the same signature, or a compile-time error occurs.
Java requires that overriding methods in a sub class MUST have :-
a) The same signature as the overridden method in the super class. (i.e. the same name as the method in the super class and the same arguments as the method in the super class)
b) The same return type as the method in the super class (unless the method in the super class is “private”)
c) If the overridden or hidden method has default (package) access, then the overriding or hiding method must not be private ; otherwise, a compile-time error occurs. (JLS 8.4.6.3)
Permitted variations in overriding method definition –
d) the subclass (overriding) method may NOT be more private than the superclass (overridden) method but may be less. (Boone & Stanek p. 210) (JLS 8.4.6.3)
e) the subclass method cannot add Exception types to those defined in the superclass method declaration.
f) Overloaded Methods. If two methods of a class (whether both declared in the same class, or both inherited by a class, or one declared and one inherited) have the same name but different signatures, then the method name is said to be overloaded. This fact causes no difficulty and never of itself results in a compile-time error. There is no required relationship between the return types or between the throws clauses of two methods with the same name but different signatures. (JLS 8.4.7) Overloaded methods let you reuse the same method name in a class, but with different arguments (and optionally, a different return type). Overloading a method often means you’re being a little nicer to those who call your methods, because your code takes on the burden of coping with different argument types rather than forcing the caller to do conversions prior to invoking your method. The rules are simple:
Overloaded methods must change the argument list. Overloaded methods can change the return type. Overloaded methods can change the access modifier.
Overloaded methods can declare new or broader checked exceptions. A method can be overloaded in the same class or in a subclass. The following table gives some examples of illegal overrides:
Illegal Override Code Problem with the Code
private void eat() { } Access modifier is more restrictive public void eat() throws IOException { } Declares a checked exception not declared
by superclass version
public void eat(String food) { } A legal overload, not an override, because the argument list changed
public String eat() { } Not an override because of the return type, but not an overload either because there’s no change in the argument list
Answer A fails to compile. Because of incompatible return type. The return type in the
super class is float and the return type in A is void. It fails point b) above. In other words, it is not an override because of the change in the return type and it is also not an overload because the argument list has not changed.
Answer B – compiled. This is not an override because of the change in the return type,
the compiler considers this to be an overloaded method because the argument list has changed.
Answer C – compiled. Standard overriding - overrides the super class method, changing
the implementation.
Answer D – compiled. This is not an override because of the change in the return type,
the compiler considers this to be an overloaded method because the argument list has changed.
NOTE – as given compilation fails in any case –
Super.java:5: class Sub is public, should be declared in a file named Sub.java
public class Sub extends Super{ In order to compile anything –
1) make both classes access default. 2) make Super public and Sub default 3) make both classes public
Source code file:
31. Click the Exhibit button. 01. class Super {
02. public int getLength() { return 4; } 03. }
04.
05. public class Sub extends Super {
06. public long getLength() { return 5; } 07.
08. public static void main(String[] args) {
09. Super sooper = new Super();
10. Sub sub = new Sub();
11. System.out.println(
12. sooper.getLength() + "," + sub.getLength());
13. }
14. }
What is the output? A. 4,4 B. 4,5 C. 5,4 D. 5,5 E. Compilation fails. Answer: E
Explanation: Refer to the explanation given in question 30
The return type of getLength( ) in the super class is int and the return type in the sub class is long. In other words, it is not an override because of the change in the return type and it is also not an overload because the argument list has not changed. Source code file:
32. Click the Exhibit button. 01. class Super {
02. public Integer getLength() {return new Integer(4); } 03. }
04.
05. public class Sub extends Super {
06. public Long getLength() {return new Long(5); } 07.
08. public static void main(String[] args) {
09. Super sooper = new Super();
10. Sub sub = new Sub();
11. System.out.println(
12. sooper.getLength().toString() + “,” +
13. sub.getLength().toString() );
14. }
15. }
What is the output? A. 4,4 B. 4,5 C. 5,4 D. 5,5 E. Compilation fails. Answer: E
Explanation: Refer to the explanation given in question 30 for more information.
Answer E is correct, compilation fails – The return type of getLength( ) in the super
class is an object of reference type Integer and the return type in the sub class is an object of reference type Long. In other words, it is not an override because of the change in the return type and it is also not an overload because the argument list has not
changed.
Source code file:
33. Given:
01. public class X {
02. public X aMethod() {return this;} 03. }
01. public class Y extends X { 02.
03. }
Which two methods can be added to the definition of class Y? (Choose two.) A. public void aMethod() {}
B. private void aMethod() {} C. public void aMethod(String s) {} D. private Y aMethod() { return null;} E. public X aMethod() { return new Y(); } Answer: CE
Explanation: Refer to the explanation given in question 30 for more information. Answer A fails - it is not an override because of the change in the return type and it is
also not an overload because the argument list has not changed.
Answer B fails - the subclass (overriding) method may NOT be more private than the
superclass (overridden) method.
Answer C is acceptable – The sub class aMethod is not an override because of the
change in the return type, it overloads the super class aMethod – matching name but different arguments.
Answer D fails – - the subclass (overriding) method may NOT be more private than the
superclass (overridden) method.
Answer E is acceptable - The sub class aMethod overrides the super class aMethod –
matching signature and return type. Source code file:
34. Click the Exhibit button. 01. interface Beta {} 02.
03. class Alpha implements Beta { 04. String testIt() {
05. return "Tested";
06. }
07. } 08.
09. public class Main1 {
10. static Beta getIt() {
11. return new Alpha();
12. }
13. public static void main(String[] args) {
14. Beta b = getIt();
15. System.out.println(b.testIt());
16. }
17. }
What is the result? A. Tested B. Compilation fails.
C. The code runs with no output. D. An exception is thrown at runtime. Answer: B
Explanation:
a) A variable whose declared type is an interface type may have as its value a reference to any instance of a class which implements the specified interface. It is not sufficient that the class happen to implement all the abstract methods of the interface; the class or one of its superclasses must actually be declared to implement the interface, or else the class is not considered to implement the interface. JLS 9
So variable b of type Beta may hold a reference to class Alpha, which implements Beta – line 3.
Method getIt() of Main1 class returns a reference to class Alpha so variable b should be created with that reference – line 14.
b) The type of the object reference determines which variable you access. The type of the underlying object determines which method you invoke. “All-in-one Java 2 Exam Guide” Boone & Stanek p.109
Answer A – is wrong. Method testIt() is not a member of Beta so cannot be referred to
by variable b (which is type Beta) – EXCEPT that the underlying reference is type Alpha and testIt() is a method of Alpha - see b) above? But the compiler can only use the compile-time reference (type Beta) to resolve the method invocation so compilation fails. If Beta declared testIt() then the reference would be valid and the overriding testIt() method in Alpha could be invoked.
(providing the access modifiers are correct - the overriding method may NOT be more private than the overridden method but may be less. (JLS 8.4.6.3) Then A would be the correct answer.
Answer B is correct. The compiler complains that it “cannot resolve symbol” (the
testIt() method). See A above.
Answer C is wrong – cannot see a means by which this could be correct. Answer D is wrong – cannot see a means by which this could be correct. Source code file:
35. Click the Exhibit button. 01. interface Animal {
02. void soundOff();
03. } 04.
05. class Elephant implements Animal { 06. public void soundOff() {
07. System.out.print1n("Trumpet");
08. }
09. } 10.
11. class Lion implements Animal { 12. public void soundOff() {
13. System.out.print1n("Roar");
14. }
15. } 16.
17. class Alpha1 {
18. static Animal get(String choice) {
19. if (choice.equalsIgnoreCase("meat eater") ) {
20. return new Lion();
21. } else {
22. return new Elephant();
23. }
24. }
25. }
Which compiles?
A. new Animal().soundOff(); B. Elephant e = new Alpha1(); C. Lion l = Alpha1.get("meat eater"); D. new Alpha1().get("veggie").soundOff(); Answer: D
Explanation: Refer to the explanation of question 34 for more information. Answer A fails –Animal is an interface and cannot be instantiated.
Answer B fails - Alpha1 is not a subclass of Elephant so Elephant is ineligible to hold a
reference to Alpha1. A reference to a class may only be assigned to a variable that has a class type of the same class or the reference must be to a subclass of the variable’s type.
Answer C fails – Incompatible types. Alpha1.get() returns a reference of type Animal.
Animal is an interface implemented by Lion and Elephant. The actual reference returned is to either Elephant or Lion. So a variable of type Animal could hold a reference to class Lion (JLS 5.2) but not the reverse, but the variable l (type Lion) receives a reference of either type Lion or type Elephant which can be cast from type Animal (interface) to type Lion (class), a narrowing reference conversion (JLS 5.1.5). This would compile if the returned reference was cast to type Lion.
Answer D will compile - Alpha1.get returns a reference of type Animal which contains a
reference to either class Lion or class Elephant, both of which implement interface Animal. The method .soundOff () is implemented by both Elephant and Lion so can be invoked by a refernce to either class.
Source code file: