User Konstantin
Konstantin
Level 36
Odesa

Exploring questions and answers from a job interview for a Java developer position. Part 8

Published in the Random group
Practice or theory? What's more important? Many people will naturally say that practice is more important. Like, practice until the sun goes down and you will be happy. I will dare to disagree with this. Exploring questions and answers from a job interview for a Java developer position. Part 8 - 1During interviews, no one will ever know how cool you are when you're practicing. Instead, you will be asked to demonstrate your theory chops. It won't be until later when you've gotten past all the layers of interviews and get assigned to a project, that you will apply your practical skills. You may object, saying sometimes they give you a test task, so practice is still needed. I don't disagree, but my point is that this is SOMETIMES, but you ALWAYS need to demonstrate knowledge of theory in an interview. Do you feel the difference? All this means that you must have a solid theoretical foundation under your feet, and that is what we're going to continue to build today. More specifically, we will continue to look at questions that are often asked in interviews.

71. What happens if we don't override Enum's toString() method?

Suppose we have the following enum:

public enum Role {
   STUDENT,
   TEACHER,
   DIRECTOR,
   SECURITY_GUARD;
}
Let's display the STUDENT field on the console by calling its toString() method:

System.out.println(Role.STUDENT.toString());
As a result, we get the following console output:
STUDENT
Thus, we see that for an enum, the default implementation of toString() returns the name of the constant itself.

72. Can you declare a constructor inside an Enum?

Yes, of course. The constructor is what sets the values of the enum's internal fields. As an example, let's add two fields to the previous enum (ageFrom and ageTo) to indicate the age range for each role:

public enum Role {
   STUDENT(5,18),
   TEACHER(20,60),
   DIRECTOR(40,70),
   SECURITY_GUARD(18,50);
 
   int ageFrom;
   int ageTo;
 
   Role(int ageFrom, int ageTo) {
       this.ageFrom = ageFrom;
       this.ageTo = ageTo;
   }
}

73. What's the difference between == and equals()?

This is one of the most common interview questions asked of would-be Java developers. To begin with, when comparing simple values (int, char, double...), we use ==, since these variables contain concrete values that can be compared directly. What's more, primitive variables are not full-fledged objects — they don't inherit the Object class and don't have an equals() method. If we're talking about comparing variables that refer to objects, then we need to know that == only compares the value of the references, i.e. whether they refer to the same object or not. Even if all the data in one object is identical to all the data in another one, using == for a comparison will yield a negative result (false), because they are separate objects. As you may have guessed, we use the equals() method to compare reference variables. This is one of the Object class's standard methods, and is necessary for a full-fledged comparison of objects. But I need to say right away that in order for this method to work correctly, it must be overridden to indicate exactly how the objects should be compared. If you don't override the method, then you'll get the default implementation, which compare the objects using ==. In IntelliJ IDEA, you can override it automatically using an IDEA shortcut: Alt+Insert. In the window that appears, select equals() and hashCode(). Then select the fields that should be involved. Voila! The methods are automatically implemented. Here's an example of how an automatically generated equals method looks for the simplest possible Cat class with two fields — int age and String name:

@Override
public boolean equals(final Object o) {
   if (this == o) return true;
   if (o == null || this.getClass() != o.getClass()) return false;
   final Cat cat = (Cat) o;
   return this.age == cat.age &&
           Objects.equals(this.name, cat.name);
}
When it comes to enum, there isn't a practical difference between == and equals(). Exploring questions and answers from a job interview for a Java developer position. Part 8 - 2After all, an enum stores constants, and even when we compare identical values using ==, we'll get true, since the compared references will always point to the same objects. And using equals() gets us the correct result as well. If you go into the body of the equals method for Enum, you will see that the Enum class has the following implementation: Exploring questions and answers from a job interview for a Java developer position. Part 8 - 3Inside we can see a good old comparison of references! To summarize, for enums, we can correctly compare using both == and equals(). Exploring questions and answers from a job interview for a Java developer position. Part 8 - 4

74. What does Enum's ordinal() method do?

When we call the int ordinal() method on an enum field, we get the zero-based index of the field in the list of enum values. Let's call this method on a field in the Role enum, which we previously considered:

System.out.println(Role.DIRECTOR.ordinal());
Accordingly, the console displays:
2

75. Can Enum be used with TreeSet or TreeMap in Java?

We can use enum types in TreeSet and TreeMap. And we can write this:

TreeSet<Role> treeSet = new TreeSet<>();
treeSet.add(Role.SECURITY_GUARD);
treeSet.add(Role.DIRECTOR);
treeSet.add(Role.TEACHER);
treeSet.add(Role.STUDENT);
treeSet.forEach(System.out::println);
And the console will display:
STUDENT TEACHER DIRECTOR SECURITY_GUARD
We got the output, but not alphabetically. The point is that if we use enum fields as TreeSet values or as TreeMap keys, then the fields are sorted in their natural order (in the order in which they are specified in the enum). Understanding that this is how it works helps us write better code.

76. How are Enum's ordinal() and compareTo() methods related?

As mentioned earlier, ordinal() returns a field's index in the list of enum fields. Also, in our consideration of the previous question, you saw that when enum fields are put into a TreeSet (which is a sorted set), they take on the order in which they are declared in the enum. And as we know, TreeSet and TreeMap sort items by calling the compareTo() method of their Comparable interface. This tells us that the Enum class implements the Comparable interface, which means it implements the compareTo() method, which internally uses the ordinal() method to determine the sort order. Going into the Enum class, we can confirm our assumption: Exploring questions and answers from a job interview for a Java developer position. Part 8 - 5And here's the body of the method itself: Exploring questions and answers from a job interview for a Java developer position. Part 8 - 6The ordinal() method is not called here. Instead, the ordinal variable is used, which is the index number of the element in the enumeration. The ordinal() method itself Exploring questions and answers from a job interview for a Java developer position. Part 8 - 7 is nothing more than a getter for the ordinal variable.

