User Konstantin
Konstantin
Level 36
Odesa

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

Published in the Random group
Hey everyone! Programming is full of pitfalls. And there is hardly a single topic that won't cause you to stumble and stub your toe. This is especially true for beginners. The only way to save your toes is to learn. In particular, you need to dive deep into the most fundamental topics. Today, we’ll continue the review of the most popular questions during interviews for Java developers. These interview questions do an excellent job of covering basic topics. Note that the list also includes some not-so-standard questions that let you approach common issues differently. Exploring questions and answers from a job interview for a Java developer position. Part 7 - 1

62. What is the string pool, and why is it needed?

Part of the memory made available to a Java program is called the heap (which we will talk about later), and part of the heap is called the String pool. It is for storing string values. In other words, when you create a string, for example, using double quotes like this:

String str = "Hello world";
The JVM checks whether the string pool already has the specified value. If it does, then the str variable is assigned a reference to that value in the pool. If it does not, a new value is created in the pool, and a reference to it is assigned to the str variable. Let's consider an example:

String firstStr = "Hello world";
String secondStr = "Hello world";
System.out.println(firstStr == secondStr);
true will be displayed on the screen. Remember that == compares references, and these two variables point to the same value in the string pool. This helps to avoid producing many identical String objects in memory. We can do this because, as you will recall, String is an immutable class, so there is nothing wrong with having multiple references to the same value. Now it is impossible to have a situation where changing the value in one place results in changes to several other references. Still, if we create a string using new:

