Last modified: January 12, 2023
In Components of a Java Program earlier, the lesson mentioned that there are two types of fields:
For learning purpose, let's say we have a class named Person:
public class Person {
String name;
int age;
...
}
The "name" and "age" above are Instance Variables. This means when we create a new Person object, the person will have their own name and age.
To create Class Variables you can simply add the static
keyword before the data type. They are also known as static fields.
In the example below we created a class variable that keeps track of the average life expectancy of people (how long they are expected to live on average).
public class Person {
String name;
int age;
static int lifeExpectancy = 82;
...
}
Instance variables are always initialized in the constructors. Even if you write code that initializes them in the same line they are declared, the initialization code doesn't actually run until a constructor is called because instance variables do not exist without an object. Class variables, on the other hand, can (and usually should be) initialized when they are declared because they exist even if there are no instances of the class.
Because lifeExpectancy
is a static field, it belongs to the class, so you should access it through the class like this:
System.out.println(Person.lifeExpectancy);
If you access a class variable through an instance of the class, it will still work, but it will potentially mislead someone reading your code into thinking the property is an instance variable. What it really does is just access the static field of the class that object is an instance of, so every instance of the same class would really be referencing the exact same field. For this reason, you should always access class variables through the class to avoid confusion. It is similar to how you should not name classes starting with a lowercase even though the compiler will not complain if you do so. There are many bad coding practices that the compiler will not complain about.
Now, every Person objected created will have the same hasBrain
.
If hasBrain is changed for one person, the change will be visible to every other person.
Inside the class where a class variable is declared, you can access it by just saying the name of the variable or by explicitly accessing it through the class. Technically you can access it through any instance of the class, but as mentioned above, that is bad practice so you should not do it that way.
public class Person {
String name;
int age;
static int lifeExpectancy = 82;
...
void doSomething(){
System.out.println(lifeExpectancy); // 82
lifeExpectancy = 81; // changed lifeExpectancy to 81
System.out.println(Person.lifeExpectancy); // 81
Person.lifeExpectancy -= 3; // reduce life expectancy by 3 (it is now 78)
System.out.println(lifeExpectancy); // 78
System.out.println(this.lifeExpectancy); // 78 (this works but is bad practice)
Person bob = new Person();
bob.lifeExpectancy = 45; // bad practice - this is equivalent to Person.lifeExpectancy = 45
Person jane = new Person();
jane.lifeExpectancy = 67; // bad practice - this is equivalent to Person.lifeExpectancy = 67
System.out.println(bob.lifeExpectancy); // 67 // bad practice - this is equivalent to System.out.println(Person.lifeExpectancy)
}
}
No matter how and where a class variable is accessed, it is referring to the same piece of data.
You can NOT have a class variable and an instance variable with the same name. Every variable name, regardless if it is class or instance, must have a unique name.
(also called static methods)
We can make a class method by adding a static
keyword before the return type. Generally you should write access modifiers like public before the static keyword.
static void doSomething(){
...
}
public static String returnSomething(){
...
}
Similar to class variables, class methods can be accessed within the same class like this:
public class Person {
static void doSomething(){ /* implementation not shown */)
public static String returnSomething(){ /* implementation not shown */)
public void callStuff() {
Person.doSomething(); // calling method explicitly on the class
String str = returnSomething(); // This is equivalent to String str = Person.returnSomething() since we are in the Person class.
}
Outside the class, we can access static methods only by explicitly calling the method on the class it is defined in:
public class Driver {
public static void main(String[] args) {
Person.doSomething();
String str = Person.returnSomething();
}
You can technically call a static method on an object, but it is bad practice since that would make it seem like it is an instance variable.
The code inside static methods can only access the parameters passed in and other static fields, but NOT any instance variables
For example:
static void doSomething(){
lifeExpectancy = 99; // ok because lifeExpectancy is a static field
name = "joe"; // ERROR! "name" is an instance variable and cannot be accessed in a static method
this.lifeExpectancy = true; // ERROR! "this" is reserved for instance methods and cannot be used in class methods
}