随笔:15 文章:8 评论:1 引用:0
BlogJava 首页 发新随笔
发新文章 联系 聚合管理

2009年3月3日

Adobe的官方文档:http://livedocs.adobe.com/flex/3/html/help.html?content=anttasks_1.html
简介
Adobe Flex Ant tasks提供了一个方便的方式来使用行业标准构建管理工具来构建你的Flex工程。如果你已经使用Ant工程来构建Flex应用程序,你可以使用Flex Ant tasks来替换你的exec或者调用mxmlc和compc编译器的java命令行。如果你还没有使用ant来构建,你可以利用这些自定义任务来快速和容易地为你的Flex应用建立起复杂的构建过程。
Flex Ant tasks功能包括两个编译器任务:mxmlx和compc。你可以使用它们来编译Flex应用,模块,和组件库。除此以外,Flex Ant tasks包括html-wrapper任务,这可以让你生成自定义的HTML包装器和这些包装器的支持文件。
mxmlc和compc Flex Ant tasks继承了java Ant task.所以,你可以在Flex Ant tasks中使用java Ant task的所有属性。这包括fork,maxmemory和classpath。
更多关于使用Ant的信息,参考http://ant.apache.org.
安装
过程非常简单,从Flex SDK ant目录拷贝flexTasks.jar到你的Ant的lib目录。如果你不拷贝,你必须在命令行中使用Ant的-lib选项。
使用Flex Ant Tasks
你可以在你已有的工程或新建一个Ant工程使用Flex Ant tasks。在你的Ant工程中,有3个任务可以使用:
   >>mxmlc -- 调用应用编译器。你可以使用这个编译器来编译Flex应用程序,模块,资源模块,和CSS SWF文件。
   >>compc -- 调用组件编译器。你可以使用这个编译器来编译SWC文件和运行共享库。
   >>html-wrapper --生成HTML包装器和Flex应用的支持文件。通过使用这个任务,你可以选择包装器的类型(是否有深度链接支持,是否有快速安装,是否有播放器检测),和指定应用配置,譬如高度、宽度和背景颜色。

在你的Ant工程中使用自定义的Flex Ant tasks,你必须添加flexTasks.jar文件到你的工程lib目录,然后在taskdef task中指向这个jar文件。一个taskdef task添加了一个任务定义的新集合到你当前的工程中。你使用它来添加那些不是默认Ant安装的任务定义。此外,对大部分工程,你设定FLEX_HOME变量的值,以方便Ant能够找到你的flex-config.xml文件,然后你就能添加frameworks目录到你的source path。

在Ant中使用Flex tasks
1. 添加一个新的taskdef 任务到你的工程。在这个任务中,指定flexTasks.tasks文件作为资源,并将classpath指向flexTasks.jar文件。例如:
<taskdef resource="flexTasks.tasks" classpath="${basedir}/flexTasks/lib/flexTasks.jar" />
2. 定义FLEX_HOME和APP_ROOT属性。使用这两个属性来指向你的FLEX SDK的根目录和应用程序的根目录。虽然不是要求,但是为这两个目录创建属性是一个通用实践,因为你将可能在你的Ant tasks中多次使用它们。例如:
<property name="FLEX_HOME" value="C:/flex/sdk"/>
<property name="APP_ROOT" value="myApps"/>
3.写一个使用Flex Ant tasks的目标。下面这个例子定义了main目标,使用了mxmlc任务来编译Main.mxml文件:
<target name="main">
    <mxmlc file="${APP_ROOT}/Main.mxml" keep-generated-actionscript="true">
        <load-config filename="${FLEX_HOME}/frameworks/flex-config.xml"/>
        <source-path path-element="${FLEX_HOME}/frameworks"/>
    </mxmlc>
</target>
下面是完整的例子:
<?xml version="1.0" encoding="utf-8"?>
<!-- mySimpleBuild.xml -->
<project name="My App Builder" basedir=".">
    <taskdef resource="flexTasks.tasks"
        classpath="${basedir}/flexTasks/lib/flexTasks.jar"/>
    <property name="FLEX_HOME" value="C:/flex/sdk"/>
    <property name="APP_ROOT" value="myApp"/>
    <target name="main">
        <mxmlc file="${APP_ROOT}/Main.mxml" keep-generated-actionscript="true">
            <load-config filename="${FLEX_HOME}/frameworks/flex-config.xml"/>
            <source-path path-element="${FLEX_HOME}/frameworks"/>
        </mxmlc>
    </target>
</project>
这个例子展示了如何为mxmlc任务使用不同类型的选项。你可以指定keep-generated-actionscript选项的值作为mxmlc任务标志的一个属性,因为它没有任何儿子标志。为指定load-config和source-path的值,你创建了mxmlc任务标志的儿子标志。更多关于使用选项的信息,可参考http://livedocs.adobe.com/flex/3/html/help.html?content=anttasks_4.html#207401

