Java Programming/Integer variables

From Wikiversity
Jump to navigation Jump to search

As part of this lesson, there are going to be some small programs, partly to illustrate some important aspects of programming in Java and partly to give you, the student, some opportunities to incrementally improve your understanding of the language.

Printing Integers in Java[edit | edit source]

In much the same way that you created the HelloWorld.java file in the previous lesson, create a file Integer0.java with the following contents.

public class Integer0
{
    public static void main(String[] arguments)
    {
        int i = 1;
        System.out.println("i is " + i);
    }
}

If you have been reading Introduction to Programming, then you might recognize that this statement int i = 1; creates a memory location of type "int", giving it the name i - it declares the variable i. It then goes and stores the value 1 in that location, a process known as assignment, where the single equal sign character is the Java operator telling the computer to assign the value on the right to the variable on the left.

The second statement is a variation on what was in the Hello World program from the previous lesson. System.out.println is a piece of code that causes whatever is inside the parentheses to be printed.

In the case of the Hello World program, what is inside the parentheses is a string literal. A string literal is a sequence of characters between a pair of quotation marks (""). In the program above, what you see is a string expression. The plus sign (+) is an addition operator when operands are numbers but if either operand is a string then it becomes a concatenation operator that glues the operands together into a single string. If one of the operands is not a string, then it attempts to create a string with a text representation of the given value.

Note that a string expression can be arbitrarily long. For example: "The area of the figure is " + area + " square centimeters" and "The volume of a cube with a radius of " + radius + " meters is " + volume + " cubic meters." are both valid examples of string expressions (assuming that the variables used are properly declared).

It should be reasonably obvious what the output of the program will be. Now save and compile the file (javac Integer0.java) and then run it (java Integer0). Did you get what you expected to see?

System.out.println is an important construct in Java programs for producing visible results. What would be the point of a program that ran calculations and didn't share the results?

A special note about programming exercises[edit | edit source]

In order to be able to program effectively, it is necessary to understand what a program is telling the computer to do. One source of errors in computer programs is that what the programmer thought and what he wrote is not always the same. When you look at a piece of code, ask yourself three questions:

  • What does this code actually do?
  • What did the programmer want it to do?
  • What is the program supposed to do?

Very often, the three answers will be identical. All too frequently, though, they are not.

Integer Variable Types[edit | edit source]

As was mentioned in Introduction to Programming, Java has five different sizes of integers.

Java integer types [1]
label size (bytes) smallest value largest value
byte 1 -128 127
short 2 -32768 32767
int 4 -2147483648 2147483647
long 8 -9223372036854775808 9223372036854775807
char 2 0 65535

What does it really mean, though, when we say that the largest value that can be stored in a byte is 127? Type the code shown below into a file called Integer1.java.

public class Integer1
{
    public static void main(String[] arguments)
    {
        byte i = 127;
        System.out.println("i is " + i);
        i = i + 1;

        System.out.println("i + 1 is " + i);        
    }
}

What do you expect the value of i + 1 to be? Compile and run it.

This is an example of a condition known as an overflow - where the result of a calculation exceeds the ability of the allocated memory location to be able to store it.

Now try this program. What do you think will happen?

public class Integer2
{
    public static void main(String[] arguments)
    {
        short i = 32767;
        System.out.println("i is " + i);
        i = i + 1;

        System.out.println("i + 1 is " + i);
    }
}

This just goes to show that you can't fool the computer - it knows that 32768 is too large to store in a variable of type short.

Now try the code shown below. Before you compile it, think about the statement short s = i;. We are asking the computer to take the value from a four byte int and store it in a two byte short. What is the computer going to do?

public class Integer3
{
    public static void main(String[] arguments)
    {
        int i = 32767;
        System.out.println("i is " + i);
        i = i + 1;

        short s = i;
        System.out.println("i + 1 is " + s);
    }
}

As you can see, the computer is not going to assume that you know what you are doing. In order to assign an int value to a short variable, you have to use a cast. In the corrected version of the program, shown below, the sequence (short) tells the compiler that, whatever the next value is, change it to a short.

// corrected version
public class Integer3
{
    public static void main(String[] arguments)
    {
        int i = 32767;
        System.out.println("i is " + i);
        i = i + 1;

        short s = (short) i;
        System.out.println("i + 1 is " + s);
    }
}

What are you going to get for output?

Now compile and run it. Do the results match your expectations? The lesson here is that, while you can use a cast to reassure the computer that you know what you're doing, you actually do have to know what you're doing if you want to get the results that you are expecting.

