Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
3 views

Java Questions

java questions for upskilling

Uploaded by

Minisha N
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

Java Questions

java questions for upskilling

Uploaded by

Minisha N
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 11

Generics in programming, particularly in Java and C#, are a way to define classes,

interfaces, and methods with placeholders for types. These placeholders are

specified when you instantiate the class or call the method, allowing for type-safe

data structures and algorithms without sacrificing performance. Generics provide the

benefits of code reusability and type safety.

A generic method can operate on objects of various types while providing

compile-time type safety. Let's look at how to write a generic method in Java that

exchanges the positions of two elements in an array.

public class GenericMethodExample {

// Generic method to swap elements in an array

public static <T> void swap(T[] array, int index1, int index2) {

if (index1 >= 0 && index1 < array.length && index2 >= 0 && index2 <

array.length) {

T temp = array[index1];

array[index1] = array[index2];

array[index2] = temp;

} else {

throw new IndexOutOfBoundsException("Index out of bounds");

}
public static void main(String[] args) {

// Integer array

Integer[] intArray = {1, 2, 3, 4, 5};

System.out.println("Before swap: " + java.util.Arrays.toString(intArray));

swap(intArray, 1, 3);

System.out.println("After swap: " + java.util.Arrays.toString(intArray));

// String array

String[] strArray = {"A", "B", "C", "D", "E"};

System.out.println("Before swap: " + java.util.Arrays.toString(strArray));

swap(strArray, 0, 4);

System.out.println("After swap: " + java.util.Arrays.toString(strArray));

ere's a Java example:

Explanation:
1. Generic Method Definition: The method swap is defined with the generic type
<T>. This means that the method can work with any type T.
2. Parameters:
● T[] array: The array of elements of type T.
● int index1: The first index of the element to swap.
● int index2: The second index of the element to swap.
3. Swap Logic: The elements at the specified indices are swapped using a
temporary variable.
4. Bounds Checking: The method checks if the provided indices are within the
bounds of the array to avoid IndexOutOfBoundsException.
5. Main Method: The main method demonstrates how to use the swap method
with different types of arrays (Integer and String).

This generic method can be used to swap elements in any array, regardless of the

type of the elements, as long as the type is specified when calling the method.

In Java Generics, a bounded type parameter restricts the types that can be used as
arguments for a generic type. This allows you to enforce certain constraints on the
types that can be passed to a generic class, method, or interface.

Bounded Type Parameter


A bounded type parameter uses the extends keyword to specify an upper bound for
the type parameter. For example:

● <T extends Number> means that T can be any type that is a subclass of
Number.

This is useful when you want to ensure that the type parameter implements certain
methods or behaviors.

public class BoundedTypeParameterExample {

// Generic method to sort an array of numbers using Bubble Sort


public static <T extends Number & Comparable<T>> void bubbleSort(T[] array) {
int n = array.length;
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - 1 - i; j++) {
if (array[j].compareTo(array[j + 1]) > 0) {
// Swap array[j] and array[j + 1] using a temporary variable
T temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
}

public static void main(String[] args) {


// Integer array
Integer[] intArray = {5, 3, 8, 1, 9};
System.out.println("Before sorting Integer array: " + java.util.Arrays.toString(intArray));
bubbleSort(intArray);
System.out.println("After sorting Integer array: " + java.util.Arrays.toString(intArray));

// Float array
Float[] floatArray = {5.5f, 3.3f, 8.8f, 1.1f, 9.9f};
System.out.println("Before sorting Float array: " + java.util.Arrays.toString(floatArray));
bubbleSort(floatArray);
System.out.println("After sorting Float array: " + java.util.Arrays.toString(floatArray));

// Double array
Double[] doubleArray = {5.5, 3.3, 8.8, 1.1, 9.9};
System.out.println("Before sorting Double array: " +
java.util.Arrays.toString(doubleArray));
bubbleSort(doubleArray);
System.out.println("After sorting Double array: " +
java.util.Arrays.toString(doubleArray));
}
}

1. Bubble Sort Algorithm:


● The bubbleSort method uses a nested loop to iterate through the
array.
● For each pair of adjacent elements, it compares them using compareTo
and swaps them if they are in the wrong order.
● This process continues until the entire array is sorted.
2. Temporary Variable: A temporary variable temp is used to hold one of the
elements during the swap process.
3. Bounded Type Parameter: The method uses the bounded type parameter <T
extends Number & Comparable<T>> to ensure that the elements can be
compared and are numeric types.
4. Main Method:
● Arrays of Integer, Float, and Double are created and printed before
sorting.
● The bubbleSort method is called for each array type, and the sorted
arrays are printed.

This implementation provides a clear example of how to use a temporary variable to


sort an array of elements using the Bubble Sort algorithm in a generic method.

What are Generics?


Generics are used to create Generic Classes and Generic methods which can work with different

Types(Classes).

Why do we need Generics? Can you give an example of


how Generics make a program more flexible?
Consider the class below:

class MyList {
private List<String> values;

void add(String value) {


values.add(value);
}

void remove(String value) {


values.remove(value);
}
}

MyList can be used to store a list of Strings only.

MyList myList = new MyList();


myList.add("Value 1");
myList.add("Value 2");
To store integers, we need to create a new class. This is problem that Generics solve. Instead of

hard-coding String class as the only type the class can work with, we make the class type a

parameter to the class.

Example with Generics

Let’s replace String with T and create a new class. Now the MyListGeneric class can be used to

create a list of Integers or a list of Strings

class MyListGeneric<T> {
private List<T> values;

void add(T value) {


values.add(value);
}

void remove(T value) {


values.remove(value);
}

T get(int index) {
return values.get(index);
}
}

MyListGeneric<String> myListString = new MyListGeneric<String>();


myListString.add("Value 1");
myListString.add("Value 2");

MyListGeneric<Integer> myListInteger = new MyListGeneric<Integer>();


myListInteger.add(1);
myListInteger.add(2);

Bounded Type Parameter


A bounded type parameter in Java Generics restricts the types that can be used as

arguments for a generic type. This allows you to enforce certain constraints on the

types that can be passed to a generic class, method, or interface, ensuring that the

type parameters adhere to specific types or interfaces.


Single Bound
The syntax for a bounded type parameter with a single bound is:

java
Copy code

class ClassName<T extends SomeClass> { // class body }

In this case, T can be any type that is a subclass of SomeClass.

Multiple Bounds
Java also supports multiple bounds for type parameters. A type parameter can have

multiple bounds by specifying an upper bound (a class) and one or more interfaces.

The syntax for multiple bounds is:

java
Copy code

class ClassName<T extends SomeClass & SomeInterface1 & SomeInterface2>

{ // class body }

In this scenario, T can be any type that extends SomeClass and implements both

SomeInterface1 and SomeInterface2. Note that a class must be specified first,

followed by any number of interfaces.

Example of Bounded Type Parameter


Let's see an example where we use a bounded type parameter with multiple bounds:

import java.util.ArrayList;

import java.util.List;

// Example of bounded type parameter with multiple bounds

interface Printable {
void print();

abstract class Shape {

abstract double area();

class Rectangle extends Shape implements Printable {

private double length, width;

Rectangle(double length, double width) {

this.length = length;

this.width = width;

@Override

double area() {

return length * width;

@Override

public void print() {

System.out.println("Rectangle with area: " + area());

class Circle extends Shape implements Printable {

private double radius;

Circle(double radius) {

this.radius = radius;

}
@Override

double area() {

return Math.PI * radius * radius;

@Override

public void print() {

System.out.println("Circle with area: " + area());

// Generic method with multiple bounds

public class BoundedTypeParameterExample {

public static <T extends Shape & Printable> void printShapes(List<T> shapes) {

for (T shape : shapes) {

shape.print();

public static void main(String[] args) {

List<Rectangle> rectangles = new ArrayList<>();

rectangles.add(new Rectangle(2, 3));

rectangles.add(new Rectangle(4, 5));

List<Circle> circles = new ArrayList<>();

circles.add(new Circle(1));

circles.add(new Circle(2));

System.out.println("Rectangles:");

printShapes(rectangles);
System.out.println("Circles:");

printShapes(circles);

Explanation:
1. Interfaces and Classes:
● Printable is an interface with a print method.
● Shape is an abstract class with an area method.
● Rectangle and Circle are concrete classes that extend Shape and
implement Printable.
2. Generic Method with Multiple Bounds:
● The method printShapes uses a bounded type parameter <T extends
Shape & Printable>. This ensures that the method can only accept
types that are subclasses of Shape and implement Printable.
3. Main Method:
● We create lists of Rectangle and Circle objects.
● We call the printShapes method with these lists, and it prints
information about the shapes.

This demonstrates how bounded type parameters can be used to enforce

constraints on generic types, ensuring that they meet specific requirements and can

safely be used in certain ways.

// Define the Drawable interface


interface Drawable {
void draw();
}

// Define the Shape enumeration that implements Drawable


enum Shape implements Drawable {
CIRCLE {
@Override
public void draw() {
System.out.println("Drawing a Circle");
}
},
SQUARE {
@Override
public void draw() {
System.out.println("Drawing a Square");
}
},
TRIANGLE {
@Override
public void draw() {
System.out.println("Drawing a Triangle");
}
}
}

// Main class to demonstrate the usage of Shape enumeration


public class Main {
public static void main(String[] args) {
// Iterate over all constants in the Shape enum
for (Shape shape : Shape.values()) {
// Call the draw() method for each shape
shape.draw();
}
}
}

You might also like