77. Write an example Enum

In the questions discussed above, I've already given examples of enums. I see no reason to duplicate code here. For example, see Question 72 regarding a constructor in an enum.

78. Can an Enum be used in a switch case?

It can be and should be! Looking at my experience, I will note that one of the most common uses of enum is in logical constructs like switch statements. In this case, you can provide all the possible cases — once you write the logic for each enum field, you don't even need a default clause! After all, if you use String or a numeric value, such as an int, you may receive an unexpected value, but that is impossible with an enum. Here is what a switch statement would look like for the above example:

public void doSomething(Role role) {
   switch (role) {
       case STUDENT:
           // some logic for STUDENT
           break;
       case TEACHER:
           // some logic for TEACHER
           break;
       case DIRECTOR:
           // some logic for DIRECTOR
           break;
       case SECURITY_GUARD:
           // some logic for SECURITY_GUARD
           break;
   }
}

79. How do I get all possible values of an Enum?

If you need to get all possible enum values, there is a values() method, which returns an array of all possible values for the enum in their natural order (that is, in the order in which they are specified in the enum). Example:

Role[] roles = Role.values();
for (Role role : roles) {
   System.out.println(role);
}
We'll have following on the console:
STUDENT TEACHER DIRECTOR SECURITY_GUARD

Stream API

80. What is a Stream in Java?

The Java Stream API is a relatively new way of interacting with a data stream, allowing us to more conveniently and compactly process big data, as well as to process data in parallel among some number of streams, potentially boosting performance.

81. Name the main properties of transactions

The topic here is the Stream API, but the question is about transactions. Hmm... First, let's understand what a transaction is. A transaction is a group of sequential operations on a database. It represents a logical unit of work. A transaction can be executed independently of other concurrent transactions either entirely and successfully, thereby maintaining data integrity, or not executed at all, in which case it has no effect. Transactions have four main properties, which we can easily remember thanks to the acronym ACID. Let's see what each letter of this acronym means: A stands for Atomicity. This property guarantees that no transaction is partially committed in the system. Either all of its suboperations will be executed, or none of them will be executed (all or nothing). С stands for Consistency. This property guarantees that each successful transaction will commit only valid results. In other words, this is a guarantee that if the transaction is successful, then all of the system's rules for specific data will be obeyed. If the transaction is not successful, then it will not be executed and the system's data will return to its previous state. I stands for Isolation. This property means that when a transaction is executed, concurrent transactions must not affect its outcome. This property is resource intensive, so, as a rule, it is partially implemented, allowing certain levels of isolation that solve specific isolation problems. We'll discuss this in more detail in the next question. D stands for Durability. This property guarantees that if the user receives confirmation that the transaction completed, then he or she can be sure that the changes will not be canceled due to some failure. That is, you can be certain that some operating system failure will not do anything to your data if you have already received confirmation that your transaction finished successfully.

82. What are the transaction isolation levels?

As I said earlier, when it comes to ACID properties, ensuring isolation is a resource-intensive process. Accordingly, this property is partially implemented. There are different levels of isolation: the higher the level, the more severe the impact on performance. Before we move on to transaction isolation levels, we need to consider various problems that occur due to insufficient transaction isolation:
  • phantom reads: when the same request, called more than once within a single transaction, yields different results due to insertions by another transaction;

  • nonrepeatable reads: when the same request, called more than once within a single transaction, yields different data due to changes (updates) and deletions by another transaction;

  • dirty reads: reading as-yet-uncommitted data that has been added or modified by a transaction and is subsequently rolled back;

  • lost updates: when one data block is simultaneously changed by different transactions, and all changes except the last one are lost (similar to a race condition in multithreading).

As it happens, transaction isolation levels are characterized by what isolation problems they protect against. Consider the following table of isolation levels and the problems they protect against:
Isolation level Phantom reads Nonrepeatable reads Dirty reads Lost update
SERIALIZABLE + + + +
REPEATABLE READ - + + +
READ COMMITTED - - + +
READ UNCOMMITTED - - - +
NONE - - - -
And don't forget the flip side: the higher the isolation level, the longer transactions take to process (given parallel execution of multiple transactions).

83. What's the difference between a Statement and a PreparedStatement?

Here we've abruptly changed transitioned to features of JDBC. In any event, let's first figure out what a Statement is all about. It is an object used to form SQL queries. JDBC uses three kinds: Statement, PreparedStatement, and CallableStatement. We won't consider CallableStatement today. Instead, we're talking about the difference between Statement and PreparedStatement.
  1. Statement is used to execute simple SQL queries without runtime input parameters. PrepareStatement can accept input parameters at runtime.

  2. To set parameters for PreparedStatement, input parameters are written as question marks in the request, so they can be replaced by some value using various setters, such as setDouble(), setFloat(), setInt(), setTime()... This means that you won't insert the wrong type of data into the request.

  3. PreparedStatement is precompiled and uses caching, so it can be executed slightly faster than a request made of Statement objects. As a result, SQL statements that are executed frequently are created as PreparedStatement objects in order to improve performance.

  4. Statement is vulnerable to SQL injection, but PreparedStatement prevents them.

And with that, we'll call it a day! Exploring questions and answers from a job interview for a Java developer position. Part 8 - 8
Read more:
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION