Introduction to Java  
 
 

Week 2

Readings:

  • Chapters 2.1 - 2.4. This should cover the basics of program creation and the example code is something we will be working with in much greater detail later on.
  • Chapters 3.1 - 3.4. This covers the concepts and use of primitives and the mathematical operators in greater detail.

Lesson Outline:

  • Classes and primitives
  • Creating your own classes
  • Memory allocation in Java
  • Adding methods
  • Standard classes and example

Lesson Goals:

  • Understand primitives and uses
  • Create and use primitives and classes
  • Understanding of how memory is allocated

Additional Reading:
In this lesson, we will be covering classes and primitives. In most simple terms, classes are molds or templates upon which objects can be created. It determines what different parts of a program can and cannot do, as well as what they are and how the information is divided up between classes. There are several relationships which can exist between different classes beyond simple interaction but we will be covering that later.

The actually objects created from the class templates are known as "instances" of that class. We will create these instance objects and examine some of their properties in this lesson.

Primitives are data types which contain various types of information and data. In Java, there are eight different types of primitives. They are byte, short, int, long, float, double, boolean, and char. We will not be getting to several of these primitives in this lesson, but we will be covering those that you will use most frequently. The most commonly appearing of these primitives are int, boolean, and char. The other five tend to be used more when either using extremely large numbers or allocating/saving memory.

Bytes are simply 8-bit signed two's complement integers. It cannot be used to represent any integer less than -128 or any more than 127.

Shorts are also mostly used when you want to save memory in large arrays, and are only 16-bit two's complement integers.

Int stands for integer, and that is the most commonly used primitive you will be using for holding whole numbers. It is a 32-bit two's complement integer and can hold a minimum value of -2,147,483,648 and a maximum value of 2,147,483,647. So it should be able to account for a great deal of your numerical needs.

Longs are essentially an integer with twice as many bits allocated to it. This makes it a 64-bit two's complement integer from -9,223,372,036,854,775,808 to a maximum value of 9,223,372,036,854,775,807.

Doubles, however, are the default usage for any decimal values you should choose to want. A double should not be used for precise values as it is stored in a 64-bit floating point representation.

Floats are the shorts of doubles. It is used for decimal values but uses only 32-bits instead of the 64-bits used by doubles, which makes them great memory savers when used in large arrays.

Boolean is a very simple primitive. It can only be one of two values, true or false. It is extremely useful for conditionals and loops, which we will be getting to in the next lesson.

Char is the data type used to hold a single Unicode character. To place this in a bit more context, Strings are made up of chars. This can be very useful when parsing Strings or assembling them one character at a time.

Just one final note before getting to the actually programming, and that is the matter of Strings. Strings are not technically considered primitives but are provided by the Java language as a special support for strings of characters. They are actually instance objects of the class String, which is automatically built into java programs when they are compiled. These are the objects you worked with previously in lesson one.

Now let's jump right in and start playing around with some primitives, instance objects, and some simple math operations.. After all, the best way to learn is to do it yourself.

First off, you should grab the two files BaseClass.java and AddOn.java from the Files To Be Downloaded panel to your right. Examine both of the files and try to predict what will be printed out when the files are executed.

Compile both of these programs and then run the BaseClass one. What is printed out? Why are b and instance.b different values? How is int x different from int y? Why is String capitalized but int, char, and boolean aren't? What is different in how the char and the String are created besides the capitalization? Try and answer each of these questions before moving on to the next section.

All right, let's see if you figured out these questions correctly.

What should have been printed out onto your terminal was:

true false a This is also an instance object

The primitives b and instance.b are different because they are referencing to two variables, which happen to share the same name but are in different classes. They are actually two different sections of memory on the computer, which is how they are two different values, despite having the same name. The reason that the AddOn primitive b was accessible from the BaseClass class was that you created an instance object of the AddOn class. This creates an object with all the variables, primitives, and methods that exist in that class, but let us manipulate them from a completely different class. This is very important to understand, as it is a key part of Java's object oriented programming and we will be using it quite a bit.

