Thứ Bảy, 23 tháng 2, 2008

Class, Object Và Vấn Đề Đa Hình trong Java

Java là một ngôn ngữ thuần hướng đối tượng. Nó mang đầy đủ các đặc tính của một ngôn ngữ hướng đối tượng như:

  • Encapsulation – đóng gói: Hides the implementation details of an object and therefore hides its complexity.
  • Abstraction – trừu tượng hóa: we just focuses on the essential features of an object.
  • Inheritance – kế thừa: creates a hierarchy of clauses and helps in reuse of attibutes and methods of class.
  • Polysmorphism – đa xạ: performs different reactions in objects in response to the some method

Các bổ tử của một method:

* public: cỏ thể truy cập từ bên ngoài class

* protected: chỉ được truy cập từ class đó và các class kế thừa từ class đó

* private: chỉ được truy cập trong class định nghĩa

* static: phương thức chung cho mọi mẫu của class

* abstract: không cài đặt gì trong class, việc cài đặt được giao cho các class đế thừa của class đó

* final: không cho phép overloading ở các class dẫn xuất

* native: một cài đặt phụ thuộc một ngôn ngữ khác, như C hay hợp ngữ

* synchronized: dùng để chỉ một phương thức tới hạn ngăn các tác động của các object khác lên object trong khi việc đồng bộ hóa đang thực hiện.

Các bổ tử của một class:

* public: lớp có thể truy cập từ các lớp khác trong package

* final: lớp không cho phép tạo dẫn xuất

* abstract: lớp trừu tượng

Lớp trừu tượng (abstract):

class không cụ thể, chứa những method nhưng không có dòng lệnh thi hành phương thức đó, việc thi hành method được giao lại cho các lớp kế thừa lớp đó

Ví dụ: thức ăn là một class trừu tượng cho các class cụ thể như cơm, cháo.

Class thức ăn có phương thức mùi vị nhưng khi nói mùi vị của thức ăn chung chung ta không định nghĩa được, nhưng class cơm kế thừa từ class thức ăn thì có mùi vị là khô, class cháo có mùi vị là có mùi vị là lỏng






Một lần nữa chúng ta khẳng định abstract là một class không thể biết và định nghĩa các phương thức nhưng không có sự thi hành cụ thể, việc thi hành các phương thức này được giao lại cho các class kế thừa. Đây là tư tưởng chính cho vấn đề đa hình, đa xạ trong Java sẽ được đề cập ở phần sau.


Giao diện (interface):

Interface là một khái niệm mới trong các ngôn ngữ lập trình hiện đại như C++, C#. Interface là giao diện của một lớp đối tượng.

Interface của một class là phần đặc tả các method của class đó nhưng không bao gồm phần cài đặt, việc cài đặt các method này được giao lại cho các class kế thừa từ các interface này.

Một class kế thừa một interface nào thì bắt buộc phải cài đặt tất cả các method của interface đó.

Một đối tượng có thể đưa ra nhiều interface của mình, và class kế thừa interface nào phải cài đặt đầy đủ các method của interface đó. Java không cho phép đa kế thừa (một class của Java không thể có hơn một class cha) nhưng nhờ đặc điểm này (interface) cho phép cài đặt nhiều giao diện để thừa hưởng thêm các vùng và method của những interface này.

Interface được khai báo như là một lớp nhưng các thuộc tính là hằng (final) và các phương thức là abstract (có nghĩa là các phương thức đều rỗng dù không có từ khóa abstract) và trong các lớp sử dụng interface phải cài đặt các phương thức này

Để một class kế thừa một giao diện ta dùng từ khóa implements (thay vì extends)

public interface MyInterface {

static final String s = "Interface";

public void outText();

}
//---------------------------
public
class Ex1 implements MyInterface{

public void outText(){
System.out.println("Ex1 thua ke interface");
}
}

//---------------------------
public
class Ex2 implements MyInterface{

public void outText(){
System.out.println("Ex2 thua ke interface");
}

}
//---------------------------

public
class Interface {

public static void main(String args[]){

Ex1 e1 = new Ex1();
e1.outText();
Ex2 e2 =
new Ex2();
e2.outText();
}
}

Đa hình trong Java:

Phát biểu bài toán:

Một công ty có 2 loại nhân viện là kỹ sư và công nhân, mỗi loại nhân viên có các thuộc tính chung như tên, lương cơ bản nhưng có phương thức tính lương khác nhau với kỹ sư hệ số lương là 2 và công nhân hệ số lương là 1. Viết chương trình tính lương nhân viên cho công ty

Mô hình hóa:

Phân tích theo hướng đối tượng ta có 2 class chính là class kỹ sư và class công nhân cùng một class chung là class nhân viên. Hai class kỹ sư và công nhân cùng kế thừa class chung là nhân viên. Vấn đề phát sinh là mỗi class có cùng method tính lương nhưng cách tính lại khác nhau. Một trong các cách giải quyết là dùng đặc tính đa hình, đa xạ trong hướng đối tượng (cụ thể ở đây là Java)

abstract class nhanVien {

protected String ten = null;
protected int lcb = 0;
abstract int tinhLuong();
}

//----------------------------
public
class congNhan extends nhanVien{

public congNhan(){
this.ten = "Cong nhan B";
this.lcb = 100;
}

public int tinhLuong(){
return (this.lcb * 1);
}
}

//---------------------------

public class kySu extends nhanVien{

public kySu(){
this.ten = "Ky su A";
this.lcb = 100;
}

public int tinhLuong(){
return (this.lcb * 2);
}
}
//---------------------------

public
class Main {

public static void main(String args[]){

nhanVien a;
a =
new congNhan();
System.
out.println(a.tinhLuong());
a =
new kySu();
System.
out.println(a.tinhLuong());
}
}

Chúng ta tạo một biến a kiểu nhanVien nhưng khi cần sử dụng a là công nhân hay kỹ sư chúng ta có thể new với class tương ứng, và khi tính lương không cần quan tâm dùng method tinhLuong() của class nào mà chỉ cần ghi a.tinhLuong().

Thứ Hai, 18 tháng 2, 2008

Tài liệu tham khảo J2ME

Đây là đề tài tham khảo bao gồm các thành phần cơ bản của công nghệ J2ME rất hữu ích cho bước đầu làm quen với J2ME LapTrinhThietBiDiDongVoiJ2ME.pdf

Bài viết kỹ thuật hỗ trợ lập trình MobileGame 2007


Bài tập thực hành tin học căn bản

Đề cương thực hành tin học căn bản (Word, Excel) bao gồm phần cơ bản, nâng cao và một số đề thi thử tham khảo
download

Ebook về Java (J2SE - J2EE)

Core Java & J2SE

Tài liệu nước ngoài
AddisonWesley-TheJavaDevelopersAlman.chm (tham khảo các đoạn code mẫu)
aprogrammersguidetojavacertificatio.chm (sách dạy Java)
core java 2, volume i fundamentals 5th.pdf (ebook of sun)
core java 2, volume ii advanced features.pdf (ebook of sun)

Tài liệu tếng Việt
Java_LaptrinhOOP.doc (lập trình hướng đối tượng trong Java)
JavaUIVN.doc (Lập trình giao diện đồ họa trong Java)
CoreJava.rar (Loạt bài Core Java tiếng Việt)

Thứ Năm, 14 tháng 2, 2008

Dùng NetBean 6.0 lập trình J2ME

Sau bài Dùng Eclipse lập trình J2ME, mình xin giới thiệu tiếp làm thế nào đề lập trình J2ME với NetBean (một IDE lập trình Java do Sun phát triển)

Đề lập trình J2ME trên IDE NetBean chúng ta cần bộ NetBeans Mobility Pack và cần lưu ý là version của bộ Mobiliy phải tương ứng với version của NetBean đang sử dụng, cũng cần lưu ý là NetBeans Mobility Pack không thể chạy trên NetBeans IDE 5.5, nếu muốn chúng ta phải sử dụng NetBeans IDE 5.5.1.

Nếu không muốn quá rắc rối chúng ta có thể down bộ NetBeans 6.0.1 đã được tích hợp sẵn phần lập trình J2ME tại địa chỉ sau:

http://download.netbeans.org/netbeans/6.0/final/

Các bạn có thể chọn NetBeans IDE 6.0 Mobility (65Mb) hay Full edition (195 Mb), để nhỏ gọn chúng ta chọn bộ NetBeans IDE 6.0 Mobility, sau này muốn bổ sung thêm các phần khác các bạn có thể vào Tools/Plugin để cập nhật thêm.

Chúng ta cũng cần WTK: Một bộ giả lập máy di động trên máy tính, ở đây mình sẽ dùng Sun Wireless Toolkit (WTK), nó sẽ tạo ra một cái máy di động ảo trong máy tính, và các ứng dụng sẽ chạy trên cái máy ảo đấy (down tại http://java.sun.com/products/sjwtoolkit/download.html).

Sau khi đã cài đặt xong 2 phần đó, chúng ta bắt đầu viết ứng dụng J2ME trên NetBean

NetBean hỗ trợ chúng ta tạo ứng dụng MIDP bằng 2 cách là bằng Visual Mobile Designer (VMD) hay bằng Source Code Editor. Có thể hiểu là

· Visual Mobile Designer (VMD): hỗ trợ giao diện kéo thả một cách trực quan để thiết kế ứng dụng

· Source Code Editor: mọi việc đều viết code thủ công.

Mỗi cách đều có các ưu khuyết điểm riêng, trong bài viết này mình xin giới thiệu cả 2 cách tùy các bạn lựa chọn.

Creating a MIDP Application Using the Visual Mobile Designer

Chọn File/New Projects…., trong hộp thoại New Project chọn Mobility trong Categories và MIDP Application trong Projects, sau đó chọn Next

Nhập tên Project trong phần Project Name, thay đổi nơi lưu trữ Project trong Project Location

Click chọn Set as Main Project và Create Hello MIDlet (cả hai đã được chọn mặc định). Chọn Next

Chọn Sun Java Wireless Toolkit 2.5.2 for CLDC trong Emulator Platform (mặc định). Chọn Next.

Mở rộng thư mục “Configuration templates provided by installed CLDC platforms" và"Sun Java Wireless Toolkit 2.52 for CLDC”. Check chọn các configurations. Chọn Finish

Sau khi đã tạo xong Project, chúng ta bắt đầu viết code.

Các bạn chọn Screen View

Các bạn chú ý dòng chữ Hello, World!, giả sử chúng ta muốn hiển thị dòng chữ khác ((VD: “Hello, J2ME”), các bạn click chọn nó. Trong cửa sổ Properties, chọn Text field và nhập text muốn hiển thị (VD: “Hello, J2ME”)

Để chạy thử ứng dụng, các bạn chọn Run / Run Main Project (F6)

Creating a MIDP Application Using Source Editor

Chọn File/New Projects…., trong hộp thoại New Project chọn Mobility trong Categories và MIDP Application trong Projects, sau đó chọn Next

Nhập tên Project trong phần Project Name, thay đổi nơi lưu trữ Project trong Project Location

Click chọn Set as Main Project và bỏ chọn Create Hello MIDlet (được chọn mặc định). Chọn Next.

Chọn Sun Java Wireless Toolkit 2.5.2 for CLDC trong Emulator Platform (mặc định). Chọn Next.

Mở rộng thư mục “Configuration templates provided by installed CLDC platforms" và"Sun Java Wireless Toolkit 2.52 for CLDC”. Check chọn các configurations. Chọn Finish

Right click vào MyHelloMIDlet trong cửa sổ Explorer và chọn New/MIDlet

Nhập HelloMIDlet trong MIDlet name. Chọn Finish.

Double click vào file HelloMIDlet.java trong cửa sổ Explorer để hiển thị source code trong Editor.

Trong cửa sổ soạn thảo thay đổi như đoạn code sau

import javax.microedition.midlet.*;

import javax.microedition.lcdui.*;

public class HelloMIDlet extends MIDlet implements CommandListener{

private Form mMainForm;

private Display display;

private Command cmdExit;

private StringItem str;

public HelloMIDlet() {

display = Display.getDisplay(this);

mMainForm = new Form("Chuong trinh so 2");

str = new StringItem(null,"Chao cac ban,MIDP");

cmdExit = new Command("Exit",Command.EXIT,0);

mMainForm.append(str);

mMainForm.addCommand(cmdExit);

mMainForm.setCommandListener(this);

}

public void startApp() {

display.setCurrent(mMainForm);

}

public void pauseApp() {

}

public void destroyApp(boolean unconditional) {

}

public void commandAction(Command c, Displayable s){

notifyDestroyed();

}

}

Thứ Tư, 13 tháng 2, 2008

Chương 2 – Phân Tích Code J2ME

Sau khi đã tìm hiểu kiến trúc J2ME ở chương 1 chúng ta bắt đầu khảo sát “lập trình J2ME như thế nào” hay nói rõ hơn là code của 1 ứng dụng J2ME được viết như thế nào.

Chương trình J2ME có thể xem là một ứng dụng thu nhỏ của J2SE (ứng dụng Java chạy trên Desktop) nên cũng bao gồm các đối tượng như Form, TextBox, ListBox,…. Các đối tượng này có thể được thêm vào ứng dụng bằng code hay các công cụ thiết kế trực quan khác và chúng ta cần biết chúng sẽ được thêm vào hiện thực như thế nào?

Như một ứng dụng J2SE để hiện thị một câu chào chúng ta có thể cần 1 Form, 1 chuỗi chứa câu chào vào cho hiển thị lên Form. Ở J2ME cũng vậy, chúng ta cùng phân tích 1 đoạn code mẫu sau đây:

import javax.microedition.midlet.*;

import javax.microedition.lcdui.*;

public class HelooJ2ME extends MIDlet implements CommandListener{

private Form mMainForm;

private Display display;

private Command cmdExit;

private StringItem str;

public HelooJ2ME() {

// TODO Auto-generated constructor stub

display = Display.getDisplay(this);

mMainForm = new Form("Chuong trinh so 2");

str = new StringItem(null,"Chao cac ban,MIDP");

cmdExit = new Command("Exit",Command.EXIT,0);

mMainForm.append(str);

mMainForm.addCommand(cmdExit);

mMainForm.setCommandListener(this);

}

protected void destroyApp(boolean arg0) throws MIDletStateChangeException

{

// TODO Auto-generated method stub

}

protected void pauseApp() {

// TODO Auto-generated method stub

}

protected void startApp() throws MIDletStateChangeException {

// TODO Auto-generated method stub

display.setCurrent(mMainForm);

}

public void commandAction(Command c, Displayable s){

notifyDestroyed();

}

}

Các bạn có thể dùng bất kì công cụ lập trình J2ME nào để chép đoạn code trên vào chạy thử nhưng để tiện theo dõi mình sử dụng IDE eclipse (các bạn có thể xem thêm bài Dùng eclipse lập trình J2ME)

Các bạn mở eclipse, chọn File/New/Project…. Trong hộp thoại New Project chọn J2ME/ J2ME Midlet Suite. Chọn Next, nhập tên Project, chọn Finish. Vậy là chúng ta đã tạo xong một Project J2ME, nhưng project này chưa có file .java nào cả hay nói khác đi là một project trống rỗng.

Để tạo thêm các file .java các bạn chọn Project mới tạo sau đó chọn File/New/Other… (hoặc Right Click vào Project mới tạo chọn File/New/Other… ). Trong hộp thoại New các bạn chọn J2ME/J2ME Midlet, chọn Next, nhập tên Midlet (không cần giống tên project) sau đó chọn Finish. Các bạn lưu ý file .java sẽ được chứa trong thư mục src của Project tương ứng.

Các bạn copy toàn bộ đoạn code trên vào file .java. Để chạy thử chúng ra right click vào file .java này chọn Run As/Emulated J2ME Midlet. Nếu không có lỗi các bạn sẽ thấy hình một chiếc di động hiện ra với câu chào “Chao cac ban,MIDP"

Bây giờ chúng ta bắt đầu phân tích đoạn code trên. Như Chương Tìm hiểu kiến trúc J2ME mình đã giới thiệu, một ứng dụng J2ME có khung chương trình chuẩn như sau

import javax.microedition.midlet.*;

import javax.microedition.lcdui.*;

public class HelooJ2ME extends MIDlet {

public HelooJ2ME() {

// TODO Auto-generated constructor stub

}

protected void destroyApp(boolean arg0) throws MIDletStateChangeException{

// TODO Auto-generated method stub

}

protected void pauseApp() {

// TODO Auto-generated method stub

}

protected void startApp() throws MIDletStateChangeException {

// TODO Auto-generated method stub

}

}

import javax.microedition.midlet.*;

import javax.microedition.lcdui.*;

include các lớp cần thiết từ các thư viện CLDC và MIDP.

public class HelooJ2ME extends MIDlet implements CommandListener{

Một ứng dụng J2ME là một lớp kế thừa từ MIDlet nên chúng ta sử dụng “extends MIDlet”, do trong chương trình chúng ta có một nút exit nên chúng ta cần tạo một bộ lắng nghe sự kiện CommandListener mục đích là đón bắt sự kiện người dùng nhấn nút exit.

Các bạn lưu ý trong J2ME có 2 giao diện Listener chính cho mỗi MID Profile là: CommandListener và ItemStateListener mục đích là lắng nghe các sự kiện do người dùng tác động vào ứng dụng như bấm nút, nhập chữ vào textbox, thay đổi lựa chọn trên listbox,….. Phần này mình sẽ trình bày kĩ hơn ở chương sau “Giao diện người dùng cấp cao”

private Form mMainForm;

private Display display;

private Command cmdExit;

private StringItem str;

tạo một Form để hiển thị, đối tượng Display (chúng ta có thể xem Display là một bộ quản lý điều khiển và hiển thị các thông tin trên màn hình), Command để người dùng chọn Exit và StringItem chứa câu chào.

public HelooJ2ME() {

// TODO Auto-generated constructor stub

display = Display.getDisplay(this);

mMainForm = new Form("Chuong trinh so 2");

str = new StringItem(null,"Chao cac ban,MIDP");

cmdExit = new Command("Exit",Command.EXIT,0);

mMainForm.append(str);

mMainForm.addCommand(cmdExit);

mMainForm.setCommandListener(this);

}

Ở phương thức khởi dụng này chúng ta thấy, đầu tiên chúng ta lấy Display hiện thời gán cho biến display, tạo một Form mới với tiêu đề là ("Chuong trinh so 2"), tạo một câu chào và một nút nhấn Exit. Phần chi tiết tạo các thành phần trên mình sẽ trình bày ở chương “Giao diện người dùng cấp cao”

Sau đó chúng ta gắn thành phần str lên form bằng lệnh append() và nút exit bằng lệnh addCommand(), tạo bộ lắng nghe sự kiện cho nút exit bằng lệnh setCommandListener(this).

protected void startApp() throws MIDletStateChangeException {

// TODO Auto-generated method stub

display.setCurrent(mMainForm);

}

Phương thức startApp() đơn giản là đưa lên form đã gắn các thành phần kia lên màn hình bằng lệnh setCurrent().

public void commandAction(Command c, Displayable s){

notifyDestroyed();

}

Do chúng ta sử dụng giao diện CommandListener nên nhất thiết phải cài đặt phương thức

commandAction(Command c, Displayable s). Chúng ta có thể hiểu rằng khi một nút được nhấn lậpo tức phương thức commandAction(Command c, Displayable s) được gọi và các lệnh trong phương thức này sẽ được thực thi, ở đây đơn giản là thoát khỏi ứng dụng. Nếu chúng ta có nhiều nút nhấn thì cần sử dụng câu lênh if ví dụ:

if (c==cmdExit)

notifyDestroyed();

else if (c==cmdHelp)

display.setCurrent(txtHelp);

else if (c==cmdBack)

display.setCurrent(mainForm);

Tổng kết:

Đến đây chúng ta có thể hình dùng chương trình sẽ chạy như sau:

B1 : đầu tiên phương thức khởi tạo sẽ được gọi và các đối tựợng cần thiết sẽ được tạo

B2: phương thức startApp() được gọi và hiện lên Form ra màn hình

B3: không làm gì cả đến khi người dùng nhấn nút exit, thực hiện phương thức commandAction(Command c, Displayable s)

Đến đây chúng ta đã hình dung được một ứng dụng J2ME sẽ được thực hiện như thế nào ở chương sau chúng ta sẽ khảo sát các đối tượng như TexBox, ListBox,… còn khung chương trình thì vẫn như trên, giả sử để tạo thêm một TextBox các bạn chỉ cần bổ sung thêm vào phương thức khởi tạo sau đó gắn nó vào Form còn phần hiển thị ra màn hình thì vẫn như cũ.


Thứ Ba, 12 tháng 2, 2008

Chương 1 - Kiến trúc J2ME

Những phiên bản Java hiện thời

  • Phiên bản chuẩn (Standard Edition - J2SE): thiết kế chạy trên Desktop và máy tính kiểu trạm làm việc
  • Phiên bản xí nghiệp (Enterprise Edition – J2EE): Đưa thêm vào những hỗ trợ dành cho Servlets, JSP và XML. Phiên bản nhắm đến những ứng dụng trên nèn Web server.
  • Phiên bản nhỏ gọn (Micro Edition – J2ME): thiết kế cho những thiết bị với bộ nhớ có hạn, cả về sức mạnh màn hình và tốc độ xử lý kém.
Giới thiệu các thành phần trong nền tảng J2ME:

Configuration (Cấu hình):Tầng cấu hình của CLDC định nghĩa giao diện ngôn ngữ Java (Java language interface) cơ bản để cho phép chương trình Java chạy trên thiết bị di động. Đây là một tập các API định nghĩa lõi của ngôn ngữ J2ME. Lập trình viên có thể sử dụng các lớp và phương thức của các API này tuy nhiên tập các API hữu dụng hơn được chứa trong tầng hiện trạng (profile layer).
Do đây là đặc tả nên các nhà sản xuất thiết bị như Samsung, Nokia …bắt buộc phải thực thi đầy đủ các đặc tả do Sun qui định để các lập trình viên có thể dựa vào môi trường lập trình nhất quán và thông qua sự nhất quán này, các ứng dụng được tạo ra có thể mang tính độc lập thiết bị cao nhất có thể. Ví dụ như một lập trình viên viết chương trình game cho điện thoại Samsung thì có thể sửa đổi chương trình của mình một cách tối thiểu nhất để có thể chạy trên điện thọai Nokia.. Hiện nay Sun đã đưa ra 2 dạng Configuration:
· CLDC (Connected Limited Device Configuration-Cấu hình thiết bị kết nối giới hạn): được thiết kế để nhắm vào thị trường các thiết bị cấp thấp (low-end), các thiết bị này thông thường là máy điện thọai di động và PDA với khoảng 512 KB bộ nhớ. Vì tài nguyên bộ nhớ hạn chế nên CLDC được gắn với Java không dây (Java Wireless ), dạng như cho phép người sử dụng mua và tải về các ứng dụng Java, ví dụ như là Midlet.
· CDC- Connected Device Configuration (Cấu hình thiết bị kết nối): CDC được đưa ra nhắm đến các thiết bị có tính năng mạnh hơn dòng thiết bị thuộc CLDC nhưng vẫn yếu hơn các hệ thống máy để bàn sử dụng J2SE. Những thiết bị này có nhiều bộ nhớ hơn (thông thường là trên 2Mb) và có bộ xử lý mạnh hơn. Các sản phẩm này có thể kể đến như các máy PDA cấp cao, điện thoại web, các thiết bị gia dụng trong gia đình …
· Cả 2 dạng Cấu hình kể trên đều chứa máy ảo Java (Java Virtual Machine) và tập hợp các lớp (class) Java cơ bản để cung cấp một môi trường cho các ứng dụng J2ME. Tuy nhiên, bạn chú ý rằng đối với các thiết bị cấp thấp, do hạn chế về tài nguyên như bộ nhớ và bộ xử lý nên không thể yêu cầu máy ảo hổ trợ tất cả các tính năng như với máy ảo của J2SE, ví dụ, các thiết bị thuộc CLDC không có phần cứng yêu cầu các phép tính toán dấu phẩy động, nên máy ảo thuộc CLDC không được yêu cầu hỗ trợ kiểu float và double.

Định nghĩa về Profile:
Profile mở rộng Configuration bằng cách thêm vào các class để bổ trợ các tính năng cho từng thiết bị chuyên biệt. Cả 2 Configuration đều có những profile liên quan và từ những profile này có thể dùng các class lẫn nhau. Đến đây ta có thể nhận thấy do mỗi profile định nghĩa một tập hợp các class khác nhau, nên thường ta không thể chuyển một ứng dụng Java viết cho một profile này và chạy trên một máy hỗ trợ một profile khác. Cũng với lý do đó, bạn không thể lấy một ứng dụng viết trên J2SE hay J2EE và chạy trên các máy hỗ trợ J2ME. Sau đây là các profile tiêu biểu:
· Mobile Information Device Profile (MIDP): profile này sẽ bổ sung các tính năng như hỗ trợ kết nối, các thành phần hỗ trợ giao diện người dùng … vào CLDC. Profile này được thiết kế chủ yếu để nhắm vào điện thọai di động với đặc tính là màn hình hiển thị hạn chế, dung lượng chứa có hạn. Do đó MIDP sẽ cung cấp một giao diện người dùng đơn giản và các tính năng mạng đơn giản dựa trên HTTP. Có thể nói MIDP là profile nổi tiếng nhất bởi vì nó là kiến thức cơ bản cho lập trình Java trên các máy di động (Wireless Java)
· PDA Profile: tương tự MIDP, nhưng với thị trường là các máy PDA với màn hình và bộ nhớ lớn hơn
· Foundation Profile: cho phép mở rộng các tính năng của CDC với phần lớn các thư viện của bộ Core Java2 1.3
· Ngoài ra còn có Personal Basis Profile, Personal Profile, RMI Profile, Game Profile.

Định nghĩa về KVM (K Virtual Machine) :
Như các bạn đã biết, cơ chế thực thi đằng sau bất kỳ ứng dụng Java nào là JVM (Java Virtual Machine). Khi bạn biên dịch mã nguồn Java thành một lớp (.class) và đặt chúng vào trong file lưu trữ .JAD của Java, máy ảo JVM sẽ biên dịch file .class này thành mã thực thi điều khiển bởi JVM. Các mã trong file .class gọi là mã bytecode
Đối với thiết bị cấu hình dạng CDC, máy ảo JVM có toàn bộ chức năng tương đương với máy ảo phục vụ môi trường J2SE. Đối với thiết bị cấu hình dạng CLDC, Sun cài đặt một phiên bản thu nhỏ hơn dành cho JVM gọi là K Virtual Machine (KVM).

Tổng kết:
Để lập trình J2ME cho thiết bị di động các bạn cần nhớ kiến trúc sau đây
Profile: dùng MIDP
Configuration: dùng CLDL
JVM: KVM
Để lập trình được J2ME các bạn cần cài đặt đầy đủ 3 thành phần trên, nếu không có thể sử dụng các plugin J2ME đã đóng gói sẵn dành cho các IDE tương ứng như plugin elipseme dành cho elipse, tất nhiên là cần phải cài đặt sẵn JDK.
Nếu không có IDE hỡ trợ các bạn có thể viết code J2ME bằng bất kì chương trình soạn thảo text nào (Notepad chẳng hạn) sau đó biên dịch chảy thử từ dòng lệnh DOS.
Chương trình J2ME được viết xong được xem như là một MIDlet, một bộ MIDlet gồm một hoặc nhiều MIDlet được đóng gói cùng nhau trong file nén JAR. File nén JAR chứa tất cả những file lớp .class của Java và các file khác như hình ảnh và dữ liệu ứng dụng, bên cạnh đó file JAR còn chứa đựng một file gọi là file thống kê hay manifest fiel, file này mô tả nội dung của file JAR. Nếu đã sử dụng IDE chúng ta không cần cấu hình file dạng này vì đã có IDE hỗ trợ

Giới thiệu MIDP

a)Định nghĩa:
Đây là Profile được định nghĩa dành riêng cho các thiết bị di động và là thành phần chính trong J2ME. MIDP cung cấp các chức năng cơ bản cho hầu hết các dòng thiêt bị di động phổ biến nhất như các máy điện thoạI di động và các máy PDA. Tuy nhiên MIDP không phải là cây đũa thần cho mọi lập trình viên vì như chúng ta đã biết, MIDP được thiết kế cho các máy di động có cấu hình rất thấp. Trong phần sau tôi sẽ liệt kê qua các tính năng mà MIDP cung cấp và những giới hạn của nó.

b)Những chức năng MIDP không thực hiện được:

Phép tính dấu phẩy động (floating point): Phép tính này đòi hỏi rất nhiều tài nguyên CPU và phần lớn các CPU cho các thiết bị di động không hỗ trợ phép tính này, do đó MIDP cũng không có.
Bộ nạp lớp (Class Loader)
Hỗ trợ từ khóa finalize() như trong J2SE: Việc “dọn dẹp“ tài nguyên trước khi nó bị xóa được đẩy về phía các lập trình viên.
Không hỗ trợ JNI
Hỗ trợ hạn chế thao tác bắt lỗi
Phần lớn các thư viện API cho Swing và AWT không thể sử dụng được trong MIDP.
Không hỗ trợ các tính năng quản lý file và thư mục: Đây có thể làm bạn ngạc nhiên nhưng thực tế là các thiết bị J2ME không có hỗ trợ các thiết bị lưu trữ thông thường như ổ cứng v.v. Tuy nhiên, điều đó không có nghĩa là bạn phải mất đi mọi dữ liệu quan trọng mỗi khi tắt máy, Sun đã cung cấp một chức năng khác tương đương gọi là Record Management system (RMS) để cung cấp khả năng lưu trữ cho các thiết bị này.


c)Những chức năng MIDP cung cấp

Các lớp và kiểu dữ liệu: Phần lớn các lớp mà các lập trình viên Java quen thuộc vẫn còn được giữ lại ví dụ như các lớp trong gói java.util như Stack, Vector và Hastable cũng như Enumeration.
Hỗ trợ đối tượng Display: Đúng như tên gọi một chương trình MIDP sẽ hỗ trợ duy nhất một đối tượng Display là đối tượng quản lý việc hiển thị dữ liệu trên màn hình điện thoại.
Hỗ trợ Form và các giao diện người dùng.
Hỗ trợ Timer và Aler
Cung cấp tính năng Record Management System (RMS) cho việc lưu trữ dữ liệu
Ngoài ra vào tháng 11 năm 2003 Sun đã tung ra MIDP 2.0 với hàng loạt tính năng khác được cung cấp thêm so với bản 1.0. Những cải tiến nổi bật so với MIDP 1.0
Nâng cấp các tính năng bảo mật như:
Download qua mạng an toàn hơn qua việc hỗ trợ giao thức HTTPS.
Kiểm soát việc kết nối giữa máy di động và server: ví dụ như các chương trình không thể kết nối tới server nếu thiếu sự chấp thuận của người sử dụng.
Thêm các API hỗ trợ Multimedia. Một trong nhưng cải tiến hấp dẫn nhất của MIDP 2.0 là tập các API media của nó. Các API này là một tập con chỉ hỗ trợ âm thanh của Mobile Media API (MMAPI).
Mở rộng các tính năng của Form. Nhiều cải tiến đã được đưa vào API javax.microedition.lcdui trong MIDP 2.0, nhưng các thay đổi lớn nhất (ngoài API cho game) là trong Form và Item.
Hỗ trợ các lập trình viên Game bằng cách tung ra Game API: Có lẽ Sun đã kịp nhận ra thị trường đầy tiềm năng của các thiết bị di động trong lĩnh vực Game. Với MIDP 1.0 thì các lập trình viên phải tự mình viết code để quản lý các hành động của nhân vật cũng như quản lý đồ họa. Việc này sẽ làm tăng kích thước file của sản phẩm cũng như việc xuất hiện các đoạn mã bị lỗi. Được hưởng lợi nhất từ Game API trong MIDP 2.0 không chỉ là các lập trình viên Game mà còn là các lập trình viên cần sử dụng các tính năng đồ họa cao cấp. Ý tưởng cơ bản của Game API là việc giả định rằng một màn hình game là tập hợp các layer (lớp). Ví dụ như: trong một game đua xe thì màn hình nền là một layer, con đường là một layer và chiếc xe được xem như đang nằm trên layer khác. Với Game API nhà phát triển còn được cung cấp các tính năng như quản lý các thao tác bàn phím.
Hỗ trợ kiểu ảnh RGB: một trong những cải tiến hấp dẫn cho các nhà phát triển MIDP là việc biểu diễn hình ảnh dưới dạng các mảng số nguyên, cho phép MIDlet thao tác với dữ liệu hình ảnh một cách trực tiếp

Môi trường phát triển J2ME

Chúng ta đã tìm hiểu sơ qua về J2ME, vậy có những công cụ nào hỡ trợ cho việc lập trình J2ME. Có nhiều môi trường phát triển ứng dụng J2ME và mỗi hãng điện thoại cũng đưa ra những môi trường phát triển cho riêng mình. Ở đây tôi sẽ giới thiệu toolkit của Sun: J2ME Wireless Toolkit. Địa chỉ download chương trình: http://java.sun.com/j2me/download.html . Ngoài ra bạn cần phải có J2SDK 1.4 trở lên.
Toolkit này hỗ trợ cũng không trực quan lắm cho người sử dụng, nếu bạn đã từng làm quen với các IDE lập trình Java (NetBean, JCreator, Jbuilder, Eclipse…) thì mỗi IDE này đều hỗ trợ các plugin dành cho việc lập trình J2ME, các bạn có thể download tại các website về sử dụng.
Sau đây mình xin tóm gọn lại quá trình tạo một ứng dụng J2ME bằng IDE để phân phối trên thiết bị di động.

Quá trình phát triển ứng dụng MIDlet với IDE (Môi trường phát triển tích hợp-Intergrated Development Environment):
Lập trình viên: Tạo các tập tin nguồn Java
Bước đầu tiên là lập trình viên phải tạo mã nguồn Java, có thể có nhiều tập tin (*.java).
Trên IDE: Bộ biên dịch Java (Java Compiler): Biên dịch mã nguồn thành mã bytecode
Bộ biên dịch Java sẽ biên dịch mã nguồn thành mã bytecode. Mã bytecode này sẽ được KVM dịch thành mã máy. Mã bytecode đã biên dịch sẽ được lưu trong các tập tin *.class và sẽ có một tập tin *.class sinh ra cho mỗi lớp Java.
Trên IDE: Bộ tiền kiểm tra (Preverifier): Kiểm tra tính hợp lệ của mã bytecode
Một trong những yêu cầu an toàn của J2ME là bảo đảm mã bytecode chuyển cho KVM là hợp lệ và không truy xuất các lớp hay bộ nhớ ngoài giới hạn của chúng. Do đó tất cả các lớp đều phải được tiền kiểm tra trước khi chúng có thể được download về thiết bị di động. Việc tiền kiểm tra được xem là một phần của môi trường phát triển làm cho KVM có thể được thu nhỏ hơn. Bộ tiền kiểm tra sẽ gán nhãn lớp bằng một thuộc tính (attribute) đặc biệt chỉ rằng lớp đó đã được tiền kiểm tra. Thuộc tính này tăng thêm khoảng 5% kích thước của lớp và sẽ được kiểm tra bởi bộ kiểm tra trên thiết bị di động.

Lập trình viên đóng gói thành file nén JAR trên IDE
IDE sẽ tạo một tập tin JAR chứa:
* Tất cả các tập tin *.class
* Các hình ảnh của ứng dụng. Hiện tại chỉ hỗ trợ tập tin *.png
* Các tập tin dữ liệu có thể được yêu cầu bởi ứng dụng
* Một tập tin kê khai (manifest.mf) cung cấp mô tả về ứng dụng cho bộ quản lý ứng dụng (application manager) trên thiết bị di động.
* Tập tin JAR được bán hoặc được phân phối đến người dùng đầu cuối
Sau khi đã gỡ rối và kiểm tra mã lệnh trên trình giả lập (simulator), mã lệnh đã sẵn sàng được kiểm tra trên điện thoại di động và sau đó được phân phối cho người dùng.

Người dùng: Download ứng dụng về thiết bị di động
Người dùng sau đó download tập tin JAR chứa ứng dụng về thiết bị di động. Trong hầu hết các điện thoại di động, có ba cách để download ứng dụng:
* Kết nối cáp dữ liệu từ PC sang cổng dữ liệu của điện thoại di động:
Việc này yêu cầu người dùng phải có tập tin JAR thật sự và phần mềm truyền thông để download ứng dụng sang thiết bị thông qua cáp dữ liệu.
* Cổng hồng ngoại IR (Infra Red) Port:Việc này yêu cầu người dùng phải có tập tin JAR thật sự và phần mềm truyền thông để download ứng dụng sang thiết bị thông qua cổng hồng ngoại.
* OTA (Over the Air): Sử dụng phương thức này, người dùng phải biết địa chỉ URL chỉ đến tập tin JAR

Khung chương trình chuẩn

1) Phát biểu import: Các phát biểu import được dùng để include các lớp cần thiết từ các thư viện CLDC và MIDP.
2) Phần chính của MIDlet: MIDlet được định nghĩa như một lớp kế thừa lớp MIDlet. Trong ví dụ này MIDletExample là bắt đầu của ứng dụng.
3) Hàm tạo (Constructor): Hàm tạo chỉ được thực thi một lần khi MIDlet được khởi tạo lần đầu tiên. Hàm tạo sẽ không được gọi lại trừ phi MIDlet thoát và sau đó khởi động lại.
4) startApp(): Phương thức startApp() được gọi bởi bộ quản lý ứng dụng khi MIDlet được khởi tạo, và mỗi khi MIDlet trở về từ trạng thái tạm dừng. Nói chung, các biến toàn cục sẽ được khởi tạo lại trừ hàm tạo bởi vì các biến đã được giải phóng trong hàm pauseApp(). Nếu không thì chúng sẽ không được khởi tạo lại bởi ứng dụng.
5) pauseApp() :Phương thức pauseApp() được gọi bởi bộ quản lý ứng dụng mỗi khi ứng dụng cần được tạm dừng (ví dụ, trong trường hợp có cuộc gọi hoặc tin nhắn đến). Cách thích hợp để sử dụng pauseApp() là giải phóng tài nguyên và các biến để dành cho các chức năng khác trong điện thoại trong khi MIDlet được tạm dừng. Cần chú ý rằng khi nhận cuộc gọi đến hệ điều hành trên điện thoại di động có thể dừng KVM thay vì dừng MIDlet. Việc này không được đề cập trong MIDP mà đó là do nhà sản xuất quyết định sẽ chọn cách nào.
6) destroyApp() :Phương thức destroyApp() được gọi khi thoát MIDlet. (ví dụ khi nhấn nút exit trong ứng dụng). Nó chỉ đơn thuần là thoát MIDlet. Nó không thật sự xóa ứng dụng khỏi điện thoại di động. Phương thức destroyApp() chỉ nhận một tham số Boolean. Nếu tham số này là true, MIDlet được tắt vô điều kiện. Nếu tham số là false, MIDlet có thêm tùy chọn từ chối thoát bằng cách ném ra một ngoại lệ MIDletStateChangeException.

Tóm tắt các trạng thái khác nhau của MIDlet:
Tạo (Created) ð Hàm tạo MIDletExample() được gọi một một lần
Hoạt động (Active) ð Phương thức startApp() được gọi khi chương trình bắt đầu hay sau khi tạm dừng
Tạm dừng (Paused) ð Phương thức pauseApp() được gọi. Có thể nhận các sự kiện timer.
Hủy (Destroyed) ð Phương thức destroy() được gọi.
Khi người dùng yêu cầu khởi động ứng dụng MIDlet, bộ quản lý ứng dụng sẽ thực thi MIDlet (thông qua lớp MIDlet). Khi ứng dụng thực thi, nó sẽ được xem là đang ở trạng thái tạm dừng. Bộ quản lý ứng dụng gọi hàm tạo và hàm startApp(). Hàm startApp() có thể được gọi nhiều lần trong suốt chu kỳ sống của ứng dụng. Hàm destroyApp() chỉ có thể gọi từ trạng thái hoạt động hay tạm dừng.

Lập trình viên cũng có thể điều khiển trạng thái của MIDlet.
Các phương thức dùng để điều khiển các trạng thái của MIDlet:
resumeRequest(): Yêu cầu vào chế độ hoạt động
Ví dụ: Khi MIDlet tạm dừng, và một sự kiện timer xuất hiện.

notifyPaused(): Cho biết MIDlet tự nguyện chuyển sang trạng thái tạm dừng
Ví dụ: Khi đợi một sự kiện timer.

notifyDestroyed(): Sẵn sàng để hủy
Ví dụ: Xử lý nút nhấn Exit

Lập trình viên có thể yêu cầu tạm dừng MIDlet trong khi đợi một sự kiện timer hết hạn. Trong trường hợp này, phương thức notifyPaused() sẽ được dùng để yêu cầu bộ quản lý ứng dụng chuyển ứng dụng sang trạng thái tạm dừng.
1.3 Tập tin JAR
Các lớp đã biên dịch của ứng dụng MIDlet được đóng gói trong một tập tin JAR (Java Archive File). Đây chính là tập tin JAR được download xuống điện thoại di động.
Tập tin JAR chứa tất cả các tập tin class từ một hay nhiều MIDlet, cũng như các tài nguyên cần thiết. Hiện tại, MIDP chỉ hỗ trợ định dạng hình .png (Portable Network Graphics). Tập tin JAR cũng chứa tập tin kê khai (manifest file) mô tả nội dung của MIDlet cho bộ quản lý ứng dụng. Nó cũng phải chứa các tập tin dữ liệu mà MIDlet cần. Tập tin JAR là toàn bộ ứng dụng MIDlet. MIDlet có thể load và triệu gọi các phương thức từ bất kỳ lớp nào trong tập tin JAR, trong MIDP, hay CLDC. Nó không thể truy xuất các lớp không phải là bộ phận của tập tin JAR hay vùng dùng chung của thiết bị di động.

Tham khảo:
Lập trình Moile Games bằng J2ME – javavietnam.org
Java Tập 3 – Phương Lan, Trần Tiến Dũng