A Quick Review of Java Classes and Objects

This page provides a quick review of how Java classes, objects, primitive types, values, and variables work together in a Java program to create various “situations”, or combinations of objects and values in “Java land” or wherever you might imagine these abstract ideas playing out (we will draw pictures to illustrate these). But in reality, these values and events happen in the computer’s RAM, or random-access memory; we will also draw some pictures of what the RAM might look like, as this can be especially helpful in understanding how assignment statements affect primitively-typed variables and Object-typed variables differently. (This difference is one of the main themes of this review page.)

Some sample code to work with

OK, imagine that we write up two different class definitions. The first contains code for a Circle class: each Circle has x and y coordinates and a radius r, which are all Java ints. In addition, Circles have two methods, one to return their circumference and one to scale them by a given scale factor s.

public class Circle {    
      int x;
      int y;
      int r;
      
      public Circle(int x, int y, int r) {
        this.x = x;
        this.y = y;
        this.r = r;
      }
      
      public float circumference() {
        return 2 * Math.pi * r;
      }
      
      public void scale(int s) {
        r = s * r;
      }
      
    }
    

(Note in passing that the circumference method implicitly applies to the Circle it is called on, returning a floatscale method implicitly affects the Circle it is called on, returning nothing (i.e., void return) but instead acting upon its object, and thus changing it.

The next class we define is just the main class for this “project”, called Example: it has a main method which will be the one that is run when the project is run.

public class Example {
      int a;
      int b;
      Circle c;
      Circle d;
      
      public static void main(String[] argh) {
      
        // the initial set-up:
      
        a = 7;
        b = 12;
        
        c = new Circle(10,5,3);
        d = new Circle(20,4,2);
        
        // ... see further code here
        
      }
      
    }
    

We are going to “run” this code, in the main method, up to the point labelled // ... see further code here and draw a picture of what the situation looks like, both in abstract picture terms but also in terms of the RAM (memory) of the computer (see below). Then we will add sample lines of further code, one or two at a time, and see how the situation changes.

(Note: if you’re reading this in a browser, it might help to open two copies of this window, one where you keep the code above visible, for reference, and another with the running examples below.)

What the situation looks like, in pictures and in RAM

Given the code above, what will the situation look like? We can visualize it as in the following picture:

Some things to note:

On the other hand, what is really going on inside the computer? Everything we are talking about (objects, primitive values, variables, even the method code!) is stored in the computer’s RAM or main memory. This is like a really big array, with weird indices (called addresses) that are written in base 16 or hexadecimal. This is just like our usual base 10, but it has 6 extra “digits” for the values 10 through 15, usually written as the letters ‘a’ through ‘f’. You might recognize numerals like these from error output in Java.

(Technically, the things stored in RAM are not so much in hexadecimal as in binary, or base 2 … but that’s pretty nasty to write out in full, so people usually use base 16, which abbreviates the base 2 more nicely than base 10 does. [Why? Because 16 is a whole power of 2, whereas 10 is not.] Even more technically, they are not “in” binary so much as there are two stable configurations of the corresponding circuits, one of which we call a ‘0’ and one that we call a a ‘1’.)

In any case, we can picture this situation (what numbers are where in RAM) as in the following picture:

Some things to note this time:

Some bits of code and their effects on the situation

OK, now let’s try out a few things: we’ll write some code and then “run it” by changing the pictures—usually just the abstract pictures, but sometimes maybe the RAM as well, for emphasis.

In each of the illustrations below, we start with some situation pictured on the left. (Often this is either our original situation or one continuing from a previous example.) Next we “apply” the code given in the middle, and we end up with the situation on the right. (See the red arrows for the left-to-right flow of time.)

Look at the pictures and verify that you understand why and how the situation changes due to the effects of the code.

All changes in the final picture should be circled in red (unless I forget some … but I’ll try not to).

Assigning primitively-typed variables

In this first example, we assign some variables of type int, which is of course primitive (in particular, it’s Java name starts with a lowercase letter). The changes can be seen as the simple over-writing of the values in the boxes:

 

Assigning class-typed variables

In this next example, we assign some variables of type Circle, which is a class type, and thus represented by references. The changes in this case can be seen as an over-writing again, but now the things over-written are references to actual objects in memory. This means that changes in one variable’s value can be “seen” through references via another variable. (Here c and d are independent of each other in the first situation, but they both reference the same object in the second one.)

Accessing an object’s variables with dot notation

Notice how the dot notation works: given a variable (or other Java expression) of a class type, the dot following it means that we “run the arrow” from the box holding the corresponding reference, then use the name to the right of the dot to pick out a variable inside the scope of the corresponding object-box. Once there, the “boxes” corresponding to variables behave just as in the outer part of the picture: we can get the value, or assign to it using the = operator.