Object Oriented Programming in Java

Object Oriented Programming in Java

Part 4

Access Control in Java:

  • Controlling Member Accessibility:

    • Java provides access modifiers (public, private, protected, and default) to control how members (fields and methods) of a class can be accessed.

    • Restricting access to data members promotes encapsulation and data protection.

  • Access Modifiers:

    • Public: Members declared as public are accessible from anywhere in the program.

    • Private: Members declared as private are only accessible within the class they are declared in.

    • Protected: Members declared as protected are accessible from within the same package and by subclasses (even from different packages).

    • Default (No Modifier): Members with no explicit access modifier are accessible within the same package but not outside of it.

Access Control Table:

Access ModifierClassPackageSubclass (Same Package)Subclass (Diff. Package)World (Diff. Package & Not Subclass)
public+++++
protected++++-
No Modifier (Default)+++--
private+----

(+ indicates accessible, - indicates not accessible)

Code Example:

// packageOne/Base.java
package packageOne;

public class Base {
  protected void display() {
    System.out.println("in Base");
  }
}

// packageTwo/Derived.java
package packageTwo;

public class Derived extends packageOne.Base {
  public void show() {
    new Base().display(); // Not allowed (Base instance in different package)
    new Derived().display(); // Allowed (Derived instance)
    display(); // Allowed (calling from subclass)
  }
}

Explanation:

  • The display method in Base is declared as protected.

  • Derived class (in a different package) can access display through inheritance and its own objects.

  • Creating a new Base instance in Derived.show() cannot call display because Base is in a different package.

Key Points about protected:

  • Subclasses can access protected members even from different packages.

  • Only the subclass object itself (or its subclass object) can access protected members through a reference variable.

  • A class cannot access protected members of another class in the same package unless they are related through inheritance.

More about Protected class:

1. Subclasses can access protected members even from different packages:

// packageOne/Base.java
package packageOne;

public class Base {
  protected void display() {
    System.out.println("in Base (protected)");
  }
}

// packageTwo/Derived.java (different package)
package packageTwo;

public class Derived extends packageOne.Base {
  public void show() {
    display(); // Allowed because Derived inherits from Base (protected access)
  }
}

public class Main {
  public static void main(String[] args) {
    Derived derived = new Derived();
    derived.show(); // This will print "in Base (protected)"
  }
}

In this example, Derived (in packageTwo) inherits from Base (in packageOne). Even though they are in different packages, Derived can access the display method because it's declared as protected.

2. Only the subclass object itself (or its subclass object) can access protected members through a reference variable:

// packageOne/Base.java
package packageOne;

public class Base {
  protected void display() {
    System.out.println("in Base (protected)");
  }
}

// packageOne/NotDerived.java (same package)
package packageOne;

public class NotDerived {
  public void accessBase() {
    // Cannot access display() directly from NotDerived
    // new Base().display(); // This would cause a compile-time error
  }
}

Here, NotDerived (in the same package as Base) cannot directly call display from a Base object because NotDerived is not a subclass of Base. Protected access applies to the subclass itself and its subclasses, not to other classes in the same package.

3. A class cannot access protected members of another class in the same package unless they are related through inheritance:

// packageOne/Util.java (same package as Base)
package packageOne;

public class Util {
  public void doSomething(Base base) {
    // Cannot access display() directly from Util
    // base.display(); // This would cause a compile-time error
  }
}

Similar to point 2, Util (in the same package as Base) cannot access display because there's no inheritance relationship. Protected access is meant for subclasses to access inherited members.

Summary:

  • protected allows access from subclasses (even in different packages) and from the same package if the accessing class inherits from the protected member's class.

  • Access through reference variables requires the object itself or its subclass to be used.

More about Packages:

  • Organization: Packages are a fundamental way to organize classes and interfaces in Java. They act like folders in a file system, promoting code maintainability and reusability.

  • Types: There are two main types of packages:

    1. Built-in Packages (Java API): These are pre-written libraries of classes and interfaces provided by Java. They cover various functionalities like input/output, networking, data structures, and more.

    2. User-Defined Packages: You can create your own packages to organize your custom classes and interfaces. This helps with modularity and avoids naming conflicts with built-in classes.

