This is some information on the Java 6 certification that I prepare. This information is not very well structured and it is most of the time an answer to the questions that come when I read the SCJP 6 book (Bates and Sierra). *** AS OF 5 OF MARCH 2010, I AM SCJP 6.0 ***

Saturday, January 30, 2010

28 - Review - xxxValue() - parseXxx() - valueOf() - Java 1.6.0_17

package chap3review;

public class Main {

    public static void main(String[] args) {
      
        // NOT STATIC
        //xxxValue()

        Byte aByte = 125;
        byte b = aByte.byteValue();
        short s = aByte.shortValue();
        int i = aByte.intValue();
        long l = aByte.longValue();
        float f = aByte.floatValue();
        double d =  aByte.doubleValue();

        Integer aInteger = 6753;
        i = aInteger.intValue();
        l = aInteger.longValue();
        f = aInteger.floatValue();
        d = aInteger.doubleValue();

        Boolean aBoolean = true;
        boolean bo = aBoolean.booleanValue();

        // Static
        // parseXxx

        b = Byte.parseByte("127"); // Exception in thread "main" java.lang.NumberFormatException: Value out of range. Value:"256" Radix:10
        // 8 bits signed -128..127 !!!
        i = Integer.parseInt("123456");
        bo = Boolean.parseBoolean("TRUE");
      
        //static 
        // valueOf()

        Byte anotherByte = Byte.valueOf("-128");
        anotherByte = Byte.valueOf(b); // NO BYTE LITTERALS !!!

        Integer  anotherInteger = Integer.valueOf("123456");
        anotherInteger = Integer.valueOf(123456);
    }
}

Friday, January 29, 2010

27 - Review - type of an array - level basic - Java 1.6.0_17 - NB 6.8

What is the output ?

package pkg1;

public class Class10 {

    static Integer[] arrayofINT = { 1, 2, 3, 4 ,5};

    public static void main(String[] args) {

        if(arrayofINT instanceof Object) {
            System.out.println("arrayofINT is an Object !");
        }
        if(arrayofINT instanceof Integer[]) {
            System.out.println("arrayofINT is an Integer[] !");
        }
    }
}

run:
arrayofINT is an Object !
arrayofINT is an Integer[] !
BUILD SUCCESSFUL (total time: 0 seconds)

26 - Review - protected - level basic - Java 1.6.0_17 - NB 6.8

??? protected ??? All the buzz about this keyword...

Let's try to do it simple...

http://en.wikibooks.org/wiki/Java_Programming/Keywords/protected

protected means default + inheritance

  • If you are in a separate pkg, you have access to the protected members ONLY if you extend the class where the protected member is defined.
  •  In the class that extends the class where the protected member is defined you have access to the member using DIRECTLY the member name (only if you didn't you the same name in the class and in this case the member protected is hidden) and using the keyword 'super'. 
  • If the protected member is hidden then use super. If you want to access a method protected in a subclass user the member name (or again if it is hidden then use super).
  • Don't try to user super.super (or super.super.super). It is not implemented... If you want a member to be accessed from all the inheritance tree then make the name unique or (it is a possibility) make a kind of proxy member that will have to call super from the parent class (I don't like this).
example :






/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pkg3.pkg31;

/**
 *
 * @author Rudy
 */
public class Class1 {

    private int a;
    private int b;

    protected int c = -1;

    protected int d = -888;

    protected Class1(int a, int b) {
        System.out.println("Class1-protected Class1(int a, int b)");
        this.a = a;
        this.b = b;
    }

    protected int calculation() {
        System.out.println("Class1-protected int calculation()");
        return a + b;
    }


    protected void simplyToAnnoyYou() {
        System.out.println("simplyToAnnoyYou");
    }




    public static void main(String[] args) {
        System.out.println("main from pkg31.Class1\n");

        System.out.println(new Class1(1, 2).calculation());
    }
}

run:
main from pkg31.Class1

Class1-protected Class1(int a, int b)
Class1-protected int calculation()
3
BUILD SUCCESSFUL (total time: 0 seconds)

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pkg3.pkg32;

/**
 *
 * @author Rudy
 */
public class Class2 extends pkg3.pkg31.Class1 {

    Class2(int a, int b) {
        super(a, b);
        System.out.println("Class2(int a, int b)");
        super.c = -2;
    }

    @Override
    protected int calculation() {
        System.out.println("Class2-protected int calculation()");
        return super.calculation();
    }

    protected int calculation1() {
        System.out.println("Class2-protected int calculation1()");
        int a = super.calculation() + super.c + c;
        return a;
    }

    public static void main(String[] args) {
        System.out.println("main from pkg32.Class2\n");

        Class2 class2 = new Class2(1, 3);

        System.out.println("class2.calculation :  " + class2.calculation());

        System.out.println("c from class1 (protected) in class 2: " + class2.c);

        System.out.println("calculation1 : " + class2.calculation1());
    }
}

run:
main from pkg32.Class2

Class1-protected Class1(int a, int b)
Class2(int a, int b)
Class2-protected int calculation()
Class1-protected int calculation()
class2.calculation :  4
c from class1 (protected) in class 2: -2
Class2-protected int calculation1()
Class1-protected int calculation()
calculation1 : 0
BUILD SUCCESSFUL (total time: 0 seconds)






/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pkg3.pkg32;

/**
 *
 * @author Rudy
 */
public class Class3 extends Class2 {

    int d = -999;

    Class3(int a, int b) {
        super(a, b);
        System.out.println("Class3(int a, int b)");
        super.c = -4;
    }

    @Override
    protected int calculation() {
        System.out.println("Class3.calculation()");
        return super.calculation();
    }

    @Override
    protected int calculation1() {
        System.out.println("Class3.calculation1()");
        int a = super.calculation() + super.c + c;
        return a;
    }

    int getD() {
        return super.d;
    }

