Let's start from where Unit 1 left off. During the first steps, we instructed our computer to write "Hello World!" to the display. Through that unit, we went through quite some material, despite it being so simple. In this unit, we'll cover more practical points rather than theoretical ones, so get ready to write some more code this time!
Variables
So, what is a variable? As the name clearly indicates, it is something that varies. A variable is just a label which you can use to store something. Let's say we want to store our user's name, we create a new label named username and assign the user's input to this label. A user types in their name and we instruct the computer to store the input somewhere which can be addressed using the word "username".
To better understand and appreciate how useful that little label is, try imagining having hundreds of such variables all without a human-friendly name. You d not need to go far, older languages had no such concept and used exclusively memory addresses.
With this knowledge, you can now think of your computer's memory as being a large room full of P.O. Boxes. Each P.O. Box may be referred to by its number. In modern languages you can give each P.O. Box its own unique name too, so it's easier for you to know what you're working with.
The next bit is theoretical, however its good to know about variable terminology.
Java is known as being strongly-typed. This strongly named description simply means that each variable can have one type, and one type only. If we declared our username variable as being of type text, it can only contain text. If we had another one for storing a number, it can only store a number. It's a restriction, but it's convenient. There are language that have variables whose types change during runtime, or weakly-typed. It's convenient too, but its easier to shoot yourself in the foot if you're new to it.
Let's make use of a variable in a more practical example. In this task, we want our text to be defined as a variable, rather than passing a direct value to System.out.println.
As you can see, the change is minor. In the new line, the only thing which may be new is the String label. A String is simply a series of characters; it is a type of variable which you'll find in the vast majority of programming languages.
To better understand and appreciate how useful that little label is, try imagining having hundreds of such variables all without a human-friendly name. You d not need to go far, older languages had no such concept and used exclusively memory addresses.
With this knowledge, you can now think of your computer's memory as being a large room full of P.O. Boxes. Each P.O. Box may be referred to by its number. In modern languages you can give each P.O. Box its own unique name too, so it's easier for you to know what you're working with.
The next bit is theoretical, however its good to know about variable terminology.
Java is known as being strongly-typed. This strongly named description simply means that each variable can have one type, and one type only. If we declared our username variable as being of type text, it can only contain text. If we had another one for storing a number, it can only store a number. It's a restriction, but it's convenient. There are language that have variables whose types change during runtime, or weakly-typed. It's convenient too, but its easier to shoot yourself in the foot if you're new to it.
Let's make use of a variable in a more practical example. In this task, we want our text to be defined as a variable, rather than passing a direct value to System.out.println.
As you can see, the change is minor. In the new line, the only thing which may be new is the String label. A String is simply a series of characters; it is a type of variable which you'll find in the vast majority of programming languages.
Variable types
Now that you have declared your first variable, and hopefully got to understand the relation between the type of the variable and the content it stores, it is safe to introduce the list of primitive types in Java. As you now know, Java is object oriented and everything is defined as a class. This implies that every instance in our program is an object. However, this is not entirely true, since objects need to be made up of something. If we keep going deeper into what constitutes and object, we find that there are only 8 primitive types. Each primitive type is made up of some number of bits. These are as follows; afterwards we'll go through them:
- boolean - no specific number of bits, but practically 1
- byte - 8 bits
- char - 16 bits
- short - 16 bits
- integer - 32 bits
- long - 64 bits
- float - 32 bits
- double - 64 bits
As you can see (assuming you're familiar with bits, the basic units of information), all types are practically increasing sizes of numbers. No letters, no images, nothing but numbers. Later I'll explain how everything can be made from these primitives, but first let's see how we can organise them into roughly three categories.
First we have the boolean type. This can have just two values, 1 or 0. Effectively we use true or false in Java, and is mostly used for setting states and flags.
Next come the natural numbers. All primitives from the byte to the long can fall under this category. Values stored by these types cannot have any values after the decimal point. One thing to note about the char type is that it does store a numeric value, however it is treated as a character. Note also that it is a 16-bit unicode.
Finally we have the real numbers; the float and double. Double, as the name implies, is just double the size of a float. It is usually much more practical to work with a double unless you're working on a high performance system where memory is precious (not all systems have gigabytes of memory to waste).
Primitive types can be easily declared or have a value assigned to them. If you want an integer with a value of 10, simply enter:
int myNumber = 10;
Composites
Now that you have the most granular types, it is possible to mix and match to create more complex types. A composite is basically another name for an object. The String type, for example, is a composite. In order to explain this composite, we need to introduce another programming term; arrays. An array is just a contiguous series of memory cells, each containing a value of the same type. Java has native support for arrays supports defining new arrays during runtime (older languages did not support this directly). The next snippet shows how we can use an array of characters to emulate a String, albeit in a less practical way.
Unlike primitives, composites, or the proper name, objects, are created using the new keyword. The declaration also follows this convention:
Type myTypeVariable = new Type();
As you can see, there is the type, the name, followed by the assignment to a new instance of the class (or type). Note though, that the String is an exceptional case in Java and can be declared like a primitive. This is only an exception and does not apply to any other class.
Probably the String is not enough, so let's go through some more examples. Let's say we want to show a picture. What constitutes a picture? Pixels, the number of pixels in width, and in height. Width and height are just numbers. The pixels are an array of the Pixel object (so we also have nested composites). And after that, what is in each pixel? Three values for the primitive colours Red, Green and Blue; again, three numbers.
Let's define our own Picture type. First, we need a Pixel. Then we'll create a Picture and we'll find its area. Using this area, we'll set the value of the pixels in our Picture, since initially this is null.
Now we'll create the program "body". The main class this time will create the image, the pixel array, and print out the area. Note how we concatenated the text and a variable using the '+' symbol. I'll explain the operators later on in this unit.
So you see, pretty much anything can be reduced to a number.
Operators are the symbols used in code, such as the '+', '-', etc. The plus can be used for concatenating anything. For example, let's say we have variables a and b. a + b could mean the following:
If a and b are primitive, the result is a primitive. If any of a or b is not a primitive, the result is always a String representation.
Other operators are only reserved for primitives:
Type myTypeVariable = new Type();
As you can see, there is the type, the name, followed by the assignment to a new instance of the class (or type). Note though, that the String is an exceptional case in Java and can be declared like a primitive. This is only an exception and does not apply to any other class.
Probably the String is not enough, so let's go through some more examples. Let's say we want to show a picture. What constitutes a picture? Pixels, the number of pixels in width, and in height. Width and height are just numbers. The pixels are an array of the Pixel object (so we also have nested composites). And after that, what is in each pixel? Three values for the primitive colours Red, Green and Blue; again, three numbers.
Let's define our own Picture type. First, we need a Pixel. Then we'll create a Picture and we'll find its area. Using this area, we'll set the value of the pixels in our Picture, since initially this is null.
Now we'll create the program "body". The main class this time will create the image, the pixel array, and print out the area. Note how we concatenated the text and a variable using the '+' symbol. I'll explain the operators later on in this unit.
So you see, pretty much anything can be reduced to a number.
Operators
As I mentioned earlier, I'll give an introduction to operators. These are not so complex so there is not much else to learn about them.Operators are the symbols used in code, such as the '+', '-', etc. The plus can be used for concatenating anything. For example, let's say we have variables a and b. a + b could mean the following:
If a and b are primitive, the result is a primitive. If any of a or b is not a primitive, the result is always a String representation.
Other operators are only reserved for primitives:
- The minus '-' used to subract;
- The star '*' is used to multiply;
- The slash '/' is to divide. The value is rounded if not of types float or double;
- The percent '%' used for obtaining the modulo;
- The hat '^' is used for bitwise XOR;
- The pipe '|' is used for bitwise OR;
- The ampersand '&' is used for bitwise AND;
- The exclamation mark '!' is used for NOT;
- The greater than '>' and less than '<', for...well greater or less than;
- The double greater and less than ('<<' and '>>') for bit shifting;
Methods
We mentioned something about methods during the first unit, mostly trying to relate them to the methods in your recipe books. This time, we shall add more methods to our little picture program. At first it might seem like overkill to have too many methods for a simple task, but as your project grows you'll come to appreciate shorter and more frequent methods.
So, the first task - adding new methods. But why, what are they going to do? Imagine we want our program to accept a user input. For this task, we'll use methods that were written by others - we'll be calling those methods. Afterwards we'll break up our program into smaller methods so that later on we can follow better programming practice. In this case we'll write our own methods too.
The program
Our next task will be to add on to the Hello World Picture program. This time the area will be calculated by the picture, rather than us having to calculate it in our main program. We'll also let the user specify the width and height of the picture. This user input will need some processing, as we shall see next.First, we'll extend the Picture class so that it can support its own methods. We shall call this PictureExtended to avoid confusion for now.
Next we'll upgrade the main program. As you can see, it has many more methods and the functionality is more granular. If we had two pictures for example, we could still call the same createPicture, thus avoiding duplicate code.
Static vs not static
Note how we put static in front of methods in the main class, while we did not put any in the PictureExtended. Now that we do have some methods and classes, it is safe to explain it.Static methods are those methods that can be called without having an instance of the enclosing class. For example, we never declare a new System or Stream class, but we call println on System.out variable (which is of type Stream). This is because it is declared static. However, we cannot call getArea() on PictureExtended by itself. We must have a new PictureExtended and place it in a variable. We are then able to call it from the variable.
This is basically the difference between static and non-static; if it is static, it can be called without an instance of the enclosing class; However, it cannot access the non-static members of the class. Let's say we make the getArea() static, in that case, we cannot access the width and height values of the PictureExtended instance.
Accepting user input
We are able to accept user input via the Scanner class. Again, this is just like System, a class already provided with Java (although we had to create a new Scanner, unlike System). Note how we passed System.in to it, telling it that we expect to receive input from the standard system input; the keyboard.
The difference from System is that Scanner resides in what is known as a package which is different from ours. We will go through packages in a later Unit, however note how we needed to import the class. The import statement has to be at the very top, outside the class declaration.
Conclusion
This was quite a long unit and covers quite a lot. We created new classes, instances of these classes, or objects, static methods and imported some other ones too. In the next units we shall go over further interesting bits of programming in Java, such as loops, cases and conditionals.
Other tutorials (which are just as good or better) may hold off explaining the details of classes and objects initially. I believe that this might send off the wrong message about Java. It is understandable that it is initially complicated, however it will embed the idea that in Java one should follow an object oriented methodology, otherwise the code will not be up to standard. Not that it is incorrect, but as projects grow, not following conventions will make Java very frustrating.
So, as a precaution, I'm giving out fairly detailed descriptions of why classes and objects before going further into the traditional loops and conditionals. Hopefully the descriptions coupled with the actual code will make it more natural.
Thank you!