SCJP 5 Preparation (Tips, Tricks & FAQs)

- Devesh Chanchlani 

I have no special talents. I am only passionately curious !!!

The Weblog is aimed at helping the SCJP aspirants become rock-steady with their concepts. After all the preparation and exercises, still there may remain a lot many pitfalls, which may hinder the aspirants' dream of a big score. The contents below are compiled in a way which is very precise and easy to grasp.

Good Luck !!!

1.
Thread t1 = new Thread("Thread1");
Thread t2 = new Thread(t1);
                // VALID
As, Thread implements Runnable, hence its valid according to the Thread Constructor:
 ----------------------------------
 | Thread(Runnable target) |
 ----------------------------------

2.
A new java.lang.Void class has been added for completeness ( in JDK 1.5), and is used by the reflection methods to represent(or wrap) "void" return types.

3.
Inner class cannot have same name as the enclosing class or classes. For ex:
class A {      
  class B {
    class A {    // INVALID
    }
  }
}
Also,

    i.  An Inner class can extend its enclosing class.

    ii. A final class can have an Inner class.

4.
yield() causes the current thread to pause temporarily and allows another thread to run. However, it is never a good idea to depend on yeild() for managing the thread execution. yield() does not guarantee that a low priority thread would run. So the point is, you really cannot be "sure" what effect will yield() have on the threads.

5.
Consider the class below:
class Widget
{
   static final String CLASS_GUID;    //Compiler Error
   Widget(){}
}
Here CLASS_GUID is a 'static final' variable. As static fields can be accessed even without creating an instance of the class, it is entirely possible that this field can be accessed before even a  single instance is created. In this case, no constructor or non-static initializer had ever been called. And so, the field  remains uninitialized. This causes the compiler to complain.
The 2 possible workarounds are:
    i.   static final String CLASS_GUID = "xyz";
    ii.  static {
                CLASS_GUID = "xyz";
           }
   
6.
What application requirements may need you to use native methods?
1) The application needs to do computation intensive job.
2) The application needs to access drivers for hardware that Java does not know about.
3) The application needs to access legacy code written in COBOL.
AND NOT:
1) The application needs to make fields of a class globally available.
2) The application needs to provide it's services to other applications.

7.
//WILL NOT COMPILE
package p1;
public class A {
      protected int i = 10;
      public int getI() { return i; }
}

package p2;
public class B extends p1.A {
   public void process(A a)
   {  a.i = a.i*2; }
   public static void main(String[] args)
   {
      A a = new B();
      B b = new B();
      b.process(a);
      System.out.println( a.getI() );
   }
}
REASON: Although, class B extends class A and 'i' is a protected member of A, B still cannot access i, (now this is imp) THROUGH A's reference because B is not involved in the implementation of A. Had the process() method been defined as process(B b); b.i would have been accessible as B is involved in the implementation of B.

8.
for(;;) {
    Math.random()<.05? break : continue;
}
This is an invalid use of ? : operator. Both sides of : should return the SAME TYPE (excluding void). Here, break and continue do not return anything.

9.
Wrapper classes do not have a no-args constructor like, "Integer i = new Integer();" is invalid.
And, String is not a wrapper class. Hence this is valid: String str = new String();

10.
Inner class can even be defined in the following way, inside the enclosing class, as:
new EnclosingClass.InnerClass();

11.
When a programmer does not define ANY constructor, the compiler inserts one automatically, the access modifier of which is same as that of the class. For example, the constructor for the below given class will be protected:
protected class A { }

12.
In the following cases a thread will definitely be alive but not be running:
1) The thread has issued a call to wait( ).
2) The thread is trying to enter a synchronized block and the monitor is not free.
3) The thread is sleeping as a result of a call to the sleep( ) method.
And, NOT:
1) A higher priority thread comes in ready to run state.
Reason: There is no guarantee that the higher priority thread will preempt the lower priority thread.
2) The thread calls yield().
Reason: There is no guarantee that this will suspend this thread.

13.
Thread a = new Thread();
a.start();
//some code
Thread.sleep(10000);  //applied on 'a' somewhere in the code
//some code
a.interrupt();

Calling interrupt() will cause an InterruptedException ONLY if the thread on which interrupt() is called, is blocked on an invocation of the wait(...), join(...), or sleep(...), methods of this class.

14.
Inside an Inner Class, you cannot access the Enclosing Class's members by using 'this' keyword. The correct way is either use the member name plainly OR EnclosingClass.this.memberName

