java - 反射和不变性应该如何协同工作

标签 java reflection concurrency jvm immutability

根据 JSR-133不可变对象(immutable对象)是线程安全的,不需要同步。然而,可以使用反射更新最终字段的值:

package com.stackoverflow;

import java.lang.reflect.Field;

public class WhatsGoingOn {

    static class Immutable {
        private final int value;

        public Immutable(int value) {
            this.value = value;
        }

        public int getValue() {
            return value;
        }
    }

    public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
        final Immutable immutable = new Immutable(Integer.MIN_VALUE);

        final Field f = Immutable.class.getDeclaredField("value");
        f.setAccessible(true);

        System.out.println(immutable.getValue());
        f.set(immutable, Integer.MAX_VALUE);
        System.out.println(immutable.getValue());
    }
}

鉴于依赖反射的框架数量(Spring 和 Hibernate 只是少数),我很好奇规范对这种情况有何看法。例如。如果我将字段更新放入同步块(synchronized block)中,将保证在其他线程中的可见性,或者值将根据最终规范缓存在寄存器中。

http://download.oracle.com/otndocs/jcp/memory_model-1.0-pfd-spec-oth-JSpec/

最佳答案

An object is considered immutable if its state cannot change after it is constructed. http://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html

您正在将该对象用作可变,因为您正在更改它的状态。

确实,使用反射会破坏本教程中定义的不变性,因为您可以使用它来更改非常量最终字段。

下面是一个抗反射不可变对象(immutable对象)的例子:

static class Immutable {
    // This field is a constant, and cannot be changed using Reflection
    private final int value = Integer.MIN_VALUE;

    public int getValue() {
        return value;
    }
}

public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
    final Immutable immutable = new Immutable();

    final Field f = Immutable.class.getDeclaredField("value");
    f.setAccessible(true);

    System.out.println(immutable.getValue());
    f.set(immutable, Integer.MAX_VALUE);
    System.out.println(immutable.getValue());
}

在这种情况下,您的反射测试将失败,并且该值将保持为 Integer.MIN_VALUE。但是,嘿,我们总是可以使用 native 代码或内存编辑器将该值更改为其他值。

如果您深入研究反射,您最好不要将您的字段称为 final 并提供操作它的方法。

关于java - 反射和不变性应该如何协同工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15831773/

相关文章:

java - JCheckbox 显示一个 displayName 但在幕后保存不同的值

java - 我将如何创建一个使用 String 类型行为进行创建的对象?

java动态调用方法

java - 反射:通过接口(interface)创建类的对象

javascript - 获取 JavaScript 类构造函数的源代码

go - 并发模式 : worker with variable number of results

c# - ConcurrentQueue.IsEmpty 是否需要内存屏障?

java - 卡在受信号量保护的交互中

java ArrayList 搜索方法

java - 使用 SecureRandom 填充数组 : Why not out of bounds?