1. What is Java, and what are the features of Java?

Java is a high-level program language and is platform-independent.
Some of the key features of Java include:

  • Object-Oriented: Java is an object-oriented programming language, which means it allows developers to create modular programs and reusable code.
  • Platform Independence: Java code can run on any platform that has a Java Virtual Machine (JVM), making it highly portable.
  • Robust: Java has strong memory management and exception handling features, which help in creating reliable and stable applications.
  • Multithreading: Java supports multithreading, allowing multiple threads to run concurrently, which can improve performance in certain applications.
  • Security: Java has built-in security features that help protect against malicious code and unauthorized access.
  • Rich API: Java provides a vast standard library (API) that includes classes and methods for various tasks, such as data structures, networking, and graphical user interfaces (GUIs).
  • Automatic Memory Management: Java uses garbage collection to automatically manage memory, which helps prevent memory leaks and other related issues.
  • High Performance: Although Java is an interpreted language, it uses Just-In-Time (JIT) compilation to improve performance, making it suitable for a wide range of applications.

2. What is the difference between JDK, JRE, and JVM?

  • JDK (Java Development Kit): The JDK is a software development kit that provides tools and libraries for developing Java applications. It includes the JRE and additional development tools such as the Java compiler (javac), debugger, and other utilities.
  • JRE (Java Runtime Environment): The JRE is a runtime environment that provides the necessary libraries and components to run Java applications. It includes the JVM and the Java class libraries but does not include development tools like the compiler.
  • JVM (Java Virtual Machine): The JVM is an abstract computing machine that enables Java bytecode to be executed on any platform. It is responsible for interpreting the compiled Java bytecode and executing it on the host machine. The JVM provides platform independence by allowing Java applications to run on any device that has a compatible JVM installed.

3. What is OOPs concepts in Java?

OOPs (Object-Oriented Programming) concepts in Java include:

  • Encapsulation: This is the process of wrapping data (variables) and code (methods) together as a single unit. It helps in hiding the internal details of an object and only exposing necessary functionalities.
  • Inheritance: This allows a new class (child class) to inherit properties and behaviors (fields and methods) from an existing class (parent class). It promotes code reusability and establishes a natural hierarchical relationship between classes.
  • Polymorphism: This allows objects of different classes to be treated as objects of a common superclass. It enables a single interface to represent different underlying forms (data types). Polymorphism can be achieved through method overloading (compile-time polymorphism) and method overriding (runtime polymorphism).
  • Abstraction: This is the process of hiding complex implementation details and showing only the necessary features of an object. It helps in reducing complexity and increasing efficiency by allowing developers to focus on interactions at a higher level.
  • Classes and Objects: A class is a blueprint for creating objects, which are instances of the class. A class defines the properties (fields) and behaviors (methods) that the objects created from the class will have.
  • Association, Aggregation, and Composition: These are relationships between classes. Association is a general relationship where one class uses another. Aggregation is a special form of association that represents a “has-a” relationship, where one class contains another class as a part of it. Composition is a stronger form of aggregation where the contained class cannot exist without the container class.

4. What are the access modifiers in Java?

Java provides four access modifiers:

  • public: The code is accessible from any class.
  • private: The code is accessible only within the same class.
  • protected: The code is accessible within the same package and subclasses in other packages.
  • default (no keyword): The code is accessible only within the same package.

5. What is the SOLID principle in Java?

The SOLID principles are a set of design principles that help developers create maintainable and scalable software. They include:

  • Single Responsibility Principle (SRP): A class should have only one reason to change, meaning it should have only one responsibility or job.
  • Open/Closed Principle (OCP): Software entities (classes, modules, functions, etc.) should be open for extension but closed for modification. This means that you should be able to add new functionality without changing existing code.
  • Liskov Substitution Principle (LSP): Objects of a superclass should be replaceable with objects of a subclass without affecting the correctness of the program. This means that subclasses should be able to stand in for their parent classes without causing errors or unexpected behavior.
  • Interface Segregation Principle (ISP): Clients should not be forced to depend on interfaces they do not use. This means that it’s better to have multiple specific interfaces rather than a single general-purpose interface.
  • Dependency Inversion Principle (DIP): High-level modules should not depend on low-level modules. Both should depend on abstractions (e.g., interfaces). This means that you should depend on abstractions rather than concrete implementations, which helps in reducing coupling and increasing flexibility in the code.