15.
//INVALID
void assertTest(Object obj) {
 assert obj != null : throw AssertionError();
}
REASON: Second operand must evaluate to an object or a primitive. (It can also be null.)

16.
System.out.println(null + true); //INVALID
System.out.println(true + null); //INVALID
System.out.println(null + null);
//INVALID
REASON: The operator + is undefined for the argument type(s) null, boolean. Also, If only one operand expression is of type String, then string conversion is performed on the other operand to produce a string at run time.

17.
When the program is run, the JVM looks for a method named main() which takes an array of strings as input and returns nothing. If it doesn't find such method, it throws a java.lang.NoSuchMethodError.
Hence, any such main() declaration is Invalid: public static long main(String[] args)

18.
A class that directly accesses member fields of another class, exhibits HIGH COUPLING.
When changing an implementation of a class, does not effect classes that use it, exhibits LOW COUPLING.

19.
To compile a file such as:
package com.enthu;
class A { }
if, its compiled in the way: javac A.java , class file does get created but without any directory structure.
If its compiled in the manner: javac -d . A.java , the class file is created with the appropriate directory structure.

20.
Following are primitive types that can be used for a switch() clause : byte, char, short or int. Note that you cannot use boolean, long, float or double. Every case constant expression(must be a constant), in a switch block must be assignable to the type of switch expression.
final int y =124; switch(b){ case y: break; } //VALID, y can be converted to byte
final int y =128; switch(b){ case y: break; }
//INVALID, y cannot be converted to byte

21.
Consider: String[] str = "name:john;;sex:m;;".split(";");
The Strring array str[] contains 3 elements. It is so because the trailing empty strings are always discarded.

22.
Consider:
void method1() throws Exception {
    try { throw new IOException(); }
    finally { throw new NullPointerException(); }
}
The method1() ends up throwing NPE, as the Exception that is thrown in the last, gets thrown by the method.

23.
Object o = null;
System.out.println(o);   //Print null
System.out.println(o.toString()); 
//Throws NPE

24.
Consider:
public static void main(String[] args) {
 String [] a = {};
 String [] b = null;
 System.out.println(args.length); //Prints 0, when run without any arguments
 System.out.println(a.length);       //Prints 0
 System.out.println(b.length);       //Throws NPE
}

25.
java -D/home=classes TestClass  //Here, the property name is /home and value is classes.
javac -d/home TestClass.java       
//Wrong. Must have a space between -d and /home.

26.
Static and Initializer blocks cannot use "throws" keyword. It is meant only for methods.
Static and Initializer blocks cannot even throw RuntimeExceptions, without enclosing them in try-catch.

27.
hashCode() method of Object class is a native method.

28.
Consider (Purpose: to prevent garbage collection of the objects of this class) :
class SelfReferencingClassToPreventGC {
 private SelfReferencingClassToPreventGC a;
 public SelfReferencingClassToPreventGC() {
  a = this;   //references itself to make sure that this is not garbage collected.
 }
}
Yes, it does not solve the purpose. All it is doing is creating a circular reference and such references do not prevent an object from garbage collection. If B is only referred to by A and if A is eligible for GC, then B is eligible for GC too. So, if A refers to B and B refers back to A, this arrangement does not prevent them from being garbage collected. This is also known as Islands of Isolation scenario.

29.
A class implements the Cloneable interface to indicate to the Object.clone() method that it is legal for that method to make a field-for-field copy of instances of that class. Invoking Object's clone method on an instance that does not implement the Cloneable interface results in the exception CloneNotSupportedException(checked Exception) being thrown. By convention, classes that implement this interface should override Object.clone (which is protected) with a public method. Note that this interface does not contain the clone method. The Object.clone method is as follows:
   protected Object clone() throws CloneNotSupportedException

30.
Consider the following code:
Float f1 = new Float(Float.NaN); 
Float f2 = new Float(Float.NaN); 
System.out.println( ""+ (f1 == f2)+"  "+f1.equals(f2)+ "  "+(Float.NaN == Float.NaN) ); 

//Prints false true false

Explanation: f1 == f2 is false because f1 and f2 are different objects and == tests whether two references point to same object or not.
Although f1.equals(f2) should return false, it returns true. Javadoc gives two exceptional cases:
. If f1 and f2 both represent Float.NaN, then the equals method returns true, even though Float.NaN==Float.NaN has the value false.
. If f1 represents +0.0f while f2 represents -0.0f, or vice versa, the equal test has the value false, even though 0.0f==-0.0f has the value true i.e.

