4

我想使用静态分析来防止“TypeError:错误#1009:无法访问空对象引用的属性或方法”。

据我所知,有一个使用@NotNull/@Nullable 的Java 静态分析器。程序员通过为每个成员/函数/参数指定这些注释来明确表达他的意图,以便工具可以验证一切是否正确,并且每个 @Nullable -> @NotNull 转换都是通过检查是否为空来进行的。对我来说,只指定@Nullable 会更舒服,这样其他所有东西都可以像@NotNull 一样对待,但这不是必需的。

我想知道 Actionscript 3 是否有这种免费工具?

我有 FlashBuilder 4.5 许可证,但除此之外我不想购买任何其他东西。我听说 IntelliJ IDEA 可能有这样的东西,但它只适用于终极版中的 Actionscript,它不是免费的 :(

所以问题是:

  1. Actionscript 3 有这样的静态分析器吗?
  2. 如果不免费的话要多少钱?
  3. 除了“检查所有内容并将代码转换成一团糟”之外,是否还有其他解决方案可以防止 1009 错误。

更新

没有给出完整的答案:(但weltraumpirat的答案是迄今为止最好的。我考虑对可空函数使用命名约定:Try*、Find*、*OrNull、*IfAny 等。名称变得更长,但可靠性更重要. 谢谢weltraumpirat!赏金是你的,但我不会将答案标记为“已接受”,因为它不完整,我希望在某个时候有人会回答所需静态分析器的链接:)

4

5 回答 5

6

据我所知,ActionScript 没有静态分析工具可以真正防止空引用错误 - AS 是一种动态语言,并且很多使它成为一种好的语言的原因发生在编译器(或静态分析)之外工具,就此而言)可以验证。

但是,您可以并且应该做的是以首先防止空引用的方式设计代码,并允许有意义的错误消息帮助您更快地发现错误。

可以这样想:如果变量实例在某个时刻不应该为空,那么是否应该允许程序运行? 在大多数情况下,答案很明确:不,不应该!

例如,一个常见的错误不是阻止空引用,而是在程序中每个可能的点添加空检查,如下所示:

function myMethod( something:* ) : void {
    if ( something != null) {
       doStuff();
    }
}

这样做的结果是,程序不会抛出错误(这将使您能够找到发生崩溃的方法的名称和行号,以便跟踪问题),程序将继续运行,但什么也没有发生。现在,当您执行手动测试时,您将看到:nothing。并且没有迹象表明出了什么问题。

处理空引用的更好方法是

  • 确保没有任何方法返回 null。 曾经

    这可以通过返回默认值来实现,例如:

    function getPropertyValue() : String { 
        return _property != null ? _property : "";
    }
    

    当然,默认值可能是有意义的,例如"Property did not have a value.",这样在您的 UI 中,您会立即注意到问题,而不会影响程序的其余部分。(请注意,这不仅适用于 getter,而且适用于任何返回值的方法——我只是选择了一个明显的例子。)

    如果由于某种原因您真的无法绕过返回 null,请确保您的方法名称反映了这一点,因此当您使用它时,您知道预期可能的 null 值:

     function getPropertyValueOrNull() : String {
         return _property;
     }
    
  • 代替无用的空检查,在应用程序的关键点创建验证方法,并抛出有意义的错误以指出问题的原因:

    function tryExecuteImportantFunction() : void {
        try {
             validate();
             executeImportantFunction();
        } catch ( e:Error ) {
             trace( "Validation failed:" + e.message );
        }
    }
    
    function validate() : void {
        if (_requiredProperty1 == null) 
            throw new Error ( "_requiredProperty1 was null, but should always contain a string value.");
        if (_requiredProperty2 == null) 
            throw new Error ( "_requiredProperty2 was null, but should always contain a dictionary.");
    }
    

    应该捕获有意义的错误并将其转发到日志或调试控制台,以便您始终知道在哪里寻找原因,并了解您必须采取哪些措施来修复它。

于 2012-05-26T12:05:26.697 回答
0

在这种情况下最有用的应该是 getter 和 setter :

protected var _value:Object;

public function get value():Object{
    if(_value){
        return _value;
    }
    trace("missing object");// or throw "missing object error"
    return new Object();
}

public function set value(v:Object):void {
    _value = v;
}

编辑:

还可以读取用于空检查的其他内容 describeType() xml 并检查可访问的值(如果存在)。

于 2012-05-26T16:51:20.093 回答
0

gui 编程的问题在于,总是存在某种状态。所描述的问题基本上是具有有效和无效状态。作为一位经验丰富的 Flex 开发人员,我可以说,不存在无效状态这样的状态。null 是一个有效的引用,所以我们必须处理它。

我要问的第一个问题是:为什么 null 不好?需要 null 来清理事物并确保我们了解状态,没有数据。

Flex 有一个生命周期的想法,这基本上会导致一个非常有趣的行为。当一个组件被初始化时,它的子组件没有被初始化。所以基本上这是一个非常脆弱的系统,乍一看。属性主要委托给视图聚合的其他组件(关于视图层)。但同样的情况也可能发生在模型、控制器或服务层上。

那么,如何处理这个问题呢?我认为这首先是一个设计决定。当 null 被视为破坏系统的值时,默认情况下系统几乎是破坏的。我认为 null 是表示数据缺失的最简单方法。

另一种方法是创建默认模型。在我看来,模型是唯一真正令人讨厌的东西,因为所有其他组件都依赖于它们。

package net.icodeapps.examples.model
{
  public class User
  {
  }
}

package net.icodeapps.examples.model
{
  public class DefaultUser extends User
  {
  }
}

拥有这样的默认模型可以很容易地使用有效的非空引用和值引导应用程序,但也必须做出决定,无论是否正在处理默认模型。

此外,还有最重要的部分:如果系统没有经过适当考虑,将 null 踢出应用程序最终会杀死内存。

于 2012-06-02T19:40:50.523 回答
0

无论 weltraumpirat 以一种完全避免空值的方式进行编程,我都支持它。但是,根据我的经验,这并不总是可能的。在我们最近做的一个项目中,我们检索并生成了大量改变类型和形状的动态数据。

网络超时、回调退出和任何其他与此相关的意外导致空值停止应用程序。我们知道空错误并不重要,并且我们在很多情况下都期望它。

这要求对游戏中的所有错误情况进行动态错误处理。try catch 语句要么太慢要么需要大量维护。Flash Player 提供了一种处理此问题的方法,尽管它可能不是对所有问题集的最合适的解决方案。它是 Flash Player 10.1 发布后引入的“UncaughtErrorEvent”。

Flash Player 未捕获错误事件

此外,有一个非常好的库可以处理这个问题。这里:

全局错误处理程序

最后,如果您查看 Flash Player 开发的未来路线图,您会注意到静态类型、重载和大量重大变化即将出现在平台上。但就目前而言,这是我用过的最好的解决方案。

Flash 播放器路线图

于 2012-05-29T09:23:11.200 回答
0

你也可以试试 FlexPMD。它与 Java 的 PMD 密切相关,并且会通过应用规则在您的源代码中发现异味。

Adobe 将其作为开源发布,您可以在 sourceforge 获得它:http: //sourceforge.net/adobe/flexpmd/home/Home/

这是一个小的介绍视频:http ://www.riagora.com/2010/04/introduction-to-flex-pmd/

据我所知,它可以很容易地与 Flex Builder 集成,但也可以与 IntelliJ 和 FDT 甚至命令行等其他 IDE 一起使用。

于 2012-06-01T04:41:03.697 回答