Java: Generic Types

Before Java 5, it was not possible to tell to a collection (like a List, a Map or a Set) only to accept objects of a specific type. At that moment, collections could hold anything that was not a primitive type (which are boxed when added into collections). For that reason, applications before Java 5 were “less type safe” and more prone do errors when manipulating collections. Here we have an example (examples on this post were built using a JDK 6):

        List list = new ArrayList();

        // We can add whatever we want...
        list.add("string");
        list.add(1);
        list.add(4.0);
        list.add(new Object());

This approach can be a little bit dangerous, particularly when working with external APIs. Suppose that in your code you call a method of an external class which manipulates lists of Strings and gets a List as parameter. For any reason, you put an Integer inside your List and you pass it to the method. Inside the method, a cast is required to get each element of the list and assign them to a variable, like String value = (String) list.get(0). Since you can have no access to the foreign code, you can inadvertently get a RuntimeException when the method will try to cast the Integer element into a String O_o

Java 5 introduced Generics. With generics now, we can guarantee which object type a collection will hold. If we mark a collection with a certain type and we try to add to it an object of a different type, we get a compiler error. The type validation is taken in charge by the compiler. Generics are not present inside the bytecode, so they are not used on runtime.

Activating generics is simple! Just add a type inside angle brackets <> immediately following the collection. This needs to be done in the variable declaration and in the constructor call. Finally, generics can also be used as type parameters and return types for methods.

import java.util.ArrayList;
import java.util.List;

public class GenericTypes {
    public static void main(String... args) {
        GenericTypes gt = new GenericTypes();

        // We define a list of Strings
        List<String> people = gt.getArrayList();

        people.add("Alice");
        people.add("Bob");

        gt.printList(people);
    }

    void printList(List<String> list) {
        // Now casts are not necessary
        for(String name : list) {
            System.out.println(name);
        }
    }

    List<String> getArrayList() {
        return new ArrayList<String>();
    }
}

Legacy code

As said before, generic types are not present on runtime. The verification for type compliance is made by the compiler. Once the code is compiled, collections post and pre-Java 5 are the same thing. The reason is simple: Sun did not want to broke all code produced before Java 5, so the type verification does not exist in runtime. By doing this, legacy and post-Java 5 code can cohabit.

import java.util.ArrayList;
import java.util.List;

public class LegacyExample {
    public static void main(String... args) {
        List<String> list = new ArrayList<String>();
        list.add("1");
        list.add("2");

        LegacyExample le = new LegacyExample();
        le.addObject(list);
    }

    void addObject(/*Parameters here are non-type safe*/ List list) {
        list.add(1);
    }
}

The code above compiles and runs without errors. Even if the object added to list inside the addObject method is different from the type hold by the list, it works. This happens because type-safe protection does NOT exist at runtime. Nevertheless, the compiler will notice that something weird can happen and advert you with warnings:

$ javac LegacyExample.java
Note: LegacyExample.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

As show in the message, it is possible to identify which method is causing problems. For that, just recompile with -Xlint:unchecked option.

$ javac -Xlint:unchecked LegacyExample.java
LegacyExample.java:18: warning: [unchecked] unchecked call to add(E) as a member of the raw type java.util.List
        list.add(1);
                ^
1 warning

So, at this point you may have a question. If it is not possible to have type-safe protection at runtime like arrays, what are the gains in using generics? Mainly, there are two main advantages:

  • Type-safe verification at compile time
  • No need to cast objects when you get something out

Generics and Polymorphism

It is important to remark that there is a couple of differences between arrays and generic collections. Let’s see some examples:

import java.util.ArrayList;
import java.util.List;

class Professional{}
class Engineer extends Professional {}

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

        Professional[] professionals = new Engineer[5]; // This works fine
        List<Professional> professionalList =
                new ArrayList<? extends Professional>(); // But this does not compile

    }
}