    public static void main(String[] args) {
        System.out.println("main from pkg32.Class2\n");

        Class3 class3 = new Class3(1, 3);

        System.out.println("class3.calculation :  " + class3.calculation());

        System.out.println("c from class1 (protected) in class 2: " + class3.c);

        System.out.println("calculation1 : " + class3.calculation1());

        System.out.println("d : " + class3.d);
        
        System.out.println("d from class1 and not defined in class 2 but hidden in class3 : " + class3.getD());

        class3.simplyToAnnoyYou();
    }
}

run:
main from pkg32.Class2

Class1-protected Class1(int a, int b)
Class2(int a, int b)
Class3(int a, int b)
Class3.calculation()
Class2-protected int calculation()
Class1-protected int calculation()
class3.calculation :  4
c from class1 (protected) in class 2: -4
Class3.calculation1()
Class2-protected int calculation()
Class1-protected int calculation()
calculation1 : -4
d : -999
d from class1 and not defined in class 2 but hidden in class3 : -888
simplyToAnnoyYou
BUILD SUCCESSFUL (total time: 0 seconds)

Can you explain all the output ?
:-)



Thursday, January 28, 2010

25 - Review - private - level basic - Java 1.6.0_17 - NB 6.8

I wanted to make you aware (if you are not) of the following...

If you make your constructor "private" you can't invoke the constructor from another class... But you can still invoke it from the SAME class. In Netbeans we are used that Netbeans will generate automatically a Main class and a pvsm (public static void main[] args) method in the main class. In this case if you try to instantiate a class using a private constructor you cant... You have to give another ways (have a look to singletons). But if you put a pvsm in the class were the private constructor is defined, no problem you can instantiate the class.

package pkg3.pkg31;



class Class1 {


    protected int a;
    protected int b;


    private Class1(int a, int b) {
        this.a = a;
        this.b = b;
    }


    protected int calculation() {
        return a + b;
    }


    public static void main(String[] args) {
        System.out.println(new Class1(1, 2).calculation());
    }
}

run:
3
BUILD SUCCESSFUL (total time: 0 seconds)

Tuesday, January 26, 2010

24 - Thread : notify/notifyall- level basic - Java 1.6.0_17 - NB 6.8

(
after all the Master Exam questions, they ask you several times to choose notify or notifyAll ...
most of the time if you answer (please read the question carefully) notifyAll, it is the wrong answer...
why ? it is because there is a producer and several consumers... after the producer produced something the producer will notify the consumers... the way they wrote the example, they do a wait but as soon as the thread is notified they do not check that something was produced (in the consumer thread)
if the producer do notifyAll, then (and it is not new) only 1 thread continues in the synchronized block...
this thread will consume what was produced and exit the synch block and it is fine...
but if notifyAll was used by the producer, then the second, third,... thread (one of those) are now notified but... nothing was produced and a thread will...consume (without checking that something was produced) and...that can cause a IndexOutOfBoundsException to be thrown if the thread calls (by ex) refArrayList.remove(0) without checking that the ArrayList is empty... If you answer notify, then only one thread will be notified and then consume... Then the producer after a while (sometimes they put a sleep) will produce and then call notify...
imho you serialize the way you produce and consume


you produce
then notify1 amongst all the threads
...

or
you produce
then notifyAll

all the threads will be able to continue before the producer produced (one by one in the synch blcok)
and that can cause a problem
(I repeat you have to find a way that the producer made something new)

*** Hope this help ***

)



3 classes. A Main that will start the threads. A producer (calling notify/notifyall) and  consumers.

The Producer

package threadnotifyall;

public class Calculator extends Thread {

    int total;

    public void run() {
        try {
            System.out.println("Calculator...");
            Thread.currentThread().sleep(1000);
            synchronized (this) {
                for (int i = 0; i < 100; i++) {
                    total += i;
                }
                Thread.currentThread().sleep(5000);
                notifyAll(); // OR
                //notify();
            }
        } catch (InterruptedException ie) {
            ie.printStackTrace();
        }
    }
}

The Consumer

package threadnotifyall;

public class Reader extends Thread {
    Calculator c; // reference to the producer

    public Reader(Calculator c) {
        this.c = c;
    }

    public void run() { // it is a thread 
        synchronized(c) { // lock the producer (try to lock)
            try {
                System.out.println(Thread.currentThread().getName() + " waiting for calculation...");
                c.wait(); // if the producer is locked but did not notify (us) wait to be notified (1 and only 1 thread !) or wait forever (see my remarks later)
            } catch(InterruptedException ie) {
                ie.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()  + " Total is :" + c.total); // show the thread that was notified
        }
    }
}

The bandmaster

package threadnotifyall;

public class Main {

    public static void main(String[] args) {
      
        Calculator calculator = new Calculator(); // the producer

        new Reader(calculator).start(); // 3 consumers threads (we pass the producer they have to wait for)
        new Reader(calculator).start();
        new Reader(calculator).start();
        calculator.start(); // the 3 consumers were started (all waiting and the producer shows up)
        System.out.println("end of main"); // end of the THREAD main (because main is a THREAD)
    }
}

With notify

IT IS AN ASSUMPTION BECAUSE THE WAY THE JAVA SCHEDULER WILL CHOOSE THE THREAD DEPENDS ON A FEW FACTORS (WE CAN INFLUENCE)

run:
Thread-1 waiting for calculation...
Thread-2 waiting for calculation...
Thread-3 waiting for calculation...
end of main
Calculator...
Thread-1 Total is :4950
Thread-3 Total is :4950
Thread-2 Total is :4950
BUILD SUCCESSFUL (total time: 5 seconds)

run:
Thread-1 waiting for calculation...
Thread-2 waiting for calculation...
end of main
Thread-3 waiting for calculation...
Calculator...
Thread-1 Total is :4950
Thread-3 Total is :4950
Thread-2 Total is :4950
BUILD SUCCESSFUL (total time: 5 seconds)

I did several executions and can report that if we use notify, it is always the first thread that was started that will be choosen (notified that the producer has something to deliver). In the output as it is Thread-1 that was the first to be started (and waiting), Thread-1 is the first to be notified... You can see that the main thread terminated BEFORE the 3 threads were terminated. But Java is polite :-) and will wait that the 3 consumers threads will terminate.

