All Interview Questions
About Lesson

Abstraction in Java refers to the process of hiding implementation details and showing only essential features of an object to the outside world

Abstraction can be implemented in Java using interfaces and abstract classes

  • interfaces: It is like a contract. They contain only method signatures, constant variables, default methods, and static methods.

  • Abstract Classes: Abstract classes are classes that cannot be instantiated on their own and may contain both abstract and concrete methods.

interface Drawable {
    void draw();
}

abstract class Shape {
    protected String color;

    abstract void resize();
}


class Circle extends Shape implements drawable {
    public void draw() {
        System.out.println(“Drawing circle”);
    }

    public void resize() {
        System.out.println(“Resizing circle”);
    }
}

The static keyword in Java is used to declare members (variables and methods) that belong to the class rather than instances of the class

Various uses of the static keyword in Java include:

  • Creating static variables and methods that belong to the class rather than instances.

  • Using static nested classes to logically group classes that are only used in the context of the outer class. like builder and singleton

  • Static methods belong to the class and are associated with the class itself, whereas instance methods belong to individual instances of the class.
  • Static methods can be called using the class name without creating an instance, while instance methods can only be called on instances of the class.
  • Static methods cannot access instance variables directly, while instance methods can access both static and instance variables.
  • Runnable is a functional interface in Java used to represent a task that can be executed asynchronously. It has a single run() method and does not return a result or throw checked exceptions.
  • Callable is a functional interface. Callable tasks are executed using the ExecutorService framework, and they return a Future object that can be used to retrieve the result of the computation once it is completed

Thread safety ensures that when multiple threads are accessing a shared resource, the resource is protected to prevent conflicts and avoid race condition.

There are various technique to this in java

  • Synchronization: Using synchronized blocks or methods to control access to shared resources and prevent data races.

  • Atomic classes: Using atomic classes like AtomicInteger, AtomicLong, and AtomicReference for operations that need to be performed atomically without explicit locking.

  • Thread-safe collections: Using thread-safe implementations of collections like ConcurrentHashMap and CopyOnWriteArrayList provided in the java.util.concurrent package.

class Main {
    public static void main(String[] args) {
        for (int i = 1; i <= 100; i++) {
            int current = i; // Capture the current value of i
            Thread t1 = new Thread(() -> {
                System.out.println(current);
            });
            t1.start();
        }
    }
}
HashMap in Java is implemented as an array of buckets, where each bucket is a linked list of key-value pairs (nodes). When an element is inserted into the HashMap, its hash code is used to determine the index of the bucket where it will be stored. If multiple elements hash to the same index (hash collision), they are stored in the same bucket as a linked list. To retrieve an element from the HashMap, its hash code is used to locate the appropriate bucket, and then a linear search is performed within the bucket’s linked list to find the desired key-value pair.
  • Comparable is an interface in Java used to define the natural ordering of objects. It defines a single method compareTo() that compares the current object with another object of the same type.
  • Comparator is a functional interface used to define custom ordering of objects. It defines a single method compare() that compares two objects of a specified type.
List<Integer> numbers = new ArrayList<>();
        numbers.add(5);
        numbers.add(2);
        numbers.add(8);
        numbers.add(1);
        numbers.add(6);

Collections.sort(numbers, (a, b) -> b – a);

The Stream API in Java provides a  functional way to process collections of data. It allows for concise code

  • Stream operations: Stream API provides various intermediate and terminal operations to perform data processing tasks such as filtering, mapping, sorting, and reducing.

  • Lazy evaluation: Stream operations are evaluated lazily, meaning that intermediate operations are only executed when needed, resulting in efficient use of resources.

  • Support for parallelism: Stream API supports parallel execution of operations on streams, allowing for automatic parallelization of computations and improved performance on multi-core processors.

  • Method chaining: Stream API allows for method chaining, where multiple operations can be chained together in a single stream pipeline, leading to more concise and readable code.

The Stream API in Java provides a  functional way to process collections of data. It allows for concise code

  • map: The map operation transforms each element of the stream using a given function and produces a new stream containing the results.

  • filter: The filter operation selects elements from the stream that satisfy a given predicate and produces a new stream containing only those elements.

  • reduce: The reduce operation performs a reduction on the elements of the stream using an associative accumulation function and produces a single result.

List<Integer> lengths = words.stream()
                            .filter(word -> word.startsWith(“b”))
                            .map(filteredWord -> filteredWord.length())
                            .collect(Collectors.toList());
    StringBuffer and StringBuilder are both classes in Java used to create mutable sequences of characters.

    StringBuffer is thread-safe and synchronized, making it suitable for use in multi-threaded environments.

    StringBuilder is not thread-safe and is not synchronized, making it more efficient for single-threaded operations.

    Use StringBuffer when thread safety is required, such as in multi-threaded applications or when concurrent access to the string buffer is needed.

  • Final: is a keyword used to declare constants, prevent method overriding, and make variables immutable.
  • Finally: we will use whenever we will use try-catch block and it will work always even you get error or not but there is one condition it will not work when the program terminates before reaching to this block.
  • Finalize: is a method in the Object class that is called by the garbage collector before reclaiming an object’s memory.and normally we will not use finalize because it is unpredictable and causes performance issues.

© GeekySanjay