Integer Literals[edit | edit source]

While there are five types of integer variables, there are only three types of integer literals - int, long and char.

An ordinary looking integer literal such as 27 is a four byte int. What if you want to use literals bigger than 2147483647, the largest possible value for a four byte int?

To turn an integer literal into an eight byte long, all you have to do is add an upper or lower case 'L' to the end. 27 is an int, but 27l or 27L is the same value as an eight byte long. Note that, while the lower case l is allowed, it is far too easy to confuse it with the numeral 1 and so it is strongly recommended that the upper case L be used for long literals.

Sometimes, people find it useful to express literals in octal or hexadecimal.

A numeric literal with an extra leading numeral 0 is treated as an octal value. For example, the number 27, given as an octal literal, would be 033. The octal literal for 0 is 00. The largest possible positive int, in octal would be 017777777777.

A numeric literal with the leading characters 0x or 0X is treated as a hexadecimal value. The compiler ignores the case of the characters in the literal and so 0xAbc, 0Xabc and 0xABC all have the same value (2748 decimal). The hexadecimal literal for 0 is 0x0. The largest possible positive int, in hexadecimal would be 0x7fffffff

Character Literals[edit | edit source]

In Introduction to Programming, it was mentioned that some languages handle text characters as a type of integer and, as you can see from the table of Java integer types (above), Java is one of those languages.

public class Integer4
{
    public static void main(String[] arguments)
    {
        short i = 'A';
        System.out.println("i is " + i);
        i += 1;

        char a = (char) i;
        System.out.println("A + 1 is " + a);
    }
}

Think about this program before you run it. What do you think the output will be? There will be two lines of output and the second line will be the easier than the first. Now go ahead and run it.

Why 65? All text including characters and character strings in Java are represented using a system known as Unicode.

Why B and not 66? The short answer is that println knows that char is not a standard integer type and automatically converts the output to the character with the appropriate Unicode character code. Whether or not your computer can correctly display a given character may depend on the specific character, the operating system of the computer and on what fonts are installed.

  • Reading: Unicode (Wikipedia article)
  • Reference: Code Charts (directory of PDF reference documentation)

If you look at the Unicode chart for Basic Latin, you will see that the code for an upper case letter 'A' from the Latin alphabet is 0x0041 which is the hexadecimal representation of 65.

You can see that Unicode supports a tremendous variety of characters from many different languages. In theory, a properly written Java program could support a wide variety of languages.

Integer Expressions[edit | edit source]

The real power of computers is in manipulating information, not just storing it. With integers, most calculations are performed in integer expressions - a sequence of values and operators that produce integers as a final result.

The Basics[edit | edit source]

As in pretty much every programming language, Java supports the use of parentheses in expressions. As in math, operators inside parentheses are evaluated before operators outside of them. The use of parenthesis to improve the readability of expressions is strongly encouraged. Everyone who programs in Java might know the rules of precedence, but forcing folks to think through them in a complex expression is just asking for trouble.

The most commonly used operators are for the four standard operations addition, subtraction, multiplication and division - plus the assignment operator.

Multiplication is represented by a single asterisk character (*) and division by a single slash character (/). Among these five, they have the highest precedence in that they are evaluated before any addition, subtraction or assignment operators. They associate left-to-right so that in the expression a * b / c the multiplication would be evaluated first.

Addition (+) and subtraction (-) have the next highest precedence and also associates left-to-right.

Assignment (=) has the lowest precedence. Unlike the others, it associates right-to-left. The result of an assignment operation is the value being assigned - i.e. the value on the right side of the equal sign.

Type In Expressions[edit | edit source]

Consider these declarations:

    byte a = 1
    short b = 2;
    char c = 3
    int d = 4;
    long e = 5;

What would be the type of a + b? b + c? a + b + c? a + b + c + d? a + b + c + d + e?

For most numeric operators, if both operands are integer types other than long then result is always an int. If either operator is a long then the result is a long. Any value in an expression that is a smaller type than the result is first converted to the larger type in a process known as a widening conversion.

So all of the expressions above are ints except a + b + c + d + e which is a long.

Integer Division[edit | edit source]

What is the value of 1 / 2? The type of the result is int (both operands are int literals). In Java, the result of an integer division is truncated, i.e. the largest integer value that is less than or equal to the actual value. So 1 / 2 is 0.

Exercise 1[edit | edit source]