4. 执行Ant工程,例如:
> ant -buildfile mySimpleBuild.xml main
如果你不拷贝flexTasks.jar文件到Ant的lib目录,你必须包括这个JAR文件,通过使用Ant的-lib选项,例如:
> ant -lib c:/ant/lib/flexTasks.jar -buildfile mySimpleBuild.xml main

输出如下:
Buildfile: mySimpleBuild.xml
main:
    [mxmlc] Loading configuration file C:\flex\sdk\frameworks\flex-config.xml
    [mxmlc] C:\myfiles\flex2\ant_tests\apps\Main.swf (150035 bytes)
BUILD SUCCESSFUL
Total time: 10 seconds
>
编译器选项
compc和mxmlc编译器共享了一组相似的选项。所以,mxmlc和compc Ant tasks的行为也相似。
你可以通过很多方式为mxmlc和compc Flex tasks指定选项:
>>任务属性
>>单参数选项
>>多参数选项
>>嵌套元素
>>含蓄的文件集

任务属性
为Flex Ant tasks指定选项最简单的方法就是指定名字和命令行选项的值为一个task属性。在下面的例子中,file和keep-generated-actionscript选项被指定为mxmlc任务的属性。
<mxmlc file="${APP_ROOT}/Main.mxml" keep-generated-actionscript="true">
很多mxmlc和compc选项有别名。Flex Ant tasks支持这些选项的所有文档别名。
单参数选项
posted @ 2009-06-19 09:46 TracyLu 阅读(1062) | 评论 (0)编辑 收藏
 
GEF是什么?
GEF(Graphical Editing Framework)允许开发人员从现有的应用模型来创建一个丰富的图形编辑器。GEF由2个插件构成,org.eclipse.draw2dorg.eclipse.geforg.eclipse.draw2d插件为显示图形提供一个布局和渲染的工具箱。然后开发人员能够利用许多GEF提供的通用的操作,或者为特定的域扩展这些操作。 GEF 采用了一个MVC (model-view-controller) 架构,使得简单的改变从视图被适用于模型。 GEF 是完全应用中性的,并且提供了基础来构建几乎任何应用,包括但是不局限于:活动图,GUI构建器,类图编辑器,状态机,甚至于所见即所得的文本编辑器。

特征:
        org.eclipse.draw2d
  • 高效的布局和渲染支持
  • 各种图形和布局实现
  • 边界 
  • 光标和提示支持
  • 连接锚、路由、和装饰。
  • 众多、透明层
  • 灵活的协调系统
  • 概览窗口(缩图与滚动)
  • 打印

org.eclipse.gef

  • 提供了选择、创建、连接、选取框工具 
  • 显示这些工具的调色板 
  • 处理调整对象和弯曲连接 
  • GEF Viewers的两种类型:Graphical和Tree 
  • 一个控制框架,映射业务模型到视图 
    • 插件规则,映射视图与模型的互动 
    • 多种实现来显示反馈和添加选择处理
    • 多种请求类型和工具或者行为来发送请求到控制器。
  • 通过命令和命令堆栈来实现取消/重做支持

 

posted @ 2009-06-09 17:57 TracyLu 阅读(257) | 评论 (0)编辑 收藏
 
提起Java内部类(Inner Class)可能很多人不太熟悉,实际上类似的概念在C++里也有,那就是嵌套类(Nested Class),关于这两者的区别与联系,在下文中会有对比。内部类从表面上看,就是在类中又定义了一个类(下文会看到,内部类可以在很多地方定义),而实际上并没有那么简单,乍看上去内部类似乎有些多余,它的用处对于初学者来说可能并不是那么显著,但是随着对它的深入了解,你会发现Java的设计者在内部类身上的确是用心良苦。学会使用内部类,是掌握Java高级编程的一部分,它可以让你更优雅地设计你的程序结构。下面从以下几个方面来介绍:
  • 第一次见面

public interface Contents {
    int value();
}

public interface Destination {
    String readLabel();
}

public class Goods {
    private class Content implements Contents {
        private int i = 11;
        public int value() {
            return i;
         }
     }

    protected class GDestination implements Destination {
        private String label;
        private GDestination(String whereTo) {
            label = whereTo;
         }
        public String readLabel() {
            return label;
         }
     }

    public Destination dest(String s) {
        return new GDestination(s);
     }
    public Contents cont() {
        returnnew Content();
     }
}

class TestGoods {
    public static void main(String[] args) {
         Goods p = new Goods();
        Contents c = p.cont();
         Destination d = p.dest("Beijing");
     }
}

     在这个例子里类Content和GDestination被定义在了类Goods内部,并且分别有着protected和private修饰符来控制访问级别。Content代表着Goods的内容,而GDestination代表着Goods的目的地。它们分别实现了两个接口Content和 Destination。在后面的main方法里,直接用 Contents c和Destination d进行操作,你甚至连这两个内部类的名字都没有看见!这样,内部类的第一个好处就体现出来了——隐藏你不想让别人知道的操作,也即封装性。

     同时,我们也发现了在外部类作用范围之外得到内部类对象的第一个方法,那就是利用其外部类的方法创建并返回。上例中的cont()和dest()方法就是这么做的。那么还有没有别的方法呢?当然有,其语法格式如下:

