Jumat, 30 Desember 2011

CLASS COLLECTION DAN CLASS ARRAY

Class Collection berisi method - method utility yang sering digunakan, seperti untuk melakukan sorting, melakukan pencarian, mengacak isi List, membalik susunan List, mengcopy potongan List, mengisi List dengan pola tertentu, dll.

Method sort digunakan untuk mengurutkan list berdasarkan logika yang ada pada method Comparable. Item didalam List harus mengimplementasikan interface Comparable, kalau tidak maka gunakan method sort dengan 2 parameter yaitu List dan Object dari class yang mengimplementasikan interface Comparator.

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

public class SortListTest{
             public static void main(){
                         List<Customer> customers = new ArrayList<Customer>();
                         Customer c1 = new Customer();
                         c1.setId(10l);
                         customers.add(c1);
                         Customer c2 = new Customer();
                         c2.setId(2l);
                         customers.add(c2);
                         Customer c3 = new Customer();
                         c3.setId(5l);
                         customers.add(c3);
                      
                         System.out.println("Isi dari List sebelum disorting");
                         for(int i=0; i < customers.size(); i++){
                                       Customer current = customers.get(i);
                                       System.out.println("index ke : " + current.getId());
                         }
                      
                         Collections.sort(customers);
                         System.out.println("Isi dari List setelah disorting");
                         for(int i=0; i < customers.size(); i++){
                                        Customer current = customers.get(i);
                                        System.out.println("index ke : " +current.getId());
                         }
             }
}

Isi dari List sebelum disorting
index ke : 10
index ke : 2
index ke : 5
Isi dari List setelah disorting
index ke : 2
index ke : 5
index ke : 10

kalau class Customer tidak mengimplementasikan interface Comparable, dapat dibuat class customerComparator yang mengimplementasikan interaface Comparator, dan menggunakan method sort yang 2 parameter list of customer dan instace dari customerComparator.

Collection.sort(customers, new customerComparator);

import java.util.Comparator;
public class customerComparator implements Comparator<Customer>{
                 public int compare(Customer c1, Customer c2){
                            return c1.getId().compareTo(c2.getId());
                 }

}

method binarySearch digunakan untuk melakukan pencarian isi List lebih cepat ketimbang menggunakan method indexOf dari interface List. Method binarySearch baru bisa dipanggil kalau isi List telah disorting terlebih dahulu. Method binarySearch menggunakan 2 parameter kalau object dalam list mengimplementasikan interface Comparable. List dan item yang ingin dicari.

public class BinarySearchTest{
            public static void main(String[] args){
                       List<Customer> customers = new ArrayList<Customer>();
                       Customer c1 = new Customer();
                       c1.setId(10l);
                       customers.add(c1);
                       Customer c2 = new Customer();
                       c2.setId(2l);
                       customers.add(c2);
                       Customer c3 = new Customer();
                       c3.setId(5l);
                       customers.add(c3);
                       Collections.sort(customers);
                       int index = Collections.binarySearch(customers, c3);
                       System.out.println("Customer dengan id : " + c3.getId() + " ditemukan diindex ke : " + index);
            }
}

Kalau class Customer tidak mengimplementasikan interaface Comparable, buat class baru customerComparator implementasi dari interaface Comparator. method binarySearch menjadi 3 parameter : list of customers, yang ingin dicari, intansi dari class CustomerCompartor

int index = Collections.binarySearch(customers, c3, new CustomerComparator());

Customer dengan id : 5 ditemukan diindex ke : 1

Untuk mengacak isi dari List ada method shuffle, method shuffle ada dua overload yang pertama hanya satu parameter berupa List, yang kedua menggunakan dua parameter berupa List dan object dari class Random, object random digunakan untuk menentukan jenis randomisasi yang ingin digunakan untuk mengacak list.

Method reverse digunakan untuk membalik isi List, yang di depan menjadi dibelakang dan sebalikya. Semakin banyak dari isi List waktu eksekusinya membesar secara linier.

Method copy digunakan untuk mengcopy isi dari List ke List yang lain, method ini dapat menghemat beberapa baris coding ketimbang mengcopy list secara manual menggunakan perulangan.

Method fill digunakan untuk mengganti isi dari sebuah List dengan sebuah object yang sama. Parameter dari method fill ada dua : List dan object item yang akan digunakan untuk menimpa semua isi dari List.

Method min dan max digunakan untuk mendapat nilai minimum dan maximum dari List. Method ini menyarankan isi dari list mengimplementasikan interface Comparable, jika tidak menambah instance dari class yang mengimplementasikan interaface Comparator kedalam method min dan max.

Method unmodifiable ada beberapa jenis: unmodifiableList, unmodifiableMap, unmodifiableSet, unmodifiableCollection digunakan untuk melindungi collection agar tidak dapat di modifikasi, collection akan bersifat read only, sehingga tidak bisa dimodifikasi dari luar class, contoh class Customer mempunyai property email yang bertipe List of  String.

public class Customer {

Selasa, 27 Desember 2011

SORTING

Sorting adalah sebuah cara untuk membuat collection terurut (sorted). Agar collection terurut perlu membuat item yang dimasukkan kedalam Set  mengimplements interface Comparable. Interface ini digunakan untuk membandingkan dua buah object, mana object yang lebih besar, lebih kecil atau sama persis.

Interface Comparable hanya mempunyai satu buah method yaitu compareTo, method ini mempunyai sebuah parameter yang bertipe Object kalau tidak menggunakan generics, dan bertipe sama dengan class yang mengimplementasikan interface Comparable kalau menggunakan generics, kembalian method berupa integer, kalau bernilai positif maka object yang dipanggil method comparenya lebih besar dari object yang dimasukkan ke parameter, nilai kembalian negatif sebaliknya, kalau nilai kembalian nol berarti sama besar.

Implementasi Comparable pada class Customer.

import java.lang.Comparable;
public class Customer implements Comparable{
           private Long id;
           public void setId (Long aId){
                      this.id = aId;
           }
           public Long getId (){
                      return this.id;
           }
           public int compareTo(Object o){
                     Customer c = (Customer) o;
                     return getId().compareTo(c.getId());
           }
           public boolean equals(Object obj){
                      if(obj == null){
                                   return false;
                      }
                      if(getClass() != obj.getClass()){
                                    return false;
                      }
                      final Customer other = (Customer) obj;
                      if(this.id != other.id && (this.id != null || !this.id.equals(other.id))){
                                    return false;
                      }
                      return true;
           }
           public int hashCode() {
                    int hash = 7;
                    hash = 53 * hash + (this.id != null ? this.id.hashCode() : 0);
                    return hash;
           }
}

Kalau menggunakan generics maka parameter method compareTo bukan bertipe Object melainkan Customer.

import java.lang.Comparable;
public class Customer implements Comparable<Customer>{
           private Long id;
           public void setId (Long aId){
                      this.id = aId;
           }
           public Long getId (){
                      return this.id;
           }