With notifyall

run:
Thread-1 waiting for calculation...
Thread-2 waiting for calculation...
end of main
Thread-3 waiting for calculation...
Calculator...
Thread-3 Total is :4950
Thread-2 Total is :4950
Thread-1 Total is :4950
BUILD SUCCESSFUL (total time: 5 seconds)

run:
Thread-1 waiting for calculation...
Thread-3 waiting for calculation...
Thread-2 waiting for calculation...
end of main
Calculator...
Thread-2 Total is :4950
Thread-3 Total is :4950
Thread-1 Total is :4950
BUILD SUCCESSFUL (total time: 5 seconds)

run:
Thread-1 waiting for calculation...
Thread-3 waiting for calculation...
Thread-2 waiting for calculation...
end of main
Calculator...
Thread-2 Total is :4950
Thread-3 Total is :4950
Thread-1 Total is :4950
BUILD SUCCESSFUL (total time: 5 seconds)

As you can see using notifyall, it is the last thread that was started that was notified this time.

Following my experimentation with the kind of JVM that I use
  • If notify is used, then it is the thread that was the FIRST to be waiting that will be notified. Then the second,... Then the third... until all the threads waiting to be notified.
  • If notifyall is used, then it is the thread that was the LAST to be waiting that will be notified, then the previous, etc.
  • The Java scheduler will choose a thread to be notified (there is a list of threads awaiting) and the one that is awaken continues JUST AFTER the wait !!! But the awaken thread does not have to execute "synchronized" to get the lock. The Java scheduler guaranty the thread to receive the lock if the thread is chosen. ALL the other threads ARE WAITING to be notified (IMHO there are NOT in the runnable queue; the threads are in a special queue). They will all be notified ONE BY ONE. The way there are chosen depends on notify / notifyall. But the mechanism to awake the threads is the same. One by one !!! But look in the beg of this post, if nothing was produced and the thread that is awaken does not check that something is produced (with notifyAll) you can cause a IndexOutOfBoundsException to be thrown !!!
  • If you inverse the consumers and the producers meaning you start the producer first and later the consumer and let's say you also put a sleep just after the producer finishes. The consumers will ALL wait to be notified but will never be notified because the producer finished before any consumers were started. You see that the main thread is finished, but all the others keep waiting FOREVER !!! Thus the sequence of events is important and it is written  in the Sierra/Bates book that you have to wait for something that will happen (by example there is something to be read  from a queue and it is your application queue) but NOT unconditionaly !!!


Monday, January 25, 2010

23 - Thread : deadlock - level basic - Java 1.6.0_17 - NB 6.8

A deadlock is rather easy to produce having 2 actors (2 threads) accessing 2 resources at the same time but in different order !

T1-------------T2
res A----------res B
res B----------res A

If T1 put a lock on res A, T2 put a lock on res B, then T1 tries to lock res B (waiting the lock on res B to be released) an then T2 tries to lock res A (waiting the lock put by T1 to be released). The 2 threads do not speak to each others and will wait...indefinitely... The JVM seems not able to deal with such a problem...
You have to deal with it !!!


package threaddeadlock;

public class Main implements Runnable {

    ClassA refA = new ClassA();
    ClassB refB = new ClassB();

    void operation1() throws Exception {
        synchronized (refA) {
            refA.method1();
            synchronized (refB) {
                refB.method2();
            }
        }
    }

    void operation2() throws Exception {
        synchronized (refB) {
            refB.method2();
            synchronized (refA) {
                refA.method1();
            }
        }
    }