outer Object=new outerClass(Constructor Parameters);

outerClass.innerClass innerObject=outerObject.new InnerClass(Constructor Parameters);

     注意在创建非静态内部类对象时,一定要先创建起相应的外部类对象。至于原因,也就引出了我们下一个话题——

  • 非静态内部类对象有着指向其外部类对象的引用

对刚才的例子稍作修改:

public class Goods {

   private valueRate=2;

    private class Content implements Contents {
        private int i = 11*valueRate;
        public int value() {
            return i;
         }
     }

    protected class GDestination implements Destination {
        private String label;
        private GDestination(String whereTo) {
            label = whereTo;
         }
        public String readLabel() {
            return label;
         }
     }

    public Destination dest(String s) {
        return new GDestination(s);
     }
    public Contents cont() {
        return new Content();
     }
}

     修改的部分用蓝色显玖恕T谡饫镂颐歉鳪oods类增加了一个private成员变量valueRate,意义是货物的价值系数,在内部类Content的方法value()计算价值时把它乘上。我们发现,value()可以访问valueRate,这也是内部类的第二个好处——一个内部类对象可以访问创建它的外部类对象的内容,甚至包括私有变量!这是一个非常有用的特性,为我们在设计时提供了更多的思路和捷径。要想实现这个功能,内部类对象就必须有指向外部类对象的引用。 Java编译器在创建内部类对象时,隐式的把其外部类对象的引用也传了进去并一直保存着。这样就使得内部类对象始终可以访问其外部类对象,同时这也是为什么在外部类作用范围之外向要创建内部类对象必须先创建其外部类对象的原因。

     有人会问,如果内部类里的一个成员变量与外部类的一个成员变量同名,也即外部类的同名成员变量被屏蔽了,怎么办?没事,Java里用如下格式表达外部类的引用:

outerClass.this

有了它,我们就不怕这种屏蔽的情况了。

  • 静态内部类

     和普通的类一样,内部类也可以有静态的。不过和非静态内部类相比,区别就在于静态内部类没有了指向外部的引用。这实际上和C++中的嵌套类很相像了,Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用这一点上,当然从设计的角度以及以它一些细节来讲还有区别。

     除此之外,在任何非静态内部类中,都不能有静态数据,静态方法或者又一个静态内部类(内部类的嵌套可以不止一层)。不过静态内部类中却可以拥有这一切。这也算是两者的第二个区别吧。

  • 局部内部类

是的,Java内部类也可以是局部的,它可以定义在一个方法甚至一个代码块之内。

public class Goods1 {
     public Destination dest(String s) {
          class GDestination implements Destination {
               private String label;
               private GDestination(String whereTo) {
                    label = whereTo;
                }
               public String readLabel() { return label; }
           }
          return new GDestination(s);
      }

     public static void main(String[] args) {
           Goods1 g= new Goods1();
           Destination d = g.dest("Beijing");
      }
}

     上面就是这样一个例子。在方法dest中我们定义了一个内部类,最后由这个方法返回这个内部类的对象。如果我们在用一个内部类的时候仅需要创建它的一个对象并创给外部,就可以这样做。当然,定义在方法中的内部类可以使设计多样化,用途绝不仅仅在这一点。

下面有一个更怪的例子:

public class Goods2{
     privatevoid internalTracking(boolean b) {
           if(b) {
               class TrackingSlip {
                    private String id;
                     TrackingSlip(String s) {
                          id = s;
                     }
                    String getSlip() { return id; }
                }
                TrackingSlip ts = new TrackingSlip("slip");
               String s = ts.getSlip();
           }
      }

     public void track() { internalTracking(true); }

     public staticvoid main(String[] args) {
           Goods2 g= new Goods2();
           g.track();
      }
}

     你不能在if之外创建这个内部类的对象,因为这已经超出了它的作用域。不过在编译的时候,内部类TrackingSlip和其他类一样同时被编译,只不过它由它自己的作用域,超出了这个范围就无效,除此之外它和其他内部类并没有区别。

  • 匿名内部类

     java的匿名内部类的语法规则看上去有些古怪,不过如同匿名数组一样,当你只需要创建一个类的对象而且用不上它的名字时,使用内部类可以使代码看上去简洁清楚。它的语法规则是这样的:

new interfacename(){......}; 或 new superclassname(){......};

下面接着前面继续举例子:

public class Goods3 {
     public Contents cont(){
          return newContents(){
               private int i = 11;
               public int value() {
                    return i;
                }
           };
      }
}

这里方法cont()使用匿名内部类直接返回了一个实现了接口Contents的类的对象,看上去的确十分简洁。

在java的事件处理的匿名适配器中,匿名内部类被大量的使用。例如在想关闭窗口时加上这样一句代码:

