Saturday, May 9, 2009

java.io and FileStream questions

****NOTE: All of these examples should be changed to use and Array, not an ArrayList!!!

 

What is the result of attempting to compile and run the following code:

package scjp;
import java.io.*;
import java.util.*;
public class Book implements Serializable {

    Collection pages = new java.util.ArrayList();
    Book(int numberOfPages){
         for(int i = 0; i<numberOfPages; i++){
            pages.add(new Page(i));
        }
    }
    public static void main(String args[]) {
        Book scjpGuide = new Book(250);
        FileOutputStream fos = new FileOutputStream("book.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(scjpGuide);
        oos.close();
    }
}

class Page implements Serializable {
    int number;
    Page(int number){this.number=number;}
}

 

a) The code fails to compile

b) The code compiles but throws a checked exception at runtime

c) The code compiles but throws an unchecked exception at runtime

d) The code compiles, runs, and saves an instance of a book with 250 pages

e) The code compiles, runs, and saves an instance of a book without any pages

f) he code compiles, runs, and saves 250 pages without a reference to the book

 

Option a) is correct.

Any time you deal with classes in the java.io package, there’s a good chance that they will throw a java.io.IOException.

In this case, a call to the constructor of the FileOutputStream has the potential of throwing a FileNotFoundException, and the attempt to write to the ObjectOutputStream has the potential to trigger an IOException.

Surrounding the offending method calls within a try catch block, or simply being lazy and appending a throws Exception clause to the main method would allow the code to compile and run as expected.

 

    public static void main(String args[]) throws Exception {
        try {
            Book scjpGuide = new Book(250);
            FileOutputStream fos = new FileOutputStream("book.ser");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(scjpGuide);
            oos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

 

******************************************************************************************

What is the result of attempting to compile and run the following code:

package scjp;
import java.io.*;
import java.util.*;
public class Book implements Serializable {

    Collection pages = new java.util.ArrayList();
    Book(int numberOfPages){
         for(int i = 0; i<numberOfPages; i++){
            pages.add(new Page(i));
        }
    }
    public static void main(String args[]) throws Exception {
        Book scjpGuide = new Book(250);
        FileOutputStream fos = new FileOutputStream("book.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(scjpGuide);
        oos.close();
    }
}

class Page implements Serializable {
    int number;
    Page(int number){this.number=number;}
}

 

a) The code fails to compile

b) The code compiles but throws a checked exception at runtime

c) The code compiles but throws an unchecked exception at runtime

d) The code compiles, runs, and saves an instance of a book with 250 pages

e) The code compiles, runs, and saves an instance of a book without any pages

f) he code compiles, runs, and saves 250 pages without a reference to the book

 

Option d) is correct.

In this example, all of the required steps that are needed to create an instance of a Book containing 250 pages, and then serialize that instance, are followed correctly.

Key points to note are that both the Page and Book classes implement the java.io.Serializable interface, and none of the properties are marked with the transient keyword. AAny attempt by the JVM to serialize an object that is not Serializable will result in a java.io.NotSerializableException being thrown at runtime.

 

******************************************************************************************

 

What is the result of attempting to compile and run the following code:

package scjp;
import java.io.*;
import java.util.*;
public class Book implements Serializable {

    Collection pages = new java.util.ArrayList();
    Book(int numberOfPages){
         for(int i = 0; i<numberOfPages; i++){
            pages.add(new Page(i));
        }
    }
    public static void main(String args[]) throws Exception {
        try {
            Book scjpGuide = new Book(250);
            FileOutputStream fos = new FileOutputStream("book.ser");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(fos);
            oos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class Page implements Serializable {
    int number;
    Page(int number){this.number=number;}
}

 

a) The code fails to compile

b) The code compiles but throws a checked exception at runtime

c) The code compiles but throws an unchecked exception at runtime

d) The code compiles, runs, and saves an instance of a book with 250 pages