Generic types do not support natural polymorphism. The reason is simple. Imagine that we have a method receiving List<Professional> list as parameter. So, we could perfectly pass an ArrayList<Engineer> list to that method. Ok. The problem is, by doing this, we allow the code inside the method to add to the list any object that passes an IS-A test with Professional that is not an Engineer. In the end, there is no guarantee that the collection of engineers given to the method in the past still holds only engineers and this can be dangerous :S

However, it is possible to add some Engineers into a collection of Professionals without problems.

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

        List<Professional> professionalList =
                new ArrayList<Professional>();  // No problem here

        professionalList.add(new Engineer());   // This is allowed

        addElements(professionalList);          // Everything is fine
    }

    static void addElements(List<Professional> list) {
        list.add(new Engineer());
    }
}

To solve the problem of manipulating sub and super types of generic collections Java brings a mechanism called “wildcards” <?>. By using the type List<? extends Professional> as a method parameter, we can pass any list to the method since its generic type passes an IS-A test for Professional. The only restriction is, when using something like List<? extends Professional> (or even simply List<?>), it is not possible to insert any object into the list. Otherwise, a compiler error will occur.

import java.util.ArrayList;
import java.util.List;

public class Wildcard {

    public static void main(String... args) {
        List<Engineer> engineers = new ArrayList<Engineer>();
        addElement(engineers);
    }

    static void addElement(List<? extends Professional> list) {
        list.add(new Engineer());   // This line does not compile
    }
}

In the example above, if we delete the instruction list.add(new Engineer()) the code compiles and runs fine.

On the other hand, it is possible to deal with the insert restriction imposed by the keyword extends used with the wildcard ?. By using the keyword super, it is possible to add elements into a collection received as parameter.

public class Wildcard2 {
    public static void main(String... args) {
        List<Professional> list = new ArrayList<Professional>();
        addElements(list);
    }

    static void addElements(List<? super Engineer> list) {
        list.add(new Engineer());   // this line compiles fine
    }
}

When the keyword super is used, Engineers and any supertype of Engineer – like Professional and obviously Object – will be accepted. Maybe this will not shock you, since upcasts are natural in Java (like putting a String into an Object).

Summarizing, List<?> and List<? extends Object> are the same thing. Nevertheless, neither of them are the same as List<Object>, because the later one will leave you add elements inside. Wildcards are employed only for reference declarations like arguments, return types and variables. They cannot be used as generic type to create new typed collections.

Parameterized Types

It is possible to use generic types to create “template classes” which can manipulate safely objects of any type. In this case, generic types are used as instance variables giving a class the chance to manipulate objects generically.

Following an example.

class Test<T> {
    T t;

    public Test(T t) {
        this.t = t;
    }

    public T getT() {
        return t;
    }
}

public class GenericTypeExample {
    public static void main(String... args) {
        Test<String> test = new Test<String>(<Generics>);
        System.out.print(test.getT());  // will print Generics
    }
}

In the example above, T is a placeholder used to designate a parameter type for a class. We could have used anything else, but T is a convention for class parameter types. The placeholder E, for example, designate “Element” and is used when the template is a collection (see List for example). Wildcard notation can be used in many ways to combine types and create templates.

class Converter<T, Y> {}
class Calculator<T extends Number> {}

public class GenericTypeExample2 {
    Converter<Integer, Long> converter = new Converter<Integer, Long>();
    Calculator<Integer> calculator = new Calculator<Integer>();
}

However, it is also possible to use parameterized types to ensure type safety only in methods. This is used when only the method needs to be aware of the generic type, not the whole class.

Let’s suppose we need a generic method to create a parameterized Map for cache purposes.

import java.util.HashMap;
import java.util.Map;

class Cache {
    static <K, V>  Map<K,V> getCache() {
        return new HashMap<K, V>();
    }
}

public class CacheTest {
    public static void main(String... args) {
        Map<Integer, String> cache = Cache.<Integer,String>getCache();
        cache.put(1, "test1");
        cache.put(2, "test2");
    }
}

