-
How to create an immutable object in Java? List all the benefits
An immutable class is a class whose state cannot be changed after it has been created. Here, the state of an object is essentially the values stored in an instance of the class, whether they be primitive types or reference types.
To make a class immutable, the following conditions must be met:
- Do not provide setters or methods that modify fields or objects that refer to fields. Setters imply changing the state of an object, which is what we want to avoid here.
- Make all fields
final
andprivate
. Fields marked withprivate
will be inaccessible from outside the class, and designating themfinal
ensures that you don't change them even by accident. - Do not allow subclasses to override methods. The easiest way to do this is to declare the class as
final
. Finalized classes in Java cannot be overridden. - Always remember that your variable instances can be either mutable or immutable. Define them and return new objects with copied content for all mutable objects (reference types). Immutable variables (primitive types) can be safely returned with no additional effort.
Also, you need to keep in mind the subsequent benefits of immutable classes. You may need them for an interview. Immutable classes:
- easy to design, test and use
- are automatically thread safe and have no synchronization issues
- do not require a copy constructor
- allow you to "lazy initialize" the hashcode and cache the return value
- do not require secure copy when used as a field
- make good
Map
keys andSet
elements (these objects should not change state when they are in the collection) - make their class permanent by creating it once, and it does not need to be re-checked
- always have “failure atomicity,” a term coined by Joshua Bloch: if an immutable object throws an exception, it will never be left in an unwanted or undefined state.
Look at the example written in this post .
-
In Java, pass by value or by reference?
The Java specification states that everything in Java is passed by value. There is no such thing as "pass by reference" in Java. These conditions are associated with calling methods and passing variables as method parameters. Well, primitive types are always passed by value without any confusion. But, the concept should be understood in the context of a method parameter of complex types.
In Java, when we pass a complex type reference as any method parameter, the memory address is always copied into the new reference variable step by step. Look at the image:
In the example above, the address bits of the first instance are copied to another reference variable, causing both references to point to the same memory location where the object is stored. Remember that by assigning null to the second reference, you will not assign null to the first reference. But a change in the state of an object with one referenced variable will be reflected in the other reference as well.
See details here .
-
What is the use of the block
finally
? Does this block guarantee the execution of its code? When isfinally
a block not called?The block
finally
is always called if the blocktry
exists. This ensures that the blockfinally
is called even if an unexpected exception occurs. Butfinally
it is more useful than just exception handling - this block allows you to clean up code that accidentally bypassed throughreturn
,continue
orbreak
. Placing cleanup code in a blockfinally
is always good practice, even when no exceptions are expected.If the virtual machine exits while the
try
or block is executingcatch
, then the blockfinally
will not be executed. Similarly, if a thread is interrupted or killed while executing atry
or blockcatch
, the blockfinally
will not be executed even though the application is still running. -
Why are there two classes
Date
, one injava.util package
and the other injava.sql
?java.util.Date
represents a date and time, butjava.sql.Date
only a date. The complement tojava.sql.Date
is the classjava.sql.Time
, which represents only time.The class
java.sql.Date
is a subclass (extension) of the classjava.util.Date
. So what has changed injava.sql.Date
:toString()
generates a different string representation: yyyy-mm-dd- static method
valueOf(String)
creates date from string with above representation - excluded getters and setters for hours, minutes and seconds
The class
java.sql.Date
is used in JDBC and is intended to not have a time component, i.e. hours, minutes, seconds and milliseconds must be zero...but this is not required for the class. -
Explain marker interfaces.
The marker interface pattern is a computer science design pattern used by programming languages that provide information about objects at run time . It provides a way to associate class metadata where the language has no explicit support for such metadata . Java uses interfaces for this without specifying methods.
A good example of using a marker interface in Java is the
Serializable
. A class implements this interface to indicate that its non-transient
data can be written to a byte stream or file system.The main problem with a marker interface is that an interface defines a convention for the classes that implement it, and that convention is inherited by all subclasses. This means that you cannot "de-realize" the token. In the example above, if you create a subclass that you don't want to serialize (perhaps because it's in a transient state), you must resort to explicit casting
NotSerializableException
. -
Why is the method
main()
declared aspublic static void
?Why public? The method
main
has an access modifierpublic
so it can be accessed everywhere and by any object that wants to use this method to launch the application. Here I'm not saying that JDK/JRE have a similar reason, because java.exe or javaw.exe (for windows) use Java Native Interface (JNI) call to run the method, so they can call it anyway, regardless of the access modifier .Why static? Let's assume that we have a
main
non-static method. Now, to call any method, you need an instance of the class. Right? Java allows you to have overloaded constructors, we all know that. Then which one should be used, and where will the parameters for the overloaded constructor come from?Why void? There is no use for the return value in the virtual machine that actually calls this method. The only thing the application wants to tell the calling process is a normal or abnormal termination. This is already possible using
System.exit(int)
. A non-zero value implies abnormal termination, otherwise everything is fine. -
What is the difference between constructing a string as
new()
a literal (using double quotes)?When we create a string using
new()
, it is created in the heap and also added to the string pool, while the string created with the literal is only created in the string pool.You need to know more about the string pool concept to answer this or similar questions. My advice is to learn the String class and string pool well .
-
How does a
substring()
class method workString
?Like other programming languages, strings in Java are sequences of characters. This class is more like a utility class for working with this sequence. The character sequence is provided by the following variable:
/** The value is used for character storage. */ /** Значение используется для хранения символов */ private final char value[]; Для доступа к этому массиву в различных сценариях используются следующие переменные
/** The offset is the first index of the storage that is used. */ /** Смещение – это первый индекс используемого хранorща. */ private final int offset; /** The count is the number of characters in the String. */ /** Счет – это количество символов в строке. */ private final int count;
Each time we create a substring from an existing string instance, the method
substring()
only sets the new values of the variablesoffset
andcount
. The internal character array is not modified. This is a possible source of a memory leak if the methodsubstring()
is used carelessly:The original value
value[]
is not changed. So if you create a string of 10000 characters and create 100 substrings with 5-10 characters each, all 101 objects will contain the same character array of 10000 characters. This is no doubt a waste of memory.This can be avoided by changing the code like this:
replace
original.substring(beginIndex)
withnew String(original.substring(beginIndex))
, whereoriginal
is the original string.Translator's note: I find it difficult to say which version of Java this applies to, but at the moment in Java 7 this paragraph of the article is not relevant. The method substring()
calls the class constructornew String(value, beginIndex, subLen)
, which in turn calls the methodArrays.copyOfRange(value, offset, offset+count)
. This means that each time we will have a new value for the variablevalue[]
containing our new number of characters. -
Explain work
HashMap
. How is the problem of duplicates solved?Most of you will surely agree that
HashMap
the most favorite topic for discussion in an interview at the present time. If someone asks me to tell you “How does it workHashMap
?”, I will simply answer: “Based on the principle of hashing.” As simple as it is.So, hashing is essentially a way to assign a unique code to any variable/object after applying any formula/algorithm to its properties.
The definition of a map (
Map
) is: "An object that binds keys to values." Very simple, right? So,HashMap
it contains its own inner classEntry
, which looks like:static class Entry implements Map.Entry { final K key; V value; Entry next; final int hash; …//More code goes here }
When someone tries to put a key-value pair into
HashMap
, the following happens:- First of all, the key object is checked against
null
. If the key isnull
, the value is stored in positiontable[0]
. Because the hashcode fornull
is always 0. - Then, the next step is to calculate the hash value by calling its method on the key variable
hashCode()
. This hash is used to calculate the index in the array to store the objectEntry
. The JDK developers were well aware that a methodhashCode()
could be poorly written and could return a very large or very small value. To solve this problem, they introduced anotherhash()
method, and pass the hashcode of the object to this method to cast this value to the size range of the array index. - The method is now called
indexFor(hash, table.length)
to calculate the exact position to store theEntry
. - Now the main part. As we know two dissimilar objects can have the same hashcode value, how can two different objects be stored in the same location in an archive [called a trash can]?
The answer is
LinkedList
. If you remember, the classEntry
has a “next” property. This property always points to the next object in the chain. This behavior is very similar toLinkedList
.So, in case of hashcode matches, Entry objects are stored in the form
LinkedList
. When an objectEntry
needs to be placed at a particular index,HashMap
checks if another object exists at that locationEntry
? If there is no record there, our object will be saved in this location.If there is already another object at our index, its field is checked
next
. If it is equal tonull
, our object becomes the next node inLinkedList
. If next is not equal to , this procedure is repeated until a field equalnull
to is found .next
null
What happens if we add another key value equal to the one we added earlier? It is logical that it should replace the old value. How does this happen? After determining the position index for the
Entry
, running through theLinkedList
, located at our index,HashMap
calls a methodequals()
on the key value for eachEntry
. All of these objectsEntry
inLinkedList
have the same hashcode value, but the methodequals()
will check for true equality. If key.equals(k)
will be true , then both will be treated as the same object. This will cause only the value object inside theEntry
.This
HashMap
ensures the uniqueness of the keys. - First of all, the key object is checked against
-
Differences between interfaces and abstract classes?
This is a very common question if you are interviewing for a junior level programmer. The most significant differences are listed below:
- In Java interfaces, variables are a priori
final
. Abstract classes may contain non-final
variables. - An interface in Java definitely cannot have an implementation. An abstract class can have instances of methods that implement the base behavior.
- Interface components must be
public
. An abstract class can have access modifiers of any kind. - The interface must be implemented with the keyword
implements
. An abstract class must be extended using the extends keyword . - In Java, a class can implement many interfaces, but can only inherit from one abstract class.
- An interface is completely abstract and cannot be instantiated. An abstract class also cannot have instances of the class, but can be called if the
main()
. - An abstract class is slightly faster than an interface because an interface expects a lookup before calling any overridden method in Java. In most cases, this is a minor difference, but if you are writing a time-critical application, you need to consider this fact as well.
- In Java interfaces, variables are a priori
-
When do you override methods
hashCode()
andequals()
?hashCode()
The and methodsequals()
are defined on the classObject
, which is the parent class of all Java objects. For this reason, all Java objects inherit the base implementation of these methods.The method
hashCode()
is used to get a unique integer value for a given object. This value is used to determine the location of the bin when the object needs to be stored in a data structure likeHashTable
. By default, the methodhashCode()
returns an integer representation of the memory address where the object is stored.The method
equals()
, as the name suggests, is used for simple object equivalence. The basic implementation of the method is to check the references of the two objects to see if they are equivalent.Note that it is usually necessary to override a method
hashCode()
whenever a method is overriddenequals()
. This is necessary to support the general method conventionhashCode
that equal objects must have equal hashcodes.The equals() method must determine the equality of the relationship (it must be recursive, symmetric, and transitive). In addition, it must be persistent (if the object has not changed, the method must return the same value). Also,
o.equals(null)
it should always return false .hashCode()
must also be persistent (if the object has not changed under the conditions of the methodequals()
, it must continue to return the same value.The relationship between the two methods is: always, if
a.equals(b)
, thena.hashCode()
must be the same asb.hashCode()
.
Andrey
Level 26
java core. Questions for the interview, part 1
For those who hear the word Java Core for the first time, these are the fundamental foundations of the language. With this knowledge, you can already safely go on an internship / internship. These questions will help you refresh your knowledge before the interview, or learn something new for yourself. For practical skills, study on CodeGym .
GO TO FULL VERSION