Every method you wrote before this topic started with public static. The methods inside your classes in the last three lessons did not. That one keyword decides who a method or field belongs to: one object, or the class itself.
A field or method without static is an instance member. Each object gets its own copy of an instance field, and an instance method runs on one particular object:
public class Counter {
public Integer count = 0;
public void increment() {
count = count + 1;
}
}
Counter a = new Counter();
Counter b = new Counter();
a.increment();
a.increment();
System.debug(a.count); // 2
System.debug(b.count); // 0
You need an object before you can call an instance method: a.increment().
A static member is shared. There is exactly one copy, no matter how many objects exist, and you reach it through the class name instead of an object:
public class MathHelper {
public static Integer square(Integer value) {
return value * value;
}
}
Integer result = MathHelper.square(4); // 16
No new is needed. You already use static methods every day: Math.max(a, b) and String.valueOf(x) are both called on the class.
Ask whether the code needs the data of one particular object. If it does, make it an instance method. If it only works on the values passed in, or on something every object shares, make it static. A static method cannot read instance fields directly, because there is no single object for it to look at.
In a real org you can put static fields and methods inside any class. The exercise editor runs your code as one anonymous block, and there a class you declare cannot hold static members. A public static method written outside every class works fine, exactly like the methods from earlier lessons, so the exercise uses that shape for the shared helper.
Salesforce code mixes both kinds all the time. Utility classes are full of static helpers, while objects that carry data, like a wrapper around a record, use instance fields. Choosing correctly keeps data from leaking between objects.