Not all interviews will focus on algorithms and data structures — often times an interview will focus solely on the language or technology that you have claimed to be an expert in. In interviews like these, there usually aren’t any “gotcha” questions, instead they require you to draw on memory and your experience with the language — in other words, they test your knowledge of the programming language.
However, it can be easy to forget all the ins and outs of a language like Java, because simply put, we don’t deal with questions like “What kind of memory does the JVM manage?” and “Describe polymorphism with an example.” on a daily basis.
Today we’ll help you brush up by reviewing interview questions on:
With thousands of potential questions to account for, preparing for the coding interview can feel like an impossible challenge. Yet with a strategic approach, coding interview prep doesn’t have to take more than a few weeks. Stop drilling endless sets of practice problems, and prepare more efficiently by learning coding interview patterns. This course teaches you the underlying patterns behind common coding interview questions. By learning these essential patterns, you will be able to unpack and answer any problem the right way — just by assessing the problem statement. This approach was created by FAANG hiring managers to help you prepare for the typical rounds of interviews at major tech companies like Apple, Google, Meta, Microsoft, and Amazon. Before long, you will have the skills you need to unlock even the most challenging questions, grok the coding interview, and level up your career with confidence. This course is also available in JavaScript, Python, Go, and C++ — with more coming soon!
Compilation to bytecode is the magic behind Java’s interoperability. Different operating systems and hardware architectures have JVMs custom designed for themselves and all JVMs can run the same bytecode. Therefore, if you write a Java program on Linux, it will run seamlessly on a JVM designed for Windows operating system, making code agnostic to the underlying hardware and OS.
JRE (Java Runtime Environment) includes the Java Virtual Machine and the standard Java APIs (core classes and supporting files.). The JRE contains just enough to execute a Java application, but not enough to compile it.
JDK (Java Development Kit) is the JRE plus the Java compiler, and a set of other tools to compile and debug code. JRE consists of Java platform libraries, Java Virtual Machine (JVM), Java Plugin and Java Web Start to run Java applications. JRE as a stand-alone does not contain compilers and debugging tools. If you need to develop Java programs you need the full Java SDK. The JRE is not enough for program development. Only the full Java SDK contains the Java compiler which turns your .java
source files into bytecode .class
files.
JVM (Java Virtual Machine) is an implementation of a specification, detailing the behavior expected of a JVM. Any implementation that conforms to the JVM specification should be able to run code compiled into Java bytecode irrespective of the language in which the code was originally written. In the Java programming language, all source code is first written in plain text files ending with the .java
extension. Those source files are then compiled into .class files by the javac
compiler. A .class
file does not contain code that is native to your processor; it instead contains bytecodes — the machine language of the Java Virtual Machine. The java launcher tool then runs your application with an instance of the Java Virtual Machine.
There’s no explicit modifier for package private. In the absence of any modifier the class or member variables are package private. A member marked package private is only visible within its own package. Consider the class below.
Package private is a slightly wider form of private. One nice thing about package-private is that you can use it to give access to methods you would otherwise consider private to unit test classes.
So, if you use helper classes which have no other use but to help your public classes do something clients need, it makes sense to make them package private as you want to keep things as simple as possible for users of the library.
finalize()
method in the Object class? What are some alternatives?The Object class provides a callback method, finalize()
, that may be invoked on an object when it becomes garbage. Object’s implementation of finalize()
does nothing — you can override finalize()
to do cleanup, such as freeing up resources.
The finalize()
method may be called automatically by the system, but when it is called, or even if it is called, is uncertain. Therefore, you should not rely on this method to do your cleanup for you. For example, if you don’t close file descriptors in your code after performing I/O and you expect finalize()
to close them for you, you may run out of file descriptors.
Here are some alternatives:
AutoCloseable
interface.PhantomReference
to perform cleanup when an object is garbage collectedCleaner
class to perform cleanup actions.close()
method, which does the cleanup and document that the method be called.final int[] array = new int[5];array[0] = 1;
It may appear counterintuitive, but we can actually change the contents of the array even though it is marked as final. The array variable points to a particular start location in the memory where the contents of the array are placed.
The location or the memory address can’t be changed. For example, the following code will not compile:
final int[] array = new int [5]array = new int[10];
However, the following code will work.
public class FinalArrayExample {final int[] array = new int[5];// allowedvoid changeArrayContents(int i, int val) {array[i] = val;}// not allowed and will not compile/*void changeArray() {array = new int [10]}*/}
Preparing for coding interviews has become a daunting task. Trying to solve enough practice questions and remember solutions can feel impossible. Fortunately, the best way to be successful in the coding interview is not to just grind through problems. The best way is to develop the skills to break down a new problem and deploy the right tools to come up with a solution. That’s why in this course, you’ll prepare for coding interviews by tackling real world problems faced by tech companies. When you solve real problems related to real projects (for example, paginating attendees in a Zoom call), not only will you have more fun preparing, but you’ll also have an easier time remembering what you’ve learned. After each project, we’ll also show you what kinds of interview problems you’ll now be able to solve using the techniques you just applied, so that your knowledge is adaptable to new problems. (This course is also available in Rust, C++, C#, Go, Python, Ruby, Elixir, Scala, Swift, Kotlin, and JavaScript.)
An abstract class can’t be instantiated, but it can be subclassed. An abstract class usually contains abstract and non-abstract methods that subclasses are forced to provide an implementation for.
An interface is a completely “abstract class” that is used to group related methods with empty bodies.
Each allow for advanced OOP constructions in Java.
Following are four main differences between abstract classes and interfaces:
An abstract class can have final variables, static variables, or class member variables whereas an interface can only have variables that are final and static by default.
An abstract class can have static, abstract, or non-abstract methods. An interface can have static, abstract, or default methods.
Members of an abstract class can have varying visibility of private, protected, or public. Whereas, in an interface all methods and constants are public.
A class can only extend another class, but it can implement multiple interfaces. Similarly, an interface can extend multiple interfaces. An interface never implements a class or an interface.
Use an abstract class when subclasses share state or use common functionality. Or you require to declare non-static, non-final fields or need access modifiers other than public.
Use an interface if you expect unrelated classes would implement your interface. For example, the interfaces Comparable and Cloneable are implemented by many unrelated classes. Interfaces are also used in instances where multiple inheritance of type is desired.
Polymorphism is the ability in object-oriented programming to present the same interface for differing underlying forms or data types. Polymorphism is when you can treat an object as a generic version of something, but when you access it, the code determines which exact type it is and calls the associated code. What this means is that polymorphism allows your code to work with different classes without needing to know which class it’s using.
Polymorphism is used to make applications more modular and extensible. Instead of messy conditional statements describing different courses of action, you create interchangeable objects that you select based on your needs. That is the basic goal of polymorphism.
The classic example of polymorphism is a Shape
class. We derive Circle
, Triangle
, and Rectangle
classes from the parent class Shape
, which exposes an abstract method draw(). The derived classes provide their custom implementations for the draw()
method. Now it is very easy to render the different types of shapes all contained within the same array by calling the draw()
method on each object. This saves us from creating separate draw methods for each shape e.g. drawTriangle()
, drawCircle()
etc.
Yes, the main
method, which is a static method, can be overloaded. But only public static void main(String[] args)
will be used when your class is launched by the JVM even if you specify one or two command-line arguments. However, programmatically one can invoke the overloaded versions of the main
method.
We can pass variable number of arguments to a method using varargs
feature. Below is an example of passing multiple arguments of the same type to a method.
public void childrenNames(string... names) {for(int i= 0; i < names.length; i++)system.out.println(names[i]);}
varargs
variable is treated like an array.varargs
variable must appear at the last in the method signature.varargs
in a method signature.The above method can be invoked as follows:
Invoking Varargs
Method
childrenNames();childrenNames("Jane");childrenNames("Jane", "Tom", "Peter");
With thousands of potential questions to account for, preparing for the coding interview can feel like an impossible challenge. Yet with a strategic approach, coding interview prep doesn’t have to take more than a few weeks. Stop drilling endless sets of practice problems, and prepare more efficiently by learning coding interview patterns. This course teaches you the underlying patterns behind common coding interview questions. By learning these essential patterns, you will be able to unpack and answer any problem the right way — just by assessing the problem statement. This approach was created by FAANG hiring managers to help you prepare for the typical rounds of interviews at major tech companies like Apple, Google, Meta, Microsoft, and Amazon. Before long, you will have the skills you need to unlock even the most challenging questions, grok the coding interview, and level up your career with confidence. This course is also available in JavaScript, Python, Go, and C++ — with more coming soon!
A semaphore can potentially act as a mutex if the number of permits it can give out is set to 1. However, the most important difference between the two is that in the case of a mutex, the same thread must call acquire and subsequent release on the mutex whereas in the case of a binary semaphore, different threads can call acquire and release on the semaphore.
This leads us to the concept of “ownership”. A mutex is owned by the thread acquiring it, till the point, it releases it, whereas for a semaphore there’s no notion of ownership.
The Serializable
interface gets us automatic serialization capability for objects of our class. On the other hand the Externalizable
interface provides a way to implement a custom serialization mechanism. A class that implements the Externalizable
interface is responsible to save and restore the contents of its own instances.
The Externalizable
interface extends the Serializable
interface and provides two methods to serialize and deserialize an object, writeExternal()
and readExternal()
.
Multiple types of exceptions thrown by a snippet of code can be handled by multiple catch block clauses followed by the try block. An example snippet of exception handling appears below:
void process(int val) {try {if (val == 1)//checked exceptionthrow new FileNotFoundException();if (val == 2)// runtime exceptionthrow new NullPointerExxception();if (val == 3)// error exceptionthrow new StackOverflowError} catch (RuntimeException re) {// catches all unchecked exceptions} catch (Exception e) {// catches all checked exceptions} catch (Error err) {// catches all errors}}
Initially, you may want to use a HashSet data structure as it will give you a better time complexity, but it makes no guarantees as to the iteration order of the set; in particular, it does not guarantee that the order will remain constant over time.
So if you are wanting to maintain the order it’s best to use a TreeSet as it stores keys in ascending order rather than in their insertion order. It’s not thread-safe. However, keep in mind that TreeSet is not thread-safe whereas a HashSet is.
Here are three key steps you can take to improve the memory footprint:
null
when not needed. This will make objects eligible for garbage collection.The best way to implement a singleton as per Josh Bloch is to use an enum
type for the singleton. Because Java ensures that only a single instance of an enum
is ever created, the singleton class implemented via enums
is safe from reflection and serialization attacks.
class Demonstration {public static void main( String args[] ) {Superman superman = Superman.INSTANCE;superman.fly();}}enum Superman {INSTANCE;private final String name = "Clark Kent";private String residence = "USA";public void fly() {System.out.println("I am flyyyyinggggg ...");}}
There has been a lot covered in this post about the Java programming language, ranging from the Java ecosystem to multi-threading and exceptions. These are the types of Java interview questions you can expect.
It’s very common to have interviews testing your knowledge of a programming language you claim to be an expert in. If you've got an interview coming up on Java soon and need to get up to speed, this is the ideal course for you. You'll refresh your memory on everything from the basics to more advanced functionality you’re likely to be asked about. Even if you're using Java every day, you may not have been exposed to parts of it in some time, so it's always useful to make sure you're updated. This course features more than 300 of the most commonly asked core Java interview questions that you're likely to face as an experienced software engineer. You'll get to explore questions by topic, as well as see detailed answers for each one, and plenty of live code examples where relevant. Get started today.
However, the material here just scratches the surface. There are many more concepts to revisit or explore.
If you’d like to take a deep dive into Java and explore hundreds of more questions about the topics mentioned above then Grokking Coding Interview Patterns in Java is going to be a great resource to get you refreshed on the core java principles — everything from the basics to more advanced functionality.
Happy learning!