Time required to pass OCP Java 17 exam

Time to prepare for OCP Java certification exam Determining the time required for passing the OCP Java 17 exam is highly dependent upon your current experience and expertise. The following estimates are based on our experience.

If you are:
  1. New to programming: 1+ Year 
  2. An expert in another language such as Python or JavaScript: 6+ months 
  3. Experienced in Java and have been programming in Java professionally for about an year: 3+ months 
  4. Already OCA 8 certified recently: 3+ months
  5. Already OCP 8 or OCP 11 certified recently: 1+ months 
This assumes about 3 hours of study per day. Study incudes reading book(s), writing test programs, and attempting mock exams. 

To get a better estimation for yourself, we suggest you to take a mock exam and see how you score. If you are able to pass the mock exam, you can go through the rest of the mock exams one by one (one per day), go through all the explanations after each mock exam. 

If you fail the mock exam but score above 50%, you may require about 1 month of effort to raise your score by 10 points. You will need to go through the topics on which you scored less from a book and write test programs before taking the next mock exams.

If you score too low, then you should to take a month or two to go through a book first and then come back to the mock exams.

Ideally, your score should increase with each mock exam and you can consider yourself ready if you are able to score about 75%.

But again, the above are just estimates based on our experience in training students. Only you know how you study and how fast you can learn new concepts. 

All the best!

Java 17 and 21 Switch statement and expression summary

Switch Statement (w/o pattern matching) Summary


Old Syntax ( : ) New Syntax( -> )
  Allows zero or more individual statements or zero or more code blocks.
Examples (all valid):
case 0:
case 1: stmt1; stmt2;
case 2: { <code block1>} { <code block 2> }
Allows either exactly one statement or exactly one code block.
Examples (all invalid):
case 0 -> //invalid, empty case
case 2 -> stmt1; stmt2; //invalid, more than one statement
case 4 -> { } { }//invalid, more than one block

Selector expression type Limited to: byte, short, int, char, and long and their wrappers, String, and enums
Not Allowed: boolean, float, and double
Limited to: byte, short, int, char, and long and their wrappers, String, and enums
Not Allowed: boolean, float, and double
Case label constant type Must be compatible with selector expression type. null is allowed in Java 21 but only if the switch is exhaustive. Must be compatible with selector expression type. null is allowed in Java 21 but only if the switch is exhaustive.
case label

Allows a single case constant. Allows multiple case constants separated by comma. Example:
case 1, 2 -> { }
default label  Not required Not required
Order of switch labels No restriction No restriction
 break Needed only to prevent fall through
Prohibited when a switch label is associated with a single statement.

Allowed within the code block  associated with a switch label but is redundant.
 yield Not allowed
Not allowed
 exhaustive Not neccessary  Not neccessary 



Switch Expression (w/o pattern matching) Summary


Old Syntax ( : ) New Syntax( -> )
  Allows one expression or one code block.
Examples:
case 0: yield 1; //valid, returns 1
case 3: yield "aa".length(); //valid, returns 2. case 2: "a".length(); //syntactically valid, no yield required for non-void method call but falls through without returning a value

case 1: 1; //invalid, missing yield keyword
Allows one expression or one code block.
Examples:
case 1 -> 1; //valid, returns 1, no yield required
case 3 -> "a".length();//valid, returns 1, no yield required
case 4 -> { yield 1; }//valid, yield is required in a block

case 0 -> //invalid, missing expression
case 2 -> yield 1; //invalid, must not write yield
Selector expression type Limited to: byte, short, int, char, and long and their wrappers, String, and enums
Not Allowed: boolean, float, and double
Limited to: byte, short, int, char, and long and their wrappers, String, and enums
Not Allowed: boolean, float, and double
Case label constant type Must be compatible with selector expression type. null is allowed in Java 21 but only if the switch is exhaustive. Must be compatible with selector expression type. null is allowed in Java 21 but only if the switch is exhaustive.
case label

Allows a single case constant. Allows multiple case constants separated by comma.
Example: case 1, 2 -> 1;
default label  Not required if already exhaustive Not required if already exhaustive
Order of switch labels No restriction No restriction
 break Prohibited Prohibited
 yield Required to return value
Required only when returning a value from a code block. Otherwise prohibited.
 exhaustive Neccessary  Neccessary 


Switch Statements and Expressions (w pattern matching) Summary (Java 21 Only)


Old Syntax ( : ) New Syntax( -> )
Selector expression type All types are allowed All types are allowed
Type of case constants Must be compatible with the type of the selector expression Must be compatible with the type of the selector expression
 exhaustive Necessary Necessary
default label 

Not required if already exhaustive
Not required if already exhaustive
Order of switch labels
Must follow the rule of dominance Must follow the rule of dominance
Fall through behavior Not allowed. So, break is required after each switch label. Fall through is not possible. break is prohibited.

1Z0 829 OCP Java 17 Certification Exam Ojectives

Java Certification 1Z0-829 Exam Objectives

Review exam topics for OCP Java 17 1Z0-829 Certification Exam (As of 2022/10/31)


Handling date, time, text, numeric and boolean values

  • Use primitives and wrapper classes including Math API, parentheses, type promotion, and casting to evaluate arithmetic and boolean expressions

  • Manipulate text, including text blocks, using String and StringBuilder classes

  • Manipulate date, time, duration, period, instant and time-zone objects using Date-Time API