Common Built-in Packages and their Use Cases:

  • java.lang (Core Functionality)
  1. Object (Base class for all Java objects)

  2. String (Immutable character sequence)

  3. Math (Mathematical operations)

  4. System (System-related functionalities)

  5. Primitive data types (int, double, char, etc.), etc

  1. File (Represents files and directories)

  2. FileReader/FileWriter (Read/write text files)

  3. BufferedReader/BufferedWriter (Buffered I/O for efficiency)

  4. Scanner (Reads formatted input from console/files)

  5. PrintStream (Prints formatted output), etc

  • java.util (Utility Classes)
  1. ArrayList (Dynamically resizing array list)

  2. LinkedList (Doubly-linked list for insertions/deletions)

  3. HashMap (Key-value pairs for fast lookups)

  4. HashSet (Set of unique elements)

  5. Collections Framework (Interfaces and classes for managing collections)

  6. Date/Calendar (Classes for working with dates and times), etc

  • java.awt (Graphical User Interfaces - Deprecated for modern applications)
  1. JFrame (Main window for GUI applications)

  2. JPanel (Container for other GUI components)

  3. JButton (Button component)

  4. JTextField (Text input field), etc

  1. Socket (Network communication endpoint)

  2. URL (Represents web addresses)

  3. URLConnection (Opens connections to URLs)

  4. ServerSocket (Listens for incoming connections), etc

  • java.sql (Database Access - Separate download)
  1. Connection (Represents a connection to a database)

  2. Statement/PreparedStatement (Executes SQL statements)

  3. ResultSet (Holds results of a database query), etc

Object Class: The Root of All Classes

  • Top of the Inheritance Tree: In Java, every class implicitly inherits from the Object class, even if you don't explicitly mention a superclass. This means every object in Java has access to the methods defined in the Object class.

  • Fundamental Methods: The Object class provides several fundamental methods that are common to all objects:

    • toString(): Returns a string representation of the object, often used for debugging or displaying information.

    • equals(Object obj): Compares two objects for logical equality, typically based on their state (field values).

    • hashCode(): Returns an integer hash code, used in data structures like HashMap for efficient storage and retrieval.

    • getClass(): Returns the Class object representing the runtime class of the object, providing information about its type.

    • clone(): Creates a shallow copy of the object, with the same field values but a different memory address.

    • finalize(): A method called by the garbage collector before an object is garbage collected, usually for cleaning up resources.

Code Example:

Java

public class ObjectDemo {

    int num;
    float gpa;

    public ObjectDemo(int num, float gpa) {
        this.num = num;
        this.gpa = gpa;
    }

    // already covered these 2
    @Override
    public String toString() {
        return super.toString();
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
    }

    @Override
    public int hashCode() {
        return super.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        return this.num == ((ObjectDemo)obj).num;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public static void main(String[] args) {
        ObjectDemo obj1 = new ObjectDemo(12, 56.8f);
        ObjectDemo obj2 = new ObjectDemo(12, 78.9f);

        if (obj1 == obj2) {
            System.out.println("obj1 is equal to obj2");
        }

        if (obj1.equals(obj2)) {
            System.out.println("obj1 is equal to obj2");
        }

        System.out.println(obj1.getClass().getName());

//        System.out.println(obj.hashCode());
//        System.out.println(obj2.hashCode());
    }

}

Key Points:

  • super Keyword: The super keyword can be used to call methods or constructors of the superclass, even the implicit Object class.

  • Inheritance Without Explicit Superclass: Even though ObjectDemo doesn't explicitly extend any class, it implicitly inherits from Object, allowing access to its methods.

  • Custom Implementations: Many classes override these methods to provide behavior specific to their type. For example, the toString() method can be customized to return a more meaningful string representation of the object's state.

Understanding the Object class and its methods is crucial for effective object-oriented programming in Java. It provides a foundation for class hierarchies and basic object behavior.