e) The code compiles, runs, and saves an instance of a book without any pages

f) he code compiles, runs, and saves 250 pages without a reference to the book

 

Option c) is correct.

This is a bit of a trick question, as the object passed to the writeObject method is not the scjpGuide as we would anticipate, but instead, is the instance of the FileOutputStream.

A FileOutputStream is not a serializable object, so we end up getting the following runtime exception: java.io.NotSerializableException: java.io.FileOutputStream.

It’s debatable as to whether knowing that the FileOutputStream is a serializable resource or not, so this may itself be a bit of a fringe question. However, a Java programmer should understand why a FileOutputStream would not be the type of object that could be sent across a network and used by some remote JVM. The idea of being able to serialize and deserialize a FileOutputStream is somewhat nonsensical, so a competent SCJP candidate should be able to answer this questions successfully.

 

******************************************************************************************

 

What is the result of attempting to compile and run the following code:

package scjp;
import java.io.*;
import java.util.*;
public class Book implements Serializable {

    Collection pages = new java.util.ArrayList();
    Book(int numberOfPages){
         for(int i = 0; i<numberOfPages; i++){
            pages.add(new Page(i));
        }
    }
    public static void main(String args[]) throws Exception {
            Book scjpGuide = new Book(250);
            FileOutputStream fos = new FileOutputStream("book.ser");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(scjpGuide);
            oos.close();
    }
}

class Page {
    int number;
    Page(int number){this.number=number;}
}

 

a) The code fails to compile

b) The code compiles but throws a checked exception at runtime

c) The code compiles but throws an unchecked exception at runtime

d) The code compiles, runs, and saves an instance of a book with 250 pages

e) The code compiles, runs, and saves an instance of a book without any pages

f) he code compiles, runs, and saves 250 pages without a reference to the book

 

Option b) is correct.

The book contains many pages, and serializing a book means serializing the various pages of the book. However, the class Page does not implement the java.io.Serializable interface, so when an attempt is made to serialize an instance of a Book, the JVM throws the following unchecked exception: java.io.NotSerializableException: scjp.Page

Two simple strategies to fix the code would be to make the Page class implement the java.io.Serializable interface, or have the Collection of pages in the book class be marked as transient.

******************************************************************************************

 

What is the result of attempting to compile and run the following code:

package scjp;
import java.io.*;
import java.util.*;
public class Book implements Serializable {

    Collection pages = new java.util.ArrayList();
    Book(int numberOfPages){
         for(int i = 0; i<numberOfPages; i++){
            pages.add(new Page(i));
        }
    }
    public static void main(String args[]) throws Exception {
            Book scjpGuide = new Book(250);
            FileOutputStream fos = new FileOutputStream("book.ser");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(scjpGuide);
            oos.close();
    }
}

class Page {
    transient private int number;
    Page(int number){this.number=number;}
}

 

a) The code fails to compile

b) The code compiles but throws a checked exception at runtime

c) The code compiles but throws an unchecked exception at runtime

d) The code compiles, runs, and saves an instance of a book with 250 pages

e) The code compiles, runs, and saves an instance of a book without any pages

f) he code compiles, runs, and saves 250 pages without a reference to the book

 

Option c) is correct.

Since the Page class is not serializable, an attempt to serialize an instance of the Book class will cause the JVM to barf when an attempt is made to serialize the associate pages.

Although the instance variable in the Page class is marked as being transient, the JVM will still try to Serialize the various Page instances. To get this code to run properly, the Collection of pages would need to be made transient, or the Page class would need to implement the java.io.Serializable interface.

 

******************************************************************************************

 

What is the result of attempting to compile and run the following code:

package scjp;
import java.io.*;
import java.util.*;
public class Book implements Serializable {

