Java Cheat Sheet

Java is a high-level programming language that is famous for its robustness, object-oriented nature, enhanced security, and easy-to-learn features also known as Java Buzzwords. Java can be considered both a platform and a programming language. The founder of Java, James Gosling, is recognised as the “Father of Java.” It was known as Oak before Java. Since Oak was already a recognised business, James Gosling and his team changed the programming language’s name to Java. Java allows programmers to write, compile, and debug code easily. It is widely used in developing reusable code and modular programs. Java is an object-oriented programming language and it focuses on reducing dependencies. A java program can be written once and executed anywhere (WORA). Java programs are first compiled into bytecode and the byte code generated can be run on any Java Virtual Machine. Java is similar to C / C++ in terms of syntax. Java is also the name of an Indonesian island. It is here that the first coffee (also known as java coffee) was grown. It is while sipping coffee near his office that James Gosling thought of this name.

Learn Java: Basics to Advanced Concepts

1. Java Polymorphism

Polymorphism is a Java feature that allows us to do a single operation in multiple ways. Polymorphism is made up of two Greek words: poly and morphism. The words "poly" and "morphs" denote "many" and "forms," respectively. As a result, polymorphism denotes the presence of several forms. Polymorphism in Java is divided into two types: compile-time polymorphism and runtime polymorphism. Compile-time Polymorphism: Compile-time polymorphism is also known as static polymorphism. In Java, this is achieved by function overloading. Method Overloading: When there are numerous functions with the same name but distinct parameters, this is referred to as overloading. Changes in the number of arguments or the kind of arguments can cause functions to become overloaded. Example -

class Sample < // Method with 2 integer parameters static int Multiply(int a, int b) // method overloading < return a * b; > // Method with same name but with 2 double parameters static double Multiply(double a, double b) // method overloading < return a * b; > > class Test < public static void main(String[] args) < // Calling method by passing // input as in arguments System.out.println(Sample.Multiply(1, 4)); System.out.println(Sample.Multiply(5.5, 4.2)); > >
4 23.1

Explanation: In the above code, the class Sample has two functions with the same name ‘multiply’ but they have different function signatures which implement method overloading. So, we have the same name for a function that returns the multiplication of two integers and a function that returns the multiplication of two doubles. Runtime Polymorphism: Runtime polymorphism, often known as Dynamic Method Dispatch, is a technique for resolving calls to overridden methods at runtime rather than at compile time. A superclass's reference variable is used to call an overridden method in this process. The object referred to by the reference variable is used to determine which method should be called. Example -

class Sample< void fun()< System.out.println("Inside Sample's fun method."); > > class Test extends Sample< void fun()< System.out.println("Inside Test's fun method."); > > class Main< public static void main(String args[])< Sample s = new Test() s.fun(); > > 
Inside Test's fun method.

Explanation - In the above code, the Test class inherits from the Sample class and both the Test class and the Sample class have a method named ‘fun’ defined. This leads to method overriding. Now in the main class, we create a ‘Sample’ reference variable and allot an instance of the ‘Test’ class to it. Now, we invoke the fun() method. Since, the reference variable stores an object of the ‘Test’ class, the fun() method of the ‘Test’ class gets invoked.

Create a free personalised study plan Create a FREE custom study plan Get into your dream companies with expert guidance Get into your dream companies with expert.. Real-Life Problems Prep for Target Roles Custom Plan Duration Flexible Plans

2. Java Multithreading

What is Multithreading? Multithreading is a Java feature that permits the execution of two or more portions of a program at the same time to maximise CPU efficiency. Each such portion of the program is referred to as a thread.
Threads are lightweight processes within processes. Multitasking is accomplished through the use of multiprocessing and multithreading. Because threads share a memory, we employ multithreading rather than multiprocessing. They conserve memory by not allocating separate memory space, and context-switching between threads takes less time than processing. The above image shows 3 processes wherein process 1 consists of 3 threads, process 2 consists of 2 threads and process 3 consists of 1 thread. Java Runnable Interface: In Java, java.lang.Runnable is an interface that a class must implement if its instances are to be executed by a thread. Java Thread Class: Thread programming is possible with Java’s Thread class. The Thread class contains constructors and methods for creating and operating on threads. Thread is a subclass of Object that implements the Runnable interface. Methods of the Java Thread Class: The following table shows the methods of the Java Thread class and its use cases.

