java - 如何保证字段被正确封装?

标签 java encapsulation static-analysis

我想知道是否有一种简单的方法来查找直接访问字段的所有方法。更准确地说:

我想确保只有一种方法可以写入字段,并且只有一种方法可以读取字段。所有其他访问都应使用这两个。

背景:当写入字段时,我需要在某个地方记录这一事实,我可以使用生成的 setter 轻松完成此操作,但我想确保我不会在某个地方规避它。

它适用于移动设备而不是服务器,所以我不想/不能使用接口(interface)或运行时字节码重写...

我知道,有 ASM,但据我所知,使用它意味着我愿意花费更多的工作。我希望有更好的方法。

更新

我没想到,但不得不声明,代码更改是允许的,但内存紧张。因此封装字段(例如 Java FX 风格)或进行备份太糟糕了。字段相当多,所以实际上任何需要触及所有字段的东西都是不好的。

我可以想象解析源代码,这要么很复杂,要么容易出现误报,因为相同的标识符根据上下文具有不同的含义。它甚至可能被隐藏(例如,在声明同名变量的嵌套类中),但我很乐意更改代码以避免该问题。

从类文件中获取结构化信息肯定会更好。

最佳答案

Java中的封装是在对象或类级别;最严格的访问控制修饰符是 private ,但即便如此,同一类中的每个方法都可以访问 private字段。因此,如果您想封装字段的行为,可以通过将字段表示为对象来实现。

这是一个表示可变字段的类:

public class MyField<T> {
    private T value;

    MyField(T initialValue) {
        value = initialValue;
    }

    public T get() {
        return value;
    }

    public void set(T newValue) {
        // any logging goes here
        value = newValue;
    }
}

然后,如果您希望将此日志记录行为应用于字段 name ,声明name作为类型 MyField<String>而不是String :

public class Person {
    private final MyField<String> name;
    private final MyField<Integer> age;

    public Person(String name, int age) {
        this.name = new MyField<>(name);
        this.age = new MyField<>(age);
    }

    public String getName() {
        return name.get();
    }

    public int getAge() {
        return age.get();
    }

    public void setName(String name) {
        this.name.set(name);
    }

    public void setAge(int age) {
        this.age.set(age);
    }
}

优点:

  • MyField.value是私有(private)的,很容易在所有实例中验证它的值在没有触发日志记录行为的情况下永远不会设置。
  • Java 编译器的静态检查足以检查该字段的值是否只能通过其 get 访问。和set方法;无需单独的验证阶段。
  • 您可以将其仅应用于您想要记录行为的字段。

缺点:

  • 其中每一个 MyField对象在内存使用方面有一些开销。
  • 额外的方法调用 getset运行时会产生一些开销。
  • 调用的额外代码 .get()不多,但可能会损害更复杂表达式的可读性。

关于java - 如何保证字段被正确封装?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58410840/

相关文章:

java - FileNotFoundException(是一个目录)

构造函数中的 Java 可重写调用

python-3.x - PUBLIC属性和方法(作用于公共(public)属性)可以被视为封装吗?

static-analysis - ACSL "assigns"C 代码内部结构和字段的注释

c++ - 如何运行 GCC/Clang 进行静态分析? (仅警告)

performance - 有什么加速静态分析工具 PC-Lint 的技巧吗?有使用 .LOB 文件的经验吗?

java - JPA @EJB 注入(inject)不起作用并给出 NullPointerException

java - Spring-boot:JUnit 测试 ApplicationContext 加载失败

java - 使用 Xuggler 使用 Java 编写 RTP 服务器

python - 在 Python 中不使用私有(private)方法和函数是不好的做法吗?