Controlling Program Flow

  • Create program flow control constructs including if/else, switch statements and expressions, loops, and break and continue statements

Utilizing Java Object-Oriented Approach

  • Declare and instantiate Java objects including nested class objects, and explain the object life-cycle including creation, reassigning references, and garbage collection

  • Create classes and records, and define and use instance and static fields and methods, constructors, and instance and static initializers

  • Implement overloading, including var-arg methods

  • Understand variable scopes, use local variable type inference, apply encapsulation, and make objects immutable

  • Implement inheritance, including abstract and sealed classes. Override methods, including that of Object class. Implement polymorphism and differentiate object type versus reference type. Perform type casting, identify object types using instanceof operator and pattern matching

  • Create and use interfaces, identify functional interfaces, and utilize private, static, and default interface methods

  • Create and use enumerations with fields, methods and constructors

Handling Exceptions

  • Handle exceptions using try/catch/finally, try-with-resources, and multi-catch blocks, including custom exceptions

Working with Arrays and Collections

  • Create Java arrays, List, Set, Map, and Deque collections, and add, remove, update, retrieve and sort their elements

Working with Streams and Lambda expressions

  • Use Java object and primitive Streams, including lambda expressions implementing functional interfaces, to supply, filter, map, consume, and sort data

  • Perform decomposition, concatenation and reduction, and grouping and partitioning on sequential and parallel streams

Packaging and deploying Java code and use the Java Platform Module System

  • Define modules and their dependencies, expose module content including for reflection. Define services, producers, and consumers

  • Compile Java code, produce modular and non-modular jars, runtime images, and implement migration using unnamed and automatic modules

Managing concurrent code execution

  • Create worker threads using Runnable and Callable, manage the thread lifecycle, including automations provided by different Executor services and concurrent API

  • Develop thread-safe code, using different locking mechanisms and concurrent API

  • Process Java collections concurrently including the use of parallel streams

Using Java I/O API

  • Read and write console and file data using I/O Streams

  • Serialize and de-serialize Java objects

  • Create, traverse, read, and write Path objects and their properties using java.nio.file API

Accessing databases using JDBC

  • Create connections, create and execute basic, prepared and callable statements, process query results and control transactions using JDBC API

Implementing Localization

  • Implement localization using locales, resource bundles, parse and format messages, dates, times, and numbers including currency and percentage values

Assume the following:

  • Missing package and import statements: If sample code do not include package or import statements, and the question does not explicitly refer to these missing statements, then assume that all sample code is in the same package, or import statements exist to support them.

  • No file or directory path names for classes: If a question does not state the file names or directory locations of classes, then assume one of the following, whichever will enable the code to compile and run:

    • All classes are in one file

    • Each class is contained in a separate file, and all files are in one directory

  • Unintended line breaks: Sample code might have unintended line breaks. If you see a line of code that looks like it has wrapped, and this creates a situation where the wrapping is significant (for example, a quoted String literal has wrapped), assume that the wrapping is an extension of the same line, and the line does not contain a hard carriage return that would cause a compilation failure.

  • Code fragments: A code fragment is a small section of source code presented without its context. Assume that all necessary supporting code exists and that the supporting environment fully supports the correct compilation and execution of the code shown and its omitted environment.

  • Descriptive comments: Take descriptive comments, such as "setter and getters go here," at face value. Assume that correct code exists, compiles, and runs successfully to create the described effect.

Candidates are also expected to:

  • Understand the basics of Java Logging API.

  • Use Annotations such as Override, Functionalnterface, Deprecated, SuppressWarnings, and SafeVarargs.

OCP Java SE 17 Developer (Exam 1Z0-829) Programmer's Guide by Khalid Mughal and Vasily Strelnikov - Book Review by Hanumant Deshmukh

OCP Java SE 17 Developer (Exam 1Z0-829) Programmer's Guide by Khalid Mughal and Vasily Strelnikov - Book Review by Hanumant Deshmukh
We, at Enthuware, are always on the lookout for good study material for various Java Certification exams. We were elated when we learnt about the new book on OCP Java 17 certification (Exam Code 1z0-817) exam written by Khalid Mughal and Vasily Strelnikov. Mr Mughal needs no introduction, as he has been a Java expert at least since I started programming in Java. I passed my first Java certification more than 20 years ago (it was called SCJP 1.2 back then) using his book. There were multiple certification books at that time, and his book stood out due to the quality of its contents in terms of coverage, depth, and technical precision.

In the present day, the latest professional level Java Certification is the OCP Java 17 certification, and a there is only one book on the market for this exam as of now (March 2023). A second book by a seasoned expert such as Mr. Mughal is greatly appreciated.

