当前位置:  编程技术>移动开发
本页文章导读:
    ▪多角度望 Java 中的泛型        多角度看 Java 中的泛型 摘自IBM中文网站 泛型是 Sun 公司发布的 JDK 5.0 中的一个重要特性,它的最大优点是提供了程序的类型安全同可以向后兼容。为了帮助读者更好地理解和使用泛型,本文.........
    ▪ 腾挪多媒体学习之一        移动多媒体学习之一     好多项目要开工了。以后会忙个像头牛,在这里学习,交流真是爽。趁着现在有那么点点时间,把今天的学习经验交流下。我想没有比开发多媒体软件更令人兴.........
    ▪ SmartTicket代码阅览笔记(二)       SmartTicket代码阅读笔记(二) 接昨天的思路继续浅谈RMSCacheHandler的使用,RemoteModelProxy、RemoteModelRequestHandle和RemoteModel之间应用了代理模式。其中RemoteModelProxy充当了代理主题角色,RemoteModel.........

[1]多角度望 Java 中的泛型
    来源: 互联网  发布时间: 2014-02-18
多角度看 Java 中的泛型

摘自IBM中文网站

泛型是 Sun 公司发布的 JDK 5.0 中的一个重要特性,它的最大优点是提供了程序的类型安全同可以向后兼容。为了帮助读者更好地理解和使用泛型,本文通过一些示例从基本原理,重要概念,关键技术,以及相似技术比较等多个角度对 Java 语言中的泛型技术进行了介绍,重点强调了泛型中的一些基本但又不是很好理解的概念。

为了避免和 C++ 中的模板混淆,本文简要介绍了 Java 中的泛型和 C++ 中的模板的主要区别,希望这种比较能够帮助读者加深对泛型的理解。

引言

很多 Java 程序员都使用过集合(Collection),集合中元素的类型是多种多样的,例如,有些集合中的元素是 Byte 类型的,而有些则可能是 String 类型的,等等。Java 语言之所以支持这么多种类的集合,是因为它允许程序员构建一个元素类型为 Object 的 Collection,所以其中的元素可以是任何类型。

当使用 Collection 时,我们经常要做的一件事情就是要进行类型转换,当转换成所需的类型以后,再对它们进行处理。很明显,这种设计给编程人员带来了极大的不便,同时也容易引入错误。

在很多 Java 应用中,上述情况非常普遍,为了解决这个问题,使 Java 语言变得更加安全好用,近些年的一些编译器对 Java 语言进行了扩充,使 Java 语言支持了"泛型",特别是 Sun 公司发布的 JDK 5.0 更是将泛型作为其中一个重要的特性加以推广。

本文首先对泛型的基本概念和特点进行简单介绍,然后通过引入几个实例来讨论带有泛型的类,泛型中的子类型,以及范化方法和受限类型参数等重要概念。为了帮助读者更加深刻的理解并使用泛型,本文还介绍了泛型的转化,即,如何将带有泛型的 Java 程序转化成一般的没有泛型的 Java 程序。这样,读者对泛型的理解就不会仅仅局限在表面上了。考虑到多数读者仅仅是使用泛型,因此本文并未介绍泛型在编译器中的具体实现。Java 中的泛型和 C++ 中的模板表面上非常相似,但实际上二者还是有很大区别的,本文最后简单介绍了 Java 中的泛型与 C++ 模板的主要区别。





回页首

泛型概览

泛型本质上是提供类型的"类型参数",它们也被称为参数化类型(parameterized type)或参量多态(parametric polymorphism)。其实泛型思想并不是 Java 最先引入的,C++ 中的模板就是一个运用泛型的例子。

GJ(Generic Java)是对 Java 语言的一种扩展,是一种带有参数化类型的 Java 语言。用 GJ 编写的程序看起来和普通的 Java 程序基本相同,只不过多了一些参数化的类型同时少了一些类型转换。实际上,这些 GJ 程序也是首先被转化成一般的不带泛型的 Java 程序后再进行处理的,编译器自动完成了从 Generic Java 到普通 Java 的翻译。具体的转化过程大致分为以下几个部分:

  • 将参数化类型中的类型参数"擦除"(erasure)掉;
  • 将类型变量用"上限(upper bound)"取代,通常情况下这些上限是 Object。这里的类型变量是指实例域,本地方法域,方法参数以及方法返回值中用来标记类型信息的"变量",例如:实例域中的变量声明 A elem;,方法声明 Node (A elem){};,其中,A 用来标记 elem 的类型,它就是类型变量。
  • 添加类型转换并插入"桥方法"(bridge method),以便覆盖(overridden)可以正常的工作。