           public int compareTo(Customer c){
                      return getId().compareTo(c.getId());
           }
           public boolean equals(Object obj){
                      if(obj == null){
                                   return false;
                      }
                      if(getClass() != obj.getClass()){
                                    return false;
                      }
                      final Customer other = (Customer) obj;
                      if(this.id != other.id && (this.id != null || !this.id.equals(other.id))){
                                    return false;
                      }
                      return true;
           }
           public int hashCode() {
                    int hash = 7;
                    hash = 53 * hash + (this.id != null ? this.id.hashCode() : 0);
                    return hash;
           }
}

perbandingan dalam method compareTo akan mengurutkan dari id yang kecil ke besar, jika ingin mengurutkan dari id besar ke kecil tinggal dibalik perbandingannya.

public int compareTo(Customer c){
            return c.getId().compareTo(getId());
}

Interface Comparable seperti diatas bisa dilakukan kalau source codenya tersedia misal source code Costumer dapat dimodifikasi class Customer, kalau misalnya class yang ingin diurutkan tidak tersedia source codenya, dapat dilakukan dengan membuat class baru yang meng extends class tersebut sekaligus implements dari class Comparable, sehingga dapat membuat terurut dari class tersebut, kalau classnya berbentuk final yang tidak mungkin di extends dapat dibuat class baru yang implements interface Comparable.

import java.lang.Comparable;
public class CustomerComparable extends Customer implements Comparable<Customer>{
            public int compareTo(Customer c){
                           return getId().compareTo(c.getId());
            }
}

Interface Comparator mempunyai bentuk generics dan bentuk bukan generics, bentuk generics parameter methodnya sudah menjadi class Customer, sedangkan bentuk bukan generics parameternya berbentuk class Object sehingga memerlukan casting untuk diubah menjadi class Customer.

import java.util.Comparator;
public class CustomerComparator implements Comparator<Customer>{
               public  int compare(Customer c1, Customer c2){
                           return c1.getId().compareTo(c2.getId());
               }
}

Setelah Customer mengimplementasi Comparable dapat digunakan collection terurut seperti TreeSet dan TreeMap.

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

public class CustomerTreeSetTest{
            public static void main(String[] args){
                        Set<Customer> customers = new TreeSet<Customer>();
                        Customer c1 = new Customer();
                        c1.setId(1l);  
                        customers.add(c1);
                        Customer c2 = new Customer();
                        c2.setId(2l);
                        customers.add(c2);
                        Customer c = new Customer();
                        c.setId(1l);
                        customers.add(c) // akan direplace yang lama dengan ini
                        Iterator<Customer> iterator = customers.iterator();
                        while(iterator.hasNext()){
                                  Customer current = iterator.next();
                                  System.out.println("Keranjang no - " + current.hashCode() + " id :  " + current.getId());
                        }
            } 
}

Keranjang no - 372 id :  1
Keranjang no - 373 id :  2

TreeSet dan TreeMap mengharuskan item yang dimasukkan mengimplementasikan Comparable. kalau tidak mengimplementasikan buat class Comparator baru yang mengimplementasikan Comparator dan memasukkan object dari class Comparator tersebut kedalam constructor dari TreeSet dan TreeMap tersebut.

Set<Customer> customers = new TreeSet<Customer>(new CustomerComparator());
Map<Customer> customerMaps = new TreeMap<Customer>(new CustomerComparator());

MAP

Map adalah bentuk struktur data yang berpasangan antara key-value. Key bersifat unik karena implementasi menggunakan Set. Key dan value adalah object, bisa object apa saja, tipe data primitif tidak bisa dimasukkan kedalam Map, juga tidak bisa dimasukkan kedalam semua jenis collection.

Implementasi Map memberi kesempatan untuk mencari value berdasarkan key. Setiap dihadapi masalah pencarian berdasarkan value dapat digunakan Map. Map tergantung method equals dan hashCode untuk menentukan apakah dua buah key sama atau tidak, jadi kalau ingin menggunakan object dari class buatan sendiri sebagai key, maka kedua object tersebut harus dioverride untuk menentukan bagaimana kedua object dianggap sama atau tidak.

HashMap adalah class yang mengimplementasikan interface Map. Sifatnya adalah tidak terurut tidak teratur. Implementasi HashMap adalah yang paling efesien implementasi yang lain membutuhkan keteraturan dan keteruturan yang akan menambah komputing sehingga kurang efisien dibandingkan HashMap. HashMap membolehkan satu buah key dengan nilai null dan banyak key bukan null yang valuenya adalah null.

method penting yang dimiliki Map
put (Object key, Object value) method yang digunakan untuk meletakkan pasangan key dengan value.
getObject(Object key) method yang digunakan untuk mendapatkan value dari key yang dimasukkan sebagai parameter.
keySet(); digunakan untuk mendapatkan Set yang berisi semua key, digunakan untuk mendapatkan Set dari key untuk mengambil nilai Map satu per satu.

Membuat Map dimana key adalah kota dan valuenya adalah kumpulan customer yang tinggal di kota tersebut.. Tipe data key adalah String dan tipe data value adalah List of Customer.

import java.util.Set;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;

public class MapTest{
           public static void main (String[] args){
                      Map<String, List<Customer>> customerByCityMap = new HashMap<String, List<Customer>>();
                       List<Customer> jakartaCust = new ArrayList<Customer>();
                       Customer a = new Customer();
                       a.setId(1l);
                       jakartaCust.add(a);
                       Customer b = new Customer();
                       b.setId(2l);
                       jakartaCust.add(b);
                       customerByCityMap.put("Jakarta",jakartaCust);
                       List<Customer> surabayaCust = new ArrayList<Customer>();
                       Customer c= new Customer();
                       c.setId(3l);
                       surabayaCust.add(c);
                       customerByCityMap.put("Surabaya",surabayaCust);
                       Set<String> keys = customerByCityMap.keySet();
                       Iterator<String> iterator = keys.iterator();
                       while(iterator.hasNext()){
                                String key = iterator.next();
                                List<Customer> customers = customerByCityMap.get(key);
                                for(int i = 0; i < customers.size(); i++){
                                        Customer cust = customers.get(i);
                                        System.out.println ("kota " + key + " customer " + cust.getId());
                                }
                       }
           }
 
}

kota Jakarta customer 1
kota Jakarta customer 2
kota Surabaya customer 3

SET

Set adalah collection yang bersifat unik, arti unik adalah dengan mengoverride method equals dah hashCode dari class yang akan dimasukkan dalam Set. Semua class wrapper seperti String telah mengoverride method equals dan hashCode, sehingga dua buah object dianggap sama jika string didalamnya sama. Untuk class yang dibuat sendiri seperti class Customer maka method equals dan hashCode harus di override dahulu sebelum dimasukkan kedalam Set, kalau tidak dioverride maka kedua object dianggap sama jika mempunya reference ke object yang sama ( tidak sesuai harapan ).

Class implementasi dari interface Set yang paling sering digunakan adalah HashSet. Nilai kembalian dari method hashCode sangat penting dalam class HashSet karena digunakan untuk menentukan dimana object tersebut diletakkan pada HashSet. Ketika method add dipanggil dengan parameter object, HashSet akan memanggil method hashCode dari object tersebut untuk menentukan di keranjang mana object tersebut akan diletakkan. Setelah menemukan nomor keranjangnya maka dicek apakah keranjang tersebut kosong atau tidak. Kalau kosong maka object akan langsung diletakkan pada keranjang tersebut. Kalau keranjang ada isinya maka dilakukan pengetesan dengan method equals, kalau ada object dalam keranjangan dilakukan pengetesan dengan method equals menghasilkan true, maka object lama akan ditimpa dengan object baru.

Kecepatan pencarian pada HashSet tergantung dari perhitungan hashCode, Kalau method hashCode selalu return 1 maka object dalam keranjang HashSet akan diletakkan pada keranjang yang sama sehingga pencarian menjadi linier karena akan dibandingkan isinya dengan method equals satu per satu. Kalau setiap object memiliki hashCode yang unik maka pencarian akan cepat.

Kalau nilai hashCode tidak selalu unik. HashSet akan melihat isi dalam keranjang, kalau ada satu object maka object tersebut merupakan kembalian pencarian, kalau tidak ada object maka kembaliannya null, kalau ada beberapa object maka akan ditest menggunakan method equals, ketika method equals menghasilkan true maka object tersebut adalah hasil pencarian.

Jika dua buah object dipanggil method equals menghasilkan nilai true tetapi hashCodenya berbeda (menyalahi aturan), maka hashSet kedua object ini dianggap berbeda karena diletakkan pada keranjang yang berbeda karenak keranjangnya berbeda maka method equals akan diabaikan, tidak pernah dipanggil. Jadi harus ditaati kalau dua object dioperasikan dengan method equals menghasilkan kembalikan true, maka hashCodenya harus berbeda.


Keranjang           1         2         3
                           "a"      "b"      "ab"
                                                 "ba"

Algoritma sederhana menghitung hashCode dari class String adalah dengan menambahkan urutan dari huruf misal, String "a" nilai hashCodenya 1, String "b" nilai hashCodenya 2, String "ab" dan "ba" nilai hashCodenya 3, string "ab" dan "ba" diletakkan pada keranjang yang sama karena nilai hashCodenya sama tetapi tidak ditimpa karena "ab".equals("ba") menghasilkan false.

import java.util.*;
public class CustomerSetTest{
              public static void main(String[] args){
                         Set<Customer> customers = new HashSet<Customer>();
                         Customer id1 = new Customer();
                         id1.setId(1l);
                         customers.add(id1);
                         Customer id2 = new Customer();
                         id2.setId(2l);
                         customers.add(id2);
                         Customer c = new Customer();
                         c.setId(1l);
                         customers.add(c); // mereplace id 1 karena no idnya sama
                         Iterator<Customer> i = customers.iterator();
                         while(i.hasNext()){
                                   Customer current = i.next();
                                   System.out.println("Keranjang no- " + current.hashCode() + " idnya : " + current.getId() );
                         }
              }
}

Keranjang no- 373 idnya : 2
Keranjang no- 372 idnya : 1

no keranjang tidak berurut dari kecil ke besar, HashSet hanya menekankan pada sifat yang unik saja, sedangkan urutan dan keteraturan tidak dijamin.

LIST

List adalah jenis collection yang teratur (ordered) tetapi tidak terurut (unsorted). List memiliki index yang disusun beradasarkan kapan item dimasukkan kedalam List. Isi dari list bersifat tidak unik, artinya dua buah item yang sama bisa dimasukkan berkali - kali kedalam List. Method penting didalam list

get (int index) : method ini digunakan untuk mengambil isi dari list berdasarkan index (urutan item masuk ke dalam List)
indexOf (Object o) : method ini digunakan untuk mengetahui berapa nomor index dari object yang ada didalam list.
add (Object o) : method ini digunakan untuk menanmbakan object kedalam List
add (int index, Object o) : menambahkan object kedalam List di index tertentu.

Class ArrayList adalah Class yang mengimplementasikan interface List, class ArrayList adalah Array yang dapat bertambah ukurannya. Vector adalah class juga yang mengimplementasikan interface List. Vector adalah pendahulu ArrayList yang performannya kurang baik.

LinkedList adalah implementasi dari interface List yang menambah method baru untuk menambah atau menghapus isi dari List dari depan atau dari belakang, cocok digunakan untuk membuat tumpukan (stack) ,  antrian (queue)

import java.util.*;
public class ListTest {
           public static void main (String[] args){
                    List<String> list = new ArrayList<String>();
                    list.add("a");
                    list.add("b");
                    list.add("c");
                    list.add("a");
                    list.add("z");
                    System.out.println("Isi dari list adalah ");
                    for(int i=0; i < list.size(); i++){
                              System.out.println("isi index ke - "+i +" = " +list.get(i));
                    }
          }
}

Isi dari list adalah
isi index ke - 0 = a
isi index ke - 1 = b
isi index ke - 2 = c
isi index ke - 3 = a
isi index ke - 4 = z

item dalam list / isi list tidak unik bisa double dan juga tidak terurut, hanya teratur sesuai index yang dimasukkan terlebih dahuli.

Senin, 26 Desember 2011

JAVA COLLECTION FRAMEWORK

Dalam Java Collection API ada beberapa interface kunci yang merupakan dasar dari collection yang ada dalam interface

Collection                Set                                     SortedSet
List                          Map                                   SortedMap
Queue                      NavigableSet                    NavigableMap

Map, Set, List, Queue diimplementasikan oleh clas

Map                          Set                            List                        Queue
HashMap                 HashSet                    ArrayList               PriorityQueue
HashTable                LinkedHashSet         Vector
TreeMap                  TreeSet                      LinkedList
LinkedHashMap

Setiap jenis collection diatas mempunya 4 variant, terurut (sorted), tidak terurut, teratur (ordered), tidak teratur.

Terurut artinya isi collection tersebut terurut berdasarkan nilai tertentu dari objectnya, contohnya class Customer terurut berdasarkan id, atau property lain di dalam class Customer.

Teratur adalah collection yang diatur berdasarkan kapan item tersebut dimasukkan kedalam collection, item yang dimasukkan pertama akan berada diawal collection, item yang dimasukkan terakhir akan berada di akhir collection

Kamis, 22 Desember 2011

EQUALS DAN HASHCODE

method equals dan hashcode berperan sangat penting dalam collection. Method equals digunakan untuk membandingkan dua buah object apakan sama atau tidak secara logis. Operator == dapat digunakan untuk membandingkan dua buah  object, tetapi perbandingan ini hanya menghasilkan nilai yang true kalau dua buah object apakah berada dalam memory yang sama, atau bisa dibilang dua buah object mempunyai reference yang sama persis, baik secara alamat memory dan otomatis sama secara logis.

Method equals akan mengembalikan nilai true kalau kedua object sama secara logis walaupun kedua object mempunyai reference yang berbeda (tidak berada di memory yang sama). Contoh String, dua buah object string akan menghasilkan false jika dioperasiakan dengan == walaupun string didalamnya sama. Tetapi method equals akan menghasilkan nilai true walaupun objectnya berada didalam memory yang berbeda asalkan nilai stringnya sama.

public class EqualsTest{
            public static void main(String[] args){
                         String abc = new String("abc");
                         String abc1 = new String("abc");
                         boolean equalsOperator = (abc == abc1);
                         System.out.println("abc == abc ? " + equalsOperator);
                         boolean equalsMethod = abc.equals(abc1);
                         System.out.println("abc.equals(abc) ? " + equalsMethod);
             }
}

abc == abc ? false
abc.equals(abc) ? true

Jika kita ingin membandingkan dua buah object apakah sama secara logis, kita akan menggunakan method equals, tetapi masalahnya implementasi method equals dari class Object sama persis dengan menggunakan operator ==, sehingga harus di override agar walau dua buah object yang berbeda tetap dianggap sama asalkan suatu kriteria terpenuhi.

Misalkan class Customer, dua buah object customer dianggap sama asalkan idnya sama, oleh karena itu method equals dioverride

public class Customer{
           private Long id;
           public void setId (Long aId){
                      this.id = aid;
           }
           public Long getId (){
                      return this.id;
           }
           public boolean equals(Object obj){
                      if(obj == null){
                                   return false;
                      }
                      if(getClass() != obj.getClass()){
                                    return false;
                      }
                      final Customer other = (Customer) obj;
                      if(this.id != other.id && (this.id != null || !this.id.equals(other.id))){
                                    return false;
                      }
                      return true;
           }
}

method hashCode akan mengembalikan nilai integer yang unik untuk setiap object yang berbeda 

method hashCode dari sebuah object harus mengembalikan nilai yang sama walaupun dieksekusi berkali kali selama nilai property didalamnya tidak berubah.
Kalau dua buah object dioperasikan dengan method equals mengembalikan nilai true maka method hashCode dari kedua object harus mengembalikan nilai integer yang sama. Sebaliknya kalau dua buah object mengembalikan nilai false maka hashCode untuk kedua object akan mengembalikan nilai integer yang berbeda.
Kalau dua buah object dioperasikan dengan method equals mengembalikan nilai false maka hashCode kedua object tidak harus mengembalikan nilai interger yang berbeda, sama pun tidak masalah.

method hashCode akan digenerate dengan sendirinya oleh IDE seperti netbeans, eclipse, dll

public class Customer{
            private Long id;
            public void setId(Long aId){
                      this.id = aId;
           }
           public Long getId(){
                        return id;
           }
           public boolean equals(Object obj){
                      if(obj == null){
                               return false;
                      }
                      if(getClass() != obj.getClass()){
                               return false;
                      }
                      final Customer other = (Customer) obj;
                      if(this.id != other.id && (this.id != null || !this.id.equals(other.id))){
                               return false;
                     }

           }
           public int hashCode() {
                    int hash = 7;
                    hash = 53 * hash + (this.id != null ? this.id.hashCode() : 0);
                    return hash;
           }

}

HashCode sangat vital ketika menggunakan collection yang memanfaatkan nilai hashCode, seperti HashSet HashMap. Perhitungan hashCode yang salah akan mengakibatkan kedua jenis collection ini berantakan.

TOSTRING

Setiap class pastin extends class Object, class Object memiliki 7 method setiap method mempunyai tujuan tertentu.
wait();
notify();
notifyAll();
finalize();
toString();
equals();
hashCode();

Method toString digunakan oleh java untuk mendapatkan representasi string dari object atau class. Implementasi default dari class object adalah mencetak nama class diikuti oleh alamat memory dari object tersebut.

public class ToStringTest{
           public static void main(String[] args){
                      ToStringTest test= new ToStringTest();
                       System.out.println("Implementasi toString dari class Object menghasilkan : " + test);
           }
}

ToStringTest@1e73498

String yang dikembalikan method toString tidak deskriptif, dapat di override method toString agar string yang dikembalikan lebih deskriptif.

public class ToStringOverrideTest{
            public String toString(){
                        return "Ini string dari class ToStringOverrideTest";
            }
            public void main (String[] args){
                       ToStringOverrideTest test = new ToStringOverrideTest();
                       System.out.println("Implementasi toString dari class Object menghasilkan : " + test);
            }
}

INTERFACE

Ketika mendeklarasikan class yang mengimplementasikan interface, menandatangani kontrak untuk mengimplementasikan semua method di dalam interface.

public interface PersonDao{
            void save(Person p);
            void delete(Person p);
            Person getById(long id);
}

Class PersonDaoImpl yang akan mengimplementasikan interface Person dao, maka semua method yang ada di interface PersonDao akan diimplementasikan juga

public class PersonDaoImpl implements PersonDao{
              public void save (Person p){
                          System.out.println("Menyimpan person");
              }
              public void delete (Person p){
                          System.out.println("Menghapus person");
             }
             public Person getById (Long id){
                          Person p = new Person();
                          p.setId(id);
                          p.setNama("abc");
                          return p;
             }
}

Cara agar tidak semua method dalam interface diimplementasikan pada class implementasinya dengan menggunakan keyword abstract pada deklarasi class, serta gunakan keyword abstract pada method yang tidak diimplementasikan.

public abstract class PersonDaoImpl implements PersonDao{
                public void save(Person p){
                          System.out.println("Menyimpan person");
                }
                public void delete(Person p){
                          System.out.println("Menghapus person");
                }
                public abstract Person getById(Long id)
}

Pada dasarnya interface adalah sebuah class yang dideklarasikan dengan keyword abstract dan semua method didalamnya bersifat public abstract, interface PersonDao statusnya setara seperti

public abstract class PersonDao{
            public abstract void save(Person p);
            public abstract void delete(Person p);
            public abstract Person getById(Long id);
}

Tetapi tetap saja interface dengan class adalah dua hal yang berbeda.
Interface sama hal nya dengan class dapat meng extends interface lain. Interface yang meng extends interface lain akan mempunyai semua method yang digunakan oleh class orang tuanya.

CASTING VARIABLE REFERENCE

Polimorfisme mengijinkan sebuah variable yang dideklarasikan menggunakan class orang tuanya diinisiasi dengan object menggunakan class anaknya. Bagaimana sebuah variable yang dideklarasikan menggunakan class orangtuanya diinisiasi dengan object menggunakan class anaknya akan diassign ke variable lain dengan tipe anaknya. Hal ini bisa dilakukan dengan menggunakan casting

Customer c = new MemberCustomer();
// casting berhasil karena c diinisiasi dengan class MemberCustomer
MemberCustomer mc = (MemberCustomer) c
c = new Customer();
// casting gagal dan terjadi ClassCastException karena c diinisiasikan dengan
// class Customer
mc = (MemberCustomer) c;
String s = "ini string";
// kode ini gagal dikompile karena String tidak ada hubungan sama sekali dengan
// class MemberCustomer
mc = (MemberCustomer) s;

Rabu, 21 Desember 2011

OVERRIDING DAN OVERLOADING

Setiap class meng extends class lain, class tersebut bisa meng overriding method yang ada di dalam class orang tuanya. Alasannya karena di class anak ingin mengimplementasikan method tersebut dengan cara yang berbeda. Misal dalam class MemberCustomer akan mengoverride method setId, untuk memeriksa apakan id yang dimasukkan null atau tidak, kalau null maka pesan akan di munculkan ke dalam console. Setelah pesan dicetak, method setId yang dipunyai oleh orang tua yang dipunyai oleh class Customer, hal ini bisa dilakukan dengan keyword super.

import java.io.Serializable;

public class MemberCustomer extends Customer implements Serializable{
            public void setId(Long aId){
                       if(aId ==  null){
                                  System.out.println("nilai id tidak boleh null");
                       }else {
                                 super.setId(aId);
                       }
            }
}

Overriding method dilakukan dengan cara mendeklarasikan method yang sama persis dengan method yang ada di class Orang Tuanya. Deklarasi method harus sama persis mulai dari access modifier, keyword yang digunakan, nama method, jumlah parameter, letak parameter, hingga deklarasi throws exception.

Apa yang terjadi jika mendeklarasikan sebuah variable dengan tipe Customer dan diinisiasi dengan object dari MemberCustomer, method setId milik siapa yang akan dieksekusi? Method yang dioverride akan terikat dengan instace dari variable bukan tipe dari variable, jadi yang akan dieksekusi adalah method dari MemberCustomer bukan dari Customer

public class OverridingTest{
          public static void main (String[] args){
                     Customer c = new Customer();
                     Customer mc = new MemberCustomer();
                     Long id = null;
                     // method yang dipanggil adalah yang dari class Customer karena c
                     // dideklarasikan dengan tipe Customer dan di inisiasi dengan class
                     // Customer
                     c.setId(id);

                     //method yang dipanggil adalah yang dari class MemberCustomer
                     // karena mc dideklarasi dengan tipe Customer dan diinisiasi dengan
                     // class MemberCustomer
                     mc.setId(id);

          }
}

Method overload merupakan feature dalam java dimana dua method dapat di deklarasikan dengan nama yang sama asalakan mempunyai argumen yang berbeda, baik dari jumlah tipe atau urutan parameternya

public void setId(Long aId){}
public void setId(Integer aId){}
public void setId(Long aId, boolean checkNull){}
public void setId(boolean checkNull, Long aId){}

Overriding dan Overloading juga berlaku pada constructor, karena pada dasarnya constructor adalah method.

POLIMORFISME (POLYMORPHISM)

Secara harfiah (makna kata) artinya banyak bentuk. Sebuah object dapat diassign kedalam tipe yang berbeda - beda. Contohnya MemberCustomer, MemberCustomer IS-A :
Object, karena semua class pasti extends Object
Customer, karena MemberCustomer turunan Customer
MemberCustomer

jadi kalau ada variable bertipe Object, Customer, MemberCustomer bisa diassign dengan instance dari MemberCustomer

Object o = new MemberCustomer();
Customer c = new MemberCustomer();
MemberCustomer mc = newMemberCustomer();

Object object = mc;
Customer cust = mc;

Interface juga bisa digunakan dalam skenario IS-A, misal class MemberCustomer juga bisa mengimplementasikan sebuah interface, kemudian interface ini bisa digunakan sebagai tipe variable yang bisa diassign dengan instace dari MemberCustomer.

public class MemberCustomer extends Customer implements Serializable {}

Sekarang kita bisa mendeklarasikan varible bertipe Serializable dengan mengassign instance dari MemberCustomer ke dalam variable tersebut, atau dengan kata lain MemberCustomer IS-A Serializable.

Serializable s = new MemberCustomer();

Jadi MemberCustomer mempunyai banyak bentuk.

INHERITANCE, IS-A, HAS-A

Inheritance (turunan) ada di mana-mana dalam Java. Sangat tidak mungkin membuat aplikasi tanpa melibatkan konsep Inheritance, faktanya setiap class yang kita tulis adalah turunan dari class Object. Anda ingin bukti? Ingat-ingat lagi bab tentang operator, di sana ada satu operator instanceof, operator ini digunakan untuk mengetes apakah sebuah object merupakan tipe dari suatu class. Operator ini akan mengembalikan true kalau tipe dari object tersebut adalah class yang ada di operand sebelah kanan dari operator instanceof, sebaliknya nilainya adalah false.

public class InheritanceTest{
            public static void main(String[] args){
                     InheritanceTest test = new InheritanceTest();
                     if (test instanceof Object ){
                               System.out.println("test tipenya Object");
                    } else {
                               System.out.println("test tipenya bukan Object");
                    }
           }
}

test tipenya Object

Terbukti bahwa walaupun tidak secara eksplisit kita defnisikan InheritanceTest sebagai turunan dari Object

Implementasi inheritance dalam kode menggunakan keyword extends. Kalau kita ingin membuat sebuah class turunan dari class yang lain, kita gunakan keyword extends setelah deklarasi nama class diikuti dengan class yang ingin digunakan sebagai orang tua dari class tersebut. Misalnya kita ingin akan membuat dua buah class, class pertama adalah Customer sedangkan class kedua adalah MemberCustomer, dimana class MemberCustomer adalah turunan dari class Customer. Kode class Customer adalah seperti di bawah ini

public class Customer{}

public class MemberCustomer extends Customer {}

Class MemberCustomer dalam hal ini mempunyai hubungan IS-A dengan class Customer. Kalimat lengkapnya adalah “MemberCustomer IS-A Customer”. Hal ini dikarenakan MemberCustomer adalah turunan Customer, analoginya kita bisa menggunakan kucing dan hewan. Kucing adalah turunan dari hewan, maka kucing adalah hewan. Sama juga seperti MemberCustomer adalah turunan dari Customer, maka MemberCustomer adalah Customer.

Apa tujuan dari inheritance dilihat dari sisi kode? Yang pertama adalah mempromosikan code reuse, yaitu penggunaan kembali kode yang sudah ditulis. Hal ini dikarenakan, sebagai turunan dari Customer, MemberCustomer akan mempunyai semua sifat-sifat (kode) dari class Customer. Misalnya kita ubah sedikit kode di atas, kita tambahkan property dan method di dalam class Customer :

public class Customer{