    public void run() {
        try {
            if (Thread.currentThread().getName().equals("t1")) {
                operation1();
            } else if (Thread.currentThread().getName().equals("t2")) {
                operation2();
            } else { // should be an assertion !!!
                System.err.println("thread name must be t1 or t2 !!!");
                System.exit(1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Main main = new Main();
        Thread t1 = new Thread(main);
        t1.setName("t1");
        Thread t2 = new Thread(main);
        t2.setName("t2");
        t1.start();
        t2.start();
    }
}

wait forever in front of your screen... :-)


run:
t1 method1
t2 method2
BUILD STOPPED (total time: 13 minutes 30 seconds)



package threaddeadlock;

public class ClassA {

     void method1() {
        System.out.println(Thread.currentThread().getName() + " method1");
    }

}

package threaddeadlock;

public class ClassB {

     void method2() {
        System.out.println(Thread.currentThread().getName() + " method2");
    }
}



22 - Thread : same or different object ? - level basic - Java 1.6.0_17 - NB 6.8

Look at the 2 versions of main
1 will create a new object of type ClassA for every thread
the second will not and look at the difference !


package threadsleep;

public class Main {

    public static void main(String[] args) {
        // 1st version new object ClassA of every thread
        //ClassA ca = new ClassA();
        //Thread thread;
        for(int i=0; i < 10; i++) {
            //thread = new Thread(ca);
            //thread.start();
            new Thread(new ClassA()).start();
        }
    }
}

run:
Thread-0
a : Thread-0 sleeping 5 seconds...
Thread-1
a : Thread-1 sleeping 5 seconds...
Thread-3
a : Thread-3 sleeping 5 seconds...
Thread-5
a : Thread-5 sleeping 5 seconds...
Thread-7
a : Thread-7 sleeping 5 seconds...
Thread-6
a : Thread-6 sleeping 5 seconds...
Thread-2
a : Thread-2 sleeping 5 seconds...
Thread-4
a : Thread-4 sleeping 5 seconds...
Thread-8
a : Thread-8 sleeping 5 seconds...
Thread-9
a : Thread-9 sleeping 5 seconds...
a : Thread-0-Thread-0 after sleeping 5 seconds...
a : Thread-1-Thread-1 after sleeping 5 seconds...
a : Thread-5-Thread-5 after sleeping 5 seconds...
a : Thread-3-Thread-3 after sleeping 5 seconds...
a : Thread-7-Thread-7 after sleeping 5 seconds...
a : Thread-6-Thread-6 after sleeping 5 seconds...
a : Thread-2-Thread-2 after sleeping 5 seconds...
a : Thread-4-Thread-4 after sleeping 5 seconds...
a : Thread-9-Thread-9 after sleeping 5 seconds...
a : Thread-8-Thread-8 after sleeping 5 seconds...
BUILD SUCCESSFUL (total time: 10 seconds)

The instance variable "a" was not modified because for every thread there is a different "a" !

public class Main {

    public static void main(String[] args) {
        // 2nd version the thread will share the same object
        ClassA ca = new ClassA();
        Thread thread;
        for(int i=0; i < 10; i++) {
            thread = new Thread(ca);
            thread.start();
            //new Thread(new ClassA()).start();
        }
    }
}

run:
Thread-0
a : Thread-0 sleeping 5 seconds...
Thread-1
a : Thread-1 sleeping 5 seconds...
Thread-2
a : Thread-2 sleeping 5 seconds...
Thread-3
a : Thread-3 sleeping 5 seconds...
Thread-5
a : Thread-5 sleeping 5 seconds...
Thread-7
a : Thread-7 sleeping 5 seconds...
Thread-9
a : Thread-9 sleeping 5 seconds...
Thread-4
a : Thread-4 sleeping 5 seconds...
Thread-6
a : Thread-6 sleeping 5 seconds...
Thread-8
a : Thread-8 sleeping 5 seconds...
a : Thread-8-Thread-0 after sleeping 5 seconds...
a : Thread-8-Thread-1 after sleeping 5 seconds...
a : Thread-8-Thread-2 after sleeping 5 seconds...
a : Thread-8-Thread-5 after sleeping 5 seconds...
a : Thread-8-Thread-3 after sleeping 5 seconds...
a : Thread-8-Thread-7 after sleeping 5 seconds...
a : Thread-8-Thread-9 after sleeping 5 seconds...
a : Thread-8-Thread-4 after sleeping 5 seconds...
a : Thread-8-Thread-6 after sleeping 5 seconds...
a : Thread-8-Thread-8 after sleeping 5 seconds...
BUILD SUCCESSFUL (total time: 11 seconds)

The thread "8" had a big influence on all the others threads because the thread "8" modified the instance variable "a" ! In fact it is because this poor thread "8" was the last to be started and as he is the last, he modified the same "a" instance variable for all the threads !!!

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package threadsleep;

public class ClassA implements Runnable {

    String a;

    public void run() {
        Thread currenthread = Thread.currentThread();
        a = currenthread.getName();
        System.out.println(a);
        try {
            System.out.println("a : " + a + " sleeping 5 seconds...");
            currenthread.sleep(10000);
            System.out.println("a : " + a + "-" + currenthread.getName()+ " after sleeping 5 seconds...");
        } catch (InterruptedException ie) {
            ie.printStackTrace();
        }
    }
}

You can share the same objects. You will avoid to waste memory... But if your threads modify the data... You have to find a way keep the operations/data modifications consistent... In other words all the operations you do that can corrupt the data have to be atomic to avoid the corruption...


- Rudy -


21 - example of Thread.join - level basic - Java 1.6.0_17 - NB 6.8

3 classes
Main
ClassA
and ClassB
Main will start 2 threads one of ClassA and one of ClassB.
The threads do a loop and wait some time after each iteration.
After 3 seconds Main will send a message to ClassA (thread A) to join the Thread B.
(ClassA will check an instance variable and if this instance variable is initialized, then it is the thread to join)


package threadjoin;

public class Main {

    public static void main(String[] args) {

        ClassA a = new ClassA();
        ClassB b = new ClassB();

        Thread ta = new Thread(a);
        Thread tb = new Thread(b);

        ta.start();
        tb.start();

        System.out.println("sleeping 3 seconds ! then will force Thread A to join Thread B !");
        Thread main = Thread.currentThread();
        try {
            main.sleep(3000);
            a.threadToJoin = tb;
        } catch (InterruptedException ie) {
            ie.printStackTrace();
        }


        System.out.println("after 3 seconds and thread A should join thread B !");
    }
}

package threadjoin;

/**
 *
 * @author Rudy
 */
public class ClassA implements Runnable {

    Thread threadToJoin;
    final static int counter = 100;
    final static int timeToWait = 100000000;

    public void run() {
        for (int c = 0; c < counter; c++) {
            System.out.println("A --- Loop #" + c);
            for (int t = 0; t < timeToWait; t++);
            if (threadToJoin != null) {
                try {
                    System.out.println("Thread A joining Thread B !!!");
                    threadToJoin.join();
                    // deactivation of the test !
                    threadToJoin = null;
                } catch (InterruptedException ie) {
                    ie.printStackTrace();
                }
            }
        }

    }
}

package threadjoin;

/**
 *
 * @author Rudy
 */
public class ClassB implements Runnable {

    final static int counter = 100;
    final static int timeToWait = 100000000;

    public void run() {
        for (int c = 0; c < counter; c++) {
            System.out.println("B --- Loop #" + c);
            for (int t = 0; t < timeToWait; t++);
        }

    }
}

run:
sleeping 3 seconds ! then will force Thread A to join Thread B !
A --- Loop #0
B --- Loop #0
A --- Loop #1
B --- Loop #1
A --- Loop #2
B --- Loop #2
A --- Loop #3
B --- Loop #3
A --- Loop #4
B --- Loop #4
A --- Loop #5
B --- Loop #5
A --- Loop #6
B --- Loop #6
B --- Loop #7
A --- Loop #7
B --- Loop #8
A --- Loop #8
B --- Loop #9
A --- Loop #9
B --- Loop #10
A --- Loop #10
B --- Loop #11
A --- Loop #11
B --- Loop #12
A --- Loop #12
B --- Loop #13
A --- Loop #13
B --- Loop #14
A --- Loop #14
B --- Loop #15
A --- Loop #15
B --- Loop #16
A --- Loop #16
B --- Loop #17
A --- Loop #17
B --- Loop #18
A --- Loop #18
B --- Loop #19
A --- Loop #19
B --- Loop #20
A --- Loop #20
B --- Loop #21
A --- Loop #21
B --- Loop #22
B --- Loop #23
A --- Loop #22
B --- Loop #24
A --- Loop #23
B --- Loop #25
A --- Loop #24
B --- Loop #26
A --- Loop #25
B --- Loop #27
A --- Loop #26
B --- Loop #28
A --- Loop #27
B --- Loop #29
A --- Loop #28
B --- Loop #30
A --- Loop #29
B --- Loop #31
A --- Loop #30
B --- Loop #32
A --- Loop #31
B --- Loop #33
A --- Loop #32
B --- Loop #34
A --- Loop #33
B --- Loop #35
A --- Loop #34
B --- Loop #36
A --- Loop #35
B --- Loop #37
A --- Loop #36
B --- Loop #38
A --- Loop #37
B --- Loop #39
A --- Loop #38
B --- Loop #40
A --- Loop #39
B --- Loop #41
A --- Loop #40
B --- Loop #42
A --- Loop #41
B --- Loop #43
A --- Loop #42
B --- Loop #44
A --- Loop #43
B --- Loop #45
A --- Loop #44
B --- Loop #46
A --- Loop #45
B --- Loop #47
A --- Loop #46
B --- Loop #48
A --- Loop #47
B --- Loop #49
A --- Loop #48
B --- Loop #50
A --- Loop #49
B --- Loop #51
A --- Loop #50
B --- Loop #52
A --- Loop #51
B --- Loop #53
after 3 seconds and thread A should join thread B !
Thread A joining Thread B !!!
B --- Loop #54
B --- Loop #55
B --- Loop #56
B --- Loop #57
B --- Loop #58
B --- Loop #59
B --- Loop #60
B --- Loop #61
B --- Loop #62
B --- Loop #63
B --- Loop #64
B --- Loop #65
B --- Loop #66
B --- Loop #67
B --- Loop #68
B --- Loop #69
B --- Loop #70
B --- Loop #71
B --- Loop #72
B --- Loop #73
B --- Loop #74
B --- Loop #75
B --- Loop #76
B --- Loop #77
B --- Loop #78
B --- Loop #79
B --- Loop #80
B --- Loop #81
B --- Loop #82
B --- Loop #83
B --- Loop #84
B --- Loop #85
B --- Loop #86
B --- Loop #87
B --- Loop #88
B --- Loop #89
B --- Loop #90
B --- Loop #91
B --- Loop #92
B --- Loop #93
B --- Loop #94
B --- Loop #95
B --- Loop #96
B --- Loop #97
B --- Loop #98
B --- Loop #99
A --- Loop #52
A --- Loop #53
A --- Loop #54
A --- Loop #55
A --- Loop #56
A --- Loop #57
A --- Loop #58
A --- Loop #59
A --- Loop #60
A --- Loop #61
A --- Loop #62
A --- Loop #63
A --- Loop #64
A --- Loop #65
A --- Loop #66
A --- Loop #67
A --- Loop #68
A --- Loop #69
A --- Loop #70
A --- Loop #71
A --- Loop #72
A --- Loop #73
A --- Loop #74
A --- Loop #75
A --- Loop #76
A --- Loop #77
A --- Loop #78
A --- Loop #79
A --- Loop #80
A --- Loop #81
A --- Loop #82
A --- Loop #83
A --- Loop #84
A --- Loop #85
A --- Loop #86
A --- Loop #87
A --- Loop #88
A --- Loop #89
A --- Loop #90
A --- Loop #91
A --- Loop #92
A --- Loop #93
A --- Loop #94
A --- Loop #95
A --- Loop #96
A --- Loop #97
A --- Loop #98
A --- Loop #99
BUILD SUCCESSFUL (total time: 9 seconds)

As you can see the Java scheduler will make the thread A and B execute at the same time.
We see

A --- Loop #0
B --- Loop #0
A --- Loop #1
B --- Loop #1
A --- Loop #2
B --- Loop #2
A --- Loop #3
B --- Loop #3
A --- Loop #4
B --- Loop #4
A --- Loop #5
B --- Loop #5
A --- Loop #6
...

Then after 3 seconds A joined B and thus A wait until the end of B.
We see

B --- Loop #54
B --- Loop #55
B --- Loop #56
B --- Loop #57
B --- Loop #58
B --- Loop #59
B --- Loop #60
B --- Loop #61
B --- Loop #62
B --- Loop #63
B --- Loop #64
B --- Loop #65
B --- Loop #66
B --- Loop #67
B --- Loop #68
B --- Loop #69
B --- Loop #70
B --- Loop #71
B --- Loop #72
B --- Loop #73
...
B --- Loop #94
B --- Loop #95
B --- Loop #96
B --- Loop #97
B --- Loop #98
B --- Loop #99

Look A is back !!!

A --- Loop #52
A --- Loop #53
A --- Loop #54
A --- Loop #55
A --- Loop #56
A --- Loop #57
A --- Loop #58
A --- Loop #59
A --- Loop #60
A --- Loop #61
A --- Loop #62
A --- Loop #63
A --- Loop #64
A --- Loop #65
A --- Loop #66
A --- Loop #67
A --- Loop #68
A --- Loop #69
A --- Loop #70
A --- Loop #71
A --- Loop #72
A --- Loop #73
A --- Loop #74
A --- Loop #75
A --- Loop #76
...
A --- Loop #86
A --- Loop #87
A --- Loop #88
A --- Loop #89
A --- Loop #90
A --- Loop #91
A --- Loop #92
A --- Loop #93
A --- Loop #94
A --- Loop #95
A --- Loop #96
A --- Loop #97
A --- Loop #98
A --- Loop #99


- Rudy -


Friday, January 22, 2010

20 - non public class and public method - level very basic - Java 1.6.0_17 - NB 6.8

OK it's for newbies...

But is it clear in your mind ?
If the class is not public even if the method is public you can't use the method !

package javaapplication10;

class Main { // where is public ???

    public void a() { // it is public !!!
        System.out.println("a");
    }

    public static void main(String[] args) {
        new Main().a(); // here you can
    }
}

package newpackage;

import javaapplication10.Main; // DOES NOT COMPILE !

public class Test {

    public static void main(String[] args) {
        new Main().a(); // DOES NOT COMPILE !

    }
}

Saturday, January 16, 2010

19 - hashCode - level basic - Java 1.6.0_17 - NB 6.8

TO BE REPHRASED !!!

To summarize

It is not enough to override "equals" and then try to retrieve keys in a map... If the 2 objects are equal, then the hash codes have to be the same. I suppose they play a max on this one...

More on this topic

You put an object in a map(the key). Then you change the object. And you base the hash code on the length of the String... The key changed but the method "get" will look in the bucket corresponding to the new hash code and will not find the value...

pseudo code

key1, value1
length("key1") => bucket 4
then you change key1 in "key11"
the object is still in bucket 4 but the hash code will reference the bucket5 !!! because lenght("key11") is... 5 !!!
It is not a good idea to change the key... I pref remove and then add...

To understand the statement on p 554, I propose to study the following example :

1) equals is overridden and hashCode is not.
2) equals is overridden and and hashCode is overridden and returns always 0.
3) equals is overridden and hashCode is overridden and returns the length of the string.