frame.addWindowListener(new WindowAdapter(){
     public void windowClosing(WindowEvent e){
           System.exit(0);
      }
});

     有一点需要注意的是,匿名内部类由于没有名字,所以它没有构造函数(但是如果这个匿名内部类继承了一个只含有带参数构造函数的父类,创建它的时候必须带上这些参数,并在实现的过程中使用super关键字调用相应的内容)。如果你想要初始化它的成员变量,有下面几种方法:

  1. 如果是在一个方法的匿名内部类,可以利用这个方法传进你想要的参数,不过记住,这些参数必须被声明为final。
  2. 将匿名内部类改造成有名字的局部内部类,这样它就可以拥有构造函数了。
  3. 在这个匿名内部类中使用初始化代码块。
  • 为什么需要内部类?

java内部类有什么好处?为什么需要内部类?

     首先举一个简单的例子,如果你想实现一个接口,但是这个接口中的一个方法和你构想的这个类中的一个方法的名称,参数相同,你应该怎么办?这时候,你可以建一个内部类实现这个接口。由于内部类对外部类的所有内容都是可访问的,所以这样做可以完成所有你直接实现这个接口的功能。

     不过你可能要质疑,更改一下方法的不就行了吗?

     的确,以此作为设计内部类的理由,实在没有说服力。

     真正的原因是这样的,java中的内部类和接口加在一起,可以的解决常被C++程序员抱怨java中存在的一个问题——没有多继承。实际上,C++的多继承设计起来很复杂,而java通过内部类加上接口,可以很好的实现多继承的效果。

    

posted @ 2009-05-18 21:55 TracyLu 阅读(158) | 评论 (0)编辑 收藏
 
FLEX内存释放优化原则:

1. 被删除对象在外部的所有引用一定要被删除干净才能被系统当成垃圾回收处理掉;

2. 父对象内部的子对象被外部其他对象引用了,会导致此子对象不会被删除,子对象不会被删除又会导致了父对象不会被删除;

3. 如果一个对象中引用了外部对象,当自己被删除或者不需要使用此引用对象时,一定要记得把此对象的引用设置为null;

4. 本对象删除不了的原因不一定是自己被引用了,也有可能是自己的孩子被外部引用了,孩子删不掉导致父亲也删不掉;

5. 除了引用需要删除外,系统组件或者全局工具、管理类如果提供了卸载方法的就一定要调用删除内部对象,否则有可能会造成内存泄露和性能损失;

6. 父对象立刻被删除了不代表子对象就会被删除或立刻被删除,可能会在后期被系统自动删除或第二次移除操作时被删除;

7. 如果父对象remove了子对象后没有清除对子对象的引用,子对象一样是不能被删除的,父对象也不能被删除;

8. 注册的事件如果没有被移除不影响自定义的强行回收机制,但有可能会影响正常的回收机制,所以最好是做到注册的事件监听器都要记得移除干净。

9. 父对象被删除了不代表其余子对象都删除了,找到一种状态的泄露代码不等于其他状态就没有泄露了,要各模块各状态逐个进行测试分析,直到测试任何状态下都能删除整个对象为止。

内存泄露举例:

1. 引用泄露:对子对象的引用,外部对本对象或子对象的引用都需要置null;

2. 系统类泄露:使用了系统类而忘记做删除操作了,如BindingUtils.bindSetter(),ChangeWatcher.watch()函数 时候完毕后需要调用ChangeWatcher.unwatch()函数来清除引用 ,否则使用此函数的对象将不会被删除;类似的还有MUSIC,VIDEO,IMAGE,TIMER,EVENT,BINDING等。

3. 效果泄露:当对组件应用效果Effect的时候,当本对象本删除时需要把本对象和子对象上的Effect动画停止掉,然后把Effect的target对象置null; 如果不停止掉动画直接把 Effect置null将不能正常移除对象。

4. SWF泄露:要完全删除一个SWF要调用它的unload()方法并且把对象置null;

5. 图片泄露:当Image对象使用完毕后要把source置null;(为测试);

6. 声音、视频泄露: 当不需要一个音乐或视频是需要停止音乐,删除对象,引用置null;


内存泄露解决方法:

1. 在组件的REMOVED_FROM_STAGE事件回掉中做垃圾处理操作(移除所有对外引用(不管是VO还是组件的都需要删除),删除监听器,调用系统类的清除方法)先remove再置null, 确保被remove或者removeAll后的对象在外部的引用全部释放干净;

2. 利用Flex的性能优化工具Profile来对项目进程进行监控,可知道历史创建过哪些对象,目前有哪些对象没有被删除,创建的数量,占用的内存比例和用量,创建过程等信息;