Last week I received a copy of the new book for review, and here are my thoughts about it:

  1. The book is huge at 1800 pages and comes in two volumes. I can easily see why that is. First, the exam covers a wide range of topics ranging from beginner to expert level. Any book that claims to prepare a student for this exam will be thick. Second, this book doesn't cut corners. If the authors feel something is important enough to be told and explained, then it is covered even if it is not directly mentioned in the exam. Third, the book can be used even by a Java beginner, so concepts are taught from the ground up.

  2. While going through the book, I noticed that it covered some topics such as Annotations and Security, that are not present on the OCP Java 17 exam anymore. They were there on the older Java 11 exam. I enquired about it with the authors and learned that they included these topics partly because they felt they were important and partly to make the book useful for candidates taking the OCP Java 11 (Exam Code 1Z0-819) exam.

  3. Complicated concepts such as Generics have been taught thoroughly. For example, students find it confusing that Node<Integer> and Node<Double> are not subtypes of Node<Number> even though Integer and Double are subtypes of Number. Concurrency and parallalism is another tough topic to grasp. The book explains all such topics in great detail.

  4. The chapters are peppered with objective questions, and at the end there is a full sized mock exam with detailed explanations for all of the questions.

  5. If you are short on time and want to just focus on passing the exam in the shortest time possible, then you may have to look for other resources because the book does include topics that are not required for the exam at all. For example, Appendix G on the Java Logging API can be skipped. But in all fairness, the official exam objectives do mention it in passing. We haven't prepared a complete list of such topics, but we might do that later as we start using the book in our training program.
Overall, the book is quite useful for anyone studying for this exam. I am happy to note that this book has maintained the same standard that I appreciated as a test taker twenty years ago, and if you are planning to have a career in Java programming, I wholeheartedly recommend studying for the OCP Java 17 exam using this book.

Hanumant Deshmukh
Director, Enthuware
OCP Java 11 Certification Sample Questions from Enthuware Practice Tests

OCP Java 11 Certification 1Z0-819 Sample Questions



The following are not 1z0-819 dumps but are sample questions extracted from Enthuware OCP Java 11 Exam Simulator, which contains more than 1000 practice questions with detailed explanations packaged in 20 practice tests. Stay away from sites offering Java certification dumps because they are highly unreliable.
Question 1.     Topic: Java OOA - Inner and final classes     Toughness: Very Tough

Which of the given options if put at //1 will correctly instantiate objects of various classes defined in the following code?


public class TestClass
{
   public class A{
   }
   public static class B {
   }
   public static void main(String args[]){
      class C{
      }
      //1
   }
}

Select 2 options:

  1. new TestClass().new A();
  2. new TestClass().new B();
  3. new TestClass.A();
    A is not static. So no outer instance of TestClass is necessary.
  4. new C();
  5. new TestClass.C();
   Click to see discussion about this Question!
Correct options are: 1, 4
class A is not static inner class of TestClass. So it cannot exist without an outer instance of TestClass. So, option 1 is the right way to instantiate it.
class B is static inner class and can be instantiated like this: new TestClass.B(). But new TestClass().new B() is not correct.
Although not related to this question, unlike popular belief, anonymous class can never be static. Even if created in a static method.

Question 2.     Topic: Streams and Lambda - Builtin Functional Interfaces     Toughness: Real Brainer

What will the following code print when compiled and run?

public class TestClass{
    
    public static int operate(IntUnaryOperator iuo){
        return iuo.applyAsInt(5);
    }
    
    public static void main(String[] args) {
        
        IntFunction<IntUnaryOperator> fo = a->b->a-b;  //1
        
        var x = operate(fo.apply(20)); //2
        System.out.println(x);
    }
}

Select 1 best option:

  1. Compilation error at //1
  2. Compilation error at //2
  3. 15
  4. -15
  5. 20
  6. Exception at run time
   Click to see discussion about this Question!
Correct option is: 3
The lambda expression a->b->a-b looks complicated but it is actually simple if you group it like this:
a->(b->a-b);

1. IntFunction is a functional interface that takes an int and returns whatever it is typed to. Here, the IntFunction is typed to IntUnaryOperator. Therefore, IntFunction<IntUnaryOperator> will take in an int and return IntUnaryOperator.
The general form of a lambda expression that captures IntFunction would be x->line of code that returns the correct return type i.e. IntUnaryOperator, in this case; where x is an int.

Now, if you look at fo = a->b->a-b;, a is the argument variable of type int (because it is being used to capture IntFunction) and b->a-b forms the method body of the IntFunction. b->a-b must somehow return an IntUnaryOperator for fo = a->b->a-b; to work.


2. IntUnaryOperator is a functional interface that takes in an int and returns another int. It cannot be typed to anything else because both the input and the output are already defined to be int.
The general form of a lambda expression that captures IntUnaryOperator would be y->line of code that returns an int; where y is an int.

Now, in the case of b->a-b; you can see that b is the argument variable and a-b is the method body. For a-b to capture IntUnaryOperator, a must already be defined and it must be an int. Only then will a-b return an int (which is required to capture IntUnaryOperator). That is indeed the case because a is already defined as the argument variable of the encompassing lambda expression and is available for use within the method body of that expression.


3. So basically, when you call fo.apply(20), you are setting a to 20. Therefore, fo.apply(20) returns an IntUnaryFunction that returns 20-b, where b is the argument passed to the IntUnaryFunction. When you call iuo.applyAsInt(5); b is being set to 5. Therefore iuo.applyAsInt(5) will return 20-5 i.e. 15.


Question 3.     Topic: Streams and Lambda - Lambda Operations on Streams     Toughness: Real Brainer

Given:

public class Student {

    public static enum Grade{ A, B , C, D, F}   

    private String name;
    private Grade grade;
    public Student(String name, Grade grade){
        this.name = name;
        this.grade = grade;
    }
    public String toString(){
        return name+":"+grade;
    }
    //getters and setters not shown
}

