允许最终字段采用默认值

时间:2013-05-08 17:46:58

标签: java final

我正在为二进制文件格式编写解析器。我创建了一些类来表示我正在阅读的反序列化结构,其中我想使用 final 变量来保存提取的数据。

class MyObject {
    final int my_x;
    final int my_y;
    final int my_z;
}

我遇到的问题是某些字段的存在取决于正在设置的某些标志。例如:

MyObject(InputStream is) {
    my_x = in.read();
    if (my_x == 1) {
        my_y = in.read();
        if (my_y == 1) {
            my_z = in.read();
        }
    }
}

但是,这会给我一个错误,因为 my_y my_z 可能无法初始化。这些条件可以是5-6级深度,我不想跟踪在分支树的每个级别可能无法读取哪些字段。另一个复杂因素是,基于某些标志,我可能希望使用与顶级结构相同的模式处理子对象。

class MyObject {
    final int my_x;
    final SubObject my_subobject;

    MyObject(InputStream is) {
        my_x = is.read();
        if (my_x == 1)
            my_subobject = new SubObject(is);
    }

    class SubObject {
        final int sub_x;
        final int sub_y;

        SubObject(InputStream is) {
            sub_x = is.read();
            if (sub_x == 1)
                sub_y = is.read();
        }
    }
}

有没有办法让我的字段最终不会扭曲代码来处理每个可能的标志组合?

1 个答案:

答案 0 :(得分:4)

使用局部变量并分配给构造函数末尾的final字段。

public MyObject(InputStream is) {
    int x = default_x_value;
    int y = default_y_value;
    int z = default_z_value;
    x = in.read();
    if (x == 1) {
        y = in.read();
        if (y == 1) {
            z = in.read();
        }
    }
    my_x = x;
    my_y = y;
    my_z = z;
}

或者(正如Jon Skeet在他的评论中所建议的那样),使用静态工厂方法来计算无默认构造函数的适当值:

public static MyObject makeMyObject(InputStream is) {
    int x = default_x_value;
    int y = default_y_value;
    int z = default_z_value;
    x = in.read();
    if (x == 1) {
        y = in.read();
        if (y == 1) {
            z = in.read();
        }
    }
    return new MyObject(x, y, z);
}

第三种方法是定义初始化对象类:

public class MyObject {
    private static class MyObjectInitializer {
        int x = default_x_value;
        int y = default_y_value;
        int z = default_z_value;
        MyObjectInitializer(InputStream is) {
            x = in.read();
            if (x == 1) {
                y = in.read();
                if (y == 1) {
                    z = in.read();
                }
            }
        }
    }
    public MyObject(InputStream is) {
        this(new MyObjectInitializer(is));
    }
    private MyObject(MyObjectInitializer init) {
        my_x = init.x;
        my_y = init.y;
        my_z = init.z;
    }
}

初始化类可能有自己的实用程序,在这种情况下,您可以将它(以及相应的MyObject构造函数)公开。

相关问题