News

November/December 2016 issue of Java Magazine, “Quiz Yourself” (1z0-809)

java-magazine-november-december-2016-issue
Written by Mushfiq Mammadov

In November/December 2016 issue of Java Magazine have been published five questions regarding 1Z0-809 Oracle Certified Professional, Java SE 8 Programmer II (OCP 8) exam:

Question 1. Given the following code:

ResourceBundle properties = ResourceBundle
          .getBundle("scratch.ConfigData", Locale.FRANCE); // line n1
System.out.println(properties.getString("help")); // line n2

And a directory and text file scratch/ConfigData.properties located on the CLASSPATH of the running program, which contains the following text:
file=File
edit=Edit
help=Help

What is the result? Choose one.

a. help
b. Help
c. Aide
d. An exception at line n1
e. An exception at line n2

Question 2. Given this code:

Collection<String> coll = new ArrayList<>();
coll.add("Fred"); coll.add("Jim"); coll.add("Sheila");
System.out.println("coll is " + coll);
coll.remove(0); // line n1
System.out.println("coll is " + coll);

What is the result? Choose one.

a. coll is [Fred, Jim, Sheila]
[nbsp count=4]coll is [Jim, Sheila]
b. coll is [Fred, Jim, Sheila]
[nbsp count=4]coll is [Fred, Jim, Sheila]
c. Compilation fails at line n1.
d. An exception is thrown at line n1.

Question 3. Given that the current working directory of the program is empty, and given this code fragment:

Path p = Paths.get("a", "b", "cee"); // line n1
System.out.println(p.endsWith(Paths.get("b", "cee")));
System.out.println(p.endsWith(Paths.get("ee")));

What is the result? Choose one.

a. true
[nbsp count=2]true

b. true
[nbsp count=2]false

c. false
[nbsp count=2]true

d. false
[nbsp count=2]false

e. An exception at line n1

Question 4. Given the following code:

class MyResource implements AutoCloseable {
    private String name;
    public MyResource(String name) {
        this.name = name;
    }

    @Override
    public void close() {
        System.out.println(name);
    }
}

public class ResourceHog {
    public static void main(String[] args) {
        try (MyResource one = new MyResource("one");
                MyResource two = new MyResource("two")) {
        } finally {
            System.out.println("three");
        }
    }
}

What is the result? Choose one.

a. one
[nbsp count=2]two
[nbsp count=2]three

b. three
[nbsp count=2]two
[nbsp count=2]one

c. three
[nbsp count=2]one
[nbsp count=2]two

d. two
[nbsp count=2]one
[nbsp count=2]three

e. The words one, two, and three are all output, but the order is not determined.

Question 5. Given this code:

class MyJobException extends Exception {}

class Job implements Callable<String> {
    public String call() throws MyJobException { // line n1
        return "Done";
    }
}

public class Jobs {
    public static void main(String[] args) {
        ExecutorService es = Executors.newFixedThreadPool(3);
        Future<String> handle = es.submit(new Job());
        try {
            String rv = handle.get();
        } // line n2
        catch (InterruptedException ex) {
            ex.printStackTrace();
        } // line n3
    }
}

Which is true? Choose one.

a. The code compiles successfully.
b. The code compiles if the throws clause at line n1 is deleted.
c. The code compiles if catch (Exception e){} is added immediately after line n2.
d. The code compiles if catch (MyJobException e){} is added immediately after line n3.
e. The code compiles if catch (Exception e){} is added immediately after line n3.

 

Answers
  1. B
  2. B
  3. B
  4. D
  5. E

 

Explanations
Question 1

The correct answer is option B. This question is really asking what happens when you try to access a resource bundle for a locale, but there is no file defining values for that particular locale.

When you deploy an internationalized application, you try to provide resource files for all the locales in which you expect your software to be used, and perhaps you even offer updates at intervals as you ind customers in new locations that you didn’t originally support. However, if the program were to throw an exception when it is used in an unexpected locale, that would be pretty harsh; so it’s a fair guess that throwing an exception isn’t going to be a good behavior. Indeed, there’s no checked exception when you try to access the file in the first place (at line n1) or when you look up the particular value (at line n2). On that basis, both option D and option E are incorrect.

If no exception is thrown, some text must result. The three remaining options amount to saying “Java can translate English to French and come up with Aide,” “Java uses the key instead of a value if the value isn’t found,” and “Java uses a less perfectly appropriate resource file.” The actual truth in this situation is the third of these: Java uses the best-fitting resource file it can ind, even if that file is the default file.

Here, the only file that exists is the default resource file, but Java takes several tries before settling on this. A locale is made of several parts. I’ll simplify the discussion by considering two main parts: the language and the region. In this case, Locale.FRANCE refers to the French language as spoken in France, which is coded as fr_FR. Given this data, the ResourceBundle mechanism tries to ind these files in order: ConfigData_fr_FR.properties and ConfigData_fr.properties.