           private Long id;

           public Long getId(){
                     return id;
          }

          public void setId (Long aId){
                     this.id = aId;
         }

}

public class MemberCustomer extends Customer {}

public class CustomerTest {
          public static void main(String[] args) {
                  MemberCustomer member = new MemberCustomer();
                  member.setId(100l);
                  System.out.println("id customer : " + member.getId());
          }
}

id customer : 100

Terlihat bahwa tidak ada error dalam proses kompilasi, padahal class MemberCustomer tidak mendefnisikan apapun, tetapi method setId dan getId dapat digunakan. Hal ini dikarenakan MemberCustomer mengextends Customer, sehingga method setId dan getId diturunkan. Catat juga bahwa property id sendiri tidak diturunkan ke dalam MemberCustomer, karena property id menggunakan private sebagai access modifer.

Hubungan HAS-A lebih sederhana. Hubungan HAS-A atau komposisi (composition) terjadi kalau sebuah class mempunyai sebuah property. Misal kita dapat melihat Customer HAS-A Long dengan nama id.

Buat satu class dengan nama Adress, class ini digunakan oleh Customer untuk mendefinisikan alamat Customer

public class Address {
            private String street;
            private String city;
            private String postCode;
}

Hubungan antara class Customer dengan Address adalah HAS-A, diimplementasikan dengan membuat property dengan tipe Address pada class Customer.

public class Customer {
            private Long id;
            private Address address;

