Java: Assignments

To start talking about assignments we need to remember some important concepts like heap and stack. The heap is a memory section where the JVM keep its objects. A stack is a memory section which contains methods and local variables. So we can consider for now:

  • Local variables live on the stack
  • Objects and instance variables live on the heap

Assignments in Java is all about put a value into a variable using the operator =, something like x = 2. Variables are bit holders of a specific type (like int, float, Object, and so on). Values can take the form of literals or references. They are literals when we manipulate primitive types and Stings, and references when dealing with Objects. Atomic operations like x = 2 are simple, but assigning the result of an expression made of variables of multiple types can be a little bit difficult.

Examples showed on this post were built using a JDK 6.

Literals

In Java, a literal is a source code representing the data of a certain type. Literals can take form of numbers, booleans, characters or strings.

Integer/Long Literals

Integer literals can be represented as: octals (base 8), decimals (base 10), and hexadecimals (base 16). Decimal literals are currently used and there is no extra aspects to care about. Octal integers use digits from 0 to 7. We represent octal integers in Java by placing a 0 in front of the number. Without the zero we can have up to 21 digits on octal numbers. Finally, hexadecimals are formed by 16 symbols which are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f. To represent hexadecimals in Java, we need to prefix the literal by 0x. Hexadecimals can hold up to 16 digits excluding the prefix.

To write literals for a long type, the suffixes l or L are necessary.

        int two = 2;    // The literal 2 is a decimal value
        int seven = 07; // The literal 07 is an octal value
        int x = 0x007;  // The literal 0x007 is an hexadecimal
        int y = 0XCAFE; // 0XCAFE is a valid value (capital and lowercase are accepted)
        long l = 0x123l;    // An hexadecimal of type long

Floating-Point Literals

Floating-point literals are defined as numbers, decimal symbols, or fractions, for example: 123.456. By default, floating-points are defined as doubles (64 bits). To assign a floating-point literal to a float variable it is necessary to use the suffixes f or F. Otherwise, the compiler will show an error to prevent the attempt to assign a big number (double by default) into a small holder (float). Optionally, it’s possible to suffix double literals with D or d.

    double d = 123.456; // 123.345 is a floating-point literal
    double s = 12.34d;  // 12.34d is a floating-point suffixed with d
    float  f = 12.50;   // Compiler error: possible loss of precision
    float  f2 = 34.1F;  // A valid floating-point

Boolean Literals

A boolean literal can only be true or false. There is no secret, if you try to put something other than these two values, the compiler will advise you with delicacy.

    boolean TRUE = true;    // Literal true
    boolean FALSE = false;  // Literal false

Character Literals

A char literal is represented by single quotes ''. To use a Unicode value we need to prefix the Unicode notation with \u. In Java, a char type can hold 16 bits and can accommodate unsigned integers since it is smaller or equal to 65535. Finally, to use special characters escape code \ need to be employed .

    char a = 'a';           // 'a' is a literal
    char n = '\u004E';      // Unicode for the letter N
    char h = 0x8;           // Hexadecimal literal
    char o = (char) 88888;  // A cast is required when the literal is out of range
    char l = '\n';          // New line

Literals for String

Even if strings are not primitives, we can represent strings as literals.

String s = "Learning literals =]";

Casting

Casting or type casting is a mechanism by which values or object references can be converted from one type to another. Casts can be implicit or explicit. Implicit casts happen in widening conversions, when putting a small value (like an int) into a big container (like a long). Implicit casts do automatic conversions, and do not require a cast operator. In the other hand, explicit casts happen when putting bit values into small containers (like putting an int into a short). In explicit casts, a cast operator is required because the compiler need to be prevented that “we know what we are doing”. If we don’t do that, we are going to get a message like “possible lost of precision”.

        long l = 5;         // Implicit casting: int to long
        float f = 100.0F;   // Explicit cast
        short s = (short) f;    // Explicit cast

When a value is narrowed on a type casting operation, Java simply truncates the higher-order bits that won’t fit. In another words, if we cast an int (32-bit signed) into a short (16-bit signed), the 16 bits on the left will just disappear when the cast is done. You can find here more details about the capacity of Java primitive data types.

Reference variable assignments follow the same logic. We can assign a subclass of a type, but not a superclass.

class Vehicle {}

class Car extends Vehicle {}

public class CastingObjects {
    public static void main(String... args) {

        Vehicle car = new Car();    // No problem,
                                    // the Car is a Vehicle

        Car vehicle = new Vehicle();    // Compiler error :
                                        // Incompatible types
    }
}

Variable Scope

Variable scope is another important element of clear code. Variables which have a scope bigger than necessary turn code vulnerable to bugs and difficult do debug.

In Java, there are four possible scopes to variables (on ascending life time):

  • Variables in a block code live only during the execution of the block
  • Local variables live as long as their method remains on the stack
  • Instance variables are created when an instance is created and they live as long as the instance lives
  • Static variables are created when the class is loaded and they stay alive as long as the class remains in the JVM

Initialization

Instance variables (also called member variables) are initialized with default values, even if there isn’t any explicit initialization. It is a good practice to initialize all instance variables explicitly, so the code becomes clearer to other programmers 😉

Here are the default values used to initialize instance variables:

And what happens when the instance variable is an array? Well, since an array is an object it will be assigned with null. Nevertheless, when an array is explicit initialized, default values are assigned to its elements. An arrays of ints, for example, will have all its elements initialized with 0. An array of Objects will have null for its elements, and so on.

In the other hand, local variables must always be initialized. A default value is not given to local variables. Even objects and arrays need to be given a value. When you try to use a variable that has not been initialized, you will get a compiler error.

Advertisements

About Diego Lemos

Trainer, coach and polyglot programmer. Agile and software craftsmanship enthusiast.
This entry was posted in Java and tagged , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s