In this example, K is replaced by Integer and V by String. In generic methods, it is necessary to declare the parameterized types before using them: static <K, V> Map<K,V> getCache(). We must do this to define what K and V are before using them as parameters or return type. If the type is defined in the class, it is not necessary to re-declare in the method. The same thing could be done using boundaries: static <K, V extends Object> Map<K,V> getCache().

Posted in Java | Tagged , | Leave a comment

Java: Operators

As in mathematics, operators in Java are used to produce new values from operands. Choosing the right operator on the right time will help you to write clear code in a fast way.

Following a quick review of Java operators.

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

Assignment Operators

The most commun assignment operator is the = operator. This operator simply assign values to variables. Nevertheless, the = operator can be composed with other operators like +-*/, >>, <<, & and | forming the compound operators: +=-=*=, /=, >>=, <<=, &= and |=.

        int i = 0;
        int j = 0;

        i += 2;         // Which is the same that i = i + 2;
        j *= 10 + 4;    // Which is the same that j = j * (10 + 4)

Relational Operators

Relational operators are often used on if tests and result in a boolean value (true or false). Java has six relational operators which are: >>=<<=, ==, and !=. All of them can perform comparisons on integers, floating-points or characters. Only the last two (== and !=) are used to perform comaprisons on boolean values, or object reference variables.

        char sex = 'f';

        if(sex
        Relational r1 = new Relational();
        Relational r2 = new Relational();

        if(r1 == r2) {} // false

        r1 = r2;        // now they hold the same reference

        if(r1 == r2) {} // true

instanceof Operator

The instanceof operator verifies if an object is of a particular type. To evaluate the type of the object (on the left), the operator uses a IS-A test for a class or interface (on the right). The IS-A test returns true if the object inherits from the class or implements the interface used on the test. Otherwise, the result is false.

class A {}
class B extends A {}

public class InstanceOf {
    public static void main(String... args) {
        A a = new B();
        B b;

        if(a instanceof B) {    // the IS-A test passes
            b = (B)a;   // we can then downcast
        }
    }
}

Arithmetic Operators

Beyond the basic arithmetic operators +-*, and /, there are three other operators also widely used which are:

  • the Remainder operator (%);
  • the String Concatenation operator (+);
  • the Increment and Decrement operators (++ and --, respectively).

The remainder operator % returns the remainder of a division operation.

        int x = 10;
        int y = 4;

        int rem = x % y;    // which will be 2

Observation: expressions are evaluated from left to right. The operators */, and % have higher priority then + and - operators. Parentheses can be used to change the evaluation order.

The operator + can act as addition operator or string concatenation operator, which depends on the operands. If there is a string among the operands, the + becomes a string concatenation operator. If the operands are numbers, the + will perform the addition.

        int i = 5;
        int j = 5;

        System.out.println("String" + i);   // will print String5

        System.out.println("String" + (i + j)); // will print String10
                                                // because the parentheses

Finally, the increment and decrement operators will increment or decrement variables by one. The operator can prefix or postfix the operand. When the prefix approach is used, the operator is placed before the variable, and the operation is performed before the variable is used. When the postfix approach is employed, the operator is placed after the variable, and the increment or decrement operation takes place after the variable is used.

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

        int i = 0;

        if(++i == 1) {
            System.out.println("++i is performed before the test");
        }

        System.out.println("i = " + i--); // output : i = 1

    }
}

Conditional Operators

The ternary conditional operator will decide which value to assign or return after evaluating a boolean expression. Here is the structure of the conditional operator:

   (boolean expression) ? value if true : value if false

The first value is assigned or returned if the result of the expression is true. Otherwise, the second value is used. The parentheses are optionals and it is possible to nest conditional operators.


public class ConditionalTest {
    public static void main(String... args) {
        int i = 4;
        int j = 5;

        String result = ++i == 4 ? "i=4" :
                (i + j++ > 10) ? "i+j>10" : "i+j    }
}

Logical Operators

Logical operators in Java basically evaluate an expression and return a boolean value.

Short-Circuit Logical Operators

Short-circuit operators evaluate boolean expressions and return boolean values. Short-circuit operators are represented as follow:

