Pull to refresh

Решение проблемы отсутствия switch(String) в Java c помощью enum

Reading time2 min
Views27K
Случилось однажды так, что моего хорошего коллегу, программирующего на Flex, перевели на проект, где использовался Ext GWT. Периодически приходилось отвечать на вопросы: «Как сделать то-то и то-то в Java?» и «Почему этого нет и как это обойти?». ActionScript, на котором мой коллега привык писать, в сравнении с Java был более гибким и позволял не особо заморачиваться на предмет приведения и описания типов переменных. Каким же было его удивление, когда в конструкции switch невозможно было делать сравнения переменных типа String. Хотя, казалось бы, существует множество технических ситуаций, когда такой switch пригодился бы (обработка разных сценариев в зависимости от содержимого переданной переменной String).

Благо, в настоящее время данная функциональность реализована в Java 7. Однако, в связи с тем, что переход на Java 7 не будет совершен моментально в большинстве проектов, то я хочу с радостью поделиться собственным «эстетическим» способом, чтобы избежать громоздких конструкций if..then..else.

Предположим, что у нас есть переменная type, которая может принимать значения «RequestOne», «RequestTwo», «RequestThree» и в зависимости от этого будут выполняться разные сценарии.

В простейшем случае, код метода, обрабатывающего запрос, мог бы выглядеть так:

public void processRequest(String type) {
	if (type.equals("RequestOne")) {
		scenarioOne();
	} else if (type.equals("RequestTwo")) {
		scenarioTwo();
	} else if (type.equals("RequestThree")) {
		scenarioThree();
	}
}


Код может быть неудобным для чтения, если type будет принимать длинные строки или для одного сценария может быть несколько вариантов значений type. В данном случае на помощь приходит перечисляемый тип: enum. Описывает перечисляемый тип RequestType следующим образом:

public enum RequestType {

	SCENARIO_ONE("RequestOne"),
	SCENARIO_TWO("RequestTwo"),
	SCENARIO_THREE("RequestThree");
	
	private String typeValue;
	
	private RequestType(String type) {
		typeValue = type;
	}
	
	static public RequestType getType(String pType) {
		for (RequestType type: RequestType.values()) {
			if (type.getTypeValue().equals(pType)) {
				return type;
			}
		}
		throw new RuntimeException("unknown type");
	}
	
	public String getTypeValue() {
		return typeValue;
	}
	
}


И тогда метод processRequest(String) преобразуется следующим образом:

public void processRequest(String type) {
	RequestType request = RequestType.getType(type);
		
	switch(request) {
		case SCENARIO_ONE: scenarioOne(); break;
		case SCENARIO_TWO: scenarioTwo(); break;
		case SCENARIO_THREE: scenarioThree(); break;
	}
}


Конечно, статический метод getType в перечисляемом типе RequestType не оптимальный, особенно, если речь идет о большом количестве возможных значений type. Но при таком подходе получается хранить список строковых значений type в одном месте и конструкция switch смотрится лаконично. Соответственно, добавление новых значений type и редактирование старых может происходить на порядок быстрее, что приводит к повышению производительности труда.

В конечном счете, соглашусь, это не лучшее решение с точки зрения производительности, но достаточно неплохой пример использования перечисляемых типов для случая, описанного выше.
Tags:
Hubs:
0
Comments17

Articles