总结:关键还是要做好清除工作,自己设置的引用自己要记得删除,自己用过的系统类要记得做好回收处理工作。 以上问题解决的好的话不需要自定义强制回收器也有可能被系统正常的自动回收掉。
posted @ 2009-04-01 11:51 TracyLu 阅读(239) | 评论 (0)编辑 收藏
 
        对于业务对象怎么封装的在过去Core J2EE Pattern上,把业务对象的属性都是散列开的。而且其中有个不佳实践,就是把业务对象当中的所有属性都变成一个传输对象(这个传输对象看上去有点像领域模型)。新的技术编程模型下(EJB3.0)应该让业务对象直接持有实体,而不是把每一个属性都列开原因在于,如果把属性都列开,那么业务对象本身应该被管理,为什么呢?如果多个事务或多个现程在访问本来相同的业务对象(标识相同) 的时候,那么由于业务对象不受管,他们创建了各自的实例,彼此不相干,但是当最后提交内容的时候,就可能会导致结果很意外这个同 容器的四种事务隔离级别的意义很类似,如果要将BO的属性都列开,那么,就应该让BO受管,相当于单独实现一个BO的容器,控制并发,控制事务这个容器 要实现多个线程共享一个标识相同的业务对象,并控制并发访问,合适的隔离事务。也就是说要做一个容器应该做的事情应该巧妙的利用容器提供的持久性容器来解决这个问题将实体放到业务对象中,对业务对象的操作,实际上是业务对象的业务方法的操作,而业务方法操纵的是持久化上下文中的实体的状态,每一个被创建出来具有相同标识的业务对象,虽然是不同的实例,但是都包含对同一个实体对象的引用。这样对业务对象状态的变更,实际上是对一个实体对象状态的变更,仍然属于受管状态但是这个时候也一定要搞清楚,业务对象包裹的这个实体的状态:新建、受管、脱管、已删除
posted @ 2009-03-23 17:44 TracyLu 阅读(169) | 评论 (0)编辑 收藏
 

Adobe 官方简体中文帮助地址大全

兄弟们下载附件要用很多银两,银两来的也不容易。

今天 收集了官方帮助文件供大家参考。

到官方在页面的右上角 有 PDF 格式帮助下载


使用 Adobe Flash CS4 Professional
http://help.adobe.com/zh_CN/Flash/10.0_UsingFlash/

扩展 Adobe Flash CS4 Professional
http://help.adobe.com/zh_CN/Flash/10.0_ExtendingFlash/
开发 Adobe Flash Lite 2.x 和 3.x 应用程序
http://help.adobe.com/zh_CN/FlashLite/2.0_FlashLiteDevGuide2/

使用 Flash
http://help.adobe.com/zh_CN/Flash/10.0_Welcome/WS0440A5AD-E290-4bd6-A402-B09F727E9A05.html

Adobe ActionScript 3.0 编程
http://help.adobe.com/zh_CN/ActionScript/3.0_ProgrammingAS3/

使用 Adobe ActionScript 3.0 组件
http://help.adobe.com/zh_CN/ActionScript/3.0_UsingComponentsAS3/

================================================================================
使用 Flash 和 Flex
http://help.adobe.com/zh_CN/Flash/10.0_UsingFlash/WSFD77A256-0DE1-46c7-86FB-CC4A8AE2EAA6.html

安装 Flex 3 SDK
http://help.adobe.com/zh_CN/AIR/1.1/devappsflex/WS5b3ccc516d4fbf351e63e3d118666ade46-7fb8.html

本地化 Flex 内容
http://help.adobe.com/zh_CN/AIR/1.1/devappsflex/WS96A067CA-8F6B-4f4a-95AB-9A6CB9BF8E8A.html
使用 Flex AIR 组件
http://help.adobe.com/zh_CN/AIR/1.1/devappsflex/WS5b3ccc516d4fbf351e63e3d118666ade46-7fb6.html

Adobe AIR 简介
http://help.adobe.com/zh_CN/AIR/1.1/devappsflash/WS5b3ccc516d4fbf351e63e3d118666ade46-7fc4.html

ActionScript 3.0 语言和组件参考
http://help.adobe.com/zh_CN/AS3LCR/Flash_10.0/ExampleInstruct.html

主页
http://help.adobe.com/zh_CN/Flash/10.0_Welcome/index.html

======================================================================================

使用 HTML 和 Ajax 开发 Adobe AIR 应用程序
http://help.adobe.com/zh_CN/AIR/1.1/devappshtml/WS5b3ccc516d4fbf351e63e3d118666ade46-7dbb.html
http://help.adobe.com/zh_CN/AIR/1.1/devappshtml/WSC04AFC0E-5BF5-4c2f-8A32-BEDE16E9DF95.html

为 Flash CS3 Professional 提供的 Adobe AIR 更新
http://help.adobe.com/zh_CN/AIR/1.1/devappsflash/WS5b3ccc516d4fbf351e63e3d118666ade46-7f57.html

