OK so I think you are confused about a few things here.
For starters, let's clean up this example a bit so it's easier to follow. I'm going to make a Person
class:
public class Person {
public String name;
}
Doesn't get much simpler than that. So, right now I have defined the class Person
but it's important to note that no Person
objects actually exist yet. The class Person
can be thought of as a blueprint for making Person
objects. So, let's make a person:
public static void main(String[] args) {
Person john = new Person();
john.name = "John";
}
Here I have initialized a Person
by calling its default constructor (note the word new
), and set its name
property to "John".
Now, if someone else was using this code they could come along and say hey let's change his name because why not?
john.name = "Bob";
But wait... a person's name changing might not make sense in the context of our program. Perhaps we don't want people to be able to change their names whenever they want as it might cause us problems later down the line. Even worse, someone could try and do something weird like turning his name into a number or any other crazy garbage that completely breaks the program. We can fix this by instead encapsulating the name
property. We do this by making name
a private
field and define a constructor as well as a way to view that field.
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Now, we must define what we want name
to be when we create the object. Let's make John again:
Person john = new Person("John");
But most importantly, there is no way to change John's name anymore. Since we have not provided a public
way to do so, it is impossible.
If we try to change john now, our program will not compile:
john.name = "Bob"; //NOT ALLOWED
And to view our name
, we will instead have to use our getter method:
System.out.println(john.getName()); //prints "John"
This is the essence of encapsulation: protecting an object's properties from undesired changes in state. Instead of just handing over our data, we hide its actual state and only allow actions on it through controlled channels. If we did want to allow names to be changed, maybe we are ok with it but only if the new name meets certain criteria. Let's say: the new name has to be at least 3 characters long (sorry Al). We can provide a setter like so:
public void setName(String newName) {
if(newName.length() < 3) {
System.out.println("name is too short!");
} else {
name = newName;
}
}
In this way we can have much greater control over how our data is used. I hope this helps clear up your confusion a bit.
Also note that if you create a new Person
you will again need to specify another String to use to set its name
in the constructor. Every object must be uniquely initialized.