    Collection pages = new java.util.ArrayList();
    Book(int numberOfPages){
         for(int i = 0; i<numberOfPages; i++){
            pages.add(new Page(i));
        }
    }
    public static void main(String args[]) throws Exception {
            Book scjpGuide = new Book(250);
            FileOutputStream fos = new FileOutputStream("book.ser");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(scjpGuide);
            oos.close();
    }
}

class Page implements Serializable {
    transient private int number;
    Page(int number){this.number=number;}
}

 

a) The code fails to compile

b) The code compiles but throws a checked exception at runtime

c) The code compiles but throws an unchecked exception at runtime

d) The code compiles, runs, and saves an instance of a book with 250 pages

e) The code compiles, runs, and saves an instance of a book without any pages

f) he code compiles, runs, and saves 250 pages without a reference to the book

 

Option d) is correct.

In this case, the code will compile and run as expected, serializing a Book instance that contains 250 instances of the Page class, all tucked inside an ArrayList named pages.

One thing to note is that the int variable called number in the page class is marked as being transient. As a result, when each Page instance is serialized, the Page number data will not be saved, and the value will be lost until a de-serialized object explicitly sets the number. Transient variables and instances are not saved when an instance is Serialized, and correspondingly, the data is not re-initialized when an instance is de-serialized.

 

******************************************************************************************

 

What is the result of attempting to compile and run the following code:

package scjp;
import java.io.*;
import java.util.*;
public class Book implements Serializable {

    public transient Collection pages = new java.util.ArrayList();
    Book(int numberOfPages){
         for(int i = 0; i<numberOfPages; i++){
            pages.add(new Page(i));
        }
    }
    public static void main(String args[]) throws Exception {
            Book scjpGuide = new Book(250);
            FileOutputStream fos = new FileOutputStream("book.ser");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(scjpGuide);
            oos.close();
    }
}

class Page implements Serializable {
    public int number;
    Page(int number){this.number=number;}
}

 

a) The code fails to compile

b) The code compiles but throws a checked exception at runtime

c) The code compiles but throws an unchecked exception at runtime

d) The code compiles, runs, and saves an instance of a book with 250 pages

e) The code compiles, runs, and saves an instance of a book without any pages

f) he code compiles, runs, and saves 250 pages without a reference to the book

 

Option e) is correct.

Since the variable named pages is marked as being transient, the JVM will not attempt to save any of the pages that are associated with an instance of a book. As a result, the writeObject call to the ObjectOutputStream will serialize an instance of the Book class, but no associated Page objects will be serialized.

 

******************************************************************************************

 

What is the result of attempting to compile and run the following code:

package scjp;
import java.io.*;
import java.util.*;
public class Book implements Serializable {

    public Collection pages = new java.util.ArrayList();
    Book(int numberOfPages){
         for(int i = 0; i<numberOfPages; i++){
            pages.add(new Page(i));
        }
    }
    public static void main(String args[]) throws Exception {
            Book scjpGuide = new Book(250);
            FileOutputStream fos = new FileOutputStream("book.ser");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(scjpGuide);
            oos.close();
    }
}

transient class Page implements Serializable {
    public int number;
    Page(int number){this.number=number;}
}

 

a) The code fails to compile

b) The code compiles but throws a checked exception at runtime

c) The code compiles but throws an unchecked exception at runtime

d) The code compiles, runs, and saves an instance of a book with 250 pages

e) The code compiles, runs, and saves an instance of a book without any pages

f) he code compiles, runs, and saves 250 pages without a reference to the book

 

Option a) is correct.

In this case, the Page class is decorated with the transient keyword; this is not allowed. Classes can only be marked with the public, abstract and final keywords.

 

******************************************************************************************

 

What is the result of attempting to compile and run the following code:

package scjp;
import java.io.*;
import java.util.*;
public class Book implements Serializable {

    transient Collection pages = new java.util.ArrayList();
    Book(int numberOfPages){
         for(int i = 0; i<numberOfPages; i++){
            pages.add(new Page(i));
        }
    }
    public static void main(String args[]) throws Exception {
            Book scjpGuide = new Book(250);
            FileOutputStream fos = new FileOutputStream("book.ser");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(scjpGuide);
            oos.close();
    }
}

