notes


Variables and Operators

Primitive Types

There are 8 primitive data types in Java. These are the only types of data that have actual representations in memory. All other Java types are classes which are composed of these fundamental types. Unlike some other languages, the size of these types are strictly defined and all 6 numerical types are always signed. (can always be positive or negative) The types are defined as follows:

TypeDescriptionSize MinMax
bytesigned integer8 bits -128127
shortsigned integer16 bits -3276832767
intsigned integer32 bits -2,147,483,6482,147,483,647
longsigned integer64 bits -9,223,372,036,854,775,8089,223,372,036,854,775,807
floatreal number32 bits +-1.40239846e-45+-3.40282347e+38
doublereal number64 bits +-4.94065645841246544e-324+-1.79769313486231570e+308
booleantrue/false1 bit N/AN/A
charUnicode character16 bits \u0000\uFFFF

Creating a name that is associated with a space in memory holding a value of a specific type is called declaration. You declare a variable by specifying a type followed by a name for the variable and a semicolon. For example, to declare an integer called myInt:

int myInt;

Note the semicolon at the end of the line. Java code is broken up into statements ending in semicolons. Each statement is like one command. Variable names cannot be the same as any keywords, such as int, boolean, public, class, etc. To assign a value to myInt, use the equal sign like so:

myInt = 36;

Here myInt is assigned the value 36. The 36 in this statement is known as an integer literal. Declaration and assignment can be done in the same statement:

int myInt = 36;

The other types are handled similarly. A variable that has been declared, but not assigned to, has its default value, which is basically the appropriate type of zero, except for booleans, which default to false. Note that boolean variables can only hold the values true or false, which are not equivalent to 1 and 0. To create a boolean called myFlag and set it to true:

boolean myFlag = true;

Variables can be assigned the values of other variables, can be assigned new values, and can be assigned the values resulting from complex expressions:

double a = 6.57;
double b = 9.822;
b = a;
b = ( 5.43 + 6.1 * 8.4 ) * ( a + 67.5 );

Integers can be assigned to each other and reals can be assigned to each other as long as a number of greater size (in bits) is not assigned to one of smaller size. So a float can be assigned to a double, but a double cannot be assigned to a float:

double d = 5.6;
float f = 2.33f;
d = f;   // this is fine
f = d;   // this is not - it will not compile
The reason for this is that assignment to a smaller type can cause loss of information. Notice that f at the end of the second line. To specify a float literal, you need to put an f after the number. A literal with a decimal point and no f is considered a double and cannot be assigned to a float directly. If you are certain that your double is small enough to fit in a float, or your long is small enough to fit in a short, you can cast it explicitly by putting the type you want it to be in parenthesis before the variable or literal like so:
double d = 7.65;
long l = 6545;
float f = (float) d;
short s = (short) l;
Primitive types that are defined in a block do not have default values. The compiler will not compile code where variables might have their value retrieved before they are assigned a value. This does not apply to member variables of objects, which do get initialized to default values - 0 for numbers, false for booleans, and \u0000 for chars.

Comments

Sometimes you want to write notes in the code that will be ignored by the compiler. These are called comments and come in two varieties. If you put a double slash on a line, any text on that line after (and including) the double slash will be ignored. So, this is all valid code:

int i = 5;  // comment here might describe what i is for
int j = i + 10; // anything you want to say can go here
j   // this is sort of
=   // pathological, but
12  // is nonetheless
+ i // syntactically
;   // correct   

Another style of comments uses /* to start a comment and */ to end it. These comments cannot be nested. That is, you cannot comment out a region of code that already contains this type of comment. For this reason, it is usually best to use the // comments for regular comments. This way, if you need to comment out a large block of code, you can use the /* */ comments. The two lines in the middle of the following code will be ignored by the compiler.

int i=0,j=1;  // yes, you can declare multiple variables of
double d=2.5; //   the same type with commas like this
/*
i = 5;     // comment
j = i + 6; // comment
*/
i = i+ 1;

There is a third type of comment similar to the second used for creating documentation from your code. We will not discuss this type of comment.


Operators

An operator is a something that can act on one or more values to produce a new value. Operators come in different varieties: arithmetic, assignment, relational, logical, String, and the special Array indexing operator. Operators can also be classified according to how many values they act upon. Unary, binary and ternary operators act on one, two and three operands respectively. (and operand is just something that gets operated on)