Notice that the filenames are constructed from three parts: the base bundle name (ConfigData, here), then the locale-derived part, and then the extension (.properties). Strictly speaking, several more local variations might be checked with more-specific information, but the concept is illustrated well enough here. If the search has still failed (as it will in this example), the search is repeated using the system’s default locale (which might or might not be fr_FR). In this case, you don’t know whether there’s a different default locale, and it doesn’t matter anyway, because only one file exists. So the second search fails, too. After that, the system falls back to searching for the default file, ConfigData.properties.

The effect of this is that the search finds the bestavailable match. If you had a file dedicated to French speakers in France, it would be found. If that’s missing, but there’s a generalized French-language file, that would be found. Finally, as is the case with this question, the system falls back to the nonspecific version, which, in this case, contains English. By the way, this nonspecific version has an official name, which is base bundle.

There is a failure mode that’s broadly consistent with option E if all potential resource files, including the base bundle, are missing. In this situation, the getBundle method throws a MissingResourceException (which is an unchecked exception, so no code has to admit this possibility). Of course, that’s not relevant to this question because the base bundle is found.

By the way, the process is explained in more detail in the API documentation.

This behavior is really quite useful. If you had a single French file, ConfigData_fr.properties, it would probably serve quite well for any French speakers, whether they were French or Canadian, or they were from any of nearly 30 countries in Africa or about a dozen others around the world.

It’s interesting to note, of course, that Java has a nontrivial multilingual capability. While it generally does not attempt to translate text between languages, it knows the names of months and days of the week in many languages, so date-type objects are converted into locale-appropriate text without help from the programmer.

Question 2

The correct answer is option B. This is one of those questions that investigates a situation where misunderstanding can easily occur—with potentially difficult-to-debug consequences. This question might be too hard for quizzes, but it’s a truly enlightening problem, so I’ll share it with you nonetheless.

So, what’s going on? Because the correct answer is option B, it appears that the code compiles and runs, but it does not modify the data in the collection. The behavior hinges on the method at line n1. If you look at this in an IDE, you’ll see that the argument to the remove method is an Object, not an int. The remove(Object) method is defined on Collection, and it removes an object that matches the argument. But this collection contains only three strings: “Fred”, “Jim”, and “Sheila”. Consequently, no change is made to the collection, and the answer makes sense.

I think that this leaves a couple of curiosities remaining. First, isn’t there a remove(int) method defined for a List? And, doesn’t that method remove the item at the given index position? Well, yes, both of those are true statements. However, the relationship between remove(int) and remove(Object) is one of method overloading, not method overriding, which means that the compiler decides which method to invoke, rather than the object that’s the target of the invocation making the decision at runtime.

In this example, the collection object is actually a List, but the code refers to it as a Collection, and Collection does not have the remove(int) method (collections are not intrinsically ordered, so positional indexes are not meaningful). Because of this, the compile-time decision is made to invoke the remove(Object) method.

As a point of interest, if you simply change the declared type of the variable coll from Collection to List, “Fred” is removed from the list and the output does indeed change from what’s shown for option B to what’s shown for option A.

But at this point, you might reasonably ask why the compiler allows the call to remove on a Collection to accept an Integer argument. Doesn’t the generics mechanism restrict the argument to a String, and wouldn’t that result in a compilation failure (option C)? If you check the documentation for this method, it does not actually take a generic argument; it takes Object. The same is true of the contains method, too. In effect, this allows you to say “if the code contains this item, remove it” while referring to an item that cannot possibly be present because it’s the wrong type. This seemingly useless behavior allows for backward compatibility with code written prior to the advent of generics. Similarly, you can ask whether a collection of automobiles contains an apple, and while the question is valid, you just get the answer “no.”

It’s interesting to note that many IDEs and style guides (including the CERT Secure Java Coding recommendations) warn against calling these methods with generically inappropriate arguments, and you can probably see why now. Also, the return value of these remove methods can be used to determine whether any change was made, and style guides often advise against ignoring such return values.

From one perspective, the difference between inheritance and overloading is simple enough, but sometimes it takes on a trickier consequence—which makes a great question and discussion, partly because you might have a horrible time trying to debug the code when a manager is yelling at you to “Fix it now!”

Question 3

The correct answer is option B. The first observation is that the Path mechanism has no problem referring to files and directories that don’t exist. That’s actually quite important, because if it were unable to do so, you’d have a problem trying to create a new file. On that basis, you should be ready to eliminate option E, which seems to be hinting that the reference to the path a/b/cee, which doesn’t exist, would cause a problem. (Note that the question states that the current working directory is empty.)

So, the remainder of the question revolves around two questions. First is whether the Path.endsWith method traverses directories (if it does, you would expect the irst line of output to be true). Second is whether it examines whole segment names or is willing to match just the tail end of a segment name, such as deciding that a/b/cee ends with ee.

It’s a rather boring matter of rote learning that, indeed, the method does match across directories, but it does not match partial segment names. Hence, the first output line is true, and the second is false—making option B the correct answer.

Question 4

The correct answer is option D. This question addresses the behavior of the try-with-resources mechanism and how it interacts with the AutoCloseable resources that it manages. Two different behaviors are addressed: 1) the timing relationship between the automatic closure and any
explicitly coded finally block, and 2) the timing relationship among multiple resources all opened in the parameter list of a single try statement.