为 Flash CS3 设置 Adobe AIR 更新
http://help.adobe.com/zh_CN/AIR/1.1/devappsflash/WS5b3ccc516d4fbf351e63e3d118666ade46-7fc3.html
http://help.adobe.com/zh_CN/AIR/1.1/devappsflash/WS5b3ccc516d4fbf351e63e3d118666ade46-7fc3.html#WS5b3ccc516d4fbf351e63e3d118666ade46-7fe1

flash CS4
为 Adobe AIR 发布
http://help.adobe.com/zh_CN/Flash/10.0_UsingFlash/WSF0126B20-BFF4-4c50-9978-BCA47C8C3C3F.html
用 Flash CS3 或 CS4创建您的第一个 AIR 应用程序
http://help.adobe.com/zh_CN/AIR/1.1/devappsflash/WS5b3ccc516d4fbf351e63e3d118676a27cc-7ffb.html

了解 Flash Player 和 AIR 运行时的 3D 功能
http://help.adobe.com/zh_CN/ActionScript/3.0_ProgrammingAS3/WS5467498E-BCF8-454f-8607-A51AD392CC07.html

为 Adobe AIR 发布
http://help.adobe.com/zh_CN/Flash/10.0_UsingFlash/WSF0126B20-BFF4-4c50-9978-BCA47C8C3C3F.html#WS25CC04BA-9718-4e5b-AF38-DAFEF461F2F9

本地化 Flash 内容
http://help.adobe.com/zh_CN/AIR/1.1/devappsflash/WSB2006AB2-8EFA-444e-92FB-DE369263382E.html

Flash Player 和 AIR 任务和系统打印
http://help.adobe.com/zh_CN/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7cc2.html

本地化 Flash 内容
http://help.adobe.com/zh_CN/AIR/1.1/devappsflash/WSB2006AB2-8EFA-444e-92FB-DE369263382E.html
posted @ 2009-03-09 09:50 TracyLu 阅读(353) | 评论 (0)编辑 收藏
 
     摘要: Basics of handling events Introduction to handling events You can think of events as occurrences of any kind in your SWF file that are of interest to you as a programmer. For example, most SWF...  阅读全文
posted @ 2009-03-04 22:38 TracyLu 阅读(343) | 评论 (0)编辑 收藏
 
关键字: java/java编程

 本文是Exception处理的一篇不错的文章,从Java Exception的概念介绍起,依次讲解了Exception的类型(Checked/Unchecked),Exception处理的最佳实现:
1. 选择Checked还是Unchecked的几个经典依据
2. Exception的封装问题
3. 如无必要不要创建自己的Exception
4. 不要用Exception来作流程控制
5. 不要轻易的忽略捕获的Exception
6. 不要简单地捕获顶层的Exception
原文地址:
http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html


关于异常处理的一个问题就是要对何时(when)和如何(how)使用它们做到了然于心。在本文中我将介绍一些关于异常处理的最佳实践,同时我也会涉及到最近争论十分激烈的checked Exception的使用问题。

作为开发员,我们都希望能写出解决问题并且是高质量的代码。不幸的是,一些副作用(side effects)伴随着异常在我们的代码中慢慢滋生。无庸置疑,没有人喜欢副作用(side effects),所以我们很快就用我们自己的方式来避免它,我曾经看到一些聪明的程序员用下面的方式来处理异常:

public void consumeAndForgetAllExceptions(){
try {
...some code that throws exceptions
} catch (Exception ex){
ex.printStacktrace();
}
}

上边的代码有什么问题么?

在回答以前让我们想想怎样才是正确的?是的,一旦程序碰到异常,它就该挂起程序而"做"点什么。那么上边的代码是这样子的么?看吧,它隐瞒了什么?它把所有的"苦水"往肚里咽(在控制台打印出异常信息),然后一切继续,从表面上看就像什么都没有发生过一样......,很显然,上边代码达到的效果并不是我们所期望的。

后来又怎样?

public void someMethod() throws Exception{
}

上边的代码又有什么问题?

很明显,上边的方法体是空的,它不实现任何的功能(没有一句代码),试问一个空方法体能抛出什么异常?当然Java并不阻止你这么干。最近,我也遇到类似的情景,方法声明会抛出异常,但是代码中并没有任何"机会"来"展示"异常。当我问开发员为什么要这样做的时候,他回答我说"我知道,它确实有点那个,但我以前就是这么干的并且它确实能为我工作。"

在C++社区曾经花了数年实践来实践如何使用异常,关于此类的争论在 java社区才刚刚开始。我曾经看到许多Java程序员针对使用异常的问题进行争论。如果对于异常处理不当的话,异常可以大大减慢应用程序的执行速度,因为它将消耗内存和CPU来创建、抛出并捕获异常。如果过分的依赖异常处理,代码对易读和易使用这两方面产生影响,以至于会让我们写出上边两处"糟糕"代码。

异常原理

大体上说,有三种不同的"情景"会导致异常的抛出:

l 编程错误导致异常(Exception due Programming errors): 这种情景下,异常往往处于编程错误(如:NullPointerException 或者 IllegalArgumentException),这时异常一旦抛出,客户端将变得无能为力。