转化后的程序和没有引入泛型时程序员不得不手工完成转换的程序是非常一致的,具体的转化过程会在后面介绍。GJ 保持了和 Java 语言以及 Java 虚拟机很好的兼容性,下面对 GJ 的特点做一个简要的总结。

  • 类型安全。 泛型的一个主要目标就是提高 Java 程序的类型安全。使用泛型可以使编译器知道变量的类型限制,进而可以在更高程度上验证类型假设。如果没有泛型,那么类型的安全性主要由程序员来把握,这显然不如带有泛型的程序安全性高。
  • 消除强制类型转换。泛型可以消除源代码中的许多强制类型转换,这样可以使代码更加可读,并减少出错的机会。
  • 向后兼容。支持泛型的 Java 编译器(例如 JDK5.0 中的 Javac)可以用来编译经过泛型扩充的 Java 程序(GJ 程序),但是现有的没有使用泛型扩充的 Java 程序仍然可以用这些编译器来编译。
  • 层次清晰,恪守规范。无论被编译的源程序是否使用泛型扩充,编译生成的字节码均可被虚拟机接受并执行。也就是说不管编译器的输入是 GJ 程序,还是一般的 Java 程序,经过编译后的字节码都严格遵循《Java 虚拟机规范》中对字节码的要求。可见,泛型主要是在编译器层面实现的,它对于 Java 虚拟机是透明的。
  • 性能收益。目前来讲,用 GJ 编写的代码和一般的 Java 代码在效率上是非常接近的。 但是由于泛型会给 Java 编译器和虚拟机带来更多的类型信息,因此利用这些信息对 Java 程序做进一步优化将成为可能。

以上是泛型的一些主要特点,下面通过几个相关的例子来对 Java 语言中的泛型进行说明。





回页首

带有泛型的类

为了帮助大家更好地理解 Java 语言中的泛型,我们在这里先来对比两段实现相同功能的 GJ 代码和 Java 代码。通过观察它们的不同点来对 Java 中的泛型有个总体的把握,首先来分析一下不带泛型的 Java 代码,程序如下:


1	interface Collection {
2	   	public void add (Object x);
3		public Iterator iterator ();
4	}
5	
6	interface Iterator {
7	   	public Object next ();
8		public boolean hasNext ();
9	}
10	
11	class NoSuchElementException extends RuntimeException {}
12	
13	class LinkedList implements Collection {
14	
15		protected class Node {
16		   	Object elt;
17			Node next = null;
18			Node (Object elt) { this.elt = elt; }
19		}
20	
21		protected Node head = null, tail = null;
22	
23		public LinkedList () {}
24	
25		public void add (Object elt) {
26			if (head == null) { head = new Node(elt); tail = head; }
27			else { tail.next = new Node(elt); tail = tail.next; }
28		}
29	
30		public Iterator iterator () {
31	
32			return new Iterator () {
33				protected Node ptr = head;
34				public boolean hasNext () { return ptr != null; }
35				public Object next () {
36					if (ptr != null) {
37						Object elt = ptr.elt; ptr = ptr.next; return elt;
38					} else throw new NoSuchElementException ();
39				}
40			};
41		}
42	}

接口 Collection 提供了两个方法,即添加元素的方法 add(Object x),见第 2 行,以及返回该 Collection 的 Iterator 实例的方法 iterator(),见第 3 行。Iterator 接口也提供了两个方法,其一就是判断是否有下一个元素的方法 hasNext(),见第 8 行,另外就是返回下一个元素的方法 next(),见第 7 行。LinkedList 类是对接口 Collection 的实现,它是一个含有一系列节点的链表,节点中的数据类型是 Object,这样就可以创建任意类型的节点了,比如 Byte, String 等等。上面这段程序就是用没有泛型的传统的 Java 语言编写的代码。接下来我们分析一下传统的 Java 语言是如何使用这个类的。

代码如下:


1	class Test {
2		    public static void main (String[] args) {
3			// byte list
4			LinkedList xs = new LinkedList();
5			xs.add(new Byte(0)); xs.add(new Byte(1));
6			Byte x = (Byte)xs.iterator().next();
7			// string list
8			LinkedList ys = new LinkedList();
9			ys.add("zero"); ys.add("one");
10			String y = (String)ys.iterator().next();
11			// string list list
12			LinkedList zss = new LinkedList();
13			zss.add(ys);
14			String z = (String)((LinkedList)zss.iterator().next()).iterator().next();
15			// string list treated as byte list
16			Byte w = (Byte)ys.iterator().next(); // run-time exception
17			}
18	}

从上面的程序我们可以看出,当从一个链表中提取元素时需要进行类型转换,这些都要由程序员显式地完成。如果我们不小心从 String 类型的链表中试图提取一个 Byte 型的元素,见第 15 到第 16 行的代码,那么这将会抛出一个运行时的异常。请注意,上面这段程序可以顺利地经过编译,不会产生任何编译时的错误,因为编译器并不做类型检查,这种检查是在运行时进行的。不难发现,传统 Java 语言的这一缺陷推迟了发现程序中错误的时间,从软件工程的角度来看,这对软件的开发是非常不利的。接下来,我们讨论一下如何用 GJ 来实现同样功能的程序。源程序如下:


1	interface Collection {
2		public void add(A x);
3		public Iterator iterator();
4	}
5	
6	interface Iterator {
7		public A next();
8		public boolean hasNext();
9	}
10	
11	class NoSuchElementException extends RuntimeException {}
12	
13	class LinkedList implements Collection {
14		protected class Node {
15			A elt;
16			Node next = null;
17			Node (A elt) { this.elt = elt; }
18		}
19	
20		protected Node head = null, tail = null;
21	
22		public LinkedList () {}
23	
24		public void add (A elt) {
25			if (head == null) { head = new Node(elt); tail = head; }
26			else { tail.next = new Node(elt); tail = tail.next; }
27		}
28	
29		public Iterator iterator () {
30			return new Iterator () {
31				protected Node ptr = head;
32				public boolean hasNext () { return ptr != null; }
33				public A next () {
34					if (ptr != null) {
35						A elt = ptr.elt; ptr = ptr.next; return elt;
36					} else throw new NoSuchElementException ();
37				}
38			};
39	 	}
40	}

程序的功能并没有任何改变,只是在实现方式上使用了泛型技术。我们注意到上面程序的接口和类均带有一个类型参数 A,它被包含在一对尖括号(< >)中,见第 1,6 和 13 行,这种表示法遵循了 C++ 中模板的表示习惯。这部分程序和上面程序的主要区别就是在 Collection, Iterator, 或 LinkedList 出现的地方均用 Collection泛型中的子类型, Iterator, 或 LinkedList 来代替,当然,第 22 行对构造函数的声明除外。

下面再来分析一下在 GJ 中是如何对这个类进行操作的,程序如下:


1	class Test {
2		public static void main (String [] args) {
3			// byte list
4			LinkedList<byte></byte> xs = new LinkedList<byte></byte>();
5			xs.add(new Byte(0)); xs.add(new Byte(1));
6			Byte x = xs.iterator().next();
7			// string list
8			LinkedList<string></string> ys = new LinkedList<string></string>();
9			ys.add("zero"); ys.add("one");
10			String y = ys.iterator().next();
11			// string list list
12			LinkedList>zss=
newLinkedList>();
13			zss.add(ys);
14			String z = zss.iterator().next().iterator().next();
15			// string list treated as byte list
16			Byte w = ys.iterator().next(); // compile-time error
17		}
18	}

在这里我们可以看到,有了泛型以后,程序员并不需要进行显式的类型转换,只要赋予一个参数化的类型即可,见第 4,8 和 12 行,这是非常方便的,同时也不会因为忘记进行类型转换而产生错误。另外需要注意的就是当试图从一个字符串类型的链表里提取出一个元素,然后将它赋值给一个 Byte 型的变量时,见第 16 行,编译器将会在编译时报出错误,而不是由虚拟机在运行时报错,这是因为编译器会在编译时刻对 GJ 代码进行类型检查,此种机制有利于尽早地发现并改正错误。

类型参数的作用域是定义这个类型参数的整个类,但是不包括静态成员函数。这是因为当访问同一个静态成员函数时,同一个类的不同实例可能有不同的类型参数,所以上述提到的那个作用域不应该包括这些静态函数,否则就会引起混乱。





回页首

 

在 Java 语言中,我们可以将某种类型的变量赋值给其父类型所对应的变量,例如,String 是 Object 的子类型,因此,我们可以将 String 类型的变量赋值给 Object 类型的变量,甚至可以将 String [ ] 类型的变量(数组)赋值给 Object [ ] 类型的变量,即 String [ ] 是 Object [ ] 的子类型。

上述情形恐怕已经深深地印在了广大读者的脑中,对于泛型来讲,上述情形有所变化,因此请广大读者务必引起注意。为了说明这种不同,我们还是先来分析一个小例子,代码如下所示:


1			List<string></string> ls = new ArrayList<string></string>(); 
2			Listlo = ls; 3 lo.add(new Integer()); 4 String s = ls.get(0); 
 

上述代码的第二行将 List<string></string> 赋值给了 List,按照以往的经验,这种赋值好像是正确的,因为 List<string></string> 应该是 List的子类型。这里需要特别注意的是,这种赋值在泛型当中是不允许的!List<string></string> 也不是 List

1 楼 kanokano 2007-07-06  
很好啊
很详细的!!!!!

    
[2] 腾挪多媒体学习之一
    来源: 互联网  发布时间: 2014-02-18
移动多媒体学习之一
    好多项目要开工了。以后会忙个像头牛,在这里学习,交流真是爽。趁着现在有那么点点时间,把今天的学习经验交流下。我想没有比开发多媒体软件更令人兴奋 了。特别是手机多媒体,以前也常常想,该怎么样来查看gif图片了。怎么样看那些mpeg的视频片段了。好了。我开始学习mma了,我想把我学习的经验与 大家交流下。
    这篇文章我只是拿个简单的官方的例子来看写,让我们大家对这个mma有个初步的了解。
 

在J2ME中,移动媒体API(MMAPI)是一个可选包,它提供了一个标准的API,可以用来表现和获得以时间为基础的媒体。例如声音轨道和视频片断。MMAPI在Java社区进程中以JSR-135开发,并且它被设计成灵活的和平台无关的,它没有对媒体格式、协议或者在未来不同设备支持的特征作任何假设。MMAPI已经在移动设备上使用,例如,Nokia3650就包含了一个实现。其它支持MMAPI的设备可以在“J2ME设备”中找到。<o:p></o:p>

这篇文章将介绍MMAPI的最新发展:MMAPI1.1中提出的新的安全考虑、MMAPI和MIDP2.0 Media API之间的不同、J2ME无线工具箱(J2ME Wireless Toolkit)对MMAPI的支持和JSR-234,高级多媒体补充(Advance Multimedia Supplement)。如果你正在寻找一个MMAPI的指南和示例代码,例如为一个音频/视频播放器,请参见“J2ME移动媒体API”和“使用MMAPI拍摄照片”。<o:p></o:p>

MMAPI组件总揽<o:p></o:p>

MMAPI有四个主要的组成部分:<o:p></o:p>

l         Player用来播放内容。它提供了方法,用来管理播放器的生命周期,和不同的重放特征。<o:p></o:p>

l         Manager是媒体的总控制者,它创建播放器。<o:p></o:p>

l         DataSource代表一个协议的控制者,它对应用程序开发者通常是不可见的。这个协议管理者读出媒体并放到播放器中进行播放。<o:p></o:p>

l         Control控制Player和重放操作的不同特征。<o:p></o:p>

MMAPI支持的控制操作<o:p></o:p>

MMAPI在javax.microedition.control包中包含了12种控制操作:<o:p></o:p>

l         MetaDataControl用来从媒体数据中获得元数据信息。<o:p></o:p>

l         MIDIControl提供对播放器表现和传输设备的访问。<o:p></o:p>

l         GUIControl代表一个具有用户界面组件的控制操作。<o:p></o:p>

l         PitchControl升高或降低重放的位置而不改变重放的速度。<o:p></o:p>

l         RateControl控制重放的速率。<o:p></o:p>

l         TempoControl控制MIDI歌曲的节奏。<o:p></o:p>

l         VolumeControl控制音量。<o:p></o:p>

l         VideoControl控制可视内容的显示。<o:p></o:p>

l         FramePositioningControl可以对一个视频帧精确定位。<o:p></o:p>

l         RecordControl记录当前被Player播放的是什么内容。<o:p></o:p>

l         StopTimeControl使应用程序可以为一个Player预先指定一个停止时间。<o:p></o:p>