Float f1 = 0.0f; 
Float f2 = -0.0f;
System.out.println(f1.equals(f2)); //Prints false
System.out.println(-0.0f == 0.0f); 
//Prints true

Also, keep in mind, the same goes for double and there's no NAN for Integer, Short or Byte, only for Float and Double.

31.
extending a class implies is-a, and implementing an interface implies is-like-a.
Aggregation defines a has-a relation.

32.
Consider:
Object o = null;
Collection c = //valid collection object.
for(o : c){ }       //INVALID - Cannot use an existing/predefined variable in the variable declaration part.
for(final Object o2 :c){ }
//VALID - final is the only modifier that is allowed here.

33.
to enable assertions for the system level classes [i.e. the classes that come bundled with the JDK] - esa OR enablesystemassertions

34.
Consider:
enum Pets {
   DOG("D"), CAT("C"), FISH("F");
   static String prefix = "I am ";
   String name;  
   Pets(String s) { name = prefix + s;} //INVALID
}

Unlike a regular java class, you cannot access a non-final static field from an enum's constructor.
Also remember, Enum constants must be declared before anything else.

35.
List<? super Number>
Read it aloud like this: A List containing instances of Number or its super class(es). Thus, this will allow you to do this: list.add(new Integer(10)); because Integer can be assigned to a variable of type Number or its super class, but it will not allow you to retrieve anything other than Object: Object obj = list.get(i); because the compiler doesn't know the exact class of objects contained by list.

List<?>
This is same as List<? extends Object>. Read it aloud like this: A List containing instances of some class that extends Object class. Thus, this will not allow you to add anything to it because the compiler doesn't know the exact class of objects contained by the list so it cannot check whether whatever you are adding is eligible to be added to the list or not. Further, this will only allow you to do this: Object o = list.get(index); because all the compiler knows is that this list contains objects.

List<? extends Number>
Read it aloud like this: A List containing instances of Number or its subclass(es). This will allow you to retrieve Number objects because the compiler knows that this list contains objects that can be assigned to a variable of class Number. However, you cannot add any object to the list because the compiler doesn't know the exact class of objects contained by the list so it cannot check whether whatever you are adding is eligible to be added to the list or not.

List<Number extends ?> //BAD SYNTAX.
List<Number super ?>     
//BAD SYNTAX.

36.
Consider:
try {
  System.exit(0);
} finally {
 System.out.println("finally is always executed!"); //Does not Execute
}
When you call System.exit(0); The JVM ends so there is no way to execute the finally block.

37.
A final variable must be initialized when an instance is constructed, or else the code will not compile. This can be done either in an instance initializer or in EVERY constructor.

38.
The interrupt() method does nothing except setting the interrupted flag to true. However, if the thread on which interrupt() is called, is blocked in an invocation of the wait(...), join(...), or sleep(...), methods of this class, then its interrupt status will be cleared and that thread (not the caller of interrupt) will receive an InterruptedException.

39.
When you try to run a class, which has no main method, you get an error:
"Exception in thread "main" java.lang.NoSuchMethodError: main"
and not NoSuchMethodException. Keep in mind, both do exist. Unlike asserts, in which there's no AssertionException, there's only AssertionError.

40.
An enum's constructor is private by default. You cannot apply public or protected  to the constructor. private is allowed but is redundant.

41.
int i = 20;
{
  int i = 8;     //INVALID: Duplicate Local Variable
}
----------------------------------------------------------
{
  int i = 8;    //VALID
}
int i = 20;   
//VALID

42.
HashSet allows null values to be stored.

43.
Consider the standard 'put' method of class HashMap.
public Object put(Object key, Object value);
Returns: previous value associated with specified key, or null if there was no mapping for key. A null return can also indicate that the HashMap previously associated null with the specified key.

44.
super.super.methodXyz(); //Such usage of 'super' is INVALID

45.
The method used to schedule a thread for execution - "start"

46.
native method cannot be abstract.