  • || short-circuit OR
  • && short-circuit AND

A short-circuit AND (&&) will evaluate the left side of an expression first. If the result is false, the operator will not waste time evaluating the right side and will return false. The right side will be evaluated only if the result of the left side is true. If the result of both sides is true, the hole expression is evaluated as true. If one of them results false, the expression is evaluated as false.

As the short-circuit AND, the short-circuit OR (||) will start evaluating the left side of the expression. Nevertheless, if the result is true the right side will not be analysed and the result of the whole expression will be true. The right side will be evaluated only if the result of the expression on left side  is false. So, if there is one true, the global result is true. If both sides are false, the final result is false.

public class ShortCircuitLogicalOperator {
    public static void main(String... args) {
        if(check(9) && check(11)) {
            System.out.println("First IF");
        }

        if(false || check(13)) {
            System.out.println("Second IF");
        }
    }

    private static boolean check(int value) {
        if(value % 2 < 2) {
            return true;
        }

        return false;
    }
}

The output of the code above is:

First IF
Second IF

Not Short-Circuit Logical Operators

Not short-circuit operators are represented as follows:

  • | non-short-circuit OR
  • & non-short-circuit AND

As not short-circuit operators will evaluate logical expressions like the operators && and ||. On the other hand, not short-circuit operators will evaluated ALWAYS both sides of the expression. Non-short-circuit OR (|) will return false if both sides of the logical expression are false. It returns true if one side is true. Non-short-circuit AND (&) returns true only if both sides are evaluated as true. Otherwise, it returns false.

public class NotShortCircuitLogicalOperator {
    public static void main(String... args) {
        int i = 0;

        if((i++ < 1 & ++i > 1) | i == 2) {
            System.out.println("Little puzzle");
        }
    }
}

Boolean Invert Logical Operator

The unary boolean invert (!) operator evaluates only boolean expression and returns its opposite value. So, if the result is true, it gets false and vice-versa.

Exclusive-OR (XOR) Logical Operator

The exclusive-OR (^) operator also used with boolean expressions and it evaluates BOTH sides of an expression. For an exclusive-OR (^) expression be true, EXACTLY one operand must be true.

public class ExclusiveOR {

    public static void main(String... args) {
        byte size1 = -127;
        byte size2 = 127;

        if(checkSize(size1) ^ checkSize(size2)) {
            System.out.println("There is a size that passes the" +
                    " check AND a size that does not match. ");
        }
    }

    private static boolean checkSize(byte i) {
        if(i < 127) {
            return true;
        }

        return false;
    }
}

Bitwise Operators

Bitwise operators are operators that evaluate the bit value of each operand. They are used in expressions with integer values. If the operand is smaller than int, the primitive value will be converted to an int.

Following a list with the bitwise operators in Java.