l         ToneControl是一个可以播放用户自定音调序列的接口。<o:p></o:p>

必须明白,并不是所有的MMAPI实现都支持所有的控制操作类型。你可以通过调用System.getProperty(String key)得到一个设备所支持的控制类型。这个规范定义如下这些属性:<o:p></o:p>

l         microedition.media.version返回一个代表MMAPI实现版本的字符串。如果当前设备支持MMAPI,返回“<st1:chmetcnv unitname="”" sourcevalue="1" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">1.0”</st1:chmetcnv>或者“<st1:chmetcnv unitname="”" sourcevalue="1.1" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">1.1”</st1:chmetcnv>,反之,则返回“null”。<o:p></o:p>

l         supports.mixing如果支持混频则返回true,否则返回false。<o:p></o:p>

l         supports.audio.capture如果支持音频记录就返回true,否则返回false。<o:p></o:p>

l         supports.video.capture如果支持视频记录就返回true,否则返回false。

l         supports.recording如果支持录制就返回true,否则返回false。

l         audio.encodings返回一个代表所支持的音频格式的字符串,如果不支持音频内容则返回“null”。

l         video.encodings返回一个代表所支持的视频格式的字符串,如果不支持视频内容则返回“null”。

l         video.snapshot.encodings返回一个代表所支持的图像格式的字符串,如果不支持视频快照则返回“null”。

l         streamable.contents返回一个代表所支持的流媒体内容类型的字符串,以MIME语法。

除了被System.getProperty()支持的属性外,Manager类还提供了几个有用的静态方法:

l         String[] getSupportedContentTypes(String protocol)传入一个协议如“http”作为参数,返回这个协议所支持的内容类型。

l         String[] getSupportedProtocols(String contentType)传入一个以MIME语法的内容类型如“video/mpeg”,返回可以用来传递这种类型的协议。

MMAPI1.1<o:p></o:p>

MMAPI1.1是MMAPI1.0的延续和更新。它主要修改了文档问题,增加了一些新的定义,并且修订了和MIDP2.0安全框架相关联的文档。它没有对类、接口以及方法定义做任何修改。

MMAPI没有定义它自己的安全框架,但是MMAPI实现从属于潜在的Profile和Configuration所提供的安全框架。如果调用者缺乏合适的安全许可,一些MMAPI方法被定义抛出一个SecurityException。因此,一个MMAPI实现必须保证:

l         当调用者没有合适的权限而执行MMAPI实现中的方法时,要抛出SecurityException。

l         当被授予合适的权限后,其中的方法可能会用到。

MMAPI的安全问题涉及到录制、网络访问和本地数据存储访问。录制关系到用户的私有权;应用程序可能默默的访问录制功能,录制和分发私人会话。另外,安全实践必须可以在适当的位置访问远程和本地资源。为了获得访问录制功能、网络和本地数据存储的权限,一个MMAPI实现必须获得实现制定的合适的权限。

MMAPI和J2ME无线工具箱2.2<o:p></o:p>

J2ME无线工具2.2版本实现JSR-135。随这个工具箱一起发布的有一个模拟器皮肤,MediaControlSkin,它主要用于在多媒体的播放和控制。这个模拟器的MMAPI实现支持一下媒体类型。

MIME类型

描述

audio/midi

MIDI文件

audio/sp-midi

可升级的多音MIDI

audio/x-tone-seq

MIDP2.0音调序列

audio/x-wav

WAV PCM取样音频

image/gif

FIG<st1:chmetcnv unitname="a" sourcevalue="89" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">89a</st1:chmetcnv>(活动的GIF)

video/mpeg

MPEG视频

video/vnd.sun.rgb565

视频记录

MMAPI MIDlets<o:p></o:p>

随工具箱发布的还有一些MMAPI的demo。一个特别用户的demo是Pausing Audio Test,它是mmademo工程的一部分。它展示了一个良好开发的MMAPI MIDlet应该如何运转。例如,你必须清楚MIDlets可能会被一些事件中止,如一个来电,如图1所示。当你的MIDlets中止时,它们应该释放比较重要的设备资源,当MIDlet恢复时,再重新分配或启动那些资源。当一个MIDlet中止时,任何播放器都应该停止,如果William Tell Overture穿过一个重要的商务电话一直播放,你的用户并不会感谢你。