Much of the time when you use try-with-resources, there’s no need for a finally block; the auto-generated code created by the compiler normally closes anything that needs to be closed. However, there are some resource-like things that do not implement AutoCloseable, and those would likely need a finally block to release them. The examples that spring to mind for me are the API-level lock utilities that exist in the java.util.concurrent package. Therefore, it is possible to have both try-with-resources and a finally block in well-thought-out code that isn’t simply illustrating an academic talking point.

Of course, the relationship between any resource being released in a finally block and the resources being managed by the try-with-resources mechanism is pretty tenuous. The lexical scope of the managed resources is necessarily limited to the try statement and the block that immediately follows it. Therefore, those resources are generally invisible to the finally block. In contrast, anything visible in the finally block must be scoped “outside” of the whole try/catch/ finally construction.

Nevertheless, Java specifies that the finally block is executed after the management of the AutoCloseable resources. Java Language Specification section 14.20.3.2, “Extended try-with-resources,” states that “all resources will have been closed (or attempted to be closed) by the time the finally block is executed.” This rules out option B and option C, which assert that the word three is printed first.

Also, section 14.20.3 (the overarching section containing the subsection mentioned above) notes that variables are “closed automatically, in the reverse order from which they were initialized.” Consequently, you can be sure that the two resources will be closed such that two is output first and one comes after.

Notice that these specification statements are explicit; they don’t leave the order of the operations uncertain in any way. The order has been pinned down as two, one, three, so the answer is not option E, but rather option D.

If you came across this in an exam, you might consider that it’s a lot of code to understand for a sub-two-minute answer. However, notice that the options offered include only the ordering of output, so you can safely ignore minor syntactic details. Instead, you need to identify only that the difference between the various options amounts to “the order of closing is defined versus undefined” and then decide between “AutoCloseable first, and then finally” and its inverse and between “auto-close in reverse order from opening” and its inverse.

Question 5

The correct answer is option E. This question investigates the relationship between the abnormal termination (otherwise known as “exception behavior”) of a Callable and the get method of the Future that connects to that Callable.

The general ExecutorService mechanism allows you to submit jobs, represented either as Runnable or Callable objects, to a pool of worker threads. The run method of a Runnable is declared to return void, and cannot throw any checked exceptions. In contrast, Callable is a generic interface, and the call method that it defines returns whatever the generic type might be. Also, call in the base interface is declared to throw Exception, permitting implementations to throw any exception they like. This means that option B, which effectively asserts that the call method may not throw an exception, is false.

Option C can immediately be rejected based on regular Java behavior. If a series of catch blocks catch exception types that are related by class hierarchy, the more-specific exception (the subclass) must come first. If the exceptions are listed with the more-general class first, compilation fails because the more-specific (later) catch block is unreachable. Java Language Specification section 14.21 states this, albeit with rather abstruse language. In option C, the suggestion is that adding a catch (Exception) block before the catch (InterruptedException) block would somehow help. But you can immediately see that this will cause, not cure, compilation failure.

Next, you must consider whether an additional catch block is even necessary, or if the right answer might actually be option A, which asserts that the code is good as it stands. It turns out that the definition of the get method of the Future interface is declared to throw checked exceptions. One, as the existing code suggests, is an InterruptedException. It’s a matter of general principle that any API in Java that blocks the current thread should break out of the blockage and throw an InterruptedException if the thread receives an interrupt from the Thread.interrupt() method. This design allows code a chance to recover from overly long blockage, or perhaps simply to shut down on request. However, the get method attempts to get the result of the job’s execution. Given that the call method of Callable is permitted to throw an exception, it’s reasonable to infer that the get method might need to report that exception. Of course, the job itself might have been shut down, and the get method would need an abnormal termination mechanism (that is, another exception) to report that. Because there is more than one possible abnormal termination situation, get actually wraps those in an ExecutionException, and if the call method threw an exception, that exception would be the cause of the ExecutionException.

Because of this structure, option A is false (there is a checked exception that must be caught to allow the code to compile) and option D is also false (the checked exception thrown by the get method is not the one declared on the call method implementation). Instead, the “ideal” exception to handle would be ExecutionException, but this isn’t offered in the available options. Therefore, option E (catching a simple Exception, but at a valid place in the source code) has to be the correct answer.

There is another observation to be made about this question. The question’s construction actually gives away more than a real exam question would typically do. Imagine that you thought the exception that arose from the get method would actually be the one that comes directly from the call method—that is, a MyJobException. That would make both option D and option E correct. But the question calls for only one correct answer. This logic is actually sufficient for you to reject option D. Here, it’s a curiosity, but in a real exam question, know that unless there’s very specific wording, you are picking correct answers rather than the best answers. And on those very rare occasions where a best answer is called for in one of the programmer certification exams, you can expect very clear wording leading you to understand the criteria that constitute “best.”

 

Source: November/December 2016 issue of Java Magazine

About the author

Mushfiq Mammadov

Leave a Comment


The reCAPTCHA verification period has expired. Please reload the page.

 

This site uses Akismet to reduce spam. Learn how your comment data is processed.