Int x is different from int y in that x is a class variable and is stored on the heap. This means it is accessible to every method in the class, except main which is static, but we will get to that later. The heap is actually where all instance variable, class variables, and objects are stored. This may seem like everything, but shortly you will see that there is another type of variable not stored on the heap, but rather on the stack. The variable y itself is also stored on the heap but it in turn only exists within the main method. Methods outside of the main cannot access it or even know about it.

The reason why String was capitalized and the other primitives were not is because String q is actually an instance object of the class String. The primitives are not objects themselves, merely variables, and the terms int, char, boolean, along with the others, are merely to tell Java's compiler what type of data it is holding in that variable, so it knows what it can and cannot do with it.

Finally, the last question is really more a matter of syntax. You will have noticed that char encloses its value in ' ', while Strings are enclosed in " ". This is an important distinction to remember, as a failure to do this will result in errors that can be extremely annoying.

Ok. It's time to adjust our code again. I want you to change BaseClass.java to match the following code:

class BaseClass{ int x = 9; public static void main(String args[]){ boolean b = true; int y = 45; char ch = 'a'; String q = "This is also an instance object."; BaseClass base = new BaseClass(); AddOn instance = new AddOn(); System.out.println(b); System.out.println(instance.b); System.out.println(ch); System.out.println(q); int d = base.squareNine(); System.out.println("Nine squared is " +d); d = instance.squareTwelve(); System.out.println("Twelve squared is " + d); } public int squareNine(){ int a = x; int answer = a*a; return answer; } }

Change AddOn.java to:

class AddOn{ int z = 12; boolean b = false; public int squareTwelve(){ int answer = z*z; return answer; } }

Now run your code again.

Notice how the x variable is automatically known by the squareNine() method. However, the a's inside of the squareNine() method are not class variables, but rather active method variables and they are stored on the stack in memory, not the heap. This is because they are created when the method is called, and when the method is finished, they disappear from the stack, no longer needed or existing in the program. Also note how all methods in main must be passed through instances of that class, even if that is an instance of the class you are currently in.

Another syntactical note to remember is how non-String variables can be added together with strings in the println commands. This is extremely useful for keeping track of what you are printing out and for error checking.

A final note is to notice that the primitive type d matches with the primitive type show next to the name of the method. Both are int's. This is an extremely important fact, as it is the method telling the instance calling it what kind of data type to be given back at the end. But this will be covered in much more detail in the next lesson.

Now it is time to cover the difference between pre-existing classes and ones you make for yourself. Remember how String objects were different from primitives, well, this distinction is important because it is an example of standard classes(or system classes), which are built in or importable classes which have already been made for you by the creators of Java for your use to save you time. These are distinct from programmer-defined classes, which are classes that you create yourself. Standard classes will be covered in much greater detail later on, when I introduce you to the Java API and standard libraries for your usage.

Create a class in a new file called Sample1.java. Here is what the code in the file should look like:

import javax.swing.*; class Sample1{ public static void main(String args[]){ JFrame myWindow = new JFrame(); myWindow.setSize(500,300); myWindow.setTitle("I like windows"); myWindow.setVisible(true); } }

Compile and run this code. Ta-daa! You've created a window. And you didn't have to make any classes, methods, or variables. All you had to do was import the javax.swing.* library, and suddenly you had everything you needed to make windows. This standard class of JFrame contains the methods setSize, setTitle, and setVisible, as well as quite a few others. These standard classes are extremely helpful and great part of Java, but just remember one thing: you still need to write the classes that import and implement them, so don't get too lazy.

Exercises:
I want you to experiment with the different mathematical operands in Java, and combine that with your new understanding of primitives. I want you to test out, in the main() method of the BaseClass, the following mathematical operators: +, -, *, /, and %(this is the remainder function).Try these on the different primitive types discussed at the beginning of this chapter. They aren't hard to create, simply type the name of the primitive type you want in front of whatever you wish to name the variable, give it a value, then attempt to add, divide, multiply and raise each of the mathematical primitives by both the same primitive and other similar primitives. For example, if you are using an int, try and multiply it with a short, or divide a long with it. By the end of this exercise, you are expected to be able to add, subtract, multiply, divide, find the remainder of, and raise to any reasonable power integers. For extra credit, try and also do this for decimal values using doubles and floats. Take careful note of any errors you encounter along the way, as they will be very useful in understand why Java does not allow it to perform that way.


Files to Be Downloaded