Consider the evaluation of the expression at the bottom of this code.

    int a = 1;
    int b = 2;
    int c = 4;

    a = b = a * b / c + 1;

What order are the operators evaluated in? What are the final values of the three variables?

Click here for the answer

Increment and Decrement[edit | edit source]

In computer programming, it is very common to need to add one to, or subtract one from, a variable. It is so common that the designers of the C programming language created operators that did nothing else. The character sequence ++ (two adjacent plus signs) is the increment operator and the sequence -- (two adjacent minus signs) is the decrement operator.

If you were to run this code:

    int i = 1;
    i++;
    System.out.println("i = " + i);

It would produce the output i = 2.

The increment and decrement operators are unary operators in that they only have one operand. Also, that operand must be a variable and not a literal. 2++ is an illegal construct - you can't increment the integer 2.

How does the compiler decide which variable is attached to an increment operator? Let's look at the expression i ++ j. In fact, it doesn't matter because increment operators aren't like regular operators, you can't put them between two variables because they take only one operand. To the compiler, i ++ j is no better than i j which is illegal.

Now look at the following code:

    int i = 1;
    int j = 2;
    int k = i+++j;
    
    System.out.println ("i = " + i);
    System.out.println ("j = " + j);
    System.out.println ("k = " + k);

What will it print? In order to figure that out, you have to know what the compiler is going to do with three adjacent plus signs. In this case, as it is examining i +++ j, it sees the variable i and it knows that an increment operator could go there, so it takes the first two plus signs as an increment operator and the final plus sign as an addition operator.

We still don't know what that means for this expression.

Prefix vs Postfix[edit | edit source]

It turns out that ++i (prefix increment) and i++ (postfix increment) do not have exactly the same meaning.

Within the context of a larger expression such as i +++ j, a prefix operators are executed before the statement as a whole is evaluated. Postfix operators are evaluated after the statement as a whole is evaluated. So int k = i +++ j; is the same as int k = i + j; i++;

One last detail. The value of i++ is the value of the variable i, not the variable itself, so the expression i++++, with two increment operators would be illegal.

Exercise 2[edit | edit source]

Now go back to the code above and determine what was printed.

For extra credit, change the declaration of k to be int k = i ++ + ++ j;. What does it print now?

Answer

One Final Note About Increment and Decrement[edit | edit source]

Using prefix/postfix operators, it is quite easy to implement some cute little tricks that are satisfyingly terse. In fact, many programmers take great pride in just how terse they can make their code.

This attitude is a big, fat mistake. Terse code is harder to read, harder to understand, harder to fix and more likely to contain defects. Unless you are infallibly omniscient, it is best to avoid writing any code that might be considered terse. In particular, avoid any expression involving increment/decrement operator where prefix or postfix would matter. Better yet, do not use one of these operators in any expression more complicated than the operator and the variable.

Compound Assignment Operators[edit | edit source]

It turns out to be fairly common need to operate on the value of a variable and then assign the result of the operation back to that same variable, as shown here:

    i = i + 1;
    j = j * 5;

The designers of the C language decided to create a class of operators to take care of this need. Every binary numeric operator in Java has a corresponding compound assignment operator which is a character sequence containing the operator with an equal sign appended. So the expression i += 1; is the same as i = i + 1;.

Increment and decrement are not binary operators and so they do not have a compound assignment form.

A Special Note About Type[edit | edit source]

The expression below requires a cast because the right hand operand of the assignment operator is an expression, that evaluates to int by default.

    short i = 2;
    i = i + 2;

Review of Concepts From This Lesson[edit | edit source]

  • declaration - the process of allocating a location in memory and giving it a name
  • assignment - the process of storing a value in a location in memory
  • overflow - when a computed value becomes too large to store in an intended memory location
  • string literal - A sequence of text characters contained in a pair of quotation characters ("")
  • concatenation operator - the plus sign (+) when used in a string expression
  • string expression - a string literal or two string expressions joined by a concatenation operator
  • Unicode - the universal system of character codes used by the Java Virtual Machine
  • prefix operator - the operator is evaluated before the remainder of the expression containing it
  • postfix operator - the operator is evaluated after the remainder of the expression containing it


Project: Introduction to Programming in Java
Previous: Introduction to Programming in Java/Introduction to Java — Java Programming/Integer variables — Next: Introduction to Programming in Java/Boolean Variables


References[edit | edit source]

  1. The Java Language Specification, Third Edition