Java: Inner Classes

Since Java 1.1, when inner classes were first introduced, they have started a lot of discussion. Some people like them and find them useful. Others hate them. Viewpoints apart, the fact is that inner classes can be efficient in many situations and it is possible to write clean code using them.

Basically, inner classes give us the possibility to define one class within another. In general, we divide classes in four groups:

  • Inner classes
  • Anonymous inner classes
  • Method-local inner classes
  • Static inner classes

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

Inner Classes

Inner classes are mostly used when some pieces of the code are intimately tied. A chat application is a good example. When someone is chatting, the application needs to handle a couple of things in background, like, listening and writing into sockets, reading messages from text fields, sending messages when the “Send” button is pressed, and so on. The handlers (the Java components that help us to send and receive messages) are strongly tied to specific instances of the chat client’s components. These handlers need to access members of a specific component instance, like buttons, text fields, etc. Thus, we tend to implement these handlers as inner classes such  way they share a special relationship with its outer class instance. As the inner class is part of the outer class, it can access the private members of its outer class.

Following an example of an inner class.

public class OuterClass {
    private int index = 0;

    class InnerClass {
        public void printIndex() {
            // Because the inner class is a member of the
            // outer class, it can access its private members
            System.out.println("Index: " + index);
        }
    }
}

Compiling the above example will produce two class files:

OuterClass.class
OuterClass$InnerClass.class

The inner class has its own class file. Nevertheless, it is not possible to execute the inner class file in the usual way by doing java OuterClass$InnerClass.  Because a simple inner class cannot have static declarations, it is not possible to put a main method on it.

The only way to access inner classes members is through an instance of the outer class. This is only possible at runtime when there is an instance of the inner class tied to its outer class. In other words, an inner class instance cannot stand alone without an outer class instance.

Following an example of an outer class using an inner class.

public class MyOuterClass {
    private int index = 0;

    public void usingInnerClass() {
        // The only way to access MyInnerClass instance is
        // through MyOuterClass instance.
        MyInnerClass innerClass = new MyInnerClass();
        innerClass.printIndex();
    }

    class MyInnerClass {
        public void printIndex() {
            // Because the inner class is a member of the
            // outer class, it can access its private members.
            System.out.println("Index: " + index);
        }
    }
}

But, it is also possible to call methods of inner classes directly from a static context. As every inner class instance is tied to its outer class instance, we need an outer class instance for this. Let’s see an example:

public class InnerClassAcessor {
    public static void main(String... args) {
        MyOuterClass.MyInnerClass myInnerClass = new MyOuterClass().new MyInnerClass();
        myInnerClass.printIndex(); // will print Index: 0
    }
}

Is this magic? No, it’s only the keyword new called from a class instance. Instantiating an inner class is the only case in which we can call new on an instance, rather than invoking new to construct an instance. This is a special way to instantiate inner class from outside the class it lives in.

Finally, since the keyword this always refers to the current object instance, the same keyword used within an inner class refers to the instance of the inner class itself. So, when an inner class needs to refer to a member of the outer class, it needs to use the NameOfTheOuterClass followed by .this.

public class SecondOuterClass {
    private String classAlias = "outer alias";

    class InnerClass {
        String classAlias = "inner alias";

        public void printAlias() {
            System.out.println("Outer: " + SecondOuterClass.this.classAlias);
            System.out.println("Inner: " + this.classAlias);
        }
    }

    public static void main(String... args) {
        InnerClass innerClass = new SecondOuterClass().new InnerClass();
        innerClass.printAlias();    // will print   Outer: outer alias
                                    //              Inner: inner alias
    }
}

Anonymous inner classes

Anonymous inner classes are called “anonymous” because they don’t have a class name. Anonymous inner classes can be used in many situations: inside a method, as a class member or even as a method argument.

Following an example of anonymous inner class defined inside a method.

abstract class Bird {
    abstract void fly();
}

public class AnonymousInnerClass {
    public static void main(String... args) {
        Bird bird = new Bird() {
            @Override
            void fly() {
                System.out.println("Flying...");
            }
        };  // Semicolon required!

        bird.fly(); // Will print Flying...
    }
}