47.
class Test {
   public static void main(String[ ] args) {
      int[] a = { 1, 2, 3, 4 };
      int[] b = { 2, 3, 1, 0 };
      System.out.println( a [ (a = b)[3] ] );
   }
}
What will it print when compiled and run ?
Answer: 1
Explanation: In an array access, the expression to the left of the brackets appears to be fully evaluated before any part of the expression within the brackets is evaluated. In the Expression a[(a=b)[3]], the expression a is fully evaluated before the expression (a=b)[3]; this means that the original value of a is fetched and remembered while the expression (a=b)[3] is evaluated. This array referenced by the original value of a is then subscripted by a value that is element 3 of another array (possibly the same array) that was referenced by b and is now also referenced by a. So, it's actually a[0] = 1. Note that, if evaluation of the expression to the left of the brackets completes abruptly, no part of the expression within the brackets will appear to have been evaluated.

48.
byte b = 320;  //INVALID
REASON: 320 cannot fit into a byte so you must cast it.: byte b = (byte) 320;

49.
How many objects will be eligible for GC just after the method returns?
public void compute(Object p)
{
 Object a = new Object();
 int x = 100;
 String str = "abc";
}

Answer: 1
Explanation: Objects passed to the method are never garbage collected in (or right after) that method. So p cannot be GCed. x is not an object. "abc" is a string literal which goes to the string pool and is not GCed. So, only a is eligible for GC.

50.
For System.out.printf, the syntax is: %[arg_index$][flags][width][.precision]conversion char
You need to remember the following flags:
a) "-" Left justify this argument - Must specify width as well.
b) "+" Include a sign (+ or -) with this argument - Applicable only if conversion char is d or f (i.e. for numbers).
c) "0" Pad this argument with zeros  - Applicable only if conversion char is d or f (i.e. for numbers). Must specify width as well.
d) "," Use locale-specific grouping separators (i.e., the comma in 123,456)  - Applicable only if conversion char is d or f (i.e. for numbers).
e) "(" Enclose negative numbers in parentheses  - Applicable only if conversion char is d or f (i.e. for numbers).

51.
Consider:
String c="abc";
String b="ab";
String d="c";
System.out.print(c == (b+d));
System.out.print(c == (b+d).intern());

Answer: false true

Explanation: The result of explicitly interning a computed string is the same string as any pre-existing literal string with the same contents. Also note, if it would have been String c = new String("abc"); , the output would have been false in both the cases, as it checks for only literals and not objects.

52.
For instantiating a non-static Inner class,
inside a non-static method of the Enclosing class: new Inner();  OR  new Outer.Inner();
inside a static method of the Enclosing class:           new Outer().new Inner();

For instantiating a static Inner class,
inside a non-static method of the Enclosing class: new Inner();  OR  new Outer.Inner();
inside a static method of the Enclosing class:           new Inner();  OR  new Outer.Inner();

53.
System.out.println(enum1.A + enum1.B);                       //INVALID, operator not defined
System.out.println(enum1.A.toString() + enum1.B); 
//VALID

54.
  i.    A non-static Inner class cannot have static members. Non-static inner classes can contain final static fields (but not methods).

  ii.  Anonymous classes cannot have explicit constructors, since they have no names.

  iii. A static inner class is also known as Top Level Nested class. So, there are two types of Top level classes. One, that is a standard class and a static class defined inside another class.

  iv. Anonymous and method Local classes cannot be static.

55.
javac does not have 'ea'(and related) option(s).

56.
class Inner1{
 public void aaaa() throws IOException{  
 }
}
class Inner2 extends Inner1{
 public void aaaa(){  
 } 
}

Inner1 i = new Inner2();
i.aaaa(); 
//INVALID

Inner2 i2 = new Inner2();
i2.aaaa(); 
//VALID

57.
class Inner1{
 public void aaaa() throws IOException{  
 }
}
class Inner2 extends Inner1{
 public void aaaa(){  
 } 
}
class Inner3 extends Inner2{
 public void aaaa() throws IOException{ //INVALID 
 } 
}

58.
MyThread mt = new MyThread();
mt.setDaemon(true);
mt.start();
mt.setDaemon(false);
 //INVALID, You can not call setDaemon() after the thread is started. It will throw IllegalThreadStateException if you do so.

59.
A program ends when all non-daemon threads end. Yes, even if daemon threads are running.
You can make any Thread (if you have permission) a daemon thread by calling setDaemon(true) before starting that thread.
You can stop any thread.

60.
native method cannot be abstract. But an abstract method can be implemented by a native method. native method declarations have no bodies. i.e. { ...}

61.
synchronized(r)  {
    r.data = "DATA "+number;
    r.notifyAll();                //LOCK not released, the lock on r is not release until the thread gets out of the                                                              //synchronized block
    r.data = "DATA";
}                                             //Lock released here