class Page implements Serializable {
    public transient int number;
    Page(int number){this.number=number;}
    public transient int getNumber() {return number;}
}

 

a) The code fails to compile

b) The code compiles but throws a checked exception at runtime

c) The code compiles but throws an unchecked exception at runtime

d) The code compiles, runs, and saves an instance of a book with 250 pages

e) The code compiles, runs, and saves an instance of a book without any pages

f) he code compiles, runs, and saves 250 pages without a reference to the book

 

Option a) is correct.

Methods cannot be decorated with the transient keyword, as the getNumber method in the Page class is, causing a compile error.

 

******************************************************************************************

What is the result of attempting to compile and run the following code:

package scjp;
import java.io.*;
import java.util.*;
public class Book implements Serializable {

    public Collection pages = new java.util.ArrayList();
    Book(int numberOfPages){
         for(int i = 0; i<numberOfPages; i++){
            pages.add(new Page(i));
        }
    }
    public static void main(String args[]) throws Exception {
            Book scjpGuide = new Book(250);
            FileOutputStream fos = new FileOutputStream("book.ser");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(scjpGuide);
            oos.close();
    }
}

class Page implements Serializable {
    public static transient int number;
    Page(int number){this.number=number;}
    public  int getNumber() {return number;}
}

 

a) The code fails to compile

b) The code compiles but throws a checked exception at runtime

c) The code compiles but throws an unchecked exception at runtime

d) The code compiles, runs, and saves an instance of a book with 250 pages

e) The code compiles, runs, and saves an instance of a book without any pages

f) he code compiles, runs, and saves 250 pages without a reference to the book

 

Option d) is correct.

This code snippet is really checking to see if you know whether or not a static variable can be transient or not – which of course, it can.

In this case, the pages numbers are transient, but each page will still be serialized when the instance of the Book is serialized, making for one serialized book containing 250 pages.

It should be noted that the use of this.number, given that the number variable is static, will generate a warning when the code is compiled, as we are referencing a static variable as though it were an instance variable. However, that doesn’t stop the code from compiling, and our compiled code will certainly run.

 

******************************************************************************************

What is the result of attempting to compile and run the following code:

package scjp;
import java.io.*;
import java.util.*;
public class Book implements Serializable {

    public Collection pages;
    Book(int numberOfPages){
         for(int i = 0; i < numberOfPages; i++){
            pages.add(new Page(i));
        }
    }
    public static void main(String args[]) throws Exception {
            Book scjpGuide = new Book(250);
            FileOutputStream fos = new FileOutputStream("book.ser");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(scjpGuide);
            oos.close();
    }
}

class Page implements Serializable {
    public static transient int number;
    Page(int number){this.number=number;}
    public  int getNumber() {return number;}
}

 

a) The code fails to compile

b) The code compiles but throws a checked exception at runtime

c) The code compiles but throws an unchecked exception at runtime

d) The code compiles, runs, and saves an instance of a book with 250 pages

e) The code compiles, runs, and saves an instance of a book without any pages

f) he code compiles, runs, and saves 250 pages without a reference to the book

 

Option c) is correct.

The collection of pages in the book class is never initialized, so the JVM simply sets this object to null. When we attempt to add pages to the collection of pages, we end up calling a method on a null instance, and predictably, we get the infamous, unchecked, NullPointerException at runtime.

This is a bit of a tricky question. All sorts of concepts are being thrown at you, but in the end, it is something as simple as the failure to initialize an instance variable that is really at the heart of this question. Always be prepared for the slight-of-hand shell games that the makers of the SCJP exam sometimes play on exam candidates. Sometimes the most complex code can obfuscate some of the most obvious problems.

No comments:

Post a Comment

Followers