  • ~ unary bitwise complement
  • & bitwise AND
  • | bitwise OR
  • ^ bitwise XOR
  • Shift operators: <<, >>, and >>>

The unary bitwise complement simply invert the bit value. The bitwise operators AND, OR and XOR evaluate bits using simple logic. The shift operator << shifts bits of to left putting zeros on the right side (low order position). The shift operator >> shifts bits to the right side saving the number sign. In other words, a negative number remains negative after the operation. Finally, the shift operator >>> move bits to right without saving the number sign. In this case, zeros are inserted as most significant bits (on the left). All the operators can be also used with the assignment (=) operator.

Bitwise operators are generally used to pack a lot of information into a single variable, like masks, flags, etc.

public class BitwiseOperators {
    public static void main(String... args) {
        short i = 127;
        long j = 0;
        byte k = 85; // binary: 0101 0101
        int l = 99; // binary: 0000 0000 0000 0000 0000 0000 0110 0011
        int m = -99; // binary: 1111 1111 1111 1111 1111 1111 1001 1101

        System.out.println("~i  = " + ~i);
        System.out.println("i&j = " + (i&j));
        System.out.println("i|j = " + (i|j));
        System.out.println("i^j = " + (i^k));

        j |= i;

        System.out.println("j (after j |= i) = " + j);

        System.out.println("m>>4 = " + (m>>4)); // binary: 1111 1111 1111 1111 1111 1111 1111 1001
        System.out.println("m>>>12 = " + (m>>>12)); // binary: 0000 0000 0000 1111 1111 1111 1111 1111
    }
}

The output of the code above will be:

~i  = -128
i&j = 0
i|j = 127
i^j = 42
j (after j |= i) = 127
m>>4 = -7
m>>>2 = 1048575

Observation: Java uses two’s-complement mechanism to sign integral types. More on this here.

Posted in Java | Tagged , | Leave a comment

Java: Garbage Collector

Garbage collection is one of the big advantages of Java. Many languages like C and C++ do not offer an automatic mechanism to perform memory management. Manually releasing every object which is not used anymore could become a fastidious and really difficult task. When memory is not correctly managed, objects can stay allocated indefinitely, making applications consume more memory than what they actually need.  This can lead to performance issues and eventually crash your application. Such problem is known as memory leak.

The garbage collector (GC) removes from the heap (memory area where Java objects live) objects which were discarded or deleted. It is the JVM that decides when to run the garbage collector. Throughout a Java program, it’s possible to ask the JVM to run the garbage collector using System.gc(). Nevertheless, there are no guarantees that the request will be attended. So, it’s never a good practice to design an application relying on the execution of the garbage collection.

In Java, objects are allocated on the heap space. The mission of the garbage collector is to make sure that the heap has as much free space as possible. It ensures that the available memory will be managed efficiently, but it cannot ensure that there is enough space.

It is important to identify when an object is eligible for garbage collection. In Java, an object is eligible for deletion when it cannot be accessed by any live thread. In other words, if all the references to an object cannot be reached by a live thread the object is marked for collection. Obviously, if there are no reachable references to an object, we don’t care about that object anymore.

There are basically three ways to mark an object for garbage collection:

  • Nullifying a reference
  • Reassigning another value to the reference
  • Isolating a reference
public class GC {
    GC gc;

    public static void main(String... args) {
        // Nulling the object
        StringBuilder nulling = new StringBuilder("nulling");
        nulling = null;  // nulling is now eligible for gargabe collection

        // Reassigning a new value to the object
        StringBuilder first = new StringBuilder("first string");
        StringBuilder second = new StringBuilder("second string");

        first = second; // now second is marked to be collected

        // Isolated island
        GC gc1 = new GC();
        GC gc2 = new GC();
        GC gc3 = new GC();

        // creating a circular reference
        gc1.gc = gc2;
        gc2.gc = gc3;
        gc3.gc = gc1;

        // now there is an island that cannot be reached
        gc1 = gc2 = gc3 = null;
    }
}

Finally, it is also possible to execute some operations just before an object is deleted by the garbage collector. To do that we need to override the method finalize() inherited from class Object. But be careful, as we have no guarantee about when GC will run, the code inside the method finalize() can wait a very long time to be executed. For that reason, it is not recommended use the finalize() method to release resources allocated by the object. Use an explicit method call for that instead.

Posted in Java | Tagged , | Leave a comment

Java: Passing Variables into Methods

Java use pass-by-value semantics, instead of pass-by-reference, when passing variables to methods. This means that Java copies the variable values used by the caller to pass them to the method. If the variable has a primitive type, the value of the variable is passed. So, if the method does change the value received as argument, the variable value on the caller will not change. Otherwise, when the argument is an object, since Java copies the variable values and in this case the value is a reference (the address of the object on the heap), operations made on the object will take effect on the caller.

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

Wrappers

Wrappers are Java objects which encapsulate primitive types. Wrappers have two main purposes:

  • Provide utility functions for primitive types
  • Allow primitive types to be used where only objects are accepted

Every primitive type has a wrapper class associated.

Since Java 5, we can use a feature called autoboxing to perform conversions between primitive types and wrappers automatically. The autoboxing feature allow us to assign wrappers to primitive types and vice-versa without the necessity of calling wrapper methods to unwrap and re-wrap. These operations are usually called boxing and unboxing.

public class Wrappers {

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

        // Before Java 5
        Integer i = new Integer(5); // create
        int x = i.intValue();       // unwrap
        x += 10;                    // use
        i = new Integer(x);         // re-wrap

        // After Java 5
        Integer j = new Integer(5); // create
        j += 10;                    // use
    }
}

Observation: two autoboxed instances of Boolean, Byte, Character from \u000 to \u007f (7f is 127 in decimal), Short and Integer (from -128 to 127) always pass a == test when their primitive values are the same. More about this can be found here.

Pop quiz: what is the output of the code below?

public class PopQuiz {
    public static void main(String... args) {
        Integer i1 = 1000;
        Integer i2 = 1000;

        if(i1 != i2) {
            System.out.print("1 ");
        }

        if(i1.equals(i2)) {
            System.out.print("2 ");
        }

        Integer i3 = 10;
        Integer i4 = 10;

        if(i3 == i4) {
            System.out.print("3 ");
        }

        if(i3.equals(i4)) {
            System.out.print("4");
        }
    }
}

Overloading

Overloading methods in Java can be a little bit difficult when many methods are eligible to match to a certain call. When this kind of situation happens, the Java compiler uses the following order of factors to determine which method will be invoked:

  • Widening
  • Autoboxing
  • Var-args

When there is a dispute widening is the winner over autoboxing and var-args. When there is a dispute between autoboxing and var-args, autoboxing wins.

public class Overloading {

    static void doSomething(long x) {
        System.out.println("long");
    }

    static void doSomething(Integer i) {
        System.out.println("Integer");
    }

    static void doSomething(Integer i, Integer j) {
        System.out.println("Integer Integer");
    }

    static void doSomething(int... ints) {
        System.out.println("ints...");
    }

    public static void main(String[] args) {
        int i = 10;
        int j = 20;

        doSomething(i);
        doSomething(i, j);
    }
}

In the example above, we first call the method doSomething passing an int as argument. As we have a widening and an autoboxing as options, widening wins and the argument is casted from int to long. In the second call, compilers need to decide between autoboxing and var-arg. Since the first one has higher priority, autoboxing will be used. The result of the execution of the code above is:

long
Integer Integer

Widening reference variables is also possible in Java. In this case, widening depends on inheritance and the IS-A test is used to perform the operation. The code below compiles normally.

class Vehicle {}

class Car extends Vehicle {}

public class OverloadingReferences {

    static void doSomething(Vehicle vehicle) {}

    public static void main(String[] args) {
        Car car = new Car();
        doSomething(car);
    }
}

Observation: type castings using references are called upcast when the object is casted to one of the classes or interfaces it inherits or implements, respectively. When the cast is made in the opposite direction (towards a more specific object) it is called downcast.

Posted in Java | Tagged , , , | Leave a comment

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.

Posted in Java | Tagged , , , | Leave a comment

Java: Object Orientation

From University, we know that object-oriented programming (OOP) is a programming paradigm which uses objects to design applications. When correctly used, principles of OOP like Encapsulation, Inheritance, Polymorphism, and Overriding/Overloading help developers to design flexible, extensible, and maintainable applications. When not used correctly, maintainability becomes expensive and flexibility compromised.

Nowadays OPP seems to be a basic subject, something everyone should know. But looking around and working on many projects, I have found that this is not completely true. There are uncountable applications which make a poor usage of OOP. In this sense, this article brings a quick review of OOP principles and best practices. The objective here is not to detail each aspect of OOP, but to present the main principles, advantages of good usage and some examples. These are the bases to advanced refactoring.

Encapsulation

Basically, encapsulation is used to allow programmers to make code changes without breaking another code. Encapsulation consists in not exposing implementation details of a class. But how to do that?

  • Creating public methods to access class’ instance variables
  • Protecting instance variables from exposure setting them private
  • Using JavaBeans convention