<v:shapetype coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f" id="_x0000_t75"><v:stroke join></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></v:path><o:lock v:ext="edit" aspectratio="t"></o:lock></v:shapetype><o:p></o:p>

图1<o:p></o:p>

MMAPI和MIDP2.0 Media API的比较<o:p></o:p>

MIDP2.0媒体API是MMAPI一个直系的子集,打算提供给那些资源有限运行MIDP2.0的设备,尽管同样的子集可能被其他需要声音支持的J2ME Profile采用。这个API实现了MIDP专家组制定的要求,包括:

l         简易音频播放

l         不依赖于任何特定的协议和内容格式

l         支持自定音调

l         支持普通的媒体流控制,如开始、停止、查找等

l         支持媒体类型特定的控制,如声音

l         支持容量查询

因为这些要求,MIDP2.0 Media API和MMAPI有以下不同:

l         如果仅仅是视频,它不包含视频或图像特定的控制操作。

l         不支持多个播放器同时使用一个普通时间基同步播放。

l         不支持通过自定义DataSource的方式自定义协议,不包含javax.microedition.media.protocol包。

l         使用Manager的一个简化版本。

MMAPI和高级多媒体补充(Advanced Multimedia Supplements)的比较<o:p></o:p>

JSR-135引入了音频和视频的基础的播放功能。JSR-234,高级多媒体补充,将会通过为高级多媒体功能定义一个可选包支持最近的硬件更新。在J2ME/CLDC环境中,新的API依赖和增加了MMAPI的特征。提供这个可选包的主要目的是为了更好的支持照相机和收音机,也为了高级音频处理。在规范中描述的一些能力有:

l         支持特定的照相机控制,如亮度对比、闪光、灯光模式和镜头变焦。

l         正确的访问收音机和其他基于频道和频率的媒体源,包括无线电数据系统。

l         高级的音频处理能力,如均衡器和音频效果。

l         媒体输出方式指定,用来选择音频是通过喇叭播放还是通过耳机播放。

总结<o:p></o:p>

MMAPI可选包为运行在MIDP设备上的应用程序,提供了一些宜人的功能,在以前这些功能并不可用。它的可扩展架构为以后在移动设备上提供更多的功能创造了机会。这篇文章描述了MMAPI的主要组成部分,讨论了在1.1版本中的变化,并且解释了MMAPI、MIDP2.0 Media API和高级多媒体补充(Advanced Multimedia Supplements)之间的关系。如果你想将MMAPI运用在实际中,请下载J2ME无线工具箱2.2,然后研究mmademo和Audiodemo工程。

上面的这个文章是j2medev里面的一个高手翻译的。看了基本上是有个了解了。

