Classes and Objects
In Java, a class serves as a blueprint for creating objects. Objects are instances of classes that encapsulate data and behavior.
Basic Class Definition
package learning;
public class Book {
public int publicationYear;
public String title;
public void display() {
System.out.println(publicationYear + " - " + title);
}
public void consume(int quantity) {
System.out.println(title + " consumed " + quantity + " times");
}
}
Using the class:
package learning;
public class Main {
public static void main(String[] args) {
Book novel = new Book();
novel.publicationYear = 2023;
novel.title = "The Great Adventure";
novel.display();
novel.consume(5);
}
}
Access Control with Private Modifier
The private keyword restricts direct access to class members from outside the class. Access is provided through getter and setter methods instead.
The this Keyword
The this reference distinguishes between parameters and instance variables when they share the same name. It also helps manage multiple object instances correctly.
Standard Class Template
A well-designed class typically includes private fields, constructors, and accessor methods:
package learning;
public class Person {
private int id;
private String fullName;
// Default constructor
public Person() {}
// Parameterized constructor
public Person(int id, String fullName) {
this.id = id;
this.fullName = fullName;
}
// Getter and setter methods
public void setId(int newId) {
this.id = newId;
}
public int getId() {
return this.id;
}
public void setFullName(String name) {
this.fullName = name;
}
public String getFullName() {
return this.fullName;
}
}
Using the standard class:
package learning;
public class Main {
public static void main(String[] args) {
Person first = new Person();
first.setFullName("Alice Johnson");
first.setId(1001);
System.out.println(first.getFullName());
System.out.println(first.getId());
Person second = new Person(1002, "Bob Smith");
System.out.println(second.getFullName());
System.out.println(second.getId());
}
}
String Handling
When comparing primitive types, Java evaluates the actual values. For reference types, comparison checks memory addresses by default.
Direct string comparison using == compares references. Use the equals() method for content comparison.
String vs StringBuilder
String object are immutable - their content cannot be changed after creation.
StringBuilder provides mutable string operations. It supports append() for adding content and reverse() for reversing strings without creating additional objects.
Converting between String and StringBuilder:
public class StringOperations {
public static void main(String[] args) {
String original = "programming";
StringBuilder builder = new StringBuilder(original);
builder.append language");
builder.reverse();
String result = builder.toString();
System.out.println(result);
}
}
Collections - ArrayList
ArrayList provides a dynamic array implemantation that can grow and shrink as needed.
import java.util.ArrayList;
public class CollectionDemo {
public static void main(String[] args) {
// Type parameter specifies element type
ArrayList<String> names = new ArrayList<String>();
// Add elements
names.add("Python");
names.add("JavaScript");
names.add("Rust");
System.out.println(names);
// Insert at specific index
names.add(1, "Go");
System.out.println(names);
// Remove by value (returns boolean)
System.out.println(names.remove("Go"));
// Remove by index (returns removed element)
System.out.println(names.remove(1));
// Get element at index
System.out.println(names.get(1));
// Get collection size
System.out.println(names.size());
// Update element at index (returns old value)
System.out.println(names.set(1, "TypeScript"));
System.out.println(names);
}
}
Inheritance
Inheritance allows a subclass to acquire properties and methods from a parent class, promoting code reuse.
The super keyword accesses parent class members, while this refers to current class members.
When a subclass object is created, the parent's no-argument constructor executes automatically.
Member Access Priority
Java searches for members in this order: subclass local variables → subclass fields → parent class members → grandparent members.
Key inheritance rules:
- Private members cannot be inherited
- Java does not support multiple inheritance (but supports multi-level inheritance)
- Subclass access modifier must be more permissive than parent: public > default > private
package inheritance;
public class Vehicle {
private int wheels;
private String model;
public Vehicle() {
System.out.println("Vehicle constructor called");
}
public Vehicle(int wheels, String model) {
this.wheels = wheels;
this.model = model;
}
public void setWheels(int w) {
this.wheels = w;
}
public int getWheels() {
return this.wheels;
}
public void setModel(String m) {
this.model = m;
}
public String getModel() {
return this.model;
}
public void drive() {
System.out.println("Vehicle is moving");
}
}
package inheritance;
public class Car extends Vehicle {
public Car() {
System.out.println("Car extends Vehicle");
}
public void displayInfo() {
System.out.println(getWheels() + " " + getModel());
}
}
package inheritance;
public class Main {
public static void main(String[] args) {
Car myCar = new Car();
myCar.setWheels(4);
myCar.setModel("Sedan");
myCar.displayInfo();
}
}
Animal Inheritance Example
package animals;
public class Animal {
private int age;
private String species;
public Animal() {
System.out.println("Animal created");
}
public Animal(int age, String species) {
this.age = age;
this.species = species;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSpecies() {
return species;
}
public void setSpecies(String species) {
this.species = species;
}
}
package animals;
public class Cat extends Animal {
public void hunt() {
System.out.println("Cat is hunting");
}
}
package animals;
public class Dog extends Animal {
public void bark() {
System.out.println("Dog is barking");
}
}
package animals;
public class Zoo {
public static void main(String[] args) {
Cat whiskers = new Cat();
whiskers.setSpecies("Persian");
System.out.println(whiskers.getSpecies());
whiskers.setAge(3);
System.out.println(whiskers.getAge());
whiskers.hunt();
Dog buddy = new Dog();
buddy.setSpecies("Golden Retriever");
buddy.setAge(5);
System.out.println(buddy.getSpecies());
System.out.println(buddy.getAge());
buddy.bark();
}
}
Package and Import
Packages organize code into folders. Use import to include classes from other packages. Multiple package levels use dot notation.
Access Modifiers Summary
| Location | public | protected | default | private |
|---|---|---|---|---|
| Same package - same class | Yes | Yes | Yes | Yes |
| Same package - subclass | Yes | Yes | Yes | No |
| Same package - unrelated | Yes | Yes | Yes | No |
| Different package - subclass | Yes | Yes | No | No |
| Different package - unrelated | Yes | No | No | No |
The final Keyword
final modifier restrictions:
- Variable: value cannot be changed (becomes constant)
- Method: cannot be overridden
- Class: cannot be inherited
When applied to local variables:
- Primitive types: value is constant
- Reference types: reference address is constant (object contents can still change)
The static Keyword
static members belong to the class rather than individual objects. They are shared across all instances and accessible via class name or object reference.
Static methods can only access static members directly.
Polymorphism
Polymorphism allows a parent class reference to point to a child class object. The prerequisite is inheritance relationship.
Polymorphism Rules
For variables: Both compile-time and runtime behavior reference the left side of the assignment.
For methods: Compile-time checks the left side (reference type), but execution uses the right side (actual object type). This is because methods can be overridden, but variables cannot.
Type Casting
Parent reference to child object is upcasting (automatic).
Child reference to parent object is downcasting (requires explicit cast).
Benefits and Limitations
Polymorphism enables program extensibility by allowing the parent type to represent various child types.
Limitation: Specific child class features become inaccessible through the parent reference.
Abstract Classes
An abstract method has no implementation body - only declaration. A class containing abstract methods must be declared as abstract.
Subclasses of an abstract class must either:
- Be declared abstract themselves, or
- Implement all abstract methods from the parent
Abstract classes are instantiated through polymorphism using concrete subclasses.
package shapes;
public abstract class Shape {
private int sides;
private String color;
public abstract void draw();
public Shape() {}
public Shape(int sides, String color) {
this.sides = sides;
this.color = color;
}
public int getSides() {
return sides;
}
public void setSides(int sides) {
this.sides = sides;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
package shapes;
public class Circle extends Shape {
public int radius = 10;
@Override
public void draw() {
System.out.println("Drawing a circle");
}
public void calculateArea() {
System.out.println("Area: " + Math.PI * radius * radius);
}
}
package shapes;
public class Rectangle extends Shape {
@Override
public void draw() {
System.out.println("Drawing a rectangle");
}
}
package shapes;
public class ShapeDemo {
public static void main(String[] args) {
Shape circle = new Circle();
circle.setSides(0);
circle.setColor("Red");
System.out.println(circle.getSides());
System.out.println(circle.getColor());
circle.draw();
Shape rectangle = new Rectangle();
rectangle.setSides(4);
rectangle.setColor("Blue");
rectangle.draw();
System.out.println(rectangle.getSides());
System.out.println(rectangle.getColor());
}
}
Polymorphism with Abstract Classes
package shapes;
public class ShapeRenderer {
public void render(Shape s) {
s.draw();
}
}
package shapes;
public class Main {
public static void main(String[] args) {
Circle c = new Circle();
System.out.println(c.radius);
Circle converted = (Circle) c;
converted.calculateArea();
ShapeRenderer renderer = new ShapeRenderer();
renderer.render(c);
}
}