package mapandkeys;


public class Dog {

    String name;

    public Dog(String n) {
        name = n;
    }

    public boolean equals(Object o) {
        System.out.println("accessing method equals");
        if((o instanceof Dog) && (((Dog)o).name == name)) {
           return true;
        }
        return false;
    }


hasCode NOT OVERRIDDEN

OR

//    public int hashCode() {
//        System.out.println("accessing method hashcode");
//        return 0;
//
//    }

OR

//    public int hashCode() {
//        System.out.println("accessing method hashcode");
//        return name.length();
//
//    }


     public String toString() {
         return name;
     }
}


package mapandkeys;

public class Cat {
}

package mapandkeys;

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

public class Main {

    public static void main(String[] args) {
        Map m = new HashMap();
        m.put("k1", "k1");
        m.put("k2", "k2");
        System.out.println("1 size:" + m.size());

        String aString = (String) m.get("k1");

The 3 will return "k1"
default : it is the same "k1" from the string pool and hashCode will return the same id
0 : all objects will return the same bucket (bucket 0)
lenght : have the same length (bucket 2)

        System.out.println("2 aString : " + aString);

        m.put(new Dog("dog1"), "dog1");
        m.put(new Dog("dog2"), "dog2");
        System.out.println("3 size:" + m.size());
        aString = (String) m.get(new Dog("dog1"));
        System.out.println("4 aString : " + aString);
        aString = (String) m.get(new Dog("dog2"));
        System.out.println("5 aString : " + aString);

default : You do a new 2 times and the default hashCode will return 2 diffent hash ! You will not be able to retrieve the values !!!
0 and length will return the hash same thus we can retrieve the keys.

        Cat aCat = new Cat();
        System.out.println("hash of aCat :" + aCat.hashCode());
        m.put(aCat, "cat1");
        System.out.println("6 size:" + m.size());
        aString = (String) m.get(aCat);
        System.out.println("7 aString : " + aString);

Nothing was overridden in the Cat class and you do a "get" on the same cat (same object and same hash code) so the "cat1" is returned.

        Dog d1Key = new Dog("cloverkey");
        Dog d1Value = new Dog("clovervalue");
        m.put(d1Key, d1Value);
        System.out.println("8 size:" + m.size());
        System.out.println("9 d1Value : " + m.get(d1Key));

It is the same object and can be found in the 3 cases.

        d1Value.name = "clovervalue1";
        System.out.println("10 size:" + m.size());
        System.out.println("11 d1Value : " + m.get(d1Key));

The value was changed but not the key. The 3 will return the same (new) value.

        d1Key.name = "1";

The key is changed !!! It was "cloverkey" and now it is "1" !

        System.out.println("12 d1Value() : " + m.get(d1Key));

This time we change the key ! The hash code will make a difference...
def and 0, both point to the same bucket
length("clovervalue") and length("1") are different... Java will try to find the key in the wrong bucket !

        Dog d2 = new Dog("1");
        System.out.println("13 d1Value() : " + m.get(d2));

default : it is a different object because we used the keyword new !
0 : OK They all use the bucket 0 and it is not performant !
lenght : NOK because the length("clovervalue") = 11  and length("1") = 1 the value is in bucket 11 and we try to find the value in bucket 1 !
If you use 0 you put all the keys and values in the same bucket !

        System.out.println("14 hash of 12:" + d1Key.hashCode());
        System.out.println("15 hash of 13:" + d2.hashCode());

      
        System.out.println("14 contains");
        if(m.containsKey(d1Key)) {
            System.out.println("true");
        }

    }
}


hashcode in Dog is not overriden

run:
1 size:2
2 aString : k1
3 size:4
4 aString : null
5 aString : null
hash of aCat :12677476
6 size:5
7 aString : cat1
8 size:6
9 d1Value : clovervalue
10 size:6
11 d1Value : clovervalue1
12 d1Value() : clovervalue1
13 d1Value() : null
14 hash of 12:33263331
15 hash of 13:6413875
14 contains
true
BUILD SUCCESSFUL (total time: 0 seconds)

hashCode is and returns 0

run:
1 size:2
2 aString : k1
accessing method hashcode
accessing method hashcode
accessing method equals
3 size:4
accessing method hashcode
accessing method equals
accessing method equals
4 aString : dog1
accessing method hashcode
accessing method equals
5 aString : dog2
hash of aCat :11394033
6 size:5
7 aString : cat1
accessing method hashcode
accessing method equals
accessing method equals
8 size:6
accessing method hashcode
9 d1Value : clovervalue
10 size:6
accessing method hashcode
11 d1Value : clovervalue1
accessing method hashcode
12 d1Value() : clovervalue1
accessing method hashcode
accessing method equals
13 d1Value() : clovervalue1
accessing method hashcode
14 hash of 12:0
accessing method hashcode
15 hash of 13:0
14 contains
accessing method hashcode
true