下面也让我们看下一个例子代码,也是出自j2medev。
java 代码
  • public class GifPlayer extends MIDlet {  
  •      
  •     private Display display = null;  
  •     private Player player = null;  
  •      
  •     public void startApp() {  
  •         if(display == null)  
  •             display = Display.getDisplay(this);  
  •         Form form = new Form("gif player");  
  •         InputStream is = getClass().getResourceAsStream("/a.gif");  
  •         createPlayer(is);  
  •         if(player == null){  
  •             form.append("can not play image/gif");  
  •         }else{  
  •             VideoControl vc = (VideoControl)player.getControl("VideoControl");  
  •             if(vc != null){  
  •                // form.append((Item)vc.initDisplayMode(
  • VideoControl.USE_GUI_PRIMITIVE,null));  
  •             }  
  •         }  
  •         display.setCurrent(form);  
  •         try {  
  •             form.append(Image.createImage("/a.gif"));  
  •         } catch (IOException e) {  
  •             // TODO 自动生成 catch 块  
  •             e.printStackTrace();  
  •         }  
  •         try {       player.realize();
    &
  • 1 楼 linginfanta 2007-02-25  
    学习一哈
    2 楼 wuhua 2007-02-26  
    这篇文章怎么不全呢。
    我写的时候不止这么少的哦。
    是不是javaeye有字数的限制啊。
    郁闷
    3 楼 avampire 2007-02-27  
    续贴罗 仿佛不全
    4 楼 wuhua 2007-02-27  
    有时间再补上去吧

        
    [3] SmartTicket代码阅览笔记(二)
        来源: 互联网  发布时间: 2014-02-18
    SmartTicket代码阅读笔记(二)
    接昨天的思路继续浅谈RMSCacheHandler的使用,RemoteModelProxy、RemoteModelRequestHandle和RemoteModel之间应用了代理模式。其中RemoteModelProxy充当了代理主题角色,RemoteModel是抽象主题角色,而RemoteModelRequestHandle是真实主题角色。
    • 代理模式(Proxy),给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。(参见RemoteModelProxy、RemoteModelRequestHandle和RemoteModel之间关系及UML图)。
    在RemoteModelProxy中也就保存了一个对RemoteModelRequestHandle的引用,如下
    java 代码
     
  • private RemoteModelRequestHandler requestHandlerChain;  
  •    private Preferences preferences = null;  
  •    private Hashtable movies = new Hashtable();  
  •   
  •    public RemoteModelProxy(String serviceURL) throws ApplicationException {  
  •        requestHandlerChain =   
  •            new RMSCacheHandler(new HTTPCommunicationHandler(null,   
  •                serviceURL));  
  •   
  •        return;  
  •    }  
  • 现在小节一下RemoteModelProxy的作用,它是一个代理主题角色,是它控制了RMSCacheHandler以及HTTPCommunicationHandler。

    看看RMSCacheHandler的constructor
    java 代码
  •      /** 
  •      * Constructs a new RMSCacheHandler which is to be inserted in a RequestHandler chain. 
  •      * @param nextHandler The next handler in the chain. 
  •      * @param progressObserver The progress observer. 
  •      */  
  •     public RMSCacheHandler(RemoteModelRequestHandler nextHandler)   
  •             throws ApplicationException {  
  •         super(nextHandler);  
  •   
  •         rmsAdapter = new RMSAdapter();  
  •   
  •         return;  
  •     } 
  • 注释中提到了RequestHandler chain,责任链模式,恩,继续查资料
    • 责任链模式(Chain of Responsibility),很多对象由每一个对象对其下家的引用而连接起来形成一条链,请求在这个链上传递,直到链上的某一个对象决定处理此请求。
    在RemoteModelProxy中有责任链模式典型的应用
    java 代码
     
  • requestHandlerChain =   
  •             new RMSCacheHandler(new HTTPCommunicationHandler(null,   
  •                 serviceURL));  
  • 可以看到,RemoteModelProxy创建了两个处理者对象,并指定RMSCacheHandler的下家是HTTPCommunicationHandler,而HTTPCommunicationHandler没有下家,真正起作用处理的是HTTPCommunicationHandler对象。

     小节:
    在这个看似简单的应用中运用了这么多的设计模式,不知道是sun的blueprint这么要求的还是普遍存在这样的设计?
    不知道这样的学习方法是否正确,欢迎大家批判:)

    to be continued......












        
    最新技术文章:
    ▪Android开发之登录验证实例教程
    ▪Android开发之注册登录方法示例
    ▪Android获取手机SIM卡运营商信息的方法
    ▪Android实现将已发送的短信写入短信数据库的...
    ▪Android发送短信功能代码
    ▪Android根据电话号码获得联系人头像实例代码
    ▪Android中GPS定位的用法实例
    ▪Android实现退出时关闭所有Activity的方法
    ▪Android实现文件的分割和组装
    ▪Android录音应用实例教程
    ▪Android双击返回键退出程序的实现方法
    ▪Android实现侦听电池状态显示、电量及充电动...
    ▪Android获取当前已连接的wifi信号强度的方法
    ▪Android实现动态显示或隐藏密码输入框的内容
    ▪根据USER-AGENT判断手机类型并跳转到相应的app...
    ▪Android Touch事件分发过程详解
    ▪Android中实现为TextView添加多个可点击的文本
    ▪Android程序设计之AIDL实例详解
    ▪Android显式启动与隐式启动Activity的区别介绍
    ▪Android按钮单击事件的四种常用写法总结
    ▪Android消息处理机制Looper和Handler详解
    ▪Android实现Back功能代码片段总结
    ▪Android实用的代码片段 常用代码总结
    ▪Android实现弹出键盘的方法
    ▪Android中通过view方式获取当前Activity的屏幕截...
    ▪Android提高之自定义Menu(TabMenu)实现方法
    ▪Android提高之多方向抽屉实现方法
    ▪Android提高之MediaPlayer播放网络音频的实现方法...
    ▪Android提高之MediaPlayer播放网络视频的实现方法...
    ▪Android提高之手游转电视游戏的模拟操控
     


    站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3