Here is an example that does not use Encapsulation:

package net.diegolemos.oop;

class NotEncapsulatedClass {
    public int attribute;
}

public class NotEncapsulated {
    public static void main(String... args) {
        NotEncapsulatedClass obj = new NotEncapsulatedClass();
        obj.attribute = -300;
    }
}

In the previous example, the instance variable attribute from class NotEncapsulated is visible for everyone, since it is declared public. There are many drawbacks when designing like that. First of all, no validation is possible when exposing a public variable. So other classes can assign any value to that variable, even a value that you are not waiting for. Secondly, cohesion and loose coupling are not respected, since other components know details from this object.

Next we are going to refactor the above example to apply the encapsulation principles.

package net.diegolemos.oop;

class EncapsulatedClass {
    private int attribute;

    public int getAttribute() {
        return attribute;
    }

    public void setAttribute(int attribute) {
        if(attribute < 0) {   // We don't want attribute smaller then zero
            this.attribute = 0;
        }
        else {
            this.attribute = attribute;
        }
    }
}

public class Encapsulated {
    public static void main(String... args) {
        EncapsulatedClass obj = new EncapsulatedClass();
        obj.setAttribute(-300);
    }
}

Inheritance

Inheritance is the mechanism by which a Java object can specialize another Java object members (instance variables and methods). In Java we can create inheritance relationships by extending a class (using keyword extends).

The common reasons to use inheritance are:

  • to use polymorphism
  • to reuse code

Reusing code is an essential aspect of OOP. Objects can inherit members of less-specialized objects avoiding code redundancy. Here is an example:

package net.diegolemos.oop;

class Person {
    void talk(){}
}

class Cop extends Person {
    void arrest(Person person){}
}

public class Inheritance {
    public static void main(String... args) {
        Person bob = new Person();
        Cop cop = new Cop();

        bob.talk();
        cop.talk();
        cop.arrest(bob);
    }
}

Polymorphism (many forms) allows specialized classes to be accessed without being necessarily known at compile time. When used correctly, code becomes clear and maintenance easier. We will talk about polymorphism later on this post.

Note: In order to avoid the “Deadly Diamond of Death” problem, Java does not support multiple inheritance. Each Java class can use the keyword extends over only one other class.

IS-A and HAS-A relationships

IS-A is an object relationship based on inheritance and interface implementation. If we have a class Plane and a class Boeing which inherits from Plane so we say that Boeing IS-A Plane. In Java, we express IS-A relationships through the keywords implements to implement an interface and extends inherit from a class.

A HAS-A relationship is characterized when an object uses another object as a member. Imagine that a class Computer has as instance variable an object Processor. So we know that Computer HAS-A Processor.

Polymorphism

In Java, Polymorphism is the ability of Java object to assume many forms. Any Java object that can pass more than one IS-A test can be considered polymorphic. As all Java objects inherit from class Object, they are all polymorphic since they pass the IS-A test for class Object and for their own type. Logically, this rule is not applicable for class Object itself.

To better understand Polymorphism, let’s remember a few concepts regarding reference variables:

  • Since a reference is a variable, it can be reassigned to any other object – when the variable is not declared final
  • We can declare a reference variable as a class type or as an interface type
  • A reference variable can have only one type (once declared, the type cannot be changed)
  • The methods that can be invoked on an object are determined by the reference variable’s type
  • A reference variable can refer to any object of the same type and to any subtype of the declared type

Since Java does not support multiple inheritance, implementing interfaces is a good manner to ensure object behaviour when the object has already a super class other than Object. Let’s see an example:

package net.diegolemos.oop;

import java.util.ArrayList;
import java.util.List;

class Bird {}

class Gull extends Bird implements Flyer {
    public void fly(){
        System.out.println("I can fly");
    }
}

class Chicken extends Bird {}

interface Flyer {
    void fly();
}