It is important to remark that when using anonymous inner classes as a class member or a local variable inside a method, the semicolon is required at the end of the class instantiation. If the semicolon is omitted the code does not compile.

Anonymous inner classes are available in two flavors. The first one is called anonymous subclass. Anonymous subclasses are created extending a class. The second flavor is called anonymous implementer and is created when implementing anonymously an interface.

Another point to be mentioned is that methods defined inside anonymous inner classes other those overridden from the super class or the interface cannot be called from the outside. Since Java is a strongly typed language, only methods defined by the type can be called. 

Method-local inner classes

Simple inner classes are defined inside a class, more specifically inside the curly braces of a class. Method-local inner classes are inner classes defined inside methods and can be used only with the method they are defined in. There is no other piece of code (inside another method or class) that can instantiate a method-local inner class.

public class MethodLocalInnerClass {
    private int x = 10;

    void printFromInner() {
        class InnerClass {
            public void printX() {
                System.out.println("x=" + x);
            }
        }

        InnerClass innerClass = new InnerClass(); // must come after the class
        innerClass.printX();
    }
}

On the other hand, there is an interesting point here: method-local inner classes cannot access the local variables of the method the inner class was defined in (trying this will produce a compiler error). The reason is simple: as the local variables of the method live in the stack, they exist only during the method execution lifetime. So, if an instance of a method-local inner class is passed to another class and it is being used there, when the method ends, its local variables don’t exist anymore. The only way to use method-local variables inside method-local inner classes is declaring them final. Once it has been assigned, the value of the final variable cannot change. This allows the Java compiler to “capture” the value of the variable at runtime and store a copy as a field in the inner class.

class MethodLocalInnerClass2 {
    private int x = 10;

    public static void main(String... args) {
        MethodLocalInnerClass2 clazz = new MethodLocalInnerClass2();
        clazz.printFromInner(); // will print x=101
    }

    void printFromInner() {
        final int y = 1;
        class InnerClass {
            public void printX() {
                System.out.println("x=" + x + y);
            }
        }

        InnerClass innerClass = new InnerClass(); // must come after the class
        innerClass.printX();
    }
}

And only to remember, local variables rules are also applied to method-local inner classes and they cannot be declared public, private, static, protected, transient, etc. Only abstract and final are allowed.

This question on stackoverflow brings some good examples about the use of method-local inner classes.

Static inner classes

Static inner classes or static nested classes are members of the outer class that can be accessed from a static context. In this case, static inner classes can be accessed like any other static member, without having an instance of the outer class.

On the other hand, there is also another point with static inner classes. Unlike the other inner classes, static inner classes don’t have any kind of special relationship with the outer class, except the namespace. In other words, they cannot access non-static members of the outer class.

class HelperClass {
    static class InnerHelper {
        void print() {
            doPrint();
        }
    }

    static void doPrint() {
        System.out.println("Printing from HelperClass");
    }
}

public class StaticInnerClassExample {
    static class AnotherHelper {
        void print() {
            System.out.println("Printing from AnotherHelper");
        }
    }

    public static void main(String... args) {
        /* Remark the way we create an instance of a static inner class
         is not the same as for inner classes */
        HelperClass.InnerHelper h1 = new HelperClass.InnerHelper();
        h1.print(); // will print: Printing from HelperClass
        AnotherHelper h2 = new AnotherHelper();
        h2.print(); // will print: Printing from AnotherHelper
    }
}

Note: A non-static nested class (or “inner class”) has full access to the members of the class within which it is nested. A static nested class does not have a reference to a nesting instance, so a static nested class cannot invoke non-static methods or access non-static fields of an instance of the class within which it is nested.

Posted in Java | Tagged , | 1 Comment

Carreira e TI

Esta foi uma palestra que eu dei na ComputerTec em Araguari-MG (Brasil) no dia 17 de fevereiro de 2012.

Junto com o pessoal da empresa, conversamos sobre a carreira do profissional de TI e as tendências do ramo. Foi um dia bem legal!

Posted in Speech | Tagged , , , | 2 Comments

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