What can be inserted in the code below so that it will print:
{C=[S3], A=[S1, S2]}


List<Student> ls = Arrays.asList(new Student("S1", Student.Grade.A), new Student("S2", Student.Grade.A), new Student("S3", Student.Grade.C));
//INSERT CODE HERE
System.out.println(grouping);

Select 1 best option:

  1. Map<Student.Grade, List<Student>> grouping = ls.stream().collect(
            Collectors.groupingBy(Student::getGrade),
            Collectors.groupingBy(Student::getName, Collectors.toList())));

    Invalid arguments to the collect method.

    Remember that Stream has only two overloaded collect methods - one that takes a Collector as an argument and another one that takes a Supplier, BiConsumer, and BiConsumer. In this option, it is trying to pass two Collectors to the collect method. Therefore, it will not compile.

    1. public <R,A> R collect(Collector<? super T,A,R> collector)
    Performs a mutable reduction operation on the elements of this stream using a Collector. A Collector encapsulates the functions used as arguments to Stream.collect(Supplier, BiConsumer, BiConsumer), allowing for reuse of collection strategies and composition of collect operations such as multiple-level grouping or partitioning.

    2.public <R> R collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner)
    Performs a mutable reduction operation on the elements of this stream. A mutable reduction is one in which the reduced value is a mutable result container, such as an ArrayList, and elements are incorporated by updating the state of the result rather than by replacing the result.
  2. Map<Student.Grade, List<String>> grouping = ls.stream().collect(
            Collectors.groupingBy(Student::getGrade,
                Collectors.groupingBy(Student::getName, Collectors.toList())));

    The right hand side of = is actually okay from a compilation perspective. It is trying to group the elements of the stream by Grade and then it is again trying to groups the elements of each grade by name. So technically, the return type of this expression would be:
    Map<Student.Grade, Map<String, List<Student>>> grouping = ...

    Even if you change the left hand side declaration as described, it will only print {C={S3=[S3:C]}, A={S1=[S1:A], S2=[S2:A]}}, which is not what is required by the question.
  3. Map<Student.Grade, List<String>> grouping = ls.stream().collect(
        Collectors.groupingBy(Student::getGrade,
        Collectors.mapping(Student::getName, Collectors.toList())));
    This code illustrates how to cascade Collectors.
    Here, you are first grouping the elements by Grade and then collecting each element of a particular grade into a list after mapping it to a String. This will produce the required output.
  4. Map<Student.Grade, List<String>> grouping = ls.stream().collect(
                    Collectors.groupingBy(Student::getGrade,
                    Collectors.mapping(Student::getName)));
    Collectors.mapping method requires two arguments - the first argument must be a Function that maps one element type into another (here, you are mapping Student to String, which is good), and the second argument must be an appropriate Collector in which you can hold the result (here, this argument is missing). Therefore, it will not compile.
   Click to see discussion about this Question!
Correct option is: 3

Question 4.     Topic: Secure coding in Java SE Application     Toughness: Very Tough

The developer of a method that accesses the file system wants to ensure that the caller has appropriate permissions. She has written the following code:


public class FileOps {
     public static void doOps() {
                return AccessController.doPrivileged(
                    new PrivilegedAction<String>() {
                        public String run() {
                            //do File operations here
                        }
                    }, AccessController.getContext()
                );
            }
}


What, if anything, is wrong with this code from a security perspective?

Select 1 best option:

  1. This code does not really check the permissions of the caller.
    The second argument to doPrivileged (for which AccessController.getContext() in being passed here), returns the caller's permissions.
  2. This code violates secure coding guidelines because it does not check the return value of AccessController.getContext() for null.
    AccessController.getContext() never returns null.
    Null check is required when an AccessControlContext object is received an argument. Since null implies no restrictions, you must check it for null before performing sensitive operations:

    public static void doOps(AccessControlContext ctx){
            if (ctx == null) {
                throw new SecurityException("Missing AccessControlContext");
            }
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        ...
                    }
                }, ctx);
    }
  3. This code is fine and does not violate secure coding guidelines.
  4. It should use AccessController.getParentContext() instead of AccessController.getContext() as the second argument to doPrivileged.
    There is no getParentContext method.
    The getContext method takes a "snapshot" of the current calling context, and places it in an AccessControlContext object, which it returns.
   Click to see discussion about this Question!
Correct option is: 3

Question 5.     Topic: Java I/O API - NIO 2 - Files class     Toughness: Very Tough

What will the following code print if file test1.txt exists but test2.txt doesn't exist?
public class FileCopier {
    
    public static void copy1(Path p1, Path p2) throws Exception {
        Files.copy(p1, p2, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING);
    }
    
    
    public static void main(String[] args) throws Exception {
        var p1 = Paths.get("c:\\temp\\test1.txt");
        var p2  = Paths.get("c:\\temp\\test2.txt");
        copy1(p1, p2);
        if(Files.isSameFile(p1, p2)){
            System.out.println("file copied");
        }else{
            System.out.println("unable to copy file");
        }
    }
}

Select 1 best option:

  1. An exception at run time if either of p1 or p1 is a symbolic link.
  2. It will print file copied and test2.txt will contains the same data as test1.txt.
  3. It will print file copied but test2.txt will NOT contain the same data as test1.txt.
  4. It will print unable to copy file but test2.txt will contain the same data as test1.txt.
  5. It will print unable to copy file and test2.txt will not be created.
   Click to see discussion about this Question!