hasCode is and returns name.lenght()

run:
1 size:2
2 aString : k1
accessing method hashcode
accessing method hashcode
accessing method equals
3 size:4
accessing method hashcode
accessing method equals
accessing method equals
4 aString : dog1
accessing method hashcode
accessing method equals
5 aString : dog2
hash of aCat :11394033
6 size:5
7 aString : cat1
accessing method hashcode
8 size:6
accessing method hashcode
9 d1Value : clovervalue
10 size:6
accessing method hashcode
11 d1Value : clovervalue1
accessing method hashcode
12 d1Value() : null
accessing method hashcode
13 d1Value() : null
accessing method hashcode
14 hash of 12:1
accessing method hashcode
15 hash of 13:1
14 contains
accessing method hashcode



18 - Sorted Sets and a strange class - level basic - Java 1.6.0_17 - NB 6.8

COULD YOU NOTICE THAT I HAD TO PUT A SINGLE QUOTE IN FRONT OF THE GREATER SIGN OF THE GENERIC. IF I DON'T DO THAT I HAVE A PROBLEM WITH THE EDITOR !

This example illustrates the fact that the objects of a collection have to be mutually comparable. If not a ClassCastException is returned by compare. Book page 583.
In this example if the object you put in the TreeSet is the a String, the comparison is made on name of the class...

package treesets;

public class StrangeClass implements Comparable <Object'> {

    Object aStrangeObject;
    String name;

    StrangeClass(Object o) {
        aStrangeObject = o;
        if (o instanceof String) {
            name = (String) o;
        } else {
            name = o.getClass().getName();
        }
    }

    public int compareTo(Object o) {
            return name.compareTo(((StrangeClass)o).name);
    }

    public String toString() {
        if (aStrangeObject instanceof String) {
            return (String) aStrangeObject;
        }
        return name;
    }
}

package treesets;

import java.util.Set;
import java.util.TreeSet;

public class TestStrangeClass {

    public static void main(String[] args) {

        boolean[] ba = new boolean[5];

        //Set s = new HashSet();
        Set s = new TreeSet<StrangeClass'>();

        ba[0] = s.add(new StrangeClass(new String("c")));
        ba[1] = s.add(new StrangeClass(new Integer(42)));
        ba[2] = s.add(new StrangeClass(new String("b")));
        ba[3] = s.add(new StrangeClass("a"));
        ba[4] = s.add(new StrangeClass(new Object()));


        for (int x = 0; x < ba.length; x++) {
            System.out.println(ba[x]);
        }

        System.out.println("Display : ");
        for (Object o : s) {
            System.out.println(o);
        }
    }
}


run:
true
true
true
true
true
Display :
a
b
c
java.lang.Integer
java.lang.Object


Friday, January 15, 2010

17 - Arrays.sort example - level basic - Java 1.6.0_17 - NB 6.8


public static void main(String[] args) {

       // reverse order
        char[] array1 = {'f', 'e', 'd', 'c', 'b', 'a'};

        for (char cs : array1) {
            System.out.println(cs);
        }
        Arrays.sort(array1);
        for (char cs : array1) {
            System.out.println(cs);
        }
    }

run:
f
e
d
c
b
a
a
b
c
d
e
f

16 - Comparable and Comparator - level basic - Java 1.6.0_17 - NB 6.8

public class DVD implements Comparable {

    String title;
    String genre;
    String leadActor;

    DVD(String t, String g, String a) {
        title = t;
        genre = g;
        leadActor = a;
    }

    String getGenre() {
        return genre;
    }

    @Override
    public String toString() {
        return title + " " + genre + " " + leadActor;
    }

    public int compareTo(DVD o) {
        //throw new UnsupportedOperationException("Not supported yet.");
        return title.compareTo(o.title);
    }
}

import java.util.Comparator;

public class GenreSort implements Comparator {

    public int compare(DVD o1, DVD o2) {
        //throw new UnsupportedOperationException("Not supported yet.");
        return o1.getGenre().compareTo(o2.getGenre());
    }

}

import java.util.ArrayList;
import java.util.Collections;

public class TestDVD {

    ArrayList dvdList = new ArrayList();

    void populateList() {
        dvdList.add(new DVD("title5", "genre4", "actor2"));
        dvdList.add(new DVD("title4", "genre3", "actor1"));
        dvdList.add(new DVD("title3", "genre2", "actor4"));
        dvdList.add(new DVD("title2", "genre1", "actor6"));
        dvdList.add(new DVD("title1", "genre2", "actor6"));
    }

    void go() {
        populateList();
        System.out.println("dvdlist :" + dvdList);
        Collections.sort(dvdList);
        System.out.println("dvdlist :" + dvdList);
        GenreSort gs  = new GenreSort();
        Collections.sort(dvdList, gs);
        System.out.println("dvdlist :" + dvdList);
    }

    public static void main(String[] args) {
        new TestDVD().go();
    }
}

run:
dvdlist :[title5 genre4 actor2, title4 genre3 actor1, title3 genre2 actor4, title2 genre1 actor6, title1 genre2 actor6]
dvdlist :[title1 genre2 actor6, title2 genre1 actor6, title3 genre2 actor4, title4 genre3 actor1, title5 genre4 actor2]
dvdlist :[title2 genre1 actor6, title1 genre2 actor6, title3 genre2 actor4, title4 genre3 actor1, title5 genre4 actor2]


A) The class implements Comparable (is thus modified) and the list is sorted on titles.
B) A new Comparator is implemented and the class is sorted on genres using the class GenreSort.
C) You can avoid to return something from a method if you throw an Exception. Did you know that ?

15 - two ways to compare - level basic - Java 1.6.0_17 - NB 6.8

A) equals IS NOT OVERRIDDEN



public class Class1 {
    int value;
    Class1() {

    }
    Class1(int value) {
        this.value = value;
    }
}

