Understanding Classes, Static and non-static Variables/Methods and Constructors in Java

Understanding Classes, Static and non-static Variables/Methods and Constructors in Java

To fully understand any programming language, you need to understand the English language behind the programming language, Java is no different. This post will explain to you what classes, constructors and instances mean in Java. Let's get right in.

What is a class in Java

Forget about code or Java for a second, let's walk into a car manufacturing plant for now, Honda for instance, okay. To manufacture an accord car, Honda has a blueprint or flow as to how the accord car should look when it is finally created/designed into existence. All production processes will follow that blueprint. Now, in Java, this blueprint is known as a class. A class in Java is a blueprint through which real-life objects are represented in code.

Using classes as a blueprint

Almost anything in real life can be represented in code, but how well something is represented is up to us and what we decide to program. Classes in Java give us a way to model or represent physical objects in code via a blueprint. A blueprint, or class, contains a set of attributes and behaviors that define an object. Let's design a car object in code using a class. The attributes might be height, diameter, and maybe even car type. Every car has these properties or attributes, but their values might not be the same. That is what makes this Class a blueprint. It contains the definition of what a car should be. As for the behaviors, running could be a behavior for the car. It's an action that the car takes, rather than an attribute representing the current state of the car. Let's create a blueprint for a car using a Class in Java.

screenshot of a Java class in Intellij IDEA

We haven't created any cars yet. Our Class says, "If we wanted to create a car, this is how it would be represented in our program."

Building objects with a constructor

Classes only represent a general blueprint but they become more tangible when you use a constructor to bring your blueprint to life. To create cars from our car class we will need to add a special type of function called a constructor to construct our car objects. To create a constructor, we will use the class name Car. We don't need a return type because the name of the function, car, counts as the return type as well since Car is the class name. This classifies it as a constructor. To build a car we will need to know what its height, diameter and car type should be. This means we'll need to add inputs to the constructor so that we can construct a custom car with the appropriate height, diameter and type. Of course, the body of the function doesn't do anything yet. We will need to set up the car we're building with the appropriate values. Using the 'this' keyword, we access the car we're creating and set the height, diameter and type on the left equal to the inputted values on the right. When this constructor is used, it will create a car with the inputted height, diameter, and car type values, let's try it. To keep our car class separate from the program we want to execute, we'll create a new class called main.

Car class with a constructor

main class

This will contain our main method which we will execute the program from. To create a car we will use the constructor, Car with the inputs 25 for the height, and 5 for the diameter and our car will be a Porsche car. In addition to using the name of the constructor, we will also need to add the new keyword. This will create a new car from our car class.

main class with new car constructor

We have created our first car. By adding a constructor to our car class and using the constructor in a main method we were able to create our first car in code.

Understanding the difference between class and instance members

So far, we've created a class blueprint and built instances using a constructor. We can continue to organize our code by using static and non-static members. We have already been writing non-static code. Non-static members are parts of a class that are accessible via an instance and belong to that instance. This means you'll need to create an instance to access a non-static member. In our car example, the height, diameter and carType are all examples of non-static members. Or specifically, non-static attributes. You'll have to create a car to access the values of these attributes. We could also refer to these non-static members as instance members because you have to create an instance to use it or access it. So what about a static member?

A static member is accessible via the class and belongs to the class. It should be an attribute or behavior that's not based on a particular instance, but rather belongs to all of the instances of that class. Height, Diameter and carType can all vary between different instances, making them non-static members. One static attribute we can create in our Car class is color. Every Car instance should have this specific color, whether it's a Tesla car or a Honda car that's just been created. To create a static color attribute, we will use the keyword static and also give it the datatype Color. For the name, we'll call it COLOR and give the value of a new color using the Color constructor with the appropriate values to create the color black.

car class with a static attribute

We just created our first static attribute or class attribute, COLOR. To access its value, we'll go to our Main class and use the class name to access it. This is different from our non-static members because we use the class name, rather than a specific instance name to access the static attribute. Now, just like we can have non-static instance-based behaviors, we can also have static class behaviors. Static behaviors or static methods do not rely on a given instance's members. Rather, they only rely on class members. Let's add a static behavior to our Car class called announceCar. To create it, we'll use the keyword static, and all it's going to do is print out a message. "Look out for that car". Notice, it does not rely on any instance methods or instance attributes in its implementation. If it did, we'd get an error saying that the attribute cannot be referenced from a static context. It also wouldn't make sense because all cars aren't of a certain type. It varies based on the instance. If we wanted to use the carType attribute in this method, we'd have to make this a non-static function. If it did, we'd get an error saying that the attribute cannot be referenced from a static context. It also wouldn't make sense because all cars aren't of a certain type. It varies based on the instance. To use the static method, we simply use the class name and access the behavior.

car class with static behavior

main class with calls to static attribute and behavior

You might notice that our Main method is also static and that's because it doesn't rely on any instance members of the Main class. Typically, if a given method does not rely on instance members, it should be static. By organizing our code with static and non-static members, we're able to make it easier for others to contribute and make changes.

conclusion

Understanding the English language behind a programming language helps you further write reusable and maintainable code.