6. What are primitive data types in Java?

Java has eight primitive data types:

  • byte: 8-bit signed integer, with a range of -128 to 127.
  • short: 16-bit signed integer, with a range of -32,768 to 32,767.
  • int: 32-bit signed integer, with a range of -2,147,483,648 to 2,147,483,647.
  • long: 64-bit signed integer, with a range of -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807.
  • float: 32-bit floating-point number.
  • double: 64-bit floating-point number.
  • char: 16-bit Unicode character.
  • boolean: Represents true or false values.

7. Order of execution in Java?

The order of execution in Java is as follows:

  1. Static blocks: These are executed when the class is loaded into memory, before any objects are created.
  2. Instance blocks: These are executed when an instance of the class is created, before the constructor is called.
  3. Constructors: These are executed when an object is created, after the instance blocks.
  4. Methods: These are executed when they are called on an object.

7.1 Order of execution in Java with inheritance:

  1. Static blocks of the parent class: These are executed first when the parent class is loaded into memory.
  2. Static blocks of the child class: These are executed after the static blocks of the parent class when the child class is loaded into memory.
  3. Instance blocks of the parent class: These are executed when an instance of the parent class is created, before the constructor of the parent class is called.
  4. Constructor of the parent class: This is executed after the instance blocks of the parent class when an instance of the parent class is created.
  5. Instance blocks of the child class: These are executed when an instance of the child class is created, before the constructor of the child class is called.
  6. Constructor of the child class: This is executed after the instance blocks of the child class when an instance of the child class is created.

8. What is the difference between method overloading and method overriding in Java?

  • Method Overloading: This occurs when multiple methods in the same class have the same name but different parameters (different type, number, or both). It is a compile-time polymorphism feature that allows methods to perform similar functions with different inputs.
  • Method Overriding: This occurs when a subclass provides a specific implementation of a method that is already defined in its superclass. The method in the subclass must have the same name, return type, and parameters as the method in the superclass. It is a runtime polymorphism feature that allows a subclass to provide a specific behavior for a method that is already defined in its parent class.

9. What are the differences between Lambda Expressions, Anonymous Classes, and Closures in Java?

  • Lambda Expressions: Lambda expressions are a concise way to represent anonymous functions in Java. They allow you to write code in a functional style and are often used with functional interfaces (interfaces with a single abstract method). Lambda expressions can be used to create instances of functional interfaces without the need for an anonymous class.
  • Anonymous Classes: Anonymous classes are a way to define and instantiate a class at the same time. They are typically used to create a one-time use class that implements an interface or extends a class. Anonymous classes can have multiple methods and can access final variables from the enclosing scope.
  • Closures: Closures are a programming concept where a function retains access to its lexical scope even when the function is executed outside that scope. In Java, lambda expressions can be considered as closures because they can capture and use variables from their enclosing scope. However, Java does not have true closures like some other programming languages, as it only allows access to final or effectively final variables from the enclosing scope.

10. What are the differences between atomic, volatile, and synchronized in Java?

  • Atomic: Atomic operations are indivisible operations that cannot be interrupted by other threads. In Java, the java.util.concurrent.atomic package provides classes that support atomic operations on single variables, such as AtomicInteger and AtomicReference. These classes use low-level atomic instructions to ensure thread safety without the need for synchronization.
  • Volatile: The volatile keyword in Java is used to indicate that a variable’s value may be modified by multiple threads. When a variable is declared as volatile, it ensures that all threads see the most up-to-date value of the variable. However, it does not provide atomicity for compound actions (like incrementing a variable), so it is not suitable for situations where multiple threads need to perform compound operations on the variable.
  • Synchronized: The synchronized keyword in Java is used to control access to a particular resource or block of code by multiple threads. When a method or block of code is synchronized, only one thread can access it at a time. This is achieved by acquiring a lock on the object or class that is being synchronized. Synchronized blocks can be used to ensure that critical sections of code are executed by only one thread, providing thread safety for shared resources. However, excessive use of synchronization can lead to performance issues and potential deadlocks if not used carefully.