public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        System.out.println("ref1Class1 and ref2Class1");
        Class1 ref1Class1 = new Class1();
        Class1 ref2Class1 = ref1Class1;
        if(ref1Class1.equals(ref2Class1)) {
            System.out.println("Objects are equal");
        } else {
            System.out.println("Objects are not equal");
        }
        if(ref1Class1 == ref2Class1) {
            System.out.println("Objects are ==");
        } else {
            System.out.println("Objects are not ==");
        }

        System.out.println("ref3Class1 and ref4Class1");
        Class1 ref3Class1 = new Class1(5);
        Class1 ref4Class1 = new Class1(5);
        if(ref3Class1.equals(ref4Class1)) {
            System.out.println("Objects are equal");
        } else {
            System.out.println("Objects are not equal");
        }
        if(ref3Class1 == ref4Class1) {
            System.out.println("Objects are ==");
        } else {
            System.out.println("Objects are not ==");
        }

    }

}

run:
ref1Class1 and ref2Class1
Objects are equal
Objects are ==
ref3Class1 and ref4Class1
Objects are not equal
Objects are not ==



B) equals IS OVERRIDDEN



    public boolean equals(Object objectToCompare) {
        return this.value == ((Class1)objectToCompare).value;
    }

run:
ref1Class1 and ref2Class1
Objects are equal
Objects are ==
ref3Class1 and ref4Class1
Objects are equal
Objects are not ==

This is Java for Beginners and you should understand the meaning of these example by yourself... :-)




Tuesday, January 12, 2010

14 - RegExp

import java.util.regex.*;
class Regex2 {
    public static void main(String[] args) {
        Pattern p = Pattern.compile(args[0]);
        Matcher m = p.matcher(args[1]);
        boolean b = false;
        while(b = m.find()) {
             System.out.print(m.start() + m.group());
        }
    }
}

1) simple

F:\SCP\CHAP6>java Regex2 "ab" "abaaaba"
0 ab
4 ab

2)

F:\SCP\CHAP6>java Regex2 "aba" "ababab"
0 aba

3) meta d : a digit

F:\SCP\CHAP6>java Regex2 "\d" "a12c3e456f"
1 1
2 2
4 3
6 4
7 5
8 6

4) meta w : a word character (letters, digits or "_")

F:\SCP\CHAP6>java Regex2 "\w" "a 1 56 _Z"
0 a
2 1
4 5
5 6
7 _
8 Z

5) 1 char !

F:\SCP\CHAP6>java Regex2 [a-cA-C] cafeBABE
0 c
1 a
4 B
5 A
6 B

6) no +

F:\SCP\CHAP6>java Regex2 "0[xX][0-9a-fA-F]" "12 0x 0x12 0Xf 0xg"
6 0x1
11 0Xf

7) +

F:\SCP\CHAP6>java Regex2 "0[xX][0-9a-fA-F]+" "12 0x 0x12 0Xf 0xg"
6 0x12
11 0Xf

8a) a digit !

F:\SCP\CHAP6>java Regex2 "\d" "1 a12 234b"
0 1
3 1
4 2
6 2
7 3
8 4

8b) a digit and a + !

F:\SCP\CHAP6>java Regex2 "\d+" "1 a12 234b"
0 1
3 12
6 234

9) parenthesis and +

F:\SCP\CHAP6>java Regex2 "0[xX]([0-9a-fA-F])+" "12 0x 0x12 0Xf 0xg 0XFAAAAA"
6 0x12
11 0Xf
19 0XFAAAAA

10) give me proj1 followed by something that is NOT a "," zero or several times

F:\SCP\CHAP6>java Regex2 "proj1[^,]*" proj3.txt,proj1sched.pdf,proj1,proj2,proj1
.java
10 proj1sched.pdf
25 proj1
37 proj1.java

11) \s is a white space

? is zero or 1
+ 1 or more
give me 3 digits followed by zero or 1 "-" or zero or 1 space followed by 4 digits

F:\SCP\CHAP6>java Regex2 "\d\d\d([-\s])?\d\d\d\d" 1234567
0 1234567

F:\SCP\CHAP6>java Regex2 "\d\d\d([-\s])?\d\d\d\d" "123 4567"
0 123 4567

F:\SCP\CHAP6>java Regex2 "\d\d\d([-\s])?\d\d\d\d" "123-4567"
0 123-4567

12) . dot is any character

the following can produce

F:\SCP\CHAP6>java Regex2 "a.c" "ac abc a c"
3 abc
7 a c

13)
greedy


F:\SCP\CHAP6>java Regex2 ".*xx" "yyxxxyxx"
0 yyxxxyxx

reluctant
F:\SCP\CHAP6>java Regex2 ".*?xx" "yyxxxyxx"
0 yyxx
4 xyxx

14) \n \b \t

15)

F:\SCP\CHAP6>java Regex2 "\d" a1b2c3d44
1 1
3 2
5 3
7 4
8 4

F:\SCP\CHAP6>java Regex2 "\d+" a1b2c3d44
1 1
3 2
5 3
7 44

F:\SCP\CHAP6>java Regex2 "\d*" a1b2c3d44
0
1 1
2
3 2
4
5 3
6
7 44
9

13 - Example with transient (3)

What can we do to avoid the serialization of an object that is not serializable ? The object have to be marked transient and null is returned from the deserialization.


import java.io.Serializable;

public class AnotherClass {
    int aInt = 7;
}


import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class Main implements Serializable {

    int bInt = 5;
    transient AnotherClass aAnotherClass = new AnotherClass();

    public static void main(String[] args) throws Exception {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("Main.ser"));
        Main aMain = new Main();
        System.out.println("" + aMain.bInt + aMain.aAnotherClass.aInt);
        oos.writeObject(aMain);
        oos.close();
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("Main.ser"));
        aMain = (Main) ois.readObject();
        ois.close();
        System.out.println("" + aMain.bInt + " " + (aMain.aAnotherClass!=null?aMain.aAnotherClass.aInt:"null"));
    }
}



run:
57
5 null

Followers