CLDC
CLDC为上层简表提供了如下支持:
Ø Java语言规范的核心特性;
Ø Java虚拟机规范的核心特性;
Ø Java核心类库,包括java.lang.*,java.util.*和java.io.*;
Ø 通用连接框架;
Ø 安全特性;
Ø 国际化支持。
CLDC只是J2SE的一个子集。事实上,很多在J2SE环境下提供的功能和API都从CLDC中删除了,目的是为了适应移动终端设备内存和处理器方面的限制。即使是CLDC从J2SE环境继承过来的类也都进行了删减。
表1-1对比了J2SE和CLDC中定义的java.util.Hashtable类的方法。
表1-1 java.util.Hashtable在CLDC1.0和J2SE 1.4.2中的对比
方法名称 | CLDC 1.0 | J2SE 1.4.2 | 备 注 |
clear() | 有 | 有 |
|
clone() | 无 | 有 |
|
contains(Object value) | 有 | 有 |
|
containtsKey(Object key) | 有 | 有 |
|
contantsValue(Object value) | 无 | 有 |
|
elements() | 有 | 有 |
|
entrySet() | 无 | 有 |
|
equals(Object obj) | 有 | 有 | 实现不同 |
get(Object key) | 有 | 有 |
|
方法名称 | CLDC 1.0 | J2SE 1.4.2 | 备 注 |
hashCode() | 有 | 有 | 实现不同 |
isEmpty() | 有 | 有 |
|
keys() | 有 | 有 |
|
keySet() | 无 | 有 |
|
put(Object key,Object value) | 有 | 有 |
|
putAll(Map t) | 无 | 有 |
|
rehash() | 有 | 有 |
|
remove(Object key) | 有 | 有 |
|
size() | 有 | 有 |
|
toString() | 有 | 有 |
|
values() | 无 | 有 |
|
从表1-1可以得出结论:CLDC是J2SE的子集,在J2SE中定义的某些方法在CLDC中去掉了,例如,Hashtable类的putAll(Map t)方法。因此开发MIDP应用程序的时候应该主要参考MIDP Java文档而不是J2SE Java文档。
1.Java语言规范特性
由于移动终端设备在诸如内存和处理器等方面的性能存在缺陷,不能与桌面电脑相提并论。因此遵循CLDC规范的虚拟机并没有支持全部的Java语言规范特性。在CLDC1.0中定义的语言特性主要有以下不同。
Ø 不支持浮点运算。由于在制定CLDC 1.0规范的时候,大多数的目标设备在硬件层面都不支持浮点运算,因此CLDC 1.0不支持浮点运算。CLDC 1.1(JSR 139)支持浮点运算。
Ø 不支持finalization,也不提供Object.finalize()方法。Object.finalize()常用于在对象被垃圾收集器收集后执行清理工作,但是基本上很少需要这个方法。
Ø 有限的错误处理能力。只提供了java.lang.Error,java.lang.OutofMemoryError和java.lang.VirtualMechineError几种错误类。
Ø 不支持弱引用。在CLDC 1.1中提供了对弱引用的支持。
2.Java虚拟机规范特性
在CLDC 1.0中定义的虚拟机与Java虚拟机规范存在以下不同:
Ø 不支持用户自定义的类装载器;
Ø 不支持线程组和守护进程;
Ø 不支持反射机制;
Ø 不支持Java本地接口(Java Native Interface)。在KVM中采用了KNI规范,但没有开放给开发者;
Ø CLDC中的虚拟机采用了新的类文件校验机制。
3.Java核心类库
CLDC中的核心类都是从J2SE中继承而来的,并且进行了适当的裁剪以适合移动终端设备的内存和处理器。主要包括3个包:java.lang.*,java.util.*和java.io.*。表1-2总结了CLDC1.0中核心类库的主要内容(未包括Exception和Error)。
表1-2 CLDC 1.0中部分核心类介绍
类 名 | 描 述 |
java.lang.Boolean | Boolean类把一个布尔类型的基本变量封装在一个对象中。一个Boolean类型的对象包含了一个布尔类型的字段 |
java.lang.Byte | Byte类是字节型变量的标准包装器 |
Java.lang.Character | Character类包装了基本字符(char)类型变量。一个Character类的对象包含了一个字符(char)类型变量的字段。另外,这个类提供了几个方法用于确定字符的类型,同时还提供了方法进行大小写转换 |
Java.lang.Class | Class的实例代表一个运行在Java应用程序中的类和接口。每个数组也属于类,其反射作为Class对象,元素类型和维数相同的数组共享一个Class对象 |
Java.lang.Integer | Integer类在对象中包装原始类型为Int的值。一个Integer对象包含一个整型的字段。另外,这个类提供了字符串和整数相互转换的方法,也包括一些常量和处理一个整型变量的方法 |
Java.lang.Long | Long类在对象中包装长整型变量。一个Long对象包含一个长整型变量的字段。另外,这个类提供了字符串和整数相互转换的方法,也包括其他的处理整型变量有用的方法 |
Java.lang.Math | Math类包括进行基本数字运算的方法 |
Java.lang.Object | Object是所有继承类的父类。所有类,包括数组都能实现它的方法 |
Java.lang.Runtime | 每个Java应用程序都有一个Runtime类的实例,其允许应用程序与应用程序的运行环境相连接。当前的运行环境可以由getRuntime()方法获得 |
Java.lang.Short | Short类是短整型变量的封装 |
Java.lang.String | String对象表示字符串。所有Java程序中的字符串,如“abc”都是这个类的实例 |
Java.lang.StringBuffer | StringBuffer实现了变长的字符序列。StringBuffer与String有些类似,不同之处在于StringBuffer类可以修改。无论怎样,它只是包含了一些特殊的字符序列,序列的长度和内容可通过方法修改 |
Java.lang.System | System类包含几个有用的类字段和方法,但不能实例化 |
Java.lang.Thread | 一个Thread就是程序中正在执行的一个分支。Java虚拟机允许一个应用程序含有多个同时运行的线程。每个线程都有优先级。高优先级的线程比低优先级的线程优先执行 |
Java.lang.Throwable | Throwable类是Java语言中所有错误和异常的父类 |
Java.lang.Runnable | Runnable接口应该被每个计划由线程运行的实例的类来实现。实现Runnable接口的类必须定义没有参数的run方法 |
类 名 | 描 述 |
Java.util.Enumeration | 一个用于实现枚举接口的对象,一次生成一个元素序列。连续的调用nextElement方法可以返回序列中相继的元素 |
Java.util.Calendar | Calendar类是为了获取和设置日期的一个抽象类 |
Java.util.Date | Date代表当前的时间,使用从标准基点时间开始计算的毫秒数来表示 |
Java.util.Random | Random类用于生成一系列的伪随机数 |
Java.util.Stack | Stack类代表了一个后进先出(LIFO)的对象栈。它扩展了Vector并提供了5个操作方法来把Vector作为栈来处理 |
Java.util.Timer | Timer是类似于线程的工具类,它可以在后台安排任务并执行。任务可以执行一次后就结束,也可以每隔一段时间执行一次 |
Java.util.TimerTask | 能够在Timer中安排执行的任务 |
Java.util.TimeZone | TimeZone代表时区偏移 |
Java.util.Vector | Vector实现了一个可增长的对象数组。可以根据整数索引来访问Vector内的成员 |
Java.io.DataInput | DataInput接口提供了从二进制数据流中读取字节的方法。可以从中重新构造出任何Java基本数据类型 |
Java.io.DataOutput | DataOutput接口可以把数据从Java基本类型转换成一系列的字节,并把这些字节写入二进制数据流中 |
Java.io.ByteArrayInputStream | ByteArrayInputStream包含一个内部的缓冲区,可以从其中读取字节 |
Java.io.ByteArrayOutputStream | 该类实现了一个以字节数组形式写入的输出流。当数据写入时,缓冲区自动增长。用toByteArray()和toString()方法能够得到缓冲区内的数据 |
Java.io.DataInputStream | DataInputStream能够使应用程序以与平台无关的方式从基本输入流中读取Java基本数据类型。应用程序向数据输出流写入数据,这些数据能够从数据输入流读取 |
Java.io.DataOutputStream | DataOutputStream能够使应用程序以简洁的方式将Java基本数据类型写入一个输出流。应用程序向数据输出流写入数据,这些数据能够从数据输入流中读取 |
Java.io.InputStream | InputStream是所有字节输入流的父类 |
Java.io.OutputStream | OutputStream是所有字节输出流的父类 |
Java.io.InputStreamReader | InputStreamReader是字节流向字符流转换的桥梁。可以使用它读取字节然后转换为字符,可以通过构造器中的name参数指定编码方式,否则将使用平台默认的编码方式 |
Java.io.OutputStreamWriter | OutputStreamWriter是字符流向字节流转换的桥梁。写入的字符将转换为字节,可以通过构造器中的name参数指定编码方式,否则将使用平台默认的编码方式 |
Java.io.PrintStream | PrintStream为打印各种数据值提供了方便的方法 |
Java.io.Reader | Reader是读取字符流的抽象类。子类必须实现的方法是read(char[], int, int)和close()。然而,大部分的子类都将覆盖这里定义的一些方法来提供更高的效率或额外的功能 |
Java.io.Writer | Writer是写入字符流的抽象类。子类必须实现的方法是write(char[], int, int),flush()和close()。然而,大部分的子类都将覆盖这里定义的一些方法,以提供更高的效率或额外的功能 |
4.通用连接框架
在J2SE中定义的标准网络连接类库并不适合CLDC,主要原因是:
Ø J2SE中定义的网络连接类的大小超过了200 KB,这对于移动终端设备来说太大了。
Ø J2SE中定义的网络连接类假设TCP/IP协议是可用的。但是很多移动终端设备并不支持TCP/IP协议,只支持HTTP协议。
因此,CLDC引入了全新的网络连接类库——通用连接框架(Generic Connection Framework,GCF)。尽管通用连接框架是在CLDC中定义的,但是只定义了基本连接类型。没有强制实现任何协议,而是把具体的实现交给了上层的简表。
通用连接框架的关键在于把所有连接都按照URL来处理,这样很容易从Connector中得到不同类型的连接,如HttpConnection和SocketConnection。本书的第6章将全面讲解通用连接框架的主要内容,这是MIDP开发中的一个重点,也是难点。下面是一些使用通用连接框架的例子。
Ø HTTP连接。
HttpConnection http = (HttpConnection)Connector.open("http://www.j2medev. com");
Ø Socket连接。
SocketConnection socket
=(SocketConnection)Connector.open("socket://129.144.11.2:9000");
Ø 访问串口。
CommConnection comm.
=(CommConnection)Connector.open("com m:0;baudrate=9600");
Ø 访问文件系统。
FileConnection file = (FileConnection)Connector.open("file:///root1/work. dat");
5.安全特性
J2SE平台的安全模型比整个CLDC的实现还要大,显然不适合直接移植到移动终端设备。JSR 30的专家组在设计CLDC安全结构的时候充分考虑到了这一点。CLDC的安全结构主要由两部分组成:底层虚拟机的安全和应用程序层的安全。
运行在虚拟机上的Class文件必须是经过校验的,运行在虚拟机上的应用程序不能以任何方式破坏设备,因此即使是恶意的应用程序也不可能伤害底层的操作系统和操作系统上的本地应用程序。Class文件校验的工作是比较消耗手机资源的,如果校验工作在手机内部完成,那么将对虚拟机造成很大的负担,因此MIDP应用程序的开发流程中增加了一环就是预校验,预校验在开发过程中完成。预校验之后的Class文件打包为jar文件安装到目标设备,目标设备再对Class文件进行一些简单的校验。第2章将详细地介绍MIDP应用程序的开发流程。
应用程序层的安全是由砂箱模型保证的。这与J2SE平台的砂箱结构有一定的区别。CLDC的砂箱模型主要包括如下要求:
Ø Java类文件必须是经过校验且是有效的Java应用程序;
Ø 只提供有限的,预先定义好的API集合给开发者使用;
Ø 开发者不能覆盖标准的类装载机制,也不能覆盖虚拟机的系统类;
Ø 不允许访问设备的本地接口,开发者不能下载并使用包含本地代码的类库。
MIDP 2.0中新增了安全模型的概念,和我们上面介绍的CLDC的安全特性不同。MIDP 2.0的安全模型将在本书的第7章进行详细的介绍。
6.国际化
J2SE平台中的Writer和Reader类提供了字符处理能力。值得庆幸的是,它们同样被引入了CLDC核心类库中,它们为字节流和Unicode字符转换提供了桥梁。CLDC中使用下面的构造器:
new InputStreamReader(InputStream is);
new InputStreamReader(InputStream is, String name);
new OutputStreamReader(OutputStream os);
new OutputStreamReader(OutputStream os, String name);
上述构造器可以通过参数name来指定编码格式,如果不指定,将采用系统默认的编码格式,开发者可以通过System.getProperty(“microedtion.encoding”)方法来获得系统默认的编码格式。如果构造器中指定的编码格式不存在,UnsupportedEncodingException将会被抛出。