Cross Training Home Concept #7 — Setters & Encapsulation

⚡ Cross Training — Concept #7

You’ve Been Calling Setters
This Whole Time

Every time you wrote img.src = ‘...’ in JavaScript, you were calling a setter. The browser built the object, locked the vault, and wrote the gate for you. Java just makes you write it yourself.

Concept #7

The Object You Already Know

Here’s a secret most web students discover too late: you have been working with objects since the very first HTML tag you ever wrote.

When you write <img id="demoIcon" src="bolt.svg" alt="bolt icon">, the browser doesn’t just park that tag somewhere and forget about it. It creates a full object — specifically an instance of a built-in class called HTMLImageElement. Every HTML attribute (src, alt, width, height) becomes a property of that object. If you were to write this as a Java class, those attributes would be private fields.

When you later write img.src = 'flash.svg' in JavaScript, it looks like simple variable assignment. It is not. It calls a setter that the browser defined for you — one that validates the URL, cancels the previous network request, and kicks off a new image load. The assignment syntax just hides all of that.

The table to the right maps every <img> attribute you already know to its Java equivalent. This is the same object — just seen through two different lenses.

New to JavaScript? No problem — this page is written for Java students first. You do not need to know JavaScript to follow the concepts here. Seeing it in comparison will make JavaScript feel far less foreign when you do encounter it.

The <img> Element as a Java Class

HTML Attribute Java Field Java Setter
src private String src setSrc(String s)
alt private String alt setAlt(String a)
width private int width setWidth(int w)
height private int height setHeight(int h)
id private String id setId(String i)
🔒

Private by Default

Java declares fields private explicitly. The browser’s HTMLImageElement does the same thing implicitly — you cannot reach into its internal storage directly. You can only change src through the interface it exposes.

Assignment Syntax Hides the Gate

In JavaScript, img.src = 'flash.svg' looks like direct field access — it is not. It calls a setter the browser defined. Java is more honest: you write img.setSrc("flash.svg") and there is no question that a method call is happening.

Two Ways to Set a Property

Same object. Same goal. Two languages with very different opinions about who controls the gate.

JavaScript
“I trust you — the setter looks like assignment”

The DOM exposes object properties through assignment syntax. Under the hood the browser calls a setter — but it looks like a plain =. When you write your own class, the set keyword makes that explicit.

// In HTML:  <img id="demoIcon" src="bolt.svg">
// The img IS an object (HTMLImageElement).
const img = document.getElementById('demoIcon');

// Looks like assignment — it's a SETTER CALL:
// (null guard: demoIcon only exists on the TNT Home page)
if (img) {
  img.src = 'images/flash.svg';  // ← setter!
}
// The browser cancels the old request and starts a new one.

// Write your own class with an explicit setter:
class TNTImage {
  constructor(src, alt) {
    this._src = src;
    this._alt = alt;
  }
  set src(value) {           // 'set' keyword = setter
    this._src = value;
  }
  get src() { return this._src; }
}

const myImg = new TNTImage('bolt.svg', 'bolt');
myImg.src = 'flash.svg';   // calls setter — still looks like =

// ⚠ JS can't fully enforce private. A determined
// developer could still write:  myImg._src = 'x';
Java
“You must write the gate — private enforces it”

Java makes encapsulation explicit. Fields declared private are physically locked — the compiler refuses to compile any code that accesses them from outside the class. The setter is the only door, and it is not optional.

public class TNTImage {
  private String src;  // padlocked — no outside access
  private String alt;

  public TNTImage(String src, String alt) {
    this.src = src;
    this.alt = alt;
  }

  // You write the gate. Java enforces it.
  public void setSrc(String src) {
    if (src == null || src.isEmpty())
      throw new IllegalArgumentException("src required");
    this.src = src;     // side effects go here
  }
  public String getSrc() { return src; }
}

/* Usage:
TNTImage myImg = new TNTImage("bolt.svg", "bolt");
myImg.setSrc("flash.svg");   // explicit method call required

// myImg.src = "flash.svg";  ← COMPILE ERROR: src is private
*/

Run it in JDoodle — File 1: TNTImage.java (copy above)  •  File 2: this driver

Java
TNTImageDriver.java — exercises the setter, validation, and side effects
// TNTImageDriver.java
// JDoodle multi-file: paste TNTImage.java as File 1, this file as File 2

public class TNTImageDriver {