Correct option is: 4
Files.copy method will copy the file test1.txt into test2.txt. If test2.txt doesn't exist, it will be created. However, Files.isSameFile method doesn't check the contents of the file. It is meant to check if the two path objects resolve to the same file or not. In this case, they are not, and so, it will return false.

The following is a brief JavaDoc description for both the methods:

public static Path copy(Path source, Path target, CopyOption... options)
                 throws IOException

Copy a file to a target file.
This method copies a file to the target file with the options parameter specifying how the copy is performed. By default, the copy fails if the target file already exists or is a symbolic link, except if the source and target are the same file, in which case the method completes without copying the file. File attributes are not required to be copied to the target file. If symbolic links are supported, and the file is a symbolic link, then the final target of the link is copied. If the file is a directory then it creates an empty directory in the target location (entries in the directory are not copied).

The options parameter may include any of the following:

REPLACE_EXISTING     If the target file exists, then the target file is replaced if it is not a non-empty directory. If the target file exists and is a symbolic link, then the symbolic link itself, not the target of the link, is replaced.

COPY_ATTRIBUTES     Attempts to copy the file attributes associated with this file to the target file. The exact file attributes that are copied is platform and file system dependent and therefore unspecified. Minimally, the last-modified-time is copied to the target file if supported by both the source and target file store. Copying of file timestamps may result in precision loss.

NOFOLLOW_LINKS     Symbolic links are not followed. If the file is a symbolic link, then the symbolic link itself, not the target of the link, is copied. It is implementation specific if file attributes can be copied to the new link. In other words, the COPY_ATTRIBUTES option may be ignored when copying a symbolic link.
An implementation of this interface may support additional implementation specific options.

Copying a file is not an atomic operation. If an IOException is thrown then it possible that the target file is incomplete or some of its file attributes have not been copied from the source file. When the REPLACE_EXISTING option is specified and the target file exists, then the target file is replaced. The check for the existence of the file and the creation of the new file may not be atomic with respect to other file system activities.



public static boolean isSameFile(Path path, Path path2)
                          throws IOException

Tests if two paths locate the same file.
If both Path objects are equal then this method returns true without checking if the file exists. If the two Path objects are associated with different providers then this method returns false. Otherwise, this method checks if both Path objects locate the same file, and depending on the implementation, may require to open or access both files.



Question 6.     Topic: Java OOA - Enumerations     Toughness: Tough

Which of the following lines will cause the compilation to fail??

public enum EnumA{ A, AA, AAA};  //1

public class TestClass //2
{
   public enum EnumB{ B, BB, BBB }; //3
   public static enum EnumC{ C, CC, CCC }; //4
   public TestClass()
   {
       enum EnumD{ D, DD, DDD } //5    
   }

   public void methodX()
   {
      public enum EnumE{ E, EE, EEE } //6
   }

   public static void main(String[] args) //7
   {
       enum EnumF{ F, FF, FFF}; //8
   }
}

Select 4 options:

  1. 1, 2, or both depending on the file name.
    Since both EnumA and TestClass are public, they must be defined in a file with a name of EnumA.java and TestClass.java respectively.
  2. 3
    A public (or non-public) enum can be defined inside any class.
  3. 4
    An enum can be defined as a static member of any class. You can also have multiple public enums with in the same class.
  4. 5
    An enum cannot be defined inside any method or constructor.
  5. 6
    An enum cannot be defined inside any method or constructor.
  6. 7
    There is nothing wrong with this line.
  7. 8
    An enum cannot be defined inside any method or constructor.
   Click to see discussion about this Question!
Correct options are: 1, 4, 5, 7

Question 7.     Topic: Database Applications with JDBC     Toughness: Real Brainer

Given:
var qr = "insert into USERINFO values( ?, ?, ?)";
try(PreparedStatement ps =  c.prepareStatement(qr);)
{
    ps.setObject(1, 1, JDBCType.INTEGER);
    ps.setObject(2, "Ally A", JDBCType.VARCHAR);
    ps.setObject(3, "101 main str", JDBCType.VARCHAR);
    var i = ps.executeUpdate(); //1
    ps.setObject(1, 2, JDBCType.INTEGER);
    ps.setObject(2, "Bob B", JDBCType.VARCHAR);
    i = ps.executeUpdate(); //2
}


What will be the result?

Select 1 best option:

  1. An exception will be thrown at //1
  2. An exception will be thrown at //2
  3. Two rows with the following values will be inserted in the USERINFO table:
    1, Ally A, 101 main str
    2, Bob B, null
  4. Two rows with the following values will be inserted in the USERINFO table:
    1, Ally A, 101 main str
    2, Bob B, 101 main str
  5. One row with the following values will be inserted in the USERINFO table:
    1, Ally A, 101 main str
    and an exception will be thrown at //2.
   Click to see discussion about this Question!
Correct option is: 4
This question is based on the fact that a PreparedStatement remembers the values that you set for every parameter until you close that PreparedStatement object (by calling close() on it). So, if you execute the same query multiple times with same values for some columns, you don't need to set the values for those columns again and again. Setting them once is fine. You need to set values for only those columns that require a change.