String str = new String("Hello world");
then a separate object is created in memory and stores the specified string value (it doesn't matter if that value is already in the string pool). To confirm this assertion, consider this:

String firstStr = new String("Hello world");
String secondStr = "Hello world";
String thirdStr = new String("Hello world");
System.out.println(firstStr == secondStr);
System.out.println(firstStr == thirdStr);
We will get two lines indicating false, which means that we have three separate strings. Basically, this is why you should create strings simply using double-quotes. That said, it is possible to add (or get a reference to) values in the string pool even when creating an object using the new keyword. To do this, we use the String class's intern() method. This method ensures that we either create the value in the string pool or we get a reference to it if it is already there. Here's an example:

String firstStr = new String("Hello world").intern();
String secondStr = "Hello world";
String thirdStr = new String("Hello world").intern();
System.out.println(firstStr == secondStr);
System.out.println(firstStr == thirdStr);
System.out.println(secondStr == thirdStr);
This code outputs true to the console three times, which tells us that all three variables refer to the same string in memory.

63. What GoF design patterns are used in the string pool?

In the string pool, the GoF design pattern is a flyweight pattern. If you've noticed another design pattern here, share it in the comments. Here we'll talk about the flyweight design pattern. It is a structural design pattern in which an object that represents itself as a unique instance in different places in the program is actually not unique. The flyweight saves memory by storing objects' shared state instead of storing identical data in each object. To understand the gist, consider this elementary example. Let's say we have an Employee interface:

public interface Employee {
   void work();
}
And it has a few implementations, such as a Lawyer class:

public class Lawyer implements Employee {
 
   public Lawyer() {
       System.out.println("A lawyer was hired.");
   }
 
   @Override
   public void work() {
       System.out.println("Settling legal issues...");
   }
}
And an Accountant class:

public class Accountant implements Employee {
 
   public Accountant() {
       System.out.println("An accountant was hired.");
   }
 
   @Override
   public void work() {
       System.out.println("Keeping accounting records...");
   }
}
The methods are entirely arbitrary — for this example, we just need to see that they are being executed. The same is true about the constructor. The console output tells us when new objects are created. We also have a human resources department whose task is to return a requested employee. If that employee isn't already on staff, then they are hired and the HR department returns the new employee:

public class HumanResourcesDepartment {
   private Map<String, Employee> currentEmployees = new HashMap<>();
 
   public Employee getEmployee(String type) throws Exception {
       Employee result;
       if (currentEmployees.containsKey(type)) {
           result = currentEmployees.get(type);
       } else {
           switch (type) {
               case "Accountant":
                   result = new Accountant();
                   currentEmployees.put(type, result);
                   break;
               case "Lawyer":
                   result = new Lawyer();
                   currentEmployees.put(type, result);
                   break;
               default:
                   throw new Exception("This employee is not on the staff!");
           }
       }
       return result;
   }
}
So, the logic is simple: if the desired object exists, return it; if not, create it, put it in storage (something like a cache), and return it. Now let's see how it all works:

public static void main(String[] args) throws Exception {
   HumanResourcesDepartment humanResourcesDepartment = new HumanResourcesDepartment();
   Employee empl1 = humanResourcesDepartment.getEmployee("Lawyer");
   empl1.work();
   Employee empl2 = humanResourcesDepartment.getEmployee("Accountant");
   empl2.work();
   Employee empl3 = humanResourcesDepartment.getEmployee("Lawyer");
   empl1.work();
   Employee empl4 = humanResourcesDepartment.getEmployee("Accountant");
   empl2.work();
   Employee empl5 = humanResourcesDepartment.getEmployee("Lawyer");
   empl1.work();
   Employee empl6 = humanResourcesDepartment.getEmployee("Accountant");
   empl2.work();
   Employee empl7 = humanResourcesDepartment.getEmployee("Lawyer");
   empl1.work();
   Employee empl8 = humanResourcesDepartment.getEmployee("Accountant");
   empl2.work();
   Employee empl9 = humanResourcesDepartment.getEmployee("Lawyer");
   empl1.work();
   Employee empl10 = humanResourcesDepartment.getEmployee("Accountant");
   empl2.work();
}
Here's what we'll see in the console:
A lawyer was hired. Settling legal issues... An accountant was hired. Keeping accounting records... Settling legal issues... Keeping accounting records... Settling legal issues... Keeping accounting records... Settling legal issues... Keeping accounting records... Settling legal issues... Keeping accounting records…
As you can see, we created only two objects and reused them many times. The example is very simple, but it demonstrates how this design pattern can conserve our resources. As you may have noticed, the logic of this pattern is painfully similar to the logic of an insurance pool. Exploring questions and answers from a job interview for a Java developer position. Part 7 - 2

64. How do we split a string into parts? Give an example of the relevant code

Obviously, this question is about the split method. The String class has two variations of this method:

String split(String regex);
and

String split(String regex);
The regex parameter is the delimiter — some regular expression used to split the string into an array of strings, for example:

String str = "Hello, world it's Amigo!";
String[] arr = str.split("\\s");
for (String s : arr) {
  System.out.println(s);
}
The console will display:
Hello, world it's Amigo!
So, our string was split into an array of strings, using a space as the delimiter (instead of the regular expression "\\s", we also could have used the ordinary string expression " "). The second, overloaded variant, has an additional limit parameter. limit is the maximum allowed size of the resulting array. In other words, once the string has been split into the maximum allowed number of substrings, the splitting stops, and the last element will contain any "leftovers" from the possibly non-split string. Example:

String str = "Hello, world it's Amigo!";
String[] arr = str.split(" ", 2);
for (String s : arr) {
  System.out.println(s);
}
Console output:
Hello, world it's Amigo!
As we can see, if it were not for limit = 2, the last element of the array could be split into three substrings.

65. Why is a character array better than a string for storing a password?

There are several reasons for preferring an array to a string when storing a password:

1. The string pool and string immutability.

When using an array (char[]), we can explicitly erase the data once we are done working with it. We can also overwrite the array as much as we want, eliminating the password from the system even before garbage collection (it's sufficient to change a couple of cells to invalid values). By contrast, String is an immutable class. This means that if we want to change the value of a String object, we will get a new one, but the old one will remain in the string pool. If we want to remove the String containing the password, we face a complicated task since we need the garbage collector to remove that value from the string pool, but that String will likely remain there for a long time. That is, when it comes to securely storing data, String is inferior to a char array.

2. If we output the String value to the console (or a log), then we get:


String password = "password";
System.out.println("Password - " + password);
Console output:
Password - password
And if you happen to print the array to the console:

char[] arr = new char[]{'p','a','s','s','w','o','r','d'};
System.out.println("Password - " + arr);
the console will display incomprehensible gibberish:
Password - [C@7f31245a
In fact, it is not gibberish. Here's how to make sense of what you see: [C is the class name - char array, @ is a delimiter, and then 7f31245a is a hexadecimal hash code.

3. The official Java Cryptography Architecture (JCA) Reference Guide explicitly mentions storing passwords in a char[] instead of a String:

"It would seem logical to collect and store the password in an object of type java.lang.String. However, here's the caveat: Objects of type String are immutable, i.e., there are no methods defined that allow you to change (overwrite) or zero out the contents of a String after usage. This feature makes String objects unsuitable for storing security-sensitive information such as user passwords. You should always collect and store security-sensitive information in a char array instead." Exploring questions and answers from a job interview for a Java developer position. Part 7 - 3

Enum

66. Give a brief description of Enum in Java

Enum is short for enumeration, which is a set of string constants united by a common type. We declare one using the enum keyword. Here's an example with enum: permitted roles on some school campus:

public enum Role {
   STUDENT,
   TEACHER,
   DIRECTOR,
   SECURITY_GUARD
}
The words written in capital letters are the enumeration constants. They are declared in a simplified way, without the new operator. Using enumerations makes life much easier since they help avoid errors and confusion in names (since the list defines the only valid values). For me, they are very convenient in the switch construct.

67. Can an Enum implement interfaces (use the implements keyword)?

Yes. After all, enums should represent more than just passive sets (such as roles on a school campus). In Java, they can represent more complex objects, so you may need to add additional functionality to them. This also allows you to take advantage of polymorphism by substituting the enum value in places where the implemented interface type is needed.

68. Can Enum extend a class (use the extends keyword)?

No, it cannot, because an enum is a subclass of the default Enum<T> class, where T is the enum type. This is nothing more than a common base class for all enum types in the Java language. The conversion from an enum to a class is done by the Java compiler at compile time. The extension is not explicitly indicated in the code, but it is always implied.

69. Is it possible to create an Enum without any instances of objects?

This question is a bit confusing, and I'm not sure I fully understand it. I have two interpretations: 1. Can you have an enum without any values? Yes, of course, but it would be like an empty class — pointless, e.g.

public enum Role {
}
And if we call:

var s = Role.values();
System.out.println(s);
We get the following in the console:
[Lflyweight.Role;@9f70c54
(an empty array of Role values) 2. Is it possible to create an enum without the new operator? Yes, of course. As I said above, you don't use the new operator for enum values, since they are static values.

70. Can we override Enum's toString() method?

Yes, of course you can override the toString() method in order to define how to display your enum when the toString method is called (when converting an enum to an ordinary string, for example, to output it to the console or logs).

public enum Role {
   STUDENT,
   TEACHER,
   DIRECTOR,
   SECURITY_GUARD;

   @Override
   public String toString() {
       return "Selected role - " + super.toString();
   }
}
That's all for me today. Until the next part! Exploring questions and answers from a job interview for a Java developer position. Part 7 - 4
Read more:
Comments (2)
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION
qwpo Level 33
28 September 2021
Would be helpful to have the links to first parts.
Abha Sharma Level 1, India
24 September 2021
Very helpful thank you for sharing