l 客户端代码错误导致异常(Exception due client code errors): 说白点就是客户端试图调用API不允许的操作。

l 资源失败导致异常(Exception due to resource failures): 如内存不足或网络连接失败导致出现异常等。这些异常的出现客户端可以采取相应的措施来恢复应用程序的继续运行。

Java中异常的类型

Java 中定义了两类异常:

l Checked exception: 这类异常都是Exception的子类

l Unchecked exception: 这类异常都是RuntimeException的子类,虽然RuntimeException同样也是Exception的子类,但是它们是特殊的,它们不能通过client code来试图解决,所以称为Unchecked exception

举个例子,下图为NullPointerException的继承关系:



图中,NullPointerException继承自RuntimeException,所以它是Unchecked exception.

以往我都是应用checked exception多于Unchecked exception,最近,在java社区激起了一场关于checked exception和使用它们的价值的争论。这场争论起源于JAVA是第一个拥有Checked exception的主流OO语言这样一个事实,而C++和C#都是根本没有Checked exception,它们所有的异常都是unchecked。

一个checked exception强迫它的客户端可以抛出并捕获它,一旦客户端不能有效地处理这些被抛出的异常就会给程序的执行带来不期望的负担。
Checked exception还可能带来封装泄漏,看下面的代码:

public List getAllAccounts() throws
FileNotFoundException, SQLException{
...
}

上边的方法抛出两个异常。客户端必须显示的对这两种异常进行捕获和处理即使是在完全不知道这种异常到底是因为文件还是数据库操作引起的情况下。因此,此时的异常处理将导致一种方法和调用之间不合适的耦合。



接下来我会给出几种设计异常的最佳实践 (Best Practises for Designing the API)

1. 当要决定是采用checked exception还是Unchecked exception的时候,你要问自己一个问题,"如果这种异常一旦抛出,客户端会做怎样的补救?"
如果客户端可以通过其他的方法恢复异常,那么这种异常就是checked exception;如果客户端对出现的这种异常无能为力,那么这种异常就是Unchecked exception;从使用上讲,当异常出现的时候要做一些试图恢复它的动作而不要仅仅的打印它的信息,总来的来说,看下表:

Client's reaction when exception happens
Exception type

Client code cannot do anything
Make it an unchecked exception

Client code will take some useful recovery action based on information in exception
Make it a checked exception


此外,尽量使用unchecked exception来处理编程错误:因为unchecked exception不用使客户端代码显示的处理它们,它们自己会在出现的地方挂起程序并打印出异常信息。Java API中提供了丰富的unchecked excetpion,譬如:NullPointerException , IllegalArgumentException 和 IllegalStateException等,因此我一般使用这些标准的异常类而不愿亲自创建新的异常类,这样使我的代码易于理解并避免的过多的消耗内存。

2. 保护封装性(Preserve encapsulation)

不要让你要抛出的checked exception升级到较高的层次。例如,不要让SQLException延伸到业务层。业务层并不需要(不关心?)SQLException。你有两种方法来解决这种问题:

l 转变SQLException为另外一个checked exception,如果客户端并不需要恢复这种异常的话;

l 转变SQLException为一个unchecked exception,如果客户端对这种异常无能为力的话;

多数情况下,客户端代码都是对SQLException无能为力的,因此你要毫不犹豫的把它转变为一个unchecked exception,看看下边的代码:
public void dataAccessCode(){
try{
..some code that throws SQLException
}catch(SQLException ex){
ex.printStacktrace();
}
}


上边的catch块紧紧打印异常信息而没有任何的直接操作,这是情有可原的,因为对于SQLException你还奢望客户端做些什么呢?(但是显然这种就象什么事情都没发生一样的做法是不可取的)那么有没有另外一种更加可行的方法呢?

public void dataAccessCode(){
try{
..some code that throws SQLException
}catch(SQLException ex){
throw new RuntimeException(ex);
}
}

上边的做法是把SQLException转换为RuntimeException,一旦SQLException被抛出,那么程序将抛出RuntimeException,此时程序被挂起并返回客户端异常信息。

如果你有足够的信心恢复它当SQLException被抛出的时候,那么你也可以把它转换为一个有意义的checked exception, 但是我发现在大多时候抛出RuntimeException已经足够用了。

3. 不要创建没有意义的异常(Try not to create new custom exceptions if they do not have useful information for client code.)

看看下面的代码有什么问题?

public class DuplicateUsernameException
extends Exception {}


它除了有一个"意义明确"的名字以外没有任何有用的信息了。不要忘记Exception跟其他的Java类一样,客户端可以调用其中的方法来得到更多的信息。

我们可以为其添加一些必要的方法,如下:

public class DuplicateUsernameException
extends Exception {
public DuplicateUsernameException
(String username){....}
public String requestedUsername(){...}
public String[] availableNames(){...}
}