62.
String String = "String";     //is a perfectly valid syntax !

63.
int ia[ ][ ] = { { 1 , 2}, null };
int ja[ ][ ] = (int[ ] [ ])ia.clone();
System.out.print((ia == ja) + " ");
System.out.println(ia[0] == ja[0] && ia[1] == ja[1]);

All array objects automatically get a public clone method. A clone of a multidimensional array is shallow, which is to say that it creates only a single new array. Sub-arrays are shared, so ia and ja are different but ia[0] and ja[0] are same.
FYI, clone() method defined in object class is protected. But an array object overrides it and has the same methods as the following class:

class A implements Cloneable
{
   public final int length = X;
   public Object clone()
   {
      try
      {
         return super.clone();
      }
      catch (CloneNotSupportedException e)
      {
         throw new InternalError(e.getMessage());
      }
   }
}

64.
Remember that parse() method of DateFormat and NumberFormat throws java.text.ParseException.

65.
public class DataObectWrapper
{
    private Object obj;

    public DataObectWrapper(Object pObj){ obj = pObj; }

    public Object getObject() { return obj; }
}

Objects of this class are thread safe because this class does not perform any operations on the wrapped objects. There is only one method that is only returning the object reference of the wrapped object which is a thread safe operation.
If this class were doing some operation on the instance variables, say:
public void modify()
{
    i =  20; //assuming i and j are instance variables.
    j = 30;
}

In this case, the objects of this class are not thread safe.

The objects wrapped by this class are not thread safe because after the reference of the wrapped object is returned, multiple threads can operate on the object. But whether the object is thread safe or not is determined by how is it implemented. That information is not given in the question, so you cannot say whether the object wrapped by this class are thread safe or not.

66.
The start() method internally calls the run method asynchronously and returns. It is the run() method that needs to end for a thread to die. A thread dies when the run( ) method ends.

67.
In if(false){ x=3; }, although the body of the condition is unreachable, this is not an error because the Java Language Specification(JLS) explicitly defines this as an exception to the rule. It allows this construct to support optimizations through the conditional compilation. For example,

if(DEBUG){ System.out.println("beginning task 1"); }

Here, the DEBUG variable can be set to false in the code while generating the production version of the class file, which will allow the compiler to optimize the code by removing the whole if statement entirely from the class file.

68.
In Java, Objects pass messages by calling each other's member methods.

69.
switch(2) {
      case 1: boolean b;
    break;
      case 2: b = true;                //VALID
    System.out.println(b);    //IF the above line is commented, you get a compiler error -                                                                                                 //"variable not initialized"
    break;
}

70.
The signature of a method in a class is as follows:
public static <E extends CharSequence> List<? super E> doIt(List<E> nums) 
This method is being called in the following code:
result = doIt(in);

ArrayList<String> in;
List out;

The input parameter has been specified as List<E>, where E has to be some class that extends CharSequence. So ArrayList<String>, List<String>, or List<CharSequence> are all valid as reference types for 'in'.
The output type of the method has been specified as List<? super E> , which means that it is a List that contains objects of some class that is a super class of E. Here, E will be typed to whatever is being used for 'in'. For example, if you declare ArrayList<String> in, E will be String.
The important concept here once the method returns, there is no way to know what is the exact class of objects stored in the returned List. So you cannot declare out in a way that ties it to any particular class, not even Object.
Thus, the only way to accomplish this is to use non-typed reference type, such as:  List result;

71.
Thread created internally by the JVM are always daemon threads -- FALSE
Main thread created by the JVM is not a daemon thread!!!

72.
The method substring() in StringBuilder/StringBuffer returns a String (and not a reference to itself, unlike append, insert, and delete).

73.
static{ throw new NullPointerException; }    //Will Throw ExceptionInInitializationException

74.
An important thing to note about javac is that if the directory specified after -d does not exist, it DOES NOT create that directory and throws an error instead. Javac only creates the directory as per the package name under the directory given after -d.

75.
interface I1{
   void m1() throws IOException;
}
interface I2{
   void m1() throws FileNotFoundException;
}
What methods have to be implemented by a class that says it implements I1 and I2 ?
public void m1() throws FileNotFoundException
In the above problem, FileNotFoundException is a subclass of IOException, so choice 2 satisfies both the interfaces.

76.
i<20 ? out1() : out2();
Assume that out1 and out2 have method signature: public void out1(); and public void out2();

Note that it is not permitted for either the second or the third operand expression to be an invocation of a void method.