Оператор переключения для представлений перечисления значений в Java

Оптимистическая Блокировка является стратегией, где Вы читаете запись, принимаете во внимание номер версии (другие методы, чтобы сделать, это включает даты, метки времени или контрольные суммы/хеши), и проверьте, что версия не изменилась перед обратной записью записи. Когда Вы пишете запись назад, Вы фильтруете обновление на версии, чтобы удостовериться, что это является атомарным. (т.е. не был обновлен между тем, когда Вы проверяете версию и пишете запись на диск), и обновите версию в одном хите.

, Если запись грязна (т.е. различная версия к Вашему) Вы прерываете транзакцию, и пользователь может перезапустить его.

Эта стратегия является самой применимой к системам большого объема и трехуровневой архитектуре, где Вы не обязательно поддерживаете соединение с базой данных для Вашей сессии. В этой ситуации клиент не может на самом деле поддержать блокировки базы данных, поскольку соединения взяты от пула, и Вы не можете использовать то же соединение от одного доступа до следующего.

Пессимистическая Блокировка состоит в том при блокировке записи для эксклюзивного использования, пока Вы не закончили с ним. Это имеет намного лучшую целостность, чем оптимистическая блокировка, но требует, чтобы Вы были осторожны с Вашим проектированием приложений для предотвращения Мертвые блокировки . Для использования пессимистической блокировки, Вам нужен любой прямое подключение к базе данных (как обычно имел бы место в два клиент-сервера уровня приложение), или внешне доступный идентификатор транзакции, который может использоваться независимо от соединения.

В последнем случае Вы открываете транзакцию с TxID и затем повторно подключаете использование тот идентификатор. DBMS поддерживает блокировки и позволяет Вам брать сессию назад через TxID. Это - то, как работают распределенные транзакции с помощью двухфазных протоколов подтверждения изменений (такой как XA или Транзакции COM + ).

5
задан Ben Lakey 27 June 2009 в 07:24
поделиться

7 ответов

You can use something like this:

import java.util.HashMap;
import java.util.Map;

public class MazeNode {

    public enum SlotValue {
        empty(0), start(1), wall(2), visited(3), end(9);

        protected int m_representation;

        SlotValue(int representation) {
            m_representation = representation;

        }

        private static final Map<Integer, SlotValue> mapping = new HashMap<Integer, SlotValue>();

        static {
            for (SlotValue slotValue : SlotValue.values()) {
                mapping.put(slotValue.m_representation, slotValue);
            }
        }

        public static SlotValue fromRepresentation(int representation) {
            SlotValue slotValue = SlotValue.mapping.get(representation);
            if (slotValue == null)
                // throw your own exception
                throw new RuntimeException("Invalid representation:" + representation);
            return slotValue;
        }
    }

    private SlotValue m_mazeNodeSlotValue;

    public MazeNode(SlotValue s) {
        m_mazeNodeSlotValue = s;
    }

    public MazeNode(int s) {
        m_mazeNodeSlotValue = SlotValue.fromRepresentation(s);

    }

    public SlotValue getSlotValue() {
        return m_mazeNodeSlotValue;
    }

    public static void main(String[] args) {
        MazeNode m = new MazeNode(2);
        System.out.println(m.getSlotValue());
        m = new MazeNode(9);
        System.out.println(m.getSlotValue());
    }

}
5
ответ дан 14 December 2019 в 08:58
поделиться

An alternate approach to the other suggestions is that you can enter the values in the enum constructors rather than having to loop over afterwards:

public class MazeNode {
    private static final Map<Integer, SlotValue> mapping = new HashMap<Integer, SlotValue>();

    enum SlotValue {
        empty(0),start(1),wall(2),visited(3),end(9);

        private final int m_representation;

        SlotValue(int representation) {
            m_representation = representation;
            mapping.put(Integer.valueOf(representation), this);
        }

    }

    SlotValue getSlotValue(int representation) {
        return mapping.get(Integer.valueOf(representation));
    }

}
2
ответ дан 14 December 2019 в 08:58
поделиться

Похоже, нет простого способа делать то, что вы хотите. Константы должны быть окончательными и назначаться при объявлении; то, что вы не можете сделать в члене перечисления.

В качестве решения я добавил статический метод decode () к перечислению SlotValue. Это сравнивает каждое поле m_presentation SlotValue и возвращает первое совпадение. Это будет работать, и это может быть не самый эффективный подход, но он выполняет свою работу всего в нескольких строках кода.