    public static void main(String[] args) {
        System.out.println("=== TNTImage Setter Demo ===\n");

        // Constructor sets the initial src — getter reads it back
        TNTImage bolt = new TNTImage("bolt.svg", "lightning bolt");
        System.out.println("getSrc():     " + bolt.getSrc());

        // setSrc() is the ONLY legal way to change src from outside
        bolt.setSrc("flash.svg");
        System.out.println("After setSrc: " + bolt.getSrc());

        // Setter validates — empty string is rejected at the gate
        System.out.println("\n--- Validation in the setter ---");
        try {
            bolt.setSrc("");
        } catch (IllegalArgumentException e) {
            System.out.println("Caught: " + e.getMessage());
        }
        System.out.println("src unchanged: " + bolt.getSrc());

        // Circle demo — setRadius() triggers side-effect recalculation
        System.out.println("\n=== Circle: Side-Effect Setter ===");
        Circle c = new Circle();
        c.setRadius(5.0);
        System.out.printf("r=5.0   area=%7.3f   circ=%7.3f%n",
            c.getArea(), c.getCircumference());
        c.setRadius(10.0);
        System.out.printf("r=10.0  area=%7.3f   circ=%7.3f%n",
            c.getArea(), c.getCircumference());

        System.out.println("\n--- Thanks for using our program! ---");
    }//end main

}//end class TNTImageDriver

// Circle: non-public class can live in the same .java file as the driver
class Circle {
    private double radius;
    private double area;
    private double circumference;

    public void setRadius(double r) {
        this.radius        = r;
        this.area          = Math.PI * r * r;   // side effect
        this.circumference = 2 * Math.PI * r;   // side effect
    }
    public double getRadius()        { return radius; }
    public double getArea()          { return area; }
    public double getCircumference() { return circumference; }
}//end class Circle
The key difference: JavaScript’s _src naming convention is a gentleman’s agreement — a determined developer can still write myImg._src = 'x' and bypass the setter entirely. Java’s private keyword is enforced by the compiler at build time. Attempt direct access and Java refuses to compile your program. The gate is not optional.

The Side Effect Problem

If a setter just stores a value, why not skip it and use a public field? The answer is side effects — the extra work that needs to happen automatically whenever a property changes.

Think about a Circle class with three properties: radius, area, and circumference. Change radius and the other two must update at the same moment. If you allow direct field access, a developer can change radius and forget to recalculate — now your object holds three numbers that contradict each other. The object is broken and it doesn’t know it.

The setter prevents that. It is the one and only place radius can change — so it is the right place to trigger the recalculation. The object stays internally consistent no matter what.

The same logic applies to img.src. When you change the source of an image, the browser doesn’t just store a new string. It cancels the in-flight network request for the old image and fires a new one for the new image. That is a side effect. If the browser let you write directly to an internal string field, none of that cleanup would happen — you would get the wrong image, or no image at all.

Circle class — with and without a setter

⚠ No Setter — Danger Zone
public class Circle {
  // public: no protection
  public double radius;
  public double area;
  public double circumference;
}

Circle c = new Circle();
c.radius = 5.0;

// c.area is still 0.0 ← WRONG!
// c.circumference still 0.0 ← WRONG!
// Nothing updated the dependent fields.
✓ With Setter — Safe
public class Circle {
  private double radius;
  private double area;
  private double circumference;

  public void setRadius(double r) {
    this.radius = r;
    // side effects: auto-recalculate
    this.area = Math.PI * r * r;
    this.circumference = 2 * Math.PI * r;
  }
  // getters: getRadius, getArea, etc.
}

Circle c = new Circle();
c.setRadius(5.0);
// area = 78.54 ✓  circumference = 31.42 ✓

The Setter That Started This Whole Conversation

Head back to the TNT home page. In the JavaScript in Action section, click Toggle Icon. Watch the bolt swap from yellow to red–orange and back. That is one line of JavaScript: img.src = 'images/np_flash_639950_ED5861.svg'. A setter call. You’ve been running it the whole time.

 See the Live Demo

Languages at a Glance

Feature JavaScript Java Python 3
Field access control Convention only — _fieldName signals “private” but is not enforced Compiler-enforced — private keyword blocks all outside access Coming Later
Setter syntax set propName(val) { } inside a class, or implicit via DOM public void setX(Type val) { } — must be written explicitly Coming Later
Getter syntax get propName() { return ...; } public Type getX() { return x; } Coming Later
Side effects in setter Yes — any code inside the set block runs on assignment Yes — any code inside the method body runs on each call Coming Later
Can the setter be bypassed? Yes — obj._field = val skips the setter entirely No — private is a compile-time barrier with no workaround Coming Later
Language philosophy “We’re all adults here — trust the convention” “Rules are rules — the compiler protects the contract” Coming Later
Python note: Python’s @property decorator handles getters and setters elegantly — it sits between JavaScript’s convention and Java’s enforcement in a very Pythonic way. It will be added to this page once your Python class reaches decorators. When that comparison arrives, it will be worth the wait.