Question 8.     Topic: Modules - Services in a Modular Application     Toughness: Real Brainer

Given the following module-info:

module book{
   requires org.pdf;
   uses org.pdf.Print;
}


Which of the following statements are correct?

Select 1 best option:

  1. book module can be compiled without requiring any module that provides Print service.
    book module depends only on the module that defines Print service. It does not depend on any module that implements Print service.

    A module providing an implementation of the Print interface will need to be available at run time on the module-path only if the book module tries to locate and use a Print service using ServiceLoader. Even at run time, if no print service is found, there will not be any exception thrown by the JVM on its own. ServiceLoader.load(Print.class) will simply return an Iterator with zero elements in that case.
  2. At least one implementation of Print service must be available on module-source-path for book module to compile.
  3. At least one implementation of Print service must be available for book module to execute without an exception.
    This is not really necessary because it depends on what the book module does. For example, if a class in book module does the following:

       ServiceLoader<Print> pLoader = ServiceLoader.load(Print.class); // note that ServiceLoader implements Iterable interface
       for (Print p : pLoader){
             p.print("Hello");
        }


    There will be no exception even if there is no module that provides Print implementation because ServiceLoader.load will return a ServiceLoader with no elements.
  4. At least one implementation of Print service must be available for book module to load successfully at run time.
    The JVM does not check whether a service implementation is present or not while loading a module.
  5. The requires org.pdf; clause in the given module-info is redundant.
    This clause is actually required because org.pdf is the module that contains org.pdf.Print interface. Coincidently, org.pdf is also the package to which Print belongs but that is irrelevant here because requires clause contains the module name, not the package name.
   Click to see discussion about this Question!
Correct option is: 1

Question 9.     Topic: Java OOA - Object Initialization     Toughness: Very Tough

Consider the classes shown below:


class A{
   public A() { }
   public A(int i) {   System.out.println(i );    }
}
class B{
   static A s1 = new A(1);
   A a = new A(2);
   public static void main(String[] args){
      var b = new B();
      var a = new A(3);
   }
   static A s2 = new A(4);
}
Which is the correct sequence of the digits that will be printed when B is run?

Select 1 best option:

  1. 1 ,2 ,3 4.
  2. 1 ,4, 2 ,3
  3. 3, 1, 2, 4
  4. 2, 1, 4, 3
  5. 2, 3, 1, 4
   Click to see discussion about this Question!
Correct option is: 2
1. All static constants, variables, and blocks. Among themselves the order is the order in which they appear in the code. This step is actually a part of "class initialization" rather than "instance initialization". Class initialization happens only if the class is being used for the first time while being instantiated. For example, if you have invoked a static method of a class or accessed a static field of that class earlier in the code, you have already used the class and the JVM would have performed initialization of this class at that time. Thus, there wouldn't be any need to initialize the class if you instantiate an object of this class now.

