Variables

Variables are convenient handles for accessing memory. We don't need to mess with memory addresses:

Figure 65. Variables: Handles to memory Slide presentation

Declaring a variable requires a type name like double and an identifier:

Figure 66. Variable declaration Slide presentation
// Variable declaration:
//     Variable's type is double
//     Variable's name is «pi» (identifier)

double pi;
{type name} {variable name} ;

We may assign values to variables or build expressions like pi * 2.0 * 2.0 :

Figure 67. Declare, assign and use Slide presentation
double pi;      // Variable declaration

pi = 3.1415926; // Assigning value to variable

// Print a circle's area of radius 2.0

System.out.println(pi * 2.0 * 2.0);

Figure 68. Combining declaration and initialization Slide presentation
Separate declaration and initialization
double pi;      // Declaration of variable pi

pi = 3.1415926; // Value assignment
Combined declaration and initialization
double pi = 3.1415926;

Figure 69. Multiple variables of same type Slide presentation
int a;
int b = 22;
int c;

being equivalent to either of:

Compact Multiple lines
int a, b = 22, c;  
int a,
    b = 22,  
    c;

Figure 70. Identifier in Java: Slide presentation
  • Variable names.

  • Class names

  • Method names, e.g.:

    public static void main(String [] args)


Figure 71. Identifier name examples: Slide presentation
Rules Legal Illegal
  • Start with a letter, _ or $, but not just a single _

  • May be followed by letters, digits, _ or $

  • Must not match:

  • $test

  • _$

  • count

  • blue

  • 2sad

  • _

  • switch

  • true


Figure 72. Java keywords. Slide presentation
abstract     continue      for          new          switch
assert       default       if           package      synchronized
boolean      do            goto         private      this
break        double        implements   protected    throw
byte         else          import       public       throws
case         enum          instanceof   return       transient
catch        extends       int          short        try
char         final         interface    static       void
class        finally       long         strictfp     volatile
const        float         native       super        while

Figure 73. Variable naming conventions Slide presentation
  • Start with a small letter like africa rather than Africa.

  • Use camel case e.g. myFirstCode.

    Variable naming conventions
  • Do not start with _ or $.


Figure 74. Constant variables Slide presentation

Modifier final prohibits changes:

final double PI = 3.1415926;
...
PI = 1.0; // Compile time error: Constant cannot be modified

Note

final variables by convention are being capitalized


Figure 75. Case sensitivity Slide presentation

Variable names are case sensitive:

int count = 32;
int Count = 44;
System.out.println(count + ":" + Count);

Resulting output:

32:44

exercise No. 12

Legal variable names

Q:

Which of the following names are legal variable names? If so, would you actually use them in your code?

Complete the following table and explain your decision with respect to the Language Fundamentals / variables section of [Kurniawan] .

Identifier Legal? (yes / no) Explanation / remark
for
sum_of_data
sumOfData
first-name
ABC
42isThesolution
println
B4
AnnualSalary
"hello"
_average
ανδρος
$sum

Tip

You may want to prepare a simple Java program testing the above names.

A:

Consider:

public static void main(String[] args) {
   int 42isThesolution = 6; // Syntax error on token "42", delete this token
}

Unfortunately this message does not explain the underlying cause: It does not hint towards an illegal identifier name.

One indication of a sound compiler implementation is its ability to provide meaningful, self explanatory error messages.

Identifier Legal? (yes / no) Explanation / remark
for no for is a Java keyword.
sum_of_data yes -
sumOfData yes -
first-name no Operators like - or + must not appear in variable names.
ABC yes Discouraged by «Best practices» if non-constant (final): Non-constant variables should start with lowercase letters.
42isThesolution no Identifiers must not start with a number.
println yes println is a method's name but is no Java keyword.
B4 yes See «ABC» above.
AnnualSalary yes See «ABC» above.
"hello" no String delimiters must not be part of an identifier.
_average yes Discouraged by «Best practices»: Identifier starting with «_» should be reserved for system code.
ανδρος yes Perfectly legal Greek Unicode characters.
$sum yes Discouraged by «Best practices»: Identifier starting with «$» should be reserved for system code.
Figure 76. Define before use Slide presentation
Correct:
double f;
f = -4.55;
Wrong:
f = -4.55;
double f;

Figure 77. Type safety Slide presentation
int i = 2;
int j = i;   // o.K.: Assigning int to int
long l = i;  // o.K.: Widening conversion

i = l;       // Wrong: Narrowing

boolean b = true;
i = b;       // Error: int and boolean are incompatible types
i = 4.3345   // Error: Cannot assign double to int
i = "Hello"; // Even worse: Assigning a String to an int

Figure 78. Compile time analysis Slide presentation
byte b127 = 127; // o.K., static check
byte b128 = 128; // Wrong: Exceeding 127

Performing static range check

int a = 120;

byte b120 = a; // Error Incompatible types
               // Required: byte
               // Found:int

No static check on int variable's value


exercise No. 13

Benefits of final

Q:

We reconsider our code from Figure 78, “Compile time analysis ”:

int a = 120;

byte b120 = a; // Error Incompatible types
               // Required: byte
               // Found:int

Adding final solves the issue:

final int a = 120;

byte b120 = a;  // o.K.

Why does introducing a final modifier solves the fatal compile time error issue?

Tip

Read Static program analysis. Why does final help the compiler in code analysis?

A:

Modifying variable a to become final assures its initial value will never change. Thus from a Data-flow analysis point of view the two snippets are equivalent:

final int a = 120;

byte b120 = a;
byte b120 = 120;

Thus the compiler is able to perform a compile time range check assuring the value of 120 to be within the interval [-128, 127].

Figure 79. Forcing conversions Slide presentation
long l = 4345;

int i = (int) l; // Casting long to int
System.out.println("i carrying long: " + i);

double d = 44.2323;
i = (int) d; // Casting double to int
System.out.println("i carrying double: " + i);
i carrying long: 4345
i carrying double: 44

Figure 80. Watch out! Slide presentation
long l = 3000000000000000L;
int i = (int) l;
System.out.println("i carrying long:" + i);

double d = 44300000000000.0;
i = (int) d;
System.out.println("i carrying double:" + i);
i carrying long:-296517632
i carrying double:2147483647

Figure 81. Casting long to int Slide presentation

Figure 82. Don't worry, be happy ... Slide presentation

«C» programming language miracles:

#include <stdio.h>

void main(void) {
  double measure = 65234.5435;
  short velocity;
  velocity = measure;
  printf("Velocity=%d\n", velocity);
}

Uups:

Velocity=-302

Figure 83. ... and watch the outcome Slide presentation
... and watch the outcome
Development costs:

~$7 billion.

Rocket and cargo

~$500 million.

related video and explanations


Figure 84. From the report Slide presentation

The cause of the failure was a software error in the inertial reference system.

Specifically, a 64 bit floating point number relating to the horizontal velocity of the rocket with respect to the platform was converted to a 16 bit signed integer.

The number was larger than 32,767, the largest integer possible in a 16 bit signed integer, and thus the conversion failed.

Related video explanation


exercise No. 14

«C» vs. Java.

Q:

We reconsider the «C» code example from Figure 82, “Don't worry, be happy ... ”:

#include <stdio.h>

void main(void) {
  double measure = 65234.5435;
  short velocity;
  velocity = measure;
  printf("Velocity=%d\n", velocity);
}

Rewrite the same code in Java. You will encounter a problem.

A:

Naively rewriting the snippet in Java yields a compile time error:

double measure = 65234.5435;
short velocity;
velocity = measure; // Error: Incompatible types. Required: short, Found: double

A type cast is being required:

double measure = 65234.5435;
short velocity;
velocity = (short) measure; // Explicit double to short conversion

Note

This allows for compilation by resolving the syntax error. However the possible overflow problem i.e. converting a double value of 65234.5435 into a short value of -302 still persists.

exercise No. 15

Assignment and type safety

Q:

We consider:

int i = -21;
double d = i;

This snippet shows correct Java code. However Figure 77, “Type safety ” suggests we should not be allowed to assign an int to a double value due to type safety.

Even worse: Swapping types yields a compile time error:

double d = 2.4;
int i = d; // Error: Incompatible types

Questions to answer:

  1. Explain on syntax level why is d = i is allowed but i = d causes an error? Hint: Read about widening and narrowing conventions.

  2. Whats the ratio behind this design decision? Hint: What would happen for larger double values?

A:

  1. The first code snippet uses the widening conversion: When assigning d = i the Java compiler implicitly converts a four byte int into an eight byte double value.

    In contrast there is no automated narrowing from double to int hence causing a compile time error.

  2. Turning a double into an int is more cumbersome: The expression e.g. i = 3.5 could be evaluated by agreeing on a specific rounding prescription. But what about e.g. i = 3457357385783573478955345.45 ? A Java int's maximum value is 2 31 - 1 unable to accommodate the double value in question by far.

    Conclusion: Java disallows double to int assignments unless using a so called cast (explicit type conversion):

Caveats using explicit casts:

  1. double d = 2.6;
    int i = (int) d; // Explicit cast double to int
    System.out.println("Result: " + i);
    Result: 2

    Notice the result of 2 rather than 3 as you might have expected assuming common rounding convention rules. Rounding does not happen unless you explicitly use methods like e.g. Math.round().

  2. double d = 3_000_000_000.;
    int i = (int) d; // Explicit cast double to int
    System.out.println("Result: " + i);
    Result: 2147483647

    This truncation of 3 billion to 2147483647 is due to the latter value being the largest possible int value to be represented in Java.

Java provides meta information on types:

Figure 85. Maximum and minimum values Slide presentation

exercise No. 16

Inventing tinyint.

Q:

Suppose Java was offering a hypothetic signed integer type tinyint using 3-bit 2-complement representation.

  1. Write down all possible decimal values among with their corresponding binary representation.

  2. Perform the following additions on binary level:

    • 1 + 2

    • -4 + 2

    • -1 - 2

    • 3 + 1

    Hint by example: -4 + 3 is:

     1   100
     2  +011
    --  ----
     ?   111  

    What is 3-bit two complement 111 in decimal?

A:

  1. Given n=3 in three bit two complement notation as usual possible values range from - 2 ( 3 - 1 ) to 2 ( 3 - 1 ) - 1 :

    Decimal Two-complement
    3 011
    2 010
    1 001
    0 000
    -1 111
    -2 110
    -3 101
    -4 100

    Thus the example hint value 111 is indeed decimal -1 equalling -4 + 3 as expected.

  2. 1 + 2
     1   001
     2  +010
    --  ----
     3   011
    -4 + 2
    -4   100
     2  +010
    --  ----
    -2   110
    -1 - 2
    -1     111
    -2    +110
    --  ------
    -3    1101 (See comment below)

    In 3-bit two complement representation the leftmost bit at position 4 will be discarded. The actual result is thus 101 as expected.

    3 + 1
     3   011
     1  +001
    --  ----
    -4   100 Surprise! See comment below

    This is actually an overflow: In 3-bit two complement representation the highest representable decimal value is 3 being equal to 2 3 - 1 - 1 . Trying to add a value of 1 leads to disaster and in suitable circumstances may cause a US$370 spacecraft plummeting from the sky! Excerpt from the Ariane 5 flight 501 failure report:

    The internal SRI software exception was caused during execution of a data conversion from 64-bit floating point to 16-bit signed integer value. The floating point number which was converted had a value greater than what could be represented by a 16-bit signed integer.

exercise No. 17

An int's minimum and maximum value

Q:

In this exercise we look at an int's the largest and smallest (negative) possible value.

A Java int is internally being represented by 4 bytes. 00000000_00000000_00000000_00000101 2 for example represents the decimal value 5.

Java implements negative values using Two's complement representation. We provide some values:

Table 1. 4 Byte Two's complement representation of int values.
Two complement representation Decimal representation
00000000_00000000_00000000_00000000 0
01111111_11111111_11111111_11111111 2 32 - 1 - 1 (Maximum)
10000000_00000000_00000000_00000000 - 2 32 - 1 (Minimum)
11111111_11111111_11111111_11111111 -1

Use int literals in binary representation like e.g. 0B1100 in the Language Fundamentals / Literals section of [Kurniawan] in order to write an int's minimum and maximum possible value to standard output.

public static void main(String[] args) {

  int minumum = ... , //TODO: provide values by
  maximum = ...;  // binary int literals

  System.out.println("Minimum:" + minumum);
  System.out.println("Maximum:" + maximum);
}

A:

We insert Two's complement representations of minimum and maximum int values according to Table 1, “4 Byte Two's complement representation of int values.”.

public static void main(String[] args) {

  int minumum = 0B10000000_00000000_00000000_00000000,
      maximum = 0B01111111_11111111_11111111_11111111;

  System.out.println("Minimum int value:" + minumum);
  System.out.println("Maximum int value:" + maximum);
}

BTW: The JDK does provide maximum value, minimum value and related information for char, byte, short and int primitive data types within their corresponding Character, Byte, Short and Integer classes. You may want to execute:

System.out.println("int minimum:" + Integer.MIN_VALUE);
System.out.println("int maximum:" + Integer.MAX_VALUE);

System.out.println("int bytes:" + Integer.BYTES);
System.out.println("int size:" + Integer.SIZE);
Figure 86. Dynamic typing in PERL Slide presentation
$test = 44;  # Assigning an int
print $test, "\n";

$test = "Jim"; # Assigning a string
print $test, "\n";

$cmp = 43.55; # A float

if ($test == $cmp) { # comparing string against float
   print "Equal\n";
} else {
   print "Different\n";
}
44
Jim
Different

Figure 87. Dynamic typing in PERL, part 2 Slide presentation
$a = 2; # An integer
$b = 3; # Another integer

print '$a + $b = ', $a + $b, "\n";

$jim = "Jim";         # A string
print '$jim + $a = ' , $jim + $a, "\n";
$a + $b = 5
$jim + $a = 2

Figure 88. Using final Slide presentation
//Bad!
double pi = 3.141592653589793;
...
pi = -4; // Woops, accidential and erroneous redefinition
//Good
final double PI = 3.141592653589793;
...
PI = -4; // Compile time error:
         // Cannot assign a value to final variable 'pi'

Figure 89. Two categories of variables Slide presentation
Primitive type
int a = -15;

Possible types: All eight primitive Java types.

Reference type (based on classes)
GpsPosition start = new GpsPosition(48.7758, 9.1829);

Possible types: Arbitrary built-in or user defined classes.


Figure 90. Reference type examples Slide presentation
GpsPosition start = new GpsPosition(48.7758, 9.1829);
String name = "Simon";
LocalDate birtday = LocalDate.of(1990, Month.JULY, 5);