Class in Java
In Java, a class is a blueprint for creating objects. A class can contain variables and methods. When an object is created from a class, we say an instance of the class is created.
There are two main types of variables in a class:
- Instance Variables (Non-static Fields): Technically speaking, objects store their individual states in non-static fields, also known as instance variables. Each instance of the class has its own copy of these variables.
- Class Variables (Static Fields): This is a special type of field that there’s only one copy of it shared by all instances of the class. A static field is also known as a class variable. They represent the “state” of the class itself, not of individual instances.
Here is a simple Java class demonstrating these concepts:
public class MyClass {
// Instance variable
int instanceVariable;
// Class variable or static field
static int classVariable;
// Constructor method
MyClass(int instanceVariable) {
this.instanceVariable = instanceVariable;
classVariable++;
}
// Instance method
void printInstanceVariable() {
System.out.println("The instance variable is: " + instanceVariable);
}
// Class method or static method
static void printClassVariable() {
System.out.println("The class variable is: " + classVariable);
}
}
public class Main {
public static void main(String[] args) {
// Creating objects of the class MyClass
MyClass object1 = new MyClass(5);
MyClass object2 = new MyClass(10);
MyClass object3 = new MyClass(20);
// Accessing instance method and variable with object1
object1.printInstanceVariable(); // It will output: The instance variable is: 5
// Accessing instance method and variable with object2
object2.printInstanceVariable(); // It will output: The instance variable is: 10
// Accessing instance method and variable with object3
object3.printInstanceVariable(); // It will output: The instance variable is: 20
// Accessing class method with the class name
MyClass.printClassVariable(); // It will output: The class variable is: 3
}
}
Inner Class in Java
An Inner Class (or Nested Class) is defined within the body of another class. Java allows you to define a class within another class. Such a class is called a nested class and it can be static or non-static.
Here is a simple example to demonstrate inner classes in Java:
// Outer class
class OuterClass {
int outerField = 10;
// Inner class
class InnerClass {
int innerField = 20;
public void display() {
System.out.println("Outer Field: " + outerField);
System.out.println("Inner Field: " + innerField);
}
}
}
public class Main {
public static void main(String[] args) {
// Creating an instance of the outer class
OuterClass outer = new OuterClass();
// Creating an instance of the inner class
OuterClass.InnerClass inner = outer.new InnerClass();
// Calling method of inner class
inner.display();
}
}
Compare Modifiers
Keywords | Within Class | Within Package | Outside Package by Subclass | Outside Package |
Public | Yes | Yes | Yes | Yes |
Private | Yes | No | No | No |
Protected | Yes | Yes | Yes | No |
Explanation of the modifiers:
- Public: The public keyword is an access modifier that makes a method or a data member visible to all classes in any package. So if you have a method or a variable defined as public , this method or variable can be accessed from any other class in the application.
- Private: The private access modifier restricts the visibility to within the class only. Private members (methods/ variables) are visible only within the class that declares them.
- Protected: The protected access modifier allows visibility to a class within the same package, or to all subclasses of the class, irrespective of what package the subclasses are in. If a class, method, or a member variable is declared as `protected`, it can be accessed from the classes within the same package or from the subclasses of this class or from the class itself.
Object-Oriented Design (OOD)
Object-Oriented Design in Java, or in any object-oriented programming language, refers to the process of planning a system of interacting objects for the purpose of solving a software problem. It is a methodology that involves designing the application by thinking in terms of objects, which are instances of classes.
An object contains data (in the form of fields, often known as attributes or properties) and code behavior (in the form of methods or functions). The goal of OOD is to design software so that it’s easy to understand, easy to modify, and easy to maintain.
Object-oriented Programming System(from https://www.javatpoint.com/)
Some key principles and concepts related to OOD:
- Abstraction: Abstraction means using simple things to represent complexity. In Java, we use classes to abstract complex real world problems. Each class gives us a blueprint for creating objects; classes encapsulate data for the object.
- Encapsulation: Encapsulation means hiding the complexity and only exposing the essential features of the object. In Java, we encapsulate fields (data members) and methods inside classes. Encapsulation makes sure that “sensitive” data is hidden from users.
- Inheritance: Inheritance is a mechanism where you can derive a class from another class for a hierarchy of classes that share a set of attributes and methods.
- Polymorphism: Polymorphism allows routines to use variables of different types at different times. In Java, method overloading and method overriding are used for achieving polymorphism.
- Modularity: This concept pertains to the compartmentalization and inter-reliability of individual components of a software package or program. A modular system can be better managed and each module can be worked on independently.
- Association: This is a relationship where two classes are related, but still have their own separate lifecycles. They can exist independently.
- Aggregation: This is a special form of Association where the class association relationship is part-to-whole. This relationship is more specific, but the part can still exist independently of the whole.
- Composition: This is a more restrictive form of Aggregation where the part cannot exist independently of the whole. If the whole is deleted, the part will be deleted as well.
- Interfaces and Abstract Classes: These are used to establish common protocols for classes that share some behaviors, but not all. They can be used to enforce certain methods that many classes will implement.
- Coupling and Cohesion: These are principles of how classes interact. Low coupling and high cohesion are desirable. Low coupling means each class is independent and changes in one class will not affect other classes. High cohesion means each class is designed around a single concept and the methods within the class are related.
Design patterns also play a significant role in OOD. These are general reusable solutions to commonly occurring problems in software design. They include creational, structural, and behavioral patterns, like Singleton, Factory, Adapter, Decorator, Observer, Strategy, etc. Object-oriented design is a complex process that requires a deep understanding of both the problem domain and the language’s features. But when used effectively, it can result in software that’s more manageable, scalable, and robust.
Abstraction
Abstraction in Java are implemented with abstract classes, interfaces and methods. Data abstraction is the process of hiding certain details and showing only essential information to the user. Abstraction can be achieved with either abstract classes or interfaces The abstract keyword is a non-access modifier, used for classes and methods.
Abstract Method and Class
Abstract method: can only be used in an abstract class, and it does not have a body. The body is provided by the subclass (inherited from).
Abstract class: is a restricted class that contains one or more abstract methods, it cannot be instantiated to create objects. An abstract class can have both abstract and regular methods.
Here is an example to demonstrate Abstraction:
// Abstract class
abstract class Animal {
// Abstract method (does not have a body)
public abstract void animalSound();
// Regular method
public void sleep() {
System.out.println("Zzz");
}
}
// Subclass (inherit from Animal)
class Pig extends Animal {
public void animalSound() {
// The body of animalSound() is provided here
System.out.println("The pig says: wee wee");
}
}
class Main {
public static void main(String[] args) {
Pig myPig = new Pig(); // Create a Pig object
myPig.animalSound();
myPig.sleep();
}
}
Interfaces
Another way to achieve abstraction in Java is with interfaces. An interface is a completely “abstract class” that is used to group related methods with empty bodies.
An interface contains only constants, method signatures, default methods, static methods, and nested types. Like a class, an interface can also have methods and variables, but the methods declared in an interface are by default abstract (only method signature, no body).
Here is a simple example to demonstrate interfaces in Java:
// Interface
interface Animal {
void sound(); // abstract method
void sleep(); // abstract method
}
// Class implements interface
class Dog implements Animal {
public void sound() {
System.out.println("The dog barks");
}
public void sleep() {
System.out.println("The dog sleeps");
}
}
public class Main {
public static void main(String[] args) {
// Creating an instance of the Dog class
Dog myDog = new Dog();
// Dog can use methods of Animal interface
myDog.sound();
myDog.sleep();
}
}
Encapsulation
Encapsulation in Java refers to the bundling of data, along with the methods that operate on that data, into a single unit. This often takes the form of having private data fields in the class and providing public getter and setter methods to access and modify the data.
public class Employee {
// The private fields are not accessible outside the class
private String name;
private int id;
// Constructor
public Employee(String name, int id) {
this.name = name;
this.id = id;
}
// Getter for the name field (public method to access private data)
public String getName() {
return this.name;
}
// Setter for the name field (public method to modify private data)
public void setName(String name) {
this.name = name;
}
// Getter for the id field
public int getId() {
return this.id;
}
// Setter for the id field
public void setId(int id) {
this.id = id;
}
}
public class Main {
public static void main(String[] args) {
// Create a new Employee object
Employee emp = new Employee("John Doe", 1234);
// Access private fields via public getter methods
System.out.println("Name: " + emp.getName());
System.out.println("ID: " + emp.getId());
// Modify private fields via public setter methods
emp.setName("Jane Doe");
emp.setId(5678);
// Access private fields via public getter methods
System.out.println("Name: " + emp.getName());
System.out.println("ID: " + emp.getId());
}
}
In this example, the Employee class encapsulates the name and id data fields. These fields are marked as private, so they cannot be directly accessed or modified from outside the class. To provide a way to interact with these fields, we have public getter and setter methods. This allows us to control how the fields are accessed and modified, and it protects the fields from being manipulated in undesired ways.
Inheritance
Inheritance allows a class (child class) to inherit the fields and methods of another class (parent class). This promotes code reuse and a logical, hierarchical structure for your classes. In Java, extends keyword is used to show a subclass is inherited from a base class.
Here is a simple example to demonstrate inheritance in Java:
// A class called "Animal" is defined. This is our parent/base class.
class Animal {
public void eat() {
System.out.println("This animal eats");
}
public void sleep() {
System.out.println("This animal sleeps");
}
}
// A class "Dog" is defined. Dog extends Animal, so it's a child/subclass of Animal.
class Dog extends Animal {
public void bark() {
System.out.println("The dog barks");
}
}
public class Main {
public static void main(String[] args) {
// Creating an object of the Dog class
Dog myDog = new Dog();
// Dog can use methods of Animal class due to inheritance
myDog.eat();
myDog.sleep();
// Dog can also use its own methods
myDog.bark();
}
}
Polymorphism
Polymorphism means “many forms”, and it occurs when there is a hierarchy of classes related through inheritance. Polymorphism allows a child class to inherit the methods of a parent class, and then override those methods to provide a specific implementation.
Here is a simple example to demonstrate polymorphism in Java:
// This is our parent/base class
class Animal {
public void sound() {
System.out.println("The animal makes a sound");
}
}
// This is a subclass of Animal
class Pig extends Animal {
// The sound method is overridden in this subclass
public void sound() {
System.out.println("The pig says: wee wee");
}
}
// This is another subclass of Animal
class Dog extends Animal {
// The sound method is also overridden in this subclass
public void sound() {
System.out.println("The dog says: woof woof");
}
}
public class Main {
public static void main(String[] args) {
// Create a Pig object
Animal myPig = new Pig();
myPig.sound();
// Create a Dog object
Animal myDog = new Dog();
myDog.sound();
}
}