public class MazeNode {
    public enum SlotValue {
        empty(0),
        start(1),
        wall(2),
        visited(3),
        end(9);

        private int m_representation;

        SlotValue(int representation) {
            m_representation = representation;
        }

        private static SlotValue decode( int in ) {
            for ( SlotValue slot : values() ) {
                if ( slot.m_representation == in ) {
                    return slot;
                }
            }
            return empty;
        }
    }

    private SlotValue m_mazeNodeSlotValue;

    public MazeNode(SlotValue s) {
        m_mazeNodeSlotValue = s;
    }

    public MazeNode(int s) {
        m_mazeNodeSlotValue = SlotValue.decode( s );
    }

    public SlotValue getSlotValue() {
        return m_mazeNodeSlotValue;
    }
}
1
ответ дан 14 December 2019 в 08:58
поделиться

I'm with olliej that you should probably accept a getter. Java (unlike C#) does not allow you to cast between a primitive (int in your case) and a enum. The internal representation (m_representation here) is just another field, not an accessible constant.

This is good (genuinely type-safe) or bad (harder to serialize and deserialize, among other things) depending how you look at it. The method below obviously is not as efficient as a switch, but I believe it's the only way to avoid redundancy.

As you probably realize, it's best to keep the data in enum form as much as possible.

public enum SlotValue
{
    empty(0),
    start(1),
    wall(2),
    visited(3),
    end(9);

    private int m_representation;

    SlotValue(int representation)
    {
        m_representation = representation;
    }

    public static SlotValue fromInt(int intSerialization)
    {
        for(SlotValue sv : SlotValue.values())
            if(sv.m_representation == intSerialization)
                return sv;
        return null;
    }
}

private SlotValue m_mazeNodeSlotValue;

public MazeNode(SlotValue s)
{
    m_mazeNodeSlotValue = s;
}

public MazeNode(int s)
{
    m_mazeNodeSlotValue = SlotValue.fromInt(s);
}
1
ответ дан 14 December 2019 в 08:58
поделиться

Все языки (за исключением JS, потому что это безумие: D) требовать, чтобы операторы switch были постоянными выражениями.

Что вы пытаетесь сделать? Вы можете легко перейти от SlotValue к int, добавив геттер в SlotValue.

0
ответ дан 14 December 2019 в 08:58
поделиться

consider doing something like this:

public class Node {
    public enum Slot {
        empty, start, wall, visited, end;
        static Slot fromInt(int s) {
            for (Slot slot : Slot.values())
                if (slot.ordinal() == s)
                    return slot;
            throw new RuntimeException("" + s + " is illegal value!");
        }
    }
    public Node(Slot slot) {
        this.slot = slot;
    }
    public Node(int s) {
        this(Slot.fromInt(s));
        switch(slot) {
            case empty: /* special stuff for empty */ break;
            case start: /* special stuff for start */ break;
            /* ... */
        }
    }
    private Slot slot;
}
0
ответ дан 14 December 2019 в 08:58
поделиться

I am not sure what's the purpose of SlotValue in your program but it seems that you are not using their full power. You can invoke methods on enum instances or query their state. Thus you translate a switch on enum value into method invocation/state querying, as show below.

Side note: Once you get used to this kind of thinking (which is quite different from the thinking induced by C's enums) you realize that there's much less need for "magic numbers" in your code. Instead of specifying an value and then giving it some meaning you just specify the enum constant and invoke methods on it. Specifcially, my feeling is that there's no real need for associating each of your enum instances with a value (empty is 0, start is 1, etc.).

Anyway, here's the code:

public class MazeNode
{
   public enum SlotValue
   {
       empty(0),
       start(1),
       wall(2),
       visited(3),
       end(9);

       private int m_representation;

       SlotValue(int representation)
       {
           m_representation = representation;
       }

       public int getRepresentation()
       {
           return m_representation;
       }

       private SlotValue next = null;

       static
       {
          empty.next = start;
          end.next = end;
       }
   }


   private SlotValue m_mazeNodeSlotValue;

   public MazeNode(SlotValue s)
   {
       m_mazeNodeSlotValue = s;
   }

   public MazeNode(int s)
   {
       m_mazeNodeSlotValue = SlotValue.values()[s].next;
   }

   public SlotValue getSlotValue()
   {
       return m_mazeNodeSlotValue;
   }
}
-2
ответ дан 14 December 2019 в 08:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: