DEV Community

Cover image for Unraveling Java: Essential Foundations to Master Object-Oriented Programming!
SavanaPoint
SavanaPoint

Posted on

Unraveling Java: Essential Foundations to Master Object-Oriented Programming!

# JAVA

Welcome to the fascinating world of Java programming! This course is an exciting journey for those who wish to explore one of the most versatile and widely used programming languages in software development.

Data Types

In Java, there are different data types you can use to store values.

Primitive Types:

  1. Integers:

    • byte: 8 bits, stores integers from -128 to 127.
    • short: 16 bits, stores integers from -32,768 to 32,767.
    • int: 32 bits, stores integers from -2,147,483,648 to 2,147,483,647.
    • long: 64 bits, stores integers from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807.
  2. Floating Point:

    • float: 32 bits, stores single-precision floating-point numbers.
    • double: 64 bits, stores double-precision floating-point numbers (recommended for general use).
  3. Boolean:

    • boolean: stores true or false values (true or false).
  4. Characters:

    • char: 16 bits, stores a single Unicode character.

Reference Types:

  1. String:

    • String: stores a sequence of characters.
  2. Objects:

    • Custom data types created by you or available in libraries, like classes, interfaces, etc.

Example Usage:

public class DataTypesExample {
    public static void main(String[] args) {
        // Primitive types
        byte age = 30;
        int number = 12345;
        double price = 99.99;
        boolean isTrue = true;
        char letter = 'A';

        // Strings
        String name = "John";

        // Console output
        System.out.println("Age: " + age);
        System.out.println("Number: " + number);
        System.out.println("Price: " + price);
        System.out.println("Is it true? " + isTrue);
        System.out.println("Letter: " + letter);
        System.out.println("Name: " + name);
    }
}
Enter fullscreen mode Exit fullscreen mode

# Variables

In Java, variables are storage locations containing data manipulated by the program. Each variable has an associated data type and a name that identifies it within the scope where it was declared. Here are the key points about variables in Java:

Variable Declaration:

  1. Basic Syntax:
    • To declare a variable in Java, you specify the data type followed by the variable name and optionally an initial value.

Example:

   int age; // Declaration of an integer variable
   double price = 99.99; // Declaration of a double variable with initial value
Enter fullscreen mode Exit fullscreen mode
  1. Initialization:
    • Variables can be initialized when declared or later in the code.

Example:

   int number; // Declaration
   number = 10; // Later initialization
Enter fullscreen mode Exit fullscreen mode

Variable Types:

  1. Primitive Variables:

    • Store direct primitive values.
    • Examples: int, double, boolean, char, byte, short, long, float.
  2. Object References:

    • Refer to objects in memory.
    • Examples: String, objects of custom classes, interfaces.

Rules for Variable Names:

  1. Can contain letters, numbers, dollar signs $, and underscores _.
  2. Must start with a letter, dollar sign $, or underscore _.
  3. Cannot contain white spaces.
  4. Cannot be reserved keywords.

Example Usage:

public class VariablesExample {
    public static void main(String[] args) {
        // Declaration and initialization of variables
        int age = 30;
        double height = 1.75;
        String name = "Mary";

        // Using the variables
        System.out.println("Name: " + name);
        System.out.println("Age: " + age);
        System.out.println("Height: " + height);
    }
}
Enter fullscreen mode Exit fullscreen mode

Variables in Java are used to store temporary or permanent data, depending on your needs. They play a fundamental role in manipulating and storing information during program execution.

Conditional Statements

In Java, conditional statements allow you to make decisions based on specific conditions. The most common structures are if, else if, and else.

if:

The if statement checks if a condition is true and executes a block of code if the condition is true.

int number = 10;

if (number > 0) {
    System.out.println("The number is positive.");
}
Enter fullscreen mode Exit fullscreen mode

if - else:

The if and else are used together to provide an alternative path if the if condition is false.

int number = -5;

if (number > 0) {
    System.out.println("The number is positive.");
} else {
    System.out.println("The number is not positive.");
}
Enter fullscreen mode Exit fullscreen mode

if - else if - else:

You can chain multiple conditions using else if to check different scenarios.

int number = 0;

if (number > 0) {
    System.out.println("The number is positive.");
} else if (number < 0) {
    System.out.println("The number is negative.");
} else {
    System.out.println("The number is zero.");
}
Enter fullscreen mode Exit fullscreen mode

Ternary Operator:

Another way to perform conditional operation is using the ternary operator ? :.

int number = 10;
String result = (number % 2 == 0) ? "Even" : "Odd";
System.out.println(result); // Output: Even
Enter fullscreen mode Exit fullscreen mode

Switch:

The switch statement is used to select one of many code blocks for execution based on the value of a specific expression.

int dayOfWeek = 3;
String dayName;

switch (dayOfWeek) {
    case 1:
        dayName = "Sunday";
        break;
    case 2:
        dayName = "Monday";
        break;
    // And so on for other cases
    default:
        dayName = "Invalid day";
}

System.out.println("Today is " + dayName);
Enter fullscreen mode Exit fullscreen mode

These conditional structures allow you to control the flow of your program based on different conditions, which is essential for decision-making logic.

Arrays

In Java, arrays are data structures that store a fixed set of elements of the same type.

Array Declaration:

// Declaration of an array of integers with 5 elements
int[] numbers; // or int numbers[];
Enter fullscreen mode Exit fullscreen mode

Initializing an Array:

There are several ways to initialize an array in Java:

  1. Direct Initialization:
   int[] numbers = {1, 2, 3, 4, 5}; // Direct initialization with values
Enter fullscreen mode Exit fullscreen mode
  1. Initialization with new operator:
   int[] numbers = new int[5]; // Initialization with an array of size 5
Enter fullscreen mode Exit fullscreen mode

Accessing Array Elements:

Array

elements are accessed using a zero-based index.

int[] numbers = {1, 2, 3, 4, 5};
int firstNumber = numbers[0]; // Accessing the first element (index 0)
int thirdNumber = numbers[2]; // Accessing the third element (index 2)
Enter fullscreen mode Exit fullscreen mode

Iterating Over an Array:

To traverse the elements of an array, you can use a for loop or for-each loop:

  1. for Loop:
   int[] numbers = {1, 2, 3, 4, 5};

   for (int i = 0; i < numbers.length; i++) {
       System.out.println(numbers[i]);
   }
Enter fullscreen mode Exit fullscreen mode
  1. for-each Loop:
   int[] numbers = {1, 2, 3, 4, 5};

   for (int number : numbers) {
       System.out.println(number);
   }
Enter fullscreen mode Exit fullscreen mode

Multidimensional Arrays:

Java also supports multidimensional arrays, like two-dimensional arrays.

// Declaration and initialization of a two-dimensional array (matrix)
int[][] matrix = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

int element = matrix[1][2]; // Accessing the element in the second row and third column (indices 1 and 2)
Enter fullscreen mode Exit fullscreen mode

Arrays in Java have a fixed size after initialization, and the size must be specified at the time of creation or initialization. Manipulating arrays offers many possibilities to store and access data in a structured way in your Java programs.

ArrayList

ArrayList in Java is an implementation of the List interface that provides a dynamic data structure to store elements. Unlike conventional arrays, an ArrayList can grow or shrink automatically to accommodate adding or removing elements.

Importing the ArrayList Class:

import java.util.ArrayList;
Enter fullscreen mode Exit fullscreen mode

Creating an ArrayList:

ArrayList<String> nameList = new ArrayList<>();
Enter fullscreen mode Exit fullscreen mode

Adding Elements:

nameList.add("Alice");
nameList.add("Bob");
nameList.add("Carol");
Enter fullscreen mode Exit fullscreen mode

Accessing Elements:

String firstName = nameList.get(0); // Accessing the first element (index 0)
Enter fullscreen mode Exit fullscreen mode

Iterating Over an ArrayList:

for (String name : nameList) {
    System.out.println(name);
}
Enter fullscreen mode Exit fullscreen mode

Removing Elements:

nameList.remove("Bob"); // Removes the element "Bob"
// or
nameList.remove(1); // Removes the element at index 1
Enter fullscreen mode Exit fullscreen mode

Checking the Size of the ArrayList:

int size = nameList.size(); // Returns the size of the list
Enter fullscreen mode Exit fullscreen mode

Arrays vs. ArrayList:

Arrays have a fixed size after creation, while ArrayList can grow or shrink dynamically. The choice between them depends on your program's needs. If you need a flexible data structure that can be easily modified, ArrayList is more convenient. If you need a structure with a fixed size, a conventional array might be more appropriate.

Typing in ArrayList:

The ArrayList is generic, which means you can specify the type of elements it will contain within the angle brackets <type> (e.g., ArrayList<String> for a list of strings). This helps prevent type errors during compilation and provides more type safety during execution.

Loops

In Java, there are several ways to create loops to execute a block of code repeatedly.

1. for Loop:

The for loop is used when you know exactly how many times you want to iterate.

for (int i = 0; i < 5; i++) {
    System.out.println(i);
}
Enter fullscreen mode Exit fullscreen mode

2. while Loop:

The while loop is used when you want to execute a block of code while a specific condition is true.

int counter = 0;
while (counter < 5) {
    System.out.println(counter);
    counter++;
}
Enter fullscreen mode Exit fullscreen mode

3. do-while Loop:

The do-while loop is similar to while but ensures that the code block executes at least once, even if the condition is false.

int counter = 0;
do {
    System.out.println(counter);
    counter++;
} while (counter < 5);
Enter fullscreen mode Exit fullscreen mode

4. for-each Loop (for iterating over arrays and collections):

The for-each loop is used to iterate over collections (such as arrays, lists) in a simple and efficient manner.

int[] numbers = {1, 2, 3, 4, 5};
for (int number : numbers) {
    System.out.println(number);
}
Enter fullscreen mode Exit fullscreen mode

Flow Control:

Within loops, you can use break to exit the loop prematurely and continue to skip the current iteration and move on to the next.

Nested Loop Example:

It's possible to nest loops, i.e., place one loop inside another.

for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
        System.out.println("i: " + i + ", j: " + j);
    }
}
Enter fullscreen mode Exit fullscreen mode

Choosing the Loop Type:

  • Use for when you know the number of iterations.
  • Use while when the termination condition is not related to the number of iterations.
  • Use do-while when you want to ensure the code block executes at least once.
  • Use for-each to iterate over collections of elements.

Casting

Casting in Java is the explicit conversion of one data type to another. It is used when you want to convert one data type into another compatible type. There are two types of casting in Java: implicit casting and explicit casting.

Implicit Casting:

Occurs when there is no data loss when converting from a smaller type to a larger type. This is done automatically by Java.

Example of implicit casting:

int integer = 10;
double decimal = integer; // Implicit conversion from int to double
Enter fullscreen mode Exit fullscreen mode

Explicit Casting:

Occurs when there is a potential data loss when converting from a larger type to a smaller type. This requires a special syntax to indicate that you are aware of the potential loss of precision.

Example of explicit casting:

double decimal = 10.5;
int integer = (int) decimal; // Explicit conversion from double to int
Enter fullscreen mode Exit fullscreen mode

Rules for Explicit Casting:

  • To perform explicit casting, you place the type in parentheses before the variable you want to convert.
  • Explicit casting can lead to data loss if the value of the larger type cannot be represented by the smaller type.
  • When converting from a larger type to a smaller type, you may lose precision information or even significant values.
int number = 130;
byte value = (byte) number; // The value will be -126 due to overflow of a byte (-128 to 127)
Enter fullscreen mode Exit fullscreen mode

Considerations:

  • Casting in Java can be useful when working with different data types, but it's essential to be aware of potential precision losses or value overflow when performing conversions.
  • Make sure to use casting carefully to avoid type compatibility issues and loss of significant data during conversions.

Classes

In Java, classes are fundamental building blocks used to create objects. They serve as templates or blueprints to create instances (objects) that have specific characteristics and behaviors.

Example of a Class:

Let's create a Person class that represents individuals with attributes like name and age, and methods to access and modify these attributes.

// Definition of the Person class
public class Person {
    // Attributes (instance variables)
    private String name;
    private int age;

    // Constructor (special method to create objects)
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Methods to access and modify attributes (getters and setters)
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    // Other methods of the Person class
    public void printDetails() {
        System.out.println("Name: " + name + ", Age: " + age);
    }
}
Enter fullscreen mode Exit fullscreen mode

Using the Class:

Now that we have the Person class, we can create objects (instances) of this class and use their methods and attributes.

public class Main {
    public static void main(String[] args) {
        // Creating objects (instances) of the Person class
        Person person1 = new Person("Alice", 30);
        Person person2 = new Person("Bob", 25);

        // Using methods of the Person class
        person1.printDetails(); // Output: Name: Alice, Age: 30
        person2.printDetails(); // Output: Name: Bob, Age: 25

        // Modifying attributes using setters
        person1.setAge(35);
        person2.setName("Robert");

        person1.printDetails(); // Output: Name: Alice, Age: 35
        person2.printDetails(); // Output: Name: Robert, Age: 25
    }
}
Enter fullscreen mode Exit fullscreen mode

Key Concepts:

  • Attributes: Represent the characteristics of objects.
  • Methods: Define the behavior of objects.
  • Constructor: A special method to initialize objects.
  • Encapsulation: Use of access modifiers (private, public, protected) to control access to class attributes.
  • Instance: Creating objects from a class using the new operator.

Classes in Java allow you to create complex and modular structures, making it easier to create and organize programs. They are the foundation of object-oriented programming in Java and are essential for building robust and reusable applications.

Objects

In Java, an object is an instance of a class. A class is a model or blueprint for creating objects that have specific attributes and behaviors. Objects are created from classes using the new operator.

Creating Objects:

To create an object, you need to use the new keyword followed by the class name and parentheses to call the class constructor.

Example of creating objects:

// Person class
public class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    public void printName() {
        System.out.println("Name: " + name);
    }
}

// Creating objects of the Person class
Person person1 = new Person("Alice");
Person person2 = new Person("Bob");
Enter fullscreen mode Exit fullscreen mode

Attributes and Methods:

Objects have attributes (instance variables) representing their characteristics and methods defining their behavior.

// Attribute 'name' in the Person class
private String name;

// Method 'printName' in the Person class
public void printName() {
    System.out.println("Name: " + name);
}
Enter fullscreen mode Exit fullscreen mode

Accessing Attributes and Methods:

You can access the attributes and methods of an object using the dot operator (.).

person1.printName(); // Output: Name: Alice
person2.printName(); // Output: Name: Bob
Enter fullscreen mode Exit fullscreen mode

Unique Instances:

Each object is a unique instance of its class. This means objects created from the same class can have different values for their attributes.

person1.setName("Carol");
person1.printName(); // Output: Name: Carol
person2.printName(); // Output: Name: Bob
Enter fullscreen mode Exit fullscreen mode

Object References:

Variables holding objects store references to those objects in memory, not the objects themselves.

Person person3 = person1;
person3.setName("Daniel");
person1.printName(); // Output: Name: Daniel (changed via reference person3)
Enter fullscreen mode Exit fullscreen mode

Encapsulation:

It's a common practice in Java to encapsulate object attributes using access modifiers (private, public, protected) and provide public methods (getters and setters) to access and modify them.

Objects in Java are fundamental to object-oriented programming, allowing the creation of complex, modular, and reusable structures. Each object represents a distinct entity with its own state and behavior.

Constructors

In Java, a constructor is a special method used to initialize objects when they are created from a class. It has the same name as the class and has no return type.

Purpose of Constructors:

  • Object Initialization: A constructor is automatically called when an object is created using the new keyword. It initializes the object's state by setting values for its attributes or performing other necessary initializations.

Types of Constructors:

  1. Default Constructor: If a class doesn't define any constructor, Java provides a default constructor without parameters. This constructor initializes default values for the class attributes.
public class MyClass {
    // Default constructor
    public MyClass() {
        // Default initialization, if needed
    }
}
Enter fullscreen mode Exit fullscreen mode
  1. Custom Constructors: You can define your own constructors with different parameters to initialize objects in specific ways.
public class Person {
    private String name;
    private int age;

    // Custom constructor with parameters
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
Enter fullscreen mode Exit fullscreen mode

Using

Constructors:

  • Automatic Invocation: The constructor is automatically called when an object is created using new ClassName().
Person person = new Person("Alice", 30); // Calls the custom constructor
Enter fullscreen mode Exit fullscreen mode

Constructor Overloading:

You can have multiple constructors in the same class with different parameter lists. This is called constructor overloading.

public class Person {
    private String name;
    private int age;

    // Constructor with one parameter
    public Person(String name) {
        this.name = name;
    }

    // Constructor with two parameters
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
Enter fullscreen mode Exit fullscreen mode

Using this in Constructors:

  • this is used to reference the attributes of the class itself when there's ambiguity with the constructor parameters.

Purpose of Constructors:

  • Initializing Attributes: Setting initial values for the class attributes.
  • Ensuring Initial Values: Ensuring the object starts in a valid state.
  • Customizing Object Creation: Providing different ways to create objects with specific values.

Constructors in Java are useful for initializing objects of a class according to their specific needs, allowing proper initialization of their attributes.

Modifiers

In Java, modifiers are keywords that provide control over access and other characteristics in classes, methods, and variables. They help define visibility, accessibility, and behavior of different elements within the code.

Access Modifiers:

  1. public:

    • Unrestricted access. Can be accessed from anywhere.
  2. private:

    • Restricted access to the class itself. Cannot be accessed from outside the class.
  3. protected:

    • Access allowed within the same package and by subclasses, even if they are in different packages.
  4. (default / no modifier):

    • Access allowed only within the same package. Cannot be accessed by classes from different packages.

Other Behavior Modifiers:

  1. static:

    • Indicates that a method or variable belongs to the class, not individual instances.
  2. final:

    • Indicates that a method, variable, or class cannot be altered or extended.
  3. abstract:

    • Applied to classes or methods, indicates that the class cannot be instantiated (only its subclasses) or that a method needs to be overridden by subclasses.
  4. synchronized:

    • Used to control concurrent access to methods or code blocks, ensuring that only one thread can access at a time.
  5. volatile:

    • Used for variables that can be accessed by multiple threads, indicating that the variable's value can be changed by external threads.
  6. transient:

    • Used to indicate that a field of a class should not be serialized during the serialization process.

Example of Usage:

public class Example {
    private int privateVariable;
    public static final double PI = 3.14;

    public void publicMethod() {
        // Method code
    }

    protected void protectedMethod() {
        // Method code
    }

    static synchronized void staticSynchronizedMethod() {
        // Method code
    }
}
Enter fullscreen mode Exit fullscreen mode

Considerations:

  • Modifiers in Java offer control over encapsulation, inheritance, access, and other aspects of code, promoting security and modularity.
  • Choosing the correct modifier depends on the design and security needs of your code. For instance, ensuring encapsulation using private and allowing inheritance using protected.
  • Proper use of modifiers helps create safer classes and methods, making code maintenance and team development easier.

Inheritance

In Java, inheritance is one of the fundamental principles of object-oriented programming, allowing a class to inherit attributes and methods from another class. It facilitates code reuse and the creation of hierarchies between classes.

Inheritance Syntax:

// Parent Class (or Superclass)
public class Animal {
    public void makeSound() {
        System.out.println("Generic animal sound.");
    }
}

// Child Class (or Subclass) that overrides the makeSound method
public class Dog extends Animal {
    public void bark() {
        System.out.println("Woof woof!");
    }
}
Enter fullscreen mode Exit fullscreen mode
  • Animal is the parent class (superclass) containing the makeSound method.
  • Dog is the child class (subclass) that inherits from Animal and adds the bark method.

extends Keyword:

  • extends is used to create an inheritance relationship between classes.
public class Dog extends Animal {
    // ...
}
Enter fullscreen mode Exit fullscreen mode

Inheriting Attributes and Methods:

  • The child class inherits all non-private attributes and methods from the parent class.
  • The child class can add new methods and attributes, as well as override existing methods if needed.

Example of Usage:

public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog();
        myDog.makeSound(); // Output: Generic animal sound.
        myDog.bark();      // Output: Woof woof!
    }
}
Enter fullscreen mode Exit fullscreen mode

Method Overriding:

  • A subclass can override a method from the superclass to provide its own implementation.
public class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Woof woof! (overridden)");
    }
}
Enter fullscreen mode Exit fullscreen mode

Considerations about Inheritance:

  • Inheritance is an "is-a" relationship (e.g., a dog is an animal).
  • It aids in code reuse, making it easier to create class hierarchies and avoiding repetition.
  • A class can inherit from only one direct superclass (Java does not support multiple inheritance of classes).
  • Ensuring that the inheritance relationship is logical and that the subclass is truly a specialized version of the superclass is essential for a solid class design.

Inheritance in Java is a powerful concept allowing the creation of class hierarchies, facilitating reuse and extension of functionalities. However, it should be used carefully to maintain clear and cohesive code design.

Polymorphism

Polymorphism is a fundamental concept in object-oriented programming that allows objects of different classes to be treated as objects of a common class. In Java, polymorphism is implemented through two mechanisms: method overloading (multiple methods with the same name in a class but with different parameters) and method overriding (methods in related classes that have the same signature).

Method Overriding Polymorphism:

In overriding, a child class provides a specific implementation for a method that is already defined in its parent class. This allows an object of the child class to be treated as an object of the parent class, but with the execution of the child class's specific method.

Example:

// Parent Class (Superclass)
class Animal {
    public void makeSound() {
        System.out.println("Generic animal sound.");
    }
}

// Child Class (Subclass) that overrides the makeSound method
class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Woof woof!");
    }
}
Enter fullscreen mode Exit fullscreen mode

Now you can do something like this:

Animal myDog = new Dog();
myDog.makeSound(); // Output: Woof woof!
Enter fullscreen mode Exit fullscreen mode

Polymorphism with Interfaces:

Interfaces in Java also support polymorphism. If a class implements an interface, you can treat objects of that class as objects of the interface.

// Interface
interface Noisy {
    void makeSound();
}

// Interface Implementation
class Dog implements Noisy {
    @Override
    public void makeSound() {
        System.out.println("Woof woof!");
    }
}
Enter fullscreen mode Exit fullscreen mode

Method Overloading Polymorphism:

In overloading, multiple methods can have the same name but with different parameter lists. This allows you to call the same method with different argument types.

Example:

class Calculator {
    public int sum(int a, int b) {
        return a + b;
    }

    public double sum(double a, double b) {
        return a + b;
    }
}
Enter fullscreen mode Exit fullscreen mode

The

call can be made polymorphically:

Calculator calc = new Calculator();
int resultInt = calc.sum(5, 10);
double resultDouble = calc.sum(3.5, 2.7);
Enter fullscreen mode Exit fullscreen mode

Advantages of Polymorphism:

  • Flexibility: Allows the same code to handle objects of different classes uniformly.
  • Maintainability: Facilitates adding new classes without changing existing code.
  • Readability: Makes the code more readable and expressive.

Polymorphism is a powerful feature of object-oriented programming that promotes flexibility and code reuse. It is commonly used in Java and is employed in conjunction with concepts like inheritance and interfaces to create more modular and extendable systems.

Congratulations on finishing the read! It's quite an achievement to have dedicated time and effort to learn about the basic concepts of Java.

Remember to stay updated. Technology is ever-evolving, and new concepts, tools, and techniques are always emerging. Keep up with blogs, forums, conferences, and online courses to stay informed about trends and advancements in the field.

In summary, keep learning, practicing, and challenging yourself. Programming is an exciting journey filled with possibilities. Good luck with your future explorations in the tech field!

By Francisco Inoque 🫶

Top comments (0)