3

我的界面中的静态最终值有奇怪的行为:

public interface IDictionaryErrorTypes {

    final static int ERROR_UNKNOWN      = 0;
    final static int ERROR_XML      = 1;
    final static int ERROR_CONNECTION   = 3;

}

public interface IDictionaryListModel extends IDictionaryErrorTypes,
                                                    //... and other interfaces
{

}

public class DictionaryListModel implements IDictionaryListModel {

// ... some code ...

private int getErrorCode(Exception error) {
    // determinate the error code
    if (error instanceof ParserConfigurationException
            || error instanceof SAXException
            || error instanceof SAXParseException) {
        return ERROR_XML;
    } else if (error instanceof UnknownHostException
            || error instanceof MalformedURLException
            || error instanceof IOException) {
        return ERROR_CONNECTION;
    } 
    return ERROR_UNKNOWN;
}

现在,当我运行应用程序 ERROR_XML 时,ERROR_CONNECTION 和 ERROR_UNKNOWN 值等于零 - 0。在我看来,这很奇怪。请看附件图片

java静态字段接口错误

如果我在我的模型中使用IDictionaryErrorTypes.ERROR_CONNECTION它仍然具有相同的行为。但是,如果我删除"implements IDictionaryErrorTypes"然后使用IDictionaryErrorTypes.ERROR_CONNECTION它就可以工作-常量值与听起来完全一样。

当我使用类而不是接口时,它也可以正常工作。

有人可以解释这种行为吗?(ps我使用的是android平台)

ps(2) 我还尝试添加/删除“final”、“static”、“public”关键字(这就是图像和代码中的接口声明有点不同的原因)。但是行为是一样的

工作版本的 smali 代码(使用类而不是接口):

.method private getErrorCode(Ljava/lang/Exception;)I
    .registers 3
    .parameter "error"

    .prologue
    .line 145
    instance-of v0, p1, Ljavax/xml/parsers/ParserConfigurationException;

    if-nez v0, :cond_c

    .line 146
    instance-of v0, p1, Lorg/xml/sax/SAXException;

    if-nez v0, :cond_c

    .line 147
    instance-of v0, p1, Lorg/xml/sax/SAXParseException;

    if-eqz v0, :cond_e

    .line 148
    :cond_c
    const/4 v0, 0x1

    .line 154
    :goto_d
    return v0

    .line 149
    :cond_e
    instance-of v0, p1, Ljava/net/UnknownHostException;

    if-nez v0, :cond_1a

    .line 150
    instance-of v0, p1, Ljava/net/MalformedURLException;

    if-nez v0, :cond_1a

    .line 151
    instance-of v0, p1, Ljava/io/IOException;

    if-eqz v0, :cond_1c

    .line 152
    :cond_1a
    const/4 v0, 0x3

    goto :goto_d

    .line 154
    :cond_1c
    const/4 v0, 0x0

    goto :goto_d
.end method

// class instead of interface

.class public Ltj/zar/projects/kathtranslator/interfaces/common/IDictionaryErrorTypes;
.super Ljava/lang/Object;
.source "IDictionaryErrorTypes.java"


# static fields
.field public static final ERROR_CONNECTION:I = 0x3

.field public static final ERROR_UNKNOWN:I = 0x0

.field public static final ERROR_XML:I = 0x1


# direct methods
.method public constructor <init>()V
    .registers 1

    .prologue
    .line 3
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V

    return-void
.end method

UNWORKING版本的smali代码:

.method private getErrorCode(Ljava/lang/Exception;)I
    .registers 3
.parameter "error"

.prologue
.line 145
instance-of v0, p1, Ljavax/xml/parsers/ParserConfigurationException;

if-nez v0, :cond_c

.line 146
instance-of v0, p1, Lorg/xml/sax/SAXException;

if-nez v0, :cond_c

.line 147
instance-of v0, p1, Lorg/xml/sax/SAXParseException;

if-eqz v0, :cond_e

.line 148
:cond_c
const/4 v0, 0x1

.line 154
:goto_d
return v0

.line 149
:cond_e
instance-of v0, p1, Ljava/net/UnknownHostException;

if-nez v0, :cond_1a

.line 150
instance-of v0, p1, Ljava/net/MalformedURLException;

if-nez v0, :cond_1a

.line 151
instance-of v0, p1, Ljava/io/IOException;

if-eqz v0, :cond_1c

.line 152
:cond_1a
const/4 v0, 0x3

goto :goto_d

.line 154
:cond_1c
const/4 v0, 0x0

goto :goto_d
.end method

// interface

.class public interface abstract Ltj/zar/projects/kathtranslator/interfaces/common/IDictionaryErrorTypes;
.super Ljava/lang/Object;
.source "IDictionaryErrorTypes.java"


# static fields
.field public static final ERROR_CONNECTION:I = 0x3

.field public static final ERROR_UNKNOWN:I = 0x0

.field public static final ERROR_XML:I = 0x1

解决

我清理了项目,将模拟器更改为真实设备并编写了一些测试。

结果

这似乎是一个调试器问题:

正如您在图像中看到的错误是“3”,ERROR_CONNECTION 是“0”。并且设备实际上运行下一个字符串(绿色字符串),这意味着调试器认为 3 == 0,但实际上它的 3 == 3

结论

调试器错误。

在此处输入图像描述

4

2 回答 2

1

您使用的任何调试器都在欺骗您(很可能是答案),或者这是您正在使用的 android SDK 中的错误。您是否想过查看该方法实际返回的内容?

另请注意,无论您做什么,默认情况下接口中的字段始终 static final是公共的 - 编译器会这样做。

public interface MyInterface
{
    public static final int TEST = 3;
}

public interface MyInterface2 extends MyInterface
{
    public final static int TEST2 = 5;
}

public class InterfaceTest implements MyInterface2
{
    public void printInterfaceConstants()
    {
        System.out.println(TEST);
        System.out.println(TEST2);
    }

    public static void main(String[] args)
    {
        InterfaceTest it = new InterfaceTest();
        it.printInterfaceConstants();
    }
}

输出:

3
5

正如已经提到的,首先不要这样做。实现细节不应该在接口中。

于 2012-10-15T01:46:19.887 回答
1

我认为唯一可能的解释是您在编辑/构建/运行/调试过程中出现了问题,并且您实际上运行的代码版本与您认为的不同。

这方面的证据是您已经反编译了您认为正在运行的类的两个版本,并且反编译的代码清楚地表明:

  1. 它使用内联常量值,并且
  2. 常量值是您期望的值。

但是当您执行代码时(假设),它的行为显然与那些字节码所说的不同。

我只能看到一个合理的解释:您没有执行那些字节码。相反,您正在执行不同版本的字节码。简而言之,您不会重新编译/重建/重新部署所有需要......完成的事情。

调试器的输出很有趣,因为它倾向于证实这个假设,因为它似乎表明您的可执行文件具有接口的副本,其中的常量与源代码所说的不同。(也可能是调试器错误……但这是一个太大的巧合。)但是,调试器输出本身并不能解释您的应用程序的行为,因为该应用程序没有使用这些值。

于 2012-10-15T03:22:00.823 回答