Java Theory Que
Java Theory Que
Java Theory Que
### 1. **Size**
- **Array**: Fixed in size. Once an array is created, its size cannot be changed.
- **ArrayList**: Dynamic in size. It can grow or shrink dynamically as elements are added or removed.
- **Array**: Can hold both primitive data types (e.g., `int`, `char`) and objects.
- **ArrayList**: Can only hold objects (not primitives). For primitive types, wrapper classes (like
`Integer`, `Character`) are used.
### 3. **Performance**
- **Array**: Faster when accessing or modifying elements because it is a simple structure with direct
memory allocation.
- **ArrayList**: Slightly slower due to dynamic resizing and method calls, but the performance is still
good for general use cases.
### 4. **Resizing**
- **Array**: You cannot change the size of an array after its creation.
- **ArrayList**: Automatically resizes when more elements are added beyond its initial capacity.
- **Array**: Allocates memory at compile time, and memory is allocated for all elements, whether they
are used or not.
- **ArrayList**: Allocates memory dynamically. It starts with a default size (typically 10) and grows as
needed.
- **Array**: Does not provide built-in methods for operations like adding, removing, or searching
elements. These operations must be manually implemented.
- **ArrayList**: Provides built-in methods such as `add()`, `remove()`, `contains()`, `get()`, `size()`, and
more for easier manipulation of data.
### 7. **Multidimensional**
- **Array**: Can be multidimensional (e.g., 2D arrays like `int[][]`).
- **ArrayList**: Cannot directly support multidimensional arrays but can be implemented using
`ArrayList<ArrayList<>>`.
### Example:
- **Array**:
```java
```
- **ArrayList**:
```java
```
In summary, an **Array** is more efficient in terms of speed but less flexible, while an **ArrayList**
offers greater flexibility at the cost of slight performance overhead.
### 1. **Structure**:
- **While Loop**: The `while` loop only includes a condition and repeatedly
executes the block of code as long as the condition is true. Initialization and
increment/decrement steps are handled separately.
```java
while (condition) {
// code to be executed
}
```
- **For Loop**: The `for` loop integrates initialization, condition, and iteration
steps all in one line, making it more compact when the number of iterations is
known.
```java
for (initialization; condition; iteration) {
// code to be executed
}
```
- **For Loop**: Best suited when the number of iterations is predetermined, such
as iterating over arrays or a fixed range of values.
In summary:
- Use a **while loop** when you don’t know how many iterations you need
ahead of time.
- Use a **for loop** when the number of iterations is known and you want a
more structured, concise loop.
- Each element of the `args` array corresponds to one argument, with `args[0]` being the first argument,
`args[1]` being the second, and so on.
```java
```
The `args` array allows users to pass data into the program, making it more dynamic and configurable.
When you run the Java program from the command line, you can pass arguments after the class name.
Each argument is separated by a space.
```java
if (args.length > 0) {
System.out.println("Command-line arguments:");
} else {
}
}
```
You can compile and run the program with command-line arguments like this:
```bash
javac CommandLineExample.java
```
Here, `"arg1"`, `"arg2"`, and `"arg3"` are the command-line arguments, and they will be stored in the
`args` array in the following way:
- `args[0] = "arg1"`
- `args[1] = "arg2"`
- `args[2] = "arg3"`
```plaintext
Command-line arguments:
args[0]: arg1
args[1]: arg2
args[2]: arg3
```
- Pass configuration parameters such as file paths, user input, or environment settings.
- Control the behavior of the program dynamically without needing to modify the code.
#### Example: Using command-line arguments to calculate the sum of two numbers:
```java
if (args.length == 2) {
} else {
```
You can run this program from the command line by passing two numbers:
```bash
java SumCalculator 5 10
```
Output:
```plaintext
Sum: 15
```
In this example, the two numbers `5` and `10` are passed as command-line arguments, and they are
used to calculate the sum within the program.
### Summary:
- The `String[] args` parameter in the `main` method allows Java programs to accept arguments from the
command line.
- This feature enables you to pass data to a program at runtime, enhancing its flexibility and
configurability.
An array in Java is a fixed-size, indexed collection of elements of the same type. Each element
in the array is identified by its index, and the index starts from 0. Arrays can store both primitive
data types (e.g., int, char, float) and objects (e.g., String, custom classes).
Characteristics of an Array:
Arrays and ArrayList are both used to store collections of elements, but they have significant
differences in terms of flexibility, performance, and usage.
Characteristics of a Constructor:
Same name as the class: The constructor must have the same name as the class it is
associated with.
No return type: Unlike regular methods, constructors do not have a return type, not even
void.
Automatically invoked: When you create an object using the new keyword, the
constructor is automatically called.
Can be overloaded: You can define multiple constructors with different parameter lists
(constructor overloading).
An **object** is an instance of a class in Java. It represents a real-world entity that has both **state**
(attributes) and **behavior** (methods). Objects are created from classes, which act as blueprints. An
object holds the actual data, while the class defines the structure and behavior the object will have.
- **State**: The data or attributes an object holds (e.g., name, age, color).
- **Behavior**: The actions or methods an object can perform (e.g., move, eat, display).
**Example**:
```java
class Dog {
int age;
System.out.println("Woof!");
}
public class Main {
```
A **class** is a blueprint or template for creating objects. It defines the attributes (variables) and
methods (functions) that the objects created from the class will have. In other words, a class
encapsulates data for the object and methods to manipulate that data.
**Example**:
```java
class Car {
int year;
```
Here, `Car` is a class that defines a car's model and year, and it has a method `start()` to represent the
behavior of starting the car.
#### **c. Method**
A **method** in Java is a block of code that performs a specific task or action and can be invoked to
perform that action. Methods define the behavior of objects and can accept parameters, return values,
and perform operations on the object's attributes.
- **Return Type**: Specifies what type of value, if any, the method will return. `void` means the method
does not return any value.
**Example**:
```java
class Calculator {
return a + b;
```
In this example, the `add()` method takes two parameters, adds them, and returns the result.
In Java, the keyword **static** is used to define class-level members (variables or methods) that are
shared among all instances of the class. A static member belongs to the class itself, rather than to any
specific object of the class, meaning it can be accessed without creating an instance of the class.
- **Static Variables**: Shared by all objects of the class and have the same value across all objects.
- **Static Methods**: Can be called without creating an instance of the class. They can only access static
data or call other static methods directly.
**Example**:
```java
class MathUtils {
return a + b;
int result = MathUtils.add(5, 10); // Calling a static method without creating an object
System.out.println(result); // Output: 15
```
In this example, `add()` is a static method and `counter` is a static variable. Both can be accessed without
creating an instance of the `MathUtils` class.
### **Summary**:
- **Class**: A blueprint that defines the structure and behavior (attributes and methods) for objects.
- **Method**: A function or block of code that performs a task and defines an object's behavior.
- **Static**: Refers to class-level variables or methods that belong to the class itself, rather than to any
specific object, and can be accessed without instantiating the class.
In Java, **local variables** are declared within a method and are only accessible inside that method,
whereas **instance variables** (also called global variables) are declared at the class level and are
accessible by all methods in that class.
Here's an example demonstrating the difference between local and instance variables and how they can
be modified and accessed within methods:
```java
class VariableScopeExample {
example.modifyAndPrintVariables();
```
- The variable `instanceVar` is declared at the class level. It is accessible in all methods of the class, and
changes made to it in any method will affect its value throughout the class.
- The variable `localVar` is declared inside the method `modifyAndPrintVariables()`. This variable is only
accessible within this method and will not exist outside of it.
- Inside the method `modifyAndPrintVariables()`, the instance variable `instanceVar` is modified, and
its new value is retained even after the method finishes executing.
- The local variable `localVar` is used within the method and goes out of scope (is no longer accessible)
once the method finishes execution.
### **Output**:
```plaintext
Local variable: 20
Instance variable: 50
```
- **Local Variables**: Exist only within the method they are declared in and cannot be accessed outside
that method. Once the method completes, the local variable is destroyed.
- **Instance Variables**: Exist as long as the object exists and can be accessed or modified by any
method within the class. Changes to an instance variable inside a method affect the variable's value
across all methods.
This demonstrates how local and instance variables behave differently with respect to their scope and
lifetime.
- **Encapsulation**: A class groups related data and methods together, hiding the internal details and
exposing only what is necessary. This helps in organizing and managing complexity in large programs.
- **Reusability**: Once a class is defined, it can be reused to create multiple objects without having to
rewrite code. This promotes code reuse.
- **Modularity**: Classes allow developers to break down large systems into smaller, manageable
components, each representing a real-world entity or concept.
- **Inheritance**: A class can be used as a base for other classes, allowing new classes to inherit
properties and methods from existing ones.
- **Abstraction**: Classes provide a simplified view of an object by exposing only essential details and
hiding unnecessary complexity.
```java
class Person {
String name;
int age;
this.name = name; // Assign the parameter 'name' to the instance variable 'name'
this.age = age; // Assign the parameter 'age' to the instance variable 'age'
```
1. **Class Definition**:
- The class `Person` defines two attributes, `name` and `age`, which represent the state of a person.
- The class also has a method `displayInfo()` that prints out the details of the person.
2. **Constructor**:
- The constructor `public Person(String name, int age)` is used to initialize the attributes (`name` and
`age`) when a new `Person` object is created.
- The constructor assigns the values passed as arguments to the instance variables.
3. **Object Creation**:
- In the `main` method, a new object `person1` is created using the `Person` class constructor, passing
`"Alice"` and `25` as arguments.
- The method `displayInfo()` is then called on the object to display the person's details.
### **Output**:
```plaintext
Name: Alice
Age: 25
```
- **Class**: Represents a blueprint for creating objects with defined attributes and methods.
- **Object**: An instance of a class that has its own state (values of attributes) and can invoke methods
to perform actions.
**Method overloading** in Java is a feature that allows a class to have more than one method with the
same name but different parameter lists. It provides flexibility by enabling different behaviors for a
method based on the number, type, or order of parameters passed to it.
- **Same method name**: All overloaded methods must have the same name.
- **Different parameter lists**: Overloaded methods differ in the number of parameters, types of
parameters, or both. The return type can be the same or different, but the primary distinction is in the
parameter list.
- **Compile-time polymorphism**: Method overloading is an example of **compile-time
polymorphism** (also known as static polymorphism), where the compiler determines which method to
invoke based on the method signature during compilation.
- It allows for cleaner and more readable code by using a single method name for different tasks.
- It enhances code reusability by grouping related operations under the same method name but with
varying inputs.
```java
class Calculator {
return a + b;
return a + b + c;
return a + b;
}
public class Main {
```
1. **Method Overloading**:
- The class `Calculator` has three `add()` methods, all with the same name but different parameter lists.
- **First `add()` method**: Takes two integer parameters and returns their sum.
- **Second `add()` method**: Takes three integer parameters and returns their sum.
- **Third `add()` method**: Takes two `double` parameters and returns their sum.
2. **Method Calls**:
- The appropriate `add()` method is called based on the type and number of arguments passed:
### **Output**:
```plaintext
Sum of two integers: 30
```
1. **Parameter list must be different**: Overloaded methods must have a different number or type of
parameters.
2. **Return type does not affect overloading**: Having a different return type alone does not make the
methods overloaded. The method signature must be unique in terms of parameters.
3. **Method name must be the same**: The name of all overloaded methods must be identical.
- **Increased readability**: Using the same name for methods with related functionality makes the
code easier to understand.
- **Code reusability**: Methods with different parameter lists but similar functionality can be grouped
under the same name.
In summary, method overloading enables the same method name to handle different types and
numbers of arguments, which simplifies method invocation and enhances flexibility.
**Method overriding** in Java occurs when a subclass provides a specific implementation for a method
that is already defined in its superclass. In other words, the subclass **overrides** the method in the
parent class to give it a new behavior while keeping the same method signature (name, return type, and
parameters). This feature is a core aspect of **runtime polymorphism** (dynamic method dispatch) in
Java.
- **Same method signature**: The overridden method in the subclass must have the same name, return
type, and parameter list as the method in the superclass.
- **Used in inheritance**: Method overriding is only possible when a subclass inherits from a
superclass.
- **Run-time polymorphism**: The method that is executed is determined at runtime based on the
object type.
- **@Override annotation**: It is a good practice to use the `@Override` annotation to indicate that a
method is being overridden, ensuring that any mismatch in method signature is caught by the compiler.
- **To provide specific functionality**: A subclass can modify or extend the behavior of a method
defined in the superclass to meet its specific requirements.
- **Polymorphism**: It allows a subclass to be treated as an instance of its superclass and still invoke
the subclass’s specific implementation of a method.
```java
// Superclass: Animal
class Animal {
// Method to be overridden
@Override
@Override
```
### **Explanation of the Example**:
1. **Superclass (Animal)**:
- The `Animal` class has a method called `sound()`, which prints "The animal makes a sound".
2. **Subclass (Dog)**:
- The `Dog` class extends the `Animal` class and **overrides** the `sound()` method to print "The dog
barks".
3. **Subclass (Cat)**:
- Similarly, the `Cat` class also extends `Animal` and **overrides** the `sound()` method to print "The
cat meows".
4. **Polymorphism**:
- In the `main` method, objects of the `Dog` and `Cat` classes are created, but they are referenced
using the `Animal` type.
- The **overridden** method in the respective subclass (`Dog` or `Cat`) is called based on the actual
object type at runtime, not the reference type. This demonstrates **runtime polymorphism**.
### **Output**:
```plaintext
```
1. **Access Modifiers**: The access level of the overriding method cannot be more restrictive than the
overridden method (e.g., if the superclass method is `public`, the overriding method must also be
`public` or have broader access).
2. **Return Type**: The return type of the overriding method must be the same as the method in the
superclass, or it can be a subclass of the return type (covariant return types).
3. **Use of `super`**: The `super` keyword can be used within the subclass to call the method of the
superclass if needed.
- Example: `super.sound();`
4. **Final Methods**: Methods marked with the `final` keyword in the superclass cannot be overridden
in the subclass.
- **Flexibility**: Subclasses can provide specific implementations that are more appropriate for their
type.
- **Polymorphism**: Enables dynamic method dispatch, where the method executed is determined by
the actual object type at runtime, even if it is referenced by a superclass type.
Method overriding allows subclasses to inherit methods from a superclass and modify their behavior,
which is essential for achieving runtime polymorphism and designing flexible and reusable code in
object-oriented programming.
In Java, inheritance is achieved using the `extends` keyword. The subclass can add its own fields and
methods in addition to the inherited ones from the superclass.
### Example of Inheritance in Java
Here’s a simple implementation of a `Person` class and a `Student` subclass that inherits from `Person`:
```java
// Superclass
class Person {
// Fields
// Constructor
this.name = name;
this.age = age;
// Getter methods
return name;
return age;
// Subclass
// Constructor
super(name, age);
this.studentId = studentId;
return studentId;
@Override
super.display();
}
// Main class to test the inheritance
// Displaying details
student.display();
```
### Explanation:
- Has its own constructor that calls the superclass constructor to set the inherited properties.
3. **Main Class**:
- Creates an instance of the `Student` class and calls its `display()` method to show the details of the
student.
This implementation showcases the basic concept of inheritance in Java, allowing `Student` to utilize the
properties and behaviors defined in `Person`.
Java
public class Person {
private String name;
private int age;
}
}
}
Explanation:
Private Fields: The name and age fields are declared as private using the private
keyword. This means they are only accessible within the Person class and cannot be
directly accessed or modified from outside.
Public Getter and Setter Methods:
o Getter Methods: The getName() and getAge() methods are public and provide
a way to retrieve the values of the private fields. They return the corresponding
values of name and age.
o Setter Methods: The setName() and setAge() methods are also public and
allow you to modify the values of the private fields. They take a parameter (the
new value) and assign it to the respective field.
Data Validation (Optional): The setAge() method includes a simple data validation
check to ensure that the age is not negative. If the age is negative, an error message is
printed.
Benefits of Encapsulation:
Data Hiding: Encapsulation hides the implementation details of a class from the outside
world, making the code more modular and easier to maintain.
Data Security: By making fields private, you can control how they are accessed and
modified, preventing unintended changes or misuse.
Code Reusability: Encapsulated classes can be reused in different parts of your
application without worrying about conflicts or side effects.
Flexibility: Encapsulation allows you to change the implementation of a class without
affecting the code that uses it, as long as the public interface (getter and setter methods)
remains the same.
By following the principles of encapsulation, you can write more robust, maintainable, and
secure Java code.
}
}
animal = cat;
animal.makeSound(); // Output: Meow!
}
}
In Java, methods can be classified into two categories: static and instance. The key difference
lies in their association with objects and their access modifiers.
Static Methods:
Belong to the class: Static methods are associated with the class itself rather than
individual objects.
No need for an object: You can call static methods directly on the class name without
creating an object.
Access modifier: Static methods can be declared as public, private, protected, or
default.
Common use cases:
o Utility methods that operate on class-level data
o Factory methods for creating objects
o Main method for starting the application
Instance Methods:
Belong to objects: Instance methods are associated with specific objects of a class.
Require an object: You need to create an object of the class to call instance methods.
Access modifier: Instance methods can be declared as public, private, protected, or
default.
Common use cases:
o Methods that operate on the instance variables of an object
o Methods that provide behavior specific to individual objects
Example Program:
Java
public class MyClass {
private int instanceVariable = 10;
Output:
Key points:
Static methods are often used for utility functions that don't require instance data.
Instance methods are used for operations that involve the specific state of an object.
Choosing between static and instance methods depends on the context and the desired
behavior.