            public void setId (Long aId){
                       this.id = aId;
            }
           
            public Long getId(){
                       return this.id;
            }

            public void setAddress (Address aAddress){
                       this.address =  aAddress;
            }

            public Address getAdress(){
                        return this.address;
            }
}

Kode diatas memperlihatkan hubungan HAS-A antara Customer dengan Address

ENKAPSULASI

Enkapsulasi adalah konsep dimana sebuah logic kode dibungkus dalam satu bentuk kode yang menggambarkan dunia nyata. Class adalah sebuah enkapsulasi dari perilaku yang diwakilinya dalam dunia nyata. Setiap entitas dalam dunia nyata mempunyai karakteristik dan perilaku. Karakteristik diwujudkan sebagai property dan perilaku diwujudkan sebagai method. Kedua hal ini karakteristik dan perilaku dienkapsulasi menjadi satu entitas dalam class.

Bahasa prosedural tidak memiliki feature enkapsulasi ini, kalau kita melihat kode kita tidak bisa melihat wujud abstract kode tersebut dengan dunia nyata. Semua hanya fungsi / method data berceceran di sana / sini. OOP memberikan konsep yang praktis bagaimana menjembatani logic yang ada didunia nyata dengan wujudnya dalam kode. Misal kita berbicara tentang customer, kita berbicara tentang customer yang nyata juga berbicara tentang class Customer yang ada dalam kode.

Enkapsulasi menyebabkan kode menjadi self explaind, artinya hanya dengan melihat kode dapat mengetahui apa logic dibalik kode ini, atau kita bisa mengetahui apa maksud dari kode yang sedang kita baca.

OOP DENGAN JAVA

Implementasi OOP yang baik dapat menyebabkan 2 kualitas dalam aplikasi
modular (modularity)
mudah dipelihara (maintenability)

DO - WHILE

Bentuk do - while digunakan kalau ingin agar setidaknya satu iterasi terjadi baru kemudian ditest kondisinya apakah iterasi berikutnya dilaksanakan atau tidak, sama dengan bentuk while bentuk do-while hanya memerlukan 1 parameter yang bentuknya kondisi di dalam whilenya.

do{

}while(kondisi);

public class DoWhileTest{
           public static void main(String[] args){
                      do{
                                 System.out.println(System.currentTimeMillis() + " Waktu sekarang dibagi 3 masih ada sisanya");
                      }while(System.currentTimeMillis() % 3 != 0);
           }
}

Setidaknya string di dalam while akan di print 1 kali.

WHILE

Bentuk iterasi while digunakan kalau kita tidak tau berapa banyak iterasi yang akan berlangsung, tetapi tau iterasi kapan berhenti dari sebuah kondisi tertentu. bentuk syntak sangat sederhana hanya memerlukan 1 parameter kondisi yang bernilai true atau false, selama kondisi di dalam parameter bernilai true makan akan dilakukan iterasi, kalau kondisi bernilai false maka iterasi akan berhenti.

while(kondisi){
}

Contoh membagi waktu sekarang jika dibagi 3 sisanya 0, selama tidak memenuhi kondisi maka iterasi akan terus berjalan.

public class WhileTest{
             public static void main(String[] args){
                          while(System.currentTimeMillis() % 3 != 0){
                                         System.out.println(System.currentTimeMillis() + " Waktu sekarang dibagi tiga masih ada sisanya");
                           }
             }
}

1324471098596 Waktu sekarang dibagi tiga masih ada sisanya
1324471098596 Waktu sekarang dibagi tiga masih ada sisanya
1324471098596 Waktu sekarang dibagi tiga masih ada sisanya
1324471098596 Waktu sekarang dibagi tiga masih ada sisanya
1324471098596 Waktu sekarang dibagi tiga masih ada sisanya
1324471098596 Waktu sekarang dibagi tiga masih ada sisanya

iterasi kode diatas bisa dilakukan 1 kali, 2 kali, banyak kali atau bahkan tidak.

FOR

keyword  for digunakan untuk melakukan iterasi kalau jumlah iterasinya tertentu, misal jika ingin melakukan iterasi sebanyak 10 kali atau 100 kali. Iterasi menggunakan for memerlukan 3 parameter, parameter pertama digunakan untuk batas bawah, parameter kedua adalah kondisi kapan iterasi berhenti, parameter ketiga digunakan untuk menaikkan atau menurunkan counter.

for(parameter1; parameter2; parameter3){

}

bentuk nyata keyword for

public class ForTest{
          public static void main(String[] args){
                     for(int i=0; i < 10; i++){
                                System.out.println("Iterasi Ke - " + i);
                     }
          }
}

Parameter pertama disi dengan int i = 0, artinya variable i digunakan sebagai counter (penghitung) diawali dengan 0, parameter kedua diisi dengan i < 10 artinya iterasi (perulangan) akan terus dilakukan sampai nilai i kurang dari 10, dan berhenti ketika nilai i mencapai 10. Parameter ketiga diisi dengan i++ artinya setiap kali iterasi maka counter i akan naik 1 nilai

Iterasi Ke - 0
Iterasi Ke - 1
Iterasi Ke - 2
Iterasi Ke - 3
Iterasi Ke - 4
Iterasi Ke - 5
Iterasi Ke - 6
Iterasi Ke - 7
Iterasi Ke - 8
Iterasi Ke - 9

iterasi juga dapat dilakukan mundur

public class ForMundurTest{
            public static void main(String[] args){
                       for(int i = 10; i > 0; i--){
                                     System.out.println("Iterasi ke - " + i);
                       }
            }
}

Iterasi ke - 10
Iterasi ke - 9
Iterasi ke - 8
Iterasi ke - 7
Iterasi ke - 6
Iterasi ke - 5
Iterasi ke - 4
Iterasi ke - 3
Iterasi ke - 2
Iterasi ke - 1

Senin, 19 Desember 2011

PERULANGAN / ITERASI

ada 3 yaitu for, while, do-while

THROWS DAN THROW

Cara kedua adalah dengan melempar exception ke method pemanggilnya, kalau tidak ada satupun method yang menangkap exception maka aplikasi akan keluar dari eksekusi. Sintaknya menggunakan keyword throws yang diletakkan di deklarasi method.

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class ThrowsExceptionTest{
               public static void main(String[] args) throws FileNotFoundException, IOException {
                           FileInputStream inputStream = new FileInputStream("buka-file.txt");
                           System.out.println("Kode setelah buka file");
              }
}

Kode diatas tidak akan error saat dikompilasi karena ada keyword throws disebelah method main yang menyebabkan method main tidak perlu lagi ada try catch, karena method main adalah method yang paling bawah pada call stack kalau ada exception yang tidak di handle oleh method main maka aplikasi akan langsung keluar, aturan ini hanya berlaku pada checked exception.

exception dilempar di satu method yang nantinya akan exception akan ditangkap oleh method pemanggilnya

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class ThrowsExceptionAnotherTest{
           public static void main(String[] args) {
                    try{
                              methodTidakBertanggungJawab();
                   } catch(FileNotFoundException ex){
                              ex.printStackTrace();
                   } catch(IOException ex){
                              ex.printStackTrace();
                   }                    
                   System.out.println("kode di dalam main");
           }
           public static void methodTidakBertanggungJawab() throws FileNotFoundException, IOException {
                    FileInputStream inputStream = new FileInputStream("buka-file.txt");
                    System.out.println("Kode setelah buka file");
           }
}

method tidak bertanggung jawab akan melempar exception pada method main, method main menghandle exception sendiri sehingga aplikasi tidak keluar dan string "kode di dalam main" di cetak.

keyword throw digunakan seperti pada Class Exception

Sabtu, 17 Desember 2011

HIRARKI CLASS EXCEPTION

Object

Throwable
Error                                               Exception