Further, if the class has a superclass, then the JVM performs this step for the superclass first (if the superclass hasn't been initialized already) and only after the superclass is initialized and static blocks are executed, does the JVM proceed with this class. This process is followed recursively up to the java.lang.Object class.

2. All non static constants, variables, and blocks. Among themselves the order is the order in which they appear in the code.

3. Constructor.

Just like the class initialization, instance initialization also happens for the superclass first. That is, if the class has a superclass, then the JVM takes steps 2 and 3 given above for the superclass first and only after the superclass's instance members are initialized, does the JVM proceed with this class. This process is also followed recursively up to the java.lang.Object class.

Question 10.     Topic: Secure coding in Java SE Application     Toughness: Very Tough

Given the following class:

class Person{
  private String name;
  private java.time.LocalDate dob;
  
  public Person(String name, java.time.LocalDate dob){
     this.name = name;
     this.dob = dob;
  }
  //public getters and setters for name and dob

}


and the following method appearing in some other class:

public List<Person> getEligiblePersons(List<Person> people){
    var pl = new ArrayList<Person>();
    for(var p : people){
        if(p.getDob().isBefore(cutoff)){
            pl.add(p);
        }
    }
    return pl;
}

Select 2 options:

  1. There is no issue with the given code.
  2. A copy of dob parameter should be made and that copy should be assigned to the dob field.
    This is not required because LocalDate is immutable.
  3. getEligiblePersons should create a deep copy of the people list before processing the elements.
    Observe that Person class is mutable (due the the presence of setter methods). Therefore, it is possible that a Person object's dob field is changed by another code while the method is processing Person objects. ( Guideline 6-3 / MUTABLE-3: Create safe copies of mutable and subclassable input values )

    Ideally, Person class should provide a copy constructor or some other means to create a copy of a Person instance. (Guideline 6-4 / MUTABLE-4: Support copy functionality for a mutable class.)
  4. Person class should provide a copy constructor.
    Since Person class is mutable, it should provide a way for users to create a copy of a Person instance which can be used independently without the threat of getting modified by some other code.

    Something like:
    public Person copy(){
       return new Person(this.getName(), this.getDob());
    }


    Guideline 6-4 / MUTABLE-4: Support copy functionality for a mutable class
  5. Person class should be made final.
   Click to see discussion about this Question!
Correct options are: 3, 4

Question 11.     Topic: Annotations     Toughness: Real Brainer

Given :

//1
public class TestClass {
//2
   public static void main(String[] args) throws Exception{
        var al = new ArrayList<Integer>();
        printElements(al);
   }

//3
    static void printElements(List<Integer>... la) {
       for(List<Integer> l : la){
           System.out.println(l);
       }
    }
}


Which option(s) will get rid of compilation warning(s) for the above code?

Select 1 best option:

  1. Apply @SuppressWarnings("all") at //1
    Although you can pass any string value to the SuppressWarnings annotation (unrecognized values are ignored), the Java specification mandates only three values - unchecked, deprecation, and removal. Different compilers and IDEs may support other values in addition to these three.

    In this particular case, "all" is not a valid argument for @SuppressWarnings. @SuppressWarnings("unchecked") will work.

    Applying @SuppressWarnings("unchecked") on the class suppresses all unchecked warnings from that class. Note that the set of warnings suppressed in a given element is a superset of the warnings suppressed in all containing elements. For example, if you annotate a class to suppress one warning and annotate a method to suppress another, both warnings will be suppressed in the method. However, note that if a warning is suppressed in a module-info file, the suppression applies to elements within the file and not to types contained within the module.

    As a matter of style, programmers should always use this annotation on the most deeply nested element where it is effective. If you want to suppress a warning in a particular method, you should annotate that method rather than its class.
  2. Apply @SuppressWarnings("unchecked") at //2
  3. Apply @SuppressWarnings("rawtypes") at //2
  4. Apply @SuppressWarnings("rawtypes") at //3
    The "rawtypes" warning is issued when you use a parameterized class without a type parameter. For example, List al = new ArrayList();. Here, List and ArrayList are parameterized classes and you should specify the type parameter in the declaration and instantiation i.e. List<String> al = new ArrayList<>();

    The "unchecked" warning is issued where a compiler is not able to check the type safety of the operation. For example:

    List al = new ArrayList(); //rawtypes warning here
    al.add(""); //unchecked warning here
  5. Apply @SuppressWarnings("unchecked") at //2 as well as //3.
    Any time you invoke a method or declare a method that uses varargs with a generic type, you will get an "unchecked" warning. Thus, @SuppressWarnings("unchecked') would be issued because of the call to printElements(al) in main and the declaration of the printElements method.
  6. Apply @SuppressWarnings("rawtypes") at //2 as well as //3.
   Click to see discussion about this Question!
Correct option is: 5

Question 12.     Topic: Java OOA - Interfaces     Toughness: Real Brainer

Which of the following statements are correct regarding abstract classes and interfaces?

Select 2 options:

  1. An abstract class can have private as well as static methods while an interface can not have static methods.
    Interfaces can have static methods (public as well as private). Interfaces cannot have protected methods. It cannot have non-public fields and instance fields.
  2. An abstract class cannot implement multiple interfaces while an interface can extend multiple interfaces.
    An abstract class (or any class for that matter) can implement any number of interfaces.
  3. Abstract classes can have abstract methods but interface cannot.
    Both abstract classes and interfaces can have abstract as well as non-abstract methods. The difference is that by default (i.e. when no modifier is specified), the methods of an abstract class have "default" access and are non-abstract (i.e. they must have a body), while the methods of an interface are public and abstract.
  4. Abstract classes can have instance fields but interfaces can't.
    Fields of an interface are always public, static, and final.
  5. An abstract class can have final methods but an interface cannot.
   Click to see discussion about this Question!
Correct options are: 4, 5

Question 13.     Topic: Streams and Lambda - Functional Interface and Lambda Expressions     Toughness: Real Brainer

Given:

//assume appropriate imports
public class Calculator{
    public static void main(String[] args) {
        double principle = 100;
        int interestrate = 5;
        double amount = compute(principle, x->x*interestrate);
    }
    
    INSERT CODE HERE
}

Which of the following methods can be inserted in the above code so that it will compile and run without any error/exception?

Select 2 options:

  1. public static double compute(double base, Function<Integer, Integer > func){
        return func.apply((int)base);
    }
  2. public static double compute(double base, Function<Integer, Double> func){
        return func.apply((int)base);
    }
    The method definition is fine. But the usage of this method i.e. compute(principle, x->x*interestrate); will not compile because the type of the expression that makes up the body of the function i.e. x*interestrate is int, while the expected return type of the Function is Double. int cannot be boxed to a Double.
    You could do this though: double amount = compute(principle, x->new Double(x*interestrate));
  3. public static double compute(double base, Function<Double, Integer> func){
        return func.apply(base);
    }
    Function<Double, Integer> implies that your argument type is Double and return type is Integer. However, the return type of the lambda expression x->x*interestrate is Double because you are passing base, which is a double, as the argument to this function..
  4. public static double compute(double base, Function<Double, Double> func){
        return func.apply(base);
    }
  5. public static double compute(double base, Function<Integer, Double> func){
        return func.apply(base);
    }
    Function<Integer, Double> implies that your argument type is Integer and return type is Double. However, you are passing base, which is double, to this function. You cannot pass a double where an int or Integer is required without explicit cast due to potential loss of precision.
   Click to see discussion about this Question!
Correct options are: 1, 4
The lambda expression x->x*interestrate basically takes an input value, modifies it, and return the new value. It is, therefore, acting as a Function.
Therefore, you need a method named compute that takes two arguments - an double value and a Function instance. Option 1 and 4 provide just such a method.

Question 14.     Topic: Concurrency     Toughness: Tough

Consider the following code:

class Account{
    private String id; private double balance;

    ReentrantLock lock = new ReentrantLock();
    
    public void withdraw(double amt){
        try{
            lock.lock();
            if(balance > amt) balance = balance - amt;
        }finally{
            lock.unlock();
        }
    }
}

What can be done to make the above code thread safe?

Select 1 best option:

  1. Change new ReentrantLock() to new ReentrantLock(true).
    ReentrantLock has two constructors - the no-args one and the boolean one. The boolean constructor allows you to specify whether you want to apply fairness policy or not.
    In this case, either of the constructors is fine. There is no need to change.
  2. Move the call to lock.lock(); to before the try block.
    Although valid, this change is not required.
  3. Declare lock variable as private and final.
    Unless lock is private and final, it can be changed to point to some other object by another thread. In that case, the whole point of locking the critical section of the code using the same lock will be lost.
  4. Make the lock variable private, final, and static.
    Making it static will cause all Account object to use the same lock. This means only one Account object can be used at any time, which will drastically reduce performance and is not desired.
  5. Make the lock variable static.
  6. No change is required.
   Click to see discussion about this Question!
Correct option is: 3

Question 15.     Topic: Modules - Migration to Modular Application     Toughness: Real Brainer

Your application uses one modular jar (a.jar), which, in turn, uses one non-modular jar (b.jar). Which of the following commands will cause jdeps to include the non-modular jar in its analysis?

Select 1 best option:

  1. jdeps -module-path lib\a.jar; -classpath lib\b.jar
    This is an invalid usage of jdeps. After specifying options, you must specify the target file that you want to analyze.

    Usage: jdeps <options> <path ...>]
    <path> can be a pathname to a .class file, a directory, a JAR file.

  2. jdeps --module-path lib\a.jar; lib\b.jar
    If you put a.jar on module-path, then jdeps will try to build its module graph. It will look for module b (because it is given in the problem statement that a.jar uses b.jar). But b.jar is not on the module-path, so jdeps will given an error saying a required module b is not found.
  3. jdeps --class-path lib\a.jar; lib\b.jar
    Ideally, since a.jar is a module, it should be put on the module-path. However, if b.jar does not refer to classes from a.jar, this will work and will do the analysis for b.jar.

    --class-path lib\a.jar; is of no use in this case.

    BTW, -cp -classpath and --class-path are equivalent.
  4. jdeps -cp lib\b.jar lib\a.jar
    Note that the problem statement says that a.jar uses b.jar. Since a.jar is a modular jar, it cannot access classes from b.jar if b.jar is put on classpath.  b.jar must be put on the module-path so that it can be converted into an automatic module and be accessible from a.jar.
    Thus, while analyzing a.jar, jdeps will generate an error saying a required module b is not found.
  5. jdeps -cp lib\b.jar;lib\a.jar
    A target path is required.
   Click to see discussion about this Question!
Correct option is: 3
Please go through the documentation for jdeps given here: https://docs.oracle.com/en/java/javase/11/tools/jdeps.html


jdeps can analyze one or multiple class file(s) or jar file(s). If a given target file depends on a module, then that module must be specified on --module-path (or -p). If the given target file depends on a non-modular jar file (or a class ), then that jar (or class) must be specified on -classpath (or --class-path or -cp).

Question 16.     Topic: Localization     Toughness: Real Brainer

Consider the following piece of code:

        Locale.setDefault(new Locale("fr", "CA")); //Set default to French Canada
        Locale l = new Locale("jp", "JP");
        ResourceBundle rb = ResourceBundle.getBundle("appmessages", l);
        String msg = rb.getString("greetings");
        System.out.println(msg);

You have created two resource bundle files with the following contents:

#In appmessages.properties:
greetings=Hello

#In appmessages_fr_FR.properties:
greetings=bonjour

Given that this code is run on machines all over the world. Which of the following statements are correct?

Select 1 best option:

  1. It will throw an exception when the default locale of the machine where it is run is different from fr/FR and fr/CA.
  2. It will throw an exception where ever it is run.
  3. It will throw an exception when the default locale of the machine is fr/CA.
  4. It will throw an exception when the default locale of the machine is jp/JP.
  5. It will run without any exception all over the world.
   Click to see discussion about this Question!
Correct option is: 5
While retrieving a message bundle, you are passing a locale explicitly (jp/JP). Therefore, it will first try to load appmessages_jp_JP.properties. Since this file is not present, it will look for a resource bundle for default locale. Since you are changing the default locale to "fr", "CA", it will look for appmessages_fr_CA.properties, which is also not present.

Remember that when a resource bundle is not found for a given locale, the default locale is used to load the resource bundle.  Every effort is made to load a resource bundle if one is not found and there are several fall back options (in absence of appmessages_fr_CA.properties, it will look for appmessages_fr.properties). As a last resort, it will try to load a resource bundle with no locale information i.e. appmessages.properties in this case. (An exception is thrown when even this resource bundle is not found.)

Since appmessages.properties is available, the code will never throw an exception in any locale.

You need to understand this aspect for the purpose of the exam. Please go through http://docs.oracle.com/javase/7/docs/api/java/util/ResourceBundle.html#getBundle(java.lang.String,%20java.util.Locale,%20java.lang.ClassLoader) for further details.