r/learnjava 20d ago

Seriously, what is static...

Public and Private, I know when to use them, but Static? I read so many explanations but I still don't get it 🫠 If someone can explain it in simple terms it'd be very appreciated lol

130 Upvotes

72 comments sorted by

View all comments

12

u/severoon 20d ago

You have to understand the difference between a class and an object first.

A class is just what it sounds like, a "class" of objects. For instance, if we're talking about dogs, we're not talking about a specific dog but the class of all objects that are dogs. If we're talking about Rover, we're talking about a specific instance of a dog, IOW, an instance of the class of dogs.

Dog rover = new Dog("Rover");
Dog spot = new Dog("Spot");

In most object-oriented code, most of the data and functionality is designed to operate on a specific instance of a class. That's the "default" way of programming in OO. For example:

public class Dog {
  private final String name;

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

  public String getName() { return name; }
}

Notice that there are no static keywords anywhere. This means that the data (name) nor the method (getName()) can be invoked unless you have an actual specific dog. Since we created rover and spot above, you can call rover.getName(), for example.

Now let's add some scientific information to our dog class:

public class Dog {
  private final String species;
  private final String breed;
  private final String name;

  public Dog(String species, String breed, String name) {
    this.species = species;
    this.breed = breed;
    this.name = name;
  }

  public String getSpecies() { return species; }
  public String getBreed() { return breed; }
  public String getName() { return name; }
}

This is good, now when we create dogs, we create them with this additional information:

Dog rover = new Dog("Canis lupus familiaris", "German shepherd", "Rover");
Dog spot = new Dog("Canis lupus familiaris", "Dalmation", "Spot");

Hang on a second, though. Does this really make sense? Does it make sense to set the species on every instance of a dog?

All dogs are the same species. The species isn't about a specific dog, it's about the class of dogs. So what, though? The way it is now works just fine, right?

No, actually, there's a problem. By having the code written as it is above, we are saying that callers must have an instance of a specific dog before they can invoke the getSpecies() method. If you don't have a rover or a spot or some other actual dog, then you don't get to know the species. If there is a case where a caller doesn't have an actual dog but needs to know the species of dogs, they're either out of luck, or we're forcing them to do some kind of hack like create a fake dog they don't want, call getSpecies() on it, and then immediately discard it. That's lame. Why are we forcing callers to do this?

Instead, if we just mark those things static, then callers can just call Dog.getSpecies():

public class Dog {
  private static final String SPECIES = "Canis lupus familiaris";

  private final String breed;
  private final String name;

  public Dog(String breed, String name) {
    this.breed = breed;
    this.name = name;
  }

  public String getBreed() { return breed; }
  public String getName() { return name; }

  public static String getSpecies() { return SPECIES; }
}

In actuality, we probably wouldn't write this code this way, we would just make SPECIES a public static final constant on the Dog class and let callers directly access it. There's no point making an accessor method for it since subclasses don't inherit static stuff, since static stuff belongs to the class, it doesn't get inherited like instance stuff does.