                                     RuntimeException

Exception dimulai dari Object kemudia ada class Throwable yang merupakan parent class dari semua jenis Exception, ada dua class yang merupakan turunan langsung dari class Throwable yaitu class Error dan class Exception, class Exception mempunyai satu turunan yaitu Runtime Exception.

Error biasa kesalahan yang tidak disebabkan terjadi karena kesalahan dalam aplilasi, lebih karena kepada keadaan JVM yang tidak normal, misalnya error karena kehabisan memory. Error tidak perlu di handle oleh try catch karena tidak ada cara untuk mengatasi itu. Secara teknis sebenarnya error bukanlah exception karena bukan merupakan turunan dari class Exception.

Class RuntimeException adalah class spesial yang disebut juga dengan unchecked exception. Disebut unchecked exception karena RuntimeException tidak perlu wajib di catch, seperti NullPointerException, ClassCastException, IndexOfBoundException

contoh RuntimeException
public class RuntimeExceptionTest{
             public static void main(String[] args){
                        int i = Integer.parseInt("abc");
                        System.out.println("kode setelah exception");
             }
}

menyebabkan error karena berusaha merubah String "abc" menjadi angka, tidak ada statement try catch untuk menghandle runtime Exception. Tanpa adanya try catch maka akan segera keluar dari method, karena ini method main dan tidak ada method yang lain (analogi call stack dengan gedung tinggi), aplikasi akan keluar dan "kode setelah exception" tidak akan ditampilkan

Jika tidak yakin dengan string yang diubah ke integer kita dapat meletakkan statement try catch.

public class RuntimeExceptionTest{
             public static void main(String[] args){
                       int i = 0;
                       try{
                                 i = Integer.parseInt("abc");
                       }catch(NumberFormatException ex){
                                 ex.printStackTrace(); 
                       }
                        System.out.println("kode setelah exception");
             }
}

saat terjadi exception kode akan melompat ke catch dan mencetak stack trace ke konsole kemudian melanjutkan print string "kode setelah exception" ke console sehingga kode menjadi lebih handal dan tidak menyebabkan program keluar sebelum eksekusi selesai semuanya.
Class Exception yang bukan turunan dari RuntimeException adalah checked exception. Kode didalam tipe ini harus diletakkan dalam blok try jika tidak maka akan terjadi kompilasi error. Contoh kode untuk membuka file yang mengandung checked exception yaitu IOException

import java.io.FileInputStream;
public class CheckedExceptionTest{
           public static void main(String[] args){
                       FileInputStream inputStream = new FileInputStream("buka-file.txt");
                       System.out.println("kode setelah buka file");
           }
}


kompilasi error


CheckedExceptionTest.java:7: error: unreported exception FileNotFoundException; must be caught or declared to be thrown
                       FileInputStream inputStream = new FileInputStream("buka-file.txt");

tambahkan try catch

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class CheckedExceptionTest{
           public static void main(String[] args){
                 try{
                       FileInputStream inputStream = new FileInputStream("buka-file.txt");
                 }catch(FileNotFoundException ex){
                       ex.printStackTrace();
                 }catch(IOException ex){
                        ex.printStackTrace();
                 }
                  System.out.println("kode setelah buka file");
           }
}

bisa juga hanya dihandle oleh IOException karena FileNotFoundException merupakan turunan dari class IOException


import java.io.FileInputStream;
import java.io.IOException;

public class CheckedExceptionTest{
           public static void main(String[] args){
                 try{
                       FileInputStream inputStream = new FileInputStream("buka-file.txt");
                 }catch(IOException ex){
                        ex.printStackTrace();

                 }
                  System.out.println("kode setelah buka file");
           }
}

IOException juga merupaka turunan dari class Exception sehingga dapat juga di tangkap dengan class Exception artinya semua exception dapat ditangkap dengan class Exception tetapi tidak demikian karena penangkapan exception harus pada class Exception yang spesifik

CLASS EXCEPTION

Exception bisa berasal dari JVM dan Aplikasi, exception yang berasal dari JVM bersifat umu dan dapat terjadi di semua aplikasi, seperti NullPointerException, IndexOfBounException, ClassNotFoundException. Dapat juga membuat class exception sendiri yang spesifik terhadap aplikasi.

public class ExceptionPertama extends Exception{
           public ExceptionPertama(){}
           public ExceptionPertama(String pesan){
                       super(pesan);
           }
}

Class ExceptionPertama harus meng-extends class Exception yang sudah disediakan JDK

public class ExceptionPertamaTest {
            public static void main(String[] args){
                       try{
                                   System.out.println("eksekusi exception pertama");
                                   throw new ExceptionPertama("ini pesan exception pertama");
                       }catch(ExceptionPertama ex){
                                   ex.printStackTrace();
                       }
            }
}

Class exception secara default akan mempunyai semua method yang dipunyai pada class Exception, salah satunya printStackTrace();