在新的代码中有两个有用的方法:reqeuestedUsername(),客户但可以通过它得到请求的名称;availableNames(),客户端可以通过它得到一组有用的usernames。这样客户端在得到其返回的信息来明确自己的操作失败的原因。但是如果你不想添加更多的信息,那么你可以抛出一个标准的Exception:

throw new Exception("Username already taken");
更甚的情况,如果你认为客户端并不想用过多的操作而仅仅想看到异常信息,你可以抛出一个unchecked exception:

throw new RuntimeException("Username already taken");

另外,你可以提供一个方法来验证该username是否被占用。

很有必要再重申一下,checked exception应该让客户端从中得到丰富的信息。要想让你的代码更加易读,请倾向于用unchecked excetpion来处理程序中的错误(Prefer unchecked exceptions for all programmatic errors)。

4. Document exceptions.

你可以通过Javadoc's @throws 标签来说明(document)你的API中要抛出checked exception或者unchecked exception。然而,我更倾向于使用来单元测试来说明(document)异常。不管你采用哪中方式,你要让客户端代码知道你的API中所要抛出的异常。这里有一个用单元测试来测试IndexOutOfBoundsException的例子:

public void testIndexOutOfBoundsException() {
ArrayList blankList = new ArrayList();
try {
blankList.get(10);
fail("Should raise an IndexOutOfBoundsException");
} catch (IndexOutOfBoundsException success) {}
}



上边的代码在请求blankList.get(10)的时候会抛出IndexOutOfBoundsException,如果没有被抛出,将fail ("Should raise an IndexOutOfBoundsException")显示说明该测试失败。通过书写测试异常的单元测试,你不但可以看到异常是怎样的工作的,而且你可以让你的代码变得越来越健壮。


下面作者将介绍界中使用异常的最佳实践(Best Practices for Using Exceptions)
1. 总是要做一些清理工作(Always clean up after yourself)

如果你使用一些资源例如数据库连接或者网络连接,请记住要做一些清理工作(如关闭数据库连接或者网络连接),如果你的API抛出Unchecked exception,那么你要用try-finally来做必要的清理工作:

java 代码
  1. public void dataAccessCode(){   
  2. Connection conn = null;   
  3. try{   
  4. conn = getConnection();   
  5. ..some code that throws SQLException   
  6. }catch(SQLException ex){   
  7. ex.printStacktrace();   
  8. finally{   
  9. DBUtil.closeConnection(conn);   
  10. }   
  11. }   
  12.   
  13. class DBUtil{   
  14. public static void closeConnection   
  15. (Connection conn){   
  16. try{   
  17. conn.close();   
  18. catch(SQLException ex){   
  19. logger.error("Cannot close connection");   
  20. throw new RuntimeException(ex);   
  21. }   
  22. }   
  23. }   

DBUtil是一个工具类来关闭Connection.有必要的说的使用的finally的重要性是不管程序是否碰到异常,它都会被执行。在上边的例子中,finally中关闭连接,如果在关闭连接的时候出现错误就抛出RuntimeException.



2. 不要使用异常来控制流程(Never use exceptions for flow control)

下边代码中,MaximumCountReachedException被用于控制流程:

java 代码
  1. public void useExceptionsForFlowControl() {   
  2. try {   
  3. while (true) {   
  4. increaseCount();   
  5. }   
  6. catch (MaximumCountReachedException ex) {   
  7. }   
  8. //Continue execution   
  9. }   
  10.   
  11. public void increaseCount()   
  12. throws MaximumCountReachedException {   
  13. if (count >= 5000)   
  14. throw new MaximumCountReachedException();   
  15. }    

上边的useExceptionsForFlowControl()用一个无限循环来增加count直到抛出异常,这种做法并没有说让代码不易读,但是它是程序执行效率降低。

记住,只在要会抛出异常的地方进行异常处理。



3. 不要忽略异常

当有异常被抛出的时候,如果你不想恢复它,那么你要毫不犹豫的将其转换为unchecked exception,而不是用一个空的catch块或者什么也不做来忽略它,以至于从表面来看象是什么也没有发生一样。



4. 不要捕获顶层的Exception

unchecked exception都是RuntimeException的子类,RuntimeException又继承Exception,因此,如果单纯的捕获Exception,那么你同样也捕获了RuntimeException,如下代码:

try{
..
}catch(Exception ex){
}
一旦你写出了上边的代码(注意catch块是空的),它将忽略所有的异常,包括unchecked exception.

5. Log exceptions just once

Logging the same exception stack trace more than once can confuse the programmer examining the stack trace about the original source of exception. So just log it once.

posted @ 2009-03-03 15:45 TracyLu 阅读(222) | 评论 (0)编辑 收藏
CALENDER
<2009年3月>
22232425262728
1234567
891011121314
15161718192021
22232425262728
2930311234

常用链接

留言簿(2)

随笔分类

随笔档案

文章分类

网站链接

搜索

  •  

最新评论

阅读排行榜

评论排行榜


Powered By: 博客园
模板提供沪江博客