public class Polymorphism {
    public static void main(String... args) {
        Bird gull = new Gull();
        Bird chicken = new Chicken();

        List<Bird> birds = new ArrayLis<Bird>();
        birds.add(gull);
        birds.add(chicken);

        for(Bird bird : birds){
            if(bird instanceof Flyer) {
                ((Flyer) bird).fly();
            }
        }
    }
}

As shown above, the classes Gull and Chicken inherit from Bird class. Therefore, we used an interface called Flyer to give to some birds the ability to fly. Thanks to instanceof operator we can identify on runtime which birds can fly. In this example, the object Gull takes the form of the Flyer interface.

Overloading and Overriding

An overloaded method is a method that reuses the name of another existing one with different arguments and/or return type. Overloading a method is generally used when developers need to communicate a behaviour already offered by another method.

To overload a method we need to observe some points:

  • A method can be overloaded in the class or in a subclass
  • Overloaded methods must change the argument list
  • Overloaded methods can change the return type
  • Overloaded methods can change the access modifier
  • Overloaded methods can change the declared checked exceptions

Bellow an example of overloading.

package net.diegolemos.oop;

public class Overloading {
    int multiply(int a, int b) {
        return a * b;
    }

    double multiply(double a, double b) {
        return a * b;
    }

    public static void main(String... args) {
        Overloading calculator = new Overloading();

        calculator.multiply(5, 4);      // Will call the first one
        calculator.multiply(2.2, 4.4);  // Will call the second
    }
}

On the other side, override occurs when we have in a subclass a method with the same signature of a method inherited from a superclass (unless the superclass method is marked final). The main advantage in overriding is that we can attribute specific behaviour to a particular subclass.

When overriding methods some rules must be respected:

  • Methods marked final or static cannot be overridden
  • The parameter list must be the same from that of the overridden method (if it is not the case overload will occur)
  • The return type must be the same or a subtype of the return type of the original method
  • The overriding method cannot be more restrictive in its access modifiers than the method being overridden (if a method have public access the overriding method cannot be private)
  • A method can be overridden only if it is inherited from the super class (private and final methods are not overridden)
  • Overriding methods can throw unchecked (runtime) exceptions
  • The overriding method cannot throw checked exceptions that aren’t the same or a subtype of the exception of the overridden method
  • You must override abstract methods from abstract classes, unless the subclass is also abstract

Here follows an overriding example:

package net.diegolemos.oop;

class Fish {
    void swim() {
        System.out.print("Let's swim");
    }
}

class Sailfish extends Fish {
    @Override
    void swim() {
        super.swim();
        System.out.println(" fast");
    }
}

public class Overriding {
    public static void main(String... args) {
        Fish someFish = new Fish();
        Fish sailfish = new Sailfish();

        someFish.swim();
        sailfish.swim();
    }
}

Since Java 5, we have the @Override annotation to help us to override and not overload a method. If a method is annotated with the keyword @Override and it does not override any method, compilers will inform you 😉

This post presents a quick-overview of OOP possibilities using Java 6+. For a better understanding, I recommend the book SCJP Sun Certified Programmer for Java 6 Exam from Katherine Sierra and Bert Bates.

Posted in Java | Tagged , | 1 Comment

JUnit Flux Eclipse plugin

Last week during the Xebia Knowledge Exchange I discovered a very useful Eclipse Plugin called junitflux.

JUnit Flux Eclipse plugin (junitflux) runs JUnit tests on each class saving. After saving a Java class, the plugin searches for the corresponding test class by adding the word ‘Test’ as a  prefix or suffix of class name. Once the code change is made, the unit test result will immediately blow up on the screen.

During the code retreat session, I installed the JUnit Flux Eclipse plugin in order to get an instant feedback while coding. It works pretty well! Since feedback is an essential element for Agile Development junitflux turns out to be very useful.

junitflux can be installed using Eclipse ‘Install New Software…’ feature. To activate the plugin right-click your project and chose ‘Add JUnit Flux Nature’ option. For more information visit the junitflux project page.

Posted in Agile | Tagged , , , | 3 Comments