I'm not quite sure I understood thread-safe correctly. I built the following registry:

public final class EntityDefinitionRegistry {

    private static final Logger logger = LogManager.getLogger(EntityDefinitionRegistry.class);

    private final HashMap<String, EntityDefinition> definitions = new HashMap<>();

    public EntityDefinitionRegistry() {
        Set<EntityDefinition> definitions = EntityDefinitionWrapperLoader.getDefinitions();

    public @NotNull EntityDefinition getDefinition(@NotNull String entityName) {
        if (StringUtils.isBlank(entityName)) {
            throw new InternalErrorException();

        EntityDefinition definition = definitions.get(entityName);
        if (definition == null) {
            throw new InternalErrorException();
        return definition;

This is initialized in the constructor and never changed again. The same is true for the contained objects. Their fields never change.

public final class EntityDefinition {

    private static final Logger logger = LogManager.getLogger(EntityDefinition.class);

    private final String name;

    private final String packageName;

    private final boolean cached;

    private final boolean abstraction;

    private final InheritanceStrategy inheritanceStrategy;

    private EntityDefinition superEntity;

    private final CopyOnWriteArraySet<EntityDefinition> subEntities = new CopyOnWriteArraySet<>();

    private final CopyOnWriteArraySet<EntityField> entityFields;

    private final CopyOnWriteArraySet<EntityField> dtoFields;

    private final CopyOnWriteArraySet<EntityRelationField> relationFields;

Have I understood correctly that the final specification and therefore only read accesses are always thread-safe?

  • I'm using Java 13.
  • 2
    \$\begingroup\$ I looked in to answering this question, but it turns out this is untested code that does not work. The class has a private final delcaration for definitions that initializes it with an empty HashMap, but the constructor shadows definitions with an incompatible HashSet that has values. As a consequence, the getDefinition will never get a non-null definition and will always throw an InternalErrorException. The code does not work. \$\endgroup\$
    – rolfl
    Nov 3, 2019 at 2:17


Browse other questions tagged or ask your own question.