And operator with its operands together form an expression, which evaluates to (returns) a value of some type. The expression 5+6, for example, evaluates to the integer 11, and can get placed anywhere 11 could be placed in the code. (except for certain issues of binding which we'll get to later - if you want it to work lke 11 eleven anywhere, you need to write it as (5+6))

The assignment operator, =, you have already seen. It just assigns the value of the expression on the right to the variable on the left and returns that value. Since it returns a value, it can be used in an expression also, so the following is valid:

int i,j;
i = (j = 5);  // first j=5 sets j to 5, then returns the value 5, which 
              // is used to set i

The binary arithmetic operators act on two numbers of the same type to produce another number of that type. They are the usual +, -, *, /, and %. % is the modulus operator, which can only operate on integers and produces the remainder when the first is divided by the second. The division operator (/) works like regular division when acting on real numbers (floats and doubles), but performs integer division when operating on integral types. This means that a / b is the greatest integer less than or equal to a divided by b. The binary arithmetic operators are infix operators, meaning they sit between their two operands. This is probably what you are used to.

The unary arithmetic operator you will be familiar with is the minus sign, which converts a number into its negative counterpart:

int i=5;
double d = -6.5;
i = -i;  // i is now -5
d = -d;  // d is now 6.5
The other unary arithmetic operators are ++ and --, which increment by one or decrement (lower) by one the value of an integral variable. After the expression they are in is evaluated, the value will be changed accordingly, but how the variable works in the expression depends on whether the ++ or -- come before or after the variable. If before, the variable is used in the expression with it's new value. If after, the variable works in the expression with its old value and is then changed after the expression is evaluated. Some examples will make this clearer:

int i = 5;
int j;
i++;         // i is now 6
j = ++i;     // j and i are now 7
j = i--;     // j is now 7, i is now 6
j = 5 + ++i; // j is now 12, i is now 7

The relational operators are used to compare values. They are <, >, <=, >=, != (not equal to), and == (equal to). They are all binary infix operators and evaluate to a boolean value. (true or false) For instance:

int i = 5, j = 5;
double a = 4.56, b = 6.78;
boolean flag;
flag = (i == j);  // flag is now true
flag = (a > b);   // flag is now false
flag = (i >= j);  // flag is now true

Note that the relational "is equal to" operator is ==, which is different from the assignment operator, =.

The logical operators perform the usual logical operations of and, or, and not, and are written &&, || and !, respectively. ! is unary and is placed before its operand. && and || are binary infix operators. They are also short-circuit operators. This means that if, after the first operand is evaluated, the expression is the same regardless of the second operand's value, the second operand is not evaluated. This is only relevant if the second operand is an expression with side effects. The three logical operators all take boolean operators and evaulate to a boolean value. See below:

boolean a = true, b = false, c;
c = a && b;   // c is now false
c = a || b;   // c is now true
c = a && !b   // c is now true
c = a || (b = true)  // c is true, but b is still false because the || is
                     // a short-circuit operator -  a was true, so the second
                     // operand, (b = true), was not evaluated. 

The String and array operators will come later when those topics are covered.



Operator Precedence

In regular math when we write, x=6+5*7, we know that x will be 41. This is because the multiplication is evaluated first, then the addition, then the assignment. Perhaps you've heard this called "order of operations". Java also has an order of operations, or precedence used in executing statements. The precedence, from higher precedence (evaluated first) to lower precedence (evaluated last) is as follows:

         postfix operators         [] . (params) expr++ expr--
         unary operators           ++expr --expr +expr -expr !
         creation or cast          new (type)expr
         multiplicative            * / %
         additive                  + -
         shift                     << >> >>>
         relational                < > <= >= instanceof
         equality                  == !=
         bitwise AND               &
         bitwise exclusive OR      ^
         bitwise inclusive OR      |
         logical AND               &&
         logical OR                ||
         conditional               ? :
         assignment                = += -= *= /= %= ^= &= |= <<= >>= >>>=

(Don't worry about the ones you haven't seen before.) Sometimes we say that operators that have higher precedence bind more tightly. You can force part of an expression to be evaluated first by using parenthesis. They work just like they do in ordinary mathematics.