Programming basics - Techniques and Tricks VI -

Joe

Thành viên VIP
21/1/13
2,935
1,304
113
Hi

(cont. of Programming basics - Techniques and Tricks V -)


8) Initialization. What? Well, it sounds trivially, but it could be deadly serious. Are you sure that you know when and why you have to initialize the objects you work with? YES? Then skip this section.

I've seen a lot of questions (on different fora and one of them is the "famous" Stackoverflow.com) about this or that and the questioners wondered why their codes went berserk. They failed to initialize the objects correctly. In particular with the global and static objects. JAVA and all other OOPL do have some initialization by default. Example:

- computational primitives are 0 by default (int, short, double, float, etc.)
- Objects are set to null (undefined) by default

But this Initialization by default is not always valid when the variable is used. JAVA throws in some cases Error during the compiling phase.
PHP:
public class Test8  {
  public static void main(String... args) {
    int a, b;
    if (a == b) System.out.println("Equal:a="+a+", b="+b);
  }
}
Code:
C:\java\Test>javac -g:none -d ./classes Test8.java
Test8.java:7: error: variable a might not have been initialized
    if (a == b) System.out.println("Equal");
        ^
Test8.java:7: error: variable b might not have been initialized
    if (a == b) System.out.println("Equal");
             ^
2 errors

C:\java\Test>
Two errors and the pointers (the ^ beneath) tell you a and b "might not have been initialized". Where is the so-called "0 by default" ? Let's change the codes.
PHP:
public class Test8  {
  static int a, b;
  public static void main(String... args) {
    if (a == b) System.out.println("Equal:a="+a+", b="+b);
  }
}
Code:
C:\java\Test>javac -g:none -d ./classes Test8.java

C:\java\Test>java Test8
Equal:a=0, b=0

C:\links\java\Test>
What a wonder ! The initialization by default works perfectly and both a, b are 0. You may wonder why global declarations work, but local declarations won't. Am I right? If you don't know the answer you don't master the art of initialization. It is so: to understand the initialization process you need to understand the compiler technology.
  • In a local environment variables are local and verifiable therefore the compiler won't initialize the variable and expects that the programmer does that (good compiler). Otherwise the result is unpredictable.
  • Global variables are usually "far-reaching" and could be declared somewhere in another module. They are accessed by reference and therefore a good compiler always takes the defaults to all uninitialized declared variables.
And that is what you see in the examples. Local = errors, global = 0 for a and b.
The question is: Is good to have global variables? It depends. Global variables consume more resources (memory + pointer or reference), long accessing time and could cause more undetected bugs than the locals. Why? The compiling errors! Thanks to the errors during the compiling phase you are able to correct the problems TIMELY before they turn out to be the hard-to-detect bugs.

The next problem is how to initialize an object or an array without having to type to death. For example: to initialize a JComboBox with a String array.
PHP:
import javax.swing.*;
import java.awt.event.*;
public class Test8a extends JFrame implements ActionListener {
  public Test8a() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    String[] list = { "Orange", "Peach", "Pear", "Lemon", "Banana" };
    jcb = new JComboBox<>(list);
    jcb.addActionListener(this);
    add(jcb);
    setSize(200, 90);
    setVisible(true);
  }
  private JComboBox<String> jcb;
  public void actionPerformed(ActionEvent e) {
    System.out.println("You have selected:"+(String)jcb.getSelectedItem());
  }
  public static void main(String... args) {
    new Test8a();
  }
}
The codes show you how circumstantial to initialize a JComboBox with an array of items (String or any Java Object). Then you have to waste a String array. I show you a trick that does the same work with an array of items. As you know, String object or literal has some useful methods and one of them is the split(). We use it.
PHP:
import javax.swing.*;
import java.awt.event.*;
public class Test8a extends JFrame implements ActionListener {
  public Test8a() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    //String[] list = { "Orange", "Peach", "Pear", "Lemon", "Banana" };
    //jcb = new JComboBox<>(list);

    jcb = new JComboBox<>("Orange,Peach,Pear,Lemon,Banana".split(","));
    jcb.addActionListener(this);
    add(jcb);
    setSize(200, 90);
    setVisible(true);
  }
  private JComboBox<String> jcb;
  public void actionPerformed(ActionEvent e) {
    System.out.println("You have selected:"+(String)jcb.getSelectedItem());
  }
  public static void main(String... args) {
    new Test8a();
  }
}
The effect is the same, but we haven't wasted an array of string, but only one literal String. Similar to this "split() trick" you need only to read carefully each JAVA object before you start to initialize it. It can save you a lot of work and time. Another example: passing or return an ArrayList means passing or returning a value of its reference. Any modification of the content effects the original, too. The API description says:
Code:
Class ArrayList<E>
   java.lang.Object
     java.util.AbstractCollection<E>
       java.util.AbstractList<E>
         java.util.ArrayList<E>
Type Parameters:
   E - the type of elements in this list
All Implemented Interfaces:
   Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess
Direct Known Subclasses:
   AttributeList, RoleList, RoleUnresolvedList
The hint of "Collection<E>" gives you the opportunity to make a copy from the original without having to create a new ArrayList + to copy the content. Why? Because one of the ArrayList constructors is: ArrayList(Collection<? extends E> c). And that is the hint for a "lithe & lissom" initialization.
PHP:
import java.util.*;
public class Test8b {
  public static ArrayList<String> test(ArrayList<String> list) {
    for (int i = 0, j = list.size()-1, s = (j+1)/2 ; i < s; ++i) {
      String tmp = list.get(i);
      list.set(i, list.get(j));
      list.set(j, tmp);
    }
    return new ArrayList<>(list);
  }
  public static void main(String... args) {
    ArrayList<String> list = new ArrayList<>();
    if (args.length > 0) {
      for (int i = 0; i < args.length; ++i) list.add(args[i]);
    } else {
      list.add("Orange");
      list.add("Peach");
      list.add("Pear");
    }
    // pass the Copy
    ArrayList<String> lst = test(new ArrayList<>(list));
    for (String s:list) System.out.println("Original:"+s);
    System.out.println("--------------------------");
    for (String s:lst) System.out.println("Returned:"+s);
  }
}
Code:
C:\java\Test>javac -g:none -d ./classes  Test8b.java

C:\java\Test>java Test8b
Original:Orange
Original:Peach
Original:Pear
--------------------------
Returned:Pear
Returned:Peach
Returned:Orange

C:\java\Test>
Neither the original from the main(), nor from the test() is effected if the content of the passing or returning ArrayList is modified.

And that is the true Art Of Initialization. The AOI !

Next: JavaJFX basics
 
  • Like
Reactions: jos le