Method Modifier and return type Use Case
start() void start() is used to begin the thread’s execution.
run() void It specifies the code to be executed by each thread.
sleep() static void This function sleeps a thread for the period of time provided.
currentThread() static Thread It returns a reference to the thread object that is presently running.
join() void This function waits for a thread to terminate.
getPriority() int This function returns the thread’s priority.
getName() String getName() returns the thread’s name.
setName() void setName() modifies the thread’s name.
isAlive() boolean isAlive() is a boolean function that determines whether or not the thread is alive.
getId() long This function returns the thread’s id.
yield() static void This function causes the presently running thread object to pause and allow other threads to run for a short period of time.
interrupt() void It interrupts the thread.
suspend() void It is used to suspend the thread.
destroy() void This function is used to destroy the thread group as well as all of its subgroups.
stop() void This function is used to terminate the thread.
resume() void resume() is a void function that is used to restart a suspended thread.
isInterrupted() boolean isInterrupted() is a boolean function that determines whether or not the thread has been interrupted.
setDaemon() void This function marks whether the thread is a daemon or a user thread.
isDaemon() boolean This function determines whether the thread is a daemon thread.
interrupted() static boolean This function checks if the current thread is interrupted.
activeCount() static int This function returns the number of active threads in the thread group of the current thread.
dumpStack() static void This function prints the current thread’s stack trace to the standard error stream.
enumerate() static int This function copies the thread group and subgroups of all current threads into the provided array.
holdLock() static boolean holdLock() is a static boolean function that returns true if and only if the current thread has the monitor lock on the provided object.
checkAccess() void This function checks whether the currently running thread has the ability to change the thread.
getStackTrace() StackTraceElement[] This method returns an array of stack trace items that describe the thread’s stack dump.
getState() Thread.State getState() is used to return the thread’s current state.
getThreadGroup() ThreadGroup getThreadGroup() returns the thread group that this thread belongs to.
notifyAll() void This method is used to send a notification to all of an object’s waiting threads.
notify() void This function is used to send a notification to only one thread that is waiting for an item.
setContextClassLoader() void This method sets the Thread’s context ClassLoader.
getContextClassLoader() ClassLoader getContextClassLoader() returns the thread’s context ClassLoader.
toString() String Returns a string representation of this thread, containing its name, priority, and thread group.
  1. It does not impede the user because threads are independent and can conduct many operations at the same time.
  2. It saves time by allowing you to conduct multiple procedures at once.
  3. Because threads are self-contained, an exception in one thread has no impact on other threads.

How to implement multithreading in Java?

Multithreading can be performed in Java using two different mechanisms:

By extending the Thread class:

We’ll make a class that extends the java.lang.Thread class. The run() method of the Thread class is overridden by this class. The run() procedure is where a thread starts its life. To begin thread execution, we construct an object of our new class and use the start() method. Start() calls the Thread object’s run() function.

class Sample extends Thread < public void run() < try < // Displaying the thread that is running System.out.println( "Thread " + Thread.currentThread().getId() + " is running"); > catch (Exception e) < // Throwing an exception System.out.println("An exception is caught"); > > > class Multithread < public static void main(String[] args) < int n = 5; // Number of threads for (int i = 0; i < n; i++) < Sample obj = new Sample(); obj.start(); > > > 
Thread 20 is running Thread 18 is running Thread 21 is running Thread 19 is running Thread 17 is running

Explanation - In the above code, the Sample class extends the Thread class present in java.lang package. In the Multithread class, we create 5 threads by creating an instance of the Sample class. We then invoke the run() method of the instance created by calling the start() method of the instance.

By implementing the Runnable Interface:

We make a new class that implements the java.lang.Runnable interface and overrides the run() method. After that, we create a Thread object and call its start() method.

class Sample implements Runnable < public void run() < try < // Displaying the thread that is running System.out.println( "Thread " + Thread.currentThread().getId() + " is running"); > catch (Exception e) < // Throwing an exception System.out.println("An exception is caught"); > > > class Multithread < public static void main(String[] args) < int n = 5; // Number of threads for (int i = 0; i < n; i++) < Thread obj = new Thread(new Sample()); obj.start(); > > > 
Thread 20 is running Thread 18 is running Thread 21 is running Thread 19 is running Thread 17 is running

Explanation: In the above code, the class Sample implements the Runnable interface. In the sample class, we override the run() method. In the Multithread class, we create 5 threads by creating an instance of the Thread class.

Runnable Interface vs. Thread Class:

The following are the key differences between using the Runnable interface and the Thread class:

  1. Because Java doesn’t support multiple inheritances, if we extend the Thread class, we won’t be able to extend any other classes. Our class, however, can still extend other base classes if we implement the Runnable interface.
  2. We can obtain rudimentary thread functionality by extending the Thread class, which has several built-in methods like yield() and interrupt() that aren’t available in the Runnable interface.
  3. When you use runnable, you’ll get an object that can be shared by numerous threads.

Additional Resources:

  1. https://www.interviewbit.com/blog/java-developer-skills/
  2. https://www.interviewbit.com/blog/java-projects/
  3. https://www.interviewbit.com/blog/java-frameworks/
  4. https://www.interviewbit.com/java-mcq/
  5. https://www.interviewbit.com/blog/java-11-features/
  6. https://www.interviewbit.com/blog/java-8-features/
  7. https://www.interviewbit.com/blog/java-books/
  8. https://www.interviewbit.com/blog/java-developer-resume/
  9. https://www.interviewbit.com/blog/top-java-applications/
  10. https://www.interviewbit.com/blog/characteristics-of-java/
  11. https://www.scaler.com/topics/java/error-vs-exception-in-java/

3. Java Generics

Generics refer to types that have been parameterized. The goal is to make type (Integer, String, etc., as well as user-defined types) a parameter for methods, classes, and interfaces. Generics can be used to design classes that function with a variety of data types. A generic entity is a type that works on a parameterized type, such as a class, interface, or method. In Java, generics are equivalent to templates in C++. Generics are used extensively in classes such as HashSet, ArrayList, HashMap, and others.

Generic class:

In the same way that C++ specifies parameter types, we use <> to define parameter types in generic class formation. The following syntax is used to construct generic class objects.

ClassName obj = new ClassName ()

Here, ‘ClassName’ denotes the name of the class whose instance is to be created. specifies the data type to be used while instantiating the object. ‘obj’ is the name of the object to be created.

class SampleT> < // Declaring an object of type T T obj; Test(T obj) // constructor < this.obj = obj; > public T getObject() < return this.obj; > > class Test < public static void main (String[] args) < // instance of Integer type Sample obj1 = new Sample(10); System.out.println(obj1.getObject()); // instance of String type Test obj2 = new Test("Interview Bit"); System.out.println(obj2.getObject()); > >
10 Interview Bit

In the above example, a generic class Sample has been created which accepts a parameter T to determine the type of the class. We create 2 instances of the Sample class. One with an Integer type and the other with a String type.

The following are the advantages of using generics in Java:

Type-safety: In generics, we can only hold one type of object. It does not allow for the storage of objects of different types. Example -

List list = new ArrayList(); list.add(1); list.add("Interview Bit");

The above code snippet runs fine. This is because we have not specified any type while creating an instance of the List class. However, if we run the below code snippet, we get a compile-time error.

List list = new ArrayList(); list.add(1); list.add("Interview Bit");// compile-time error

This is because we have specified the instance of the List class to be of type Integer.

Typecasting isn’t necessary: When we use generics, we do not need to typecast the object when we access it.

List list = new ArrayList(); list.add("Interview Bit"); String s = (String) list.get(0);//typecasting 

In the above code, we can see that before accessing the element of the list, we need to typecast it to String type explicitly. This is because we have not declared the list instance to be of a specific type. However, if we run the below code snippet, we do not need to typecast it explicitly.

List list = new ArrayList(); list.add("Interview bit"); String s = list.get(0);

This is because we have specified the instance of the List class to be of String type.

Checking at Compile Time: It is checked at compile time to ensure that an issue does not arise at runtime. It is considerably better to handle the problem at compile time than at runtime, according to an excellent programming approach.

List list = new ArrayList(); list.add("Interview Bit"); list.add(100);//Compile Time Error 

The above code snippet gives a compile-time error. This verifies that the code is checked at compile-time.