Использование ярлыков в java без "петель"
Я всегда думал, что метки должны использоваться только с циклами, но это не так. Предоставление такого кода:
public class LabelTest {
public static void main(String[] args) {
label1: System.out.println("");
label2: LabelTest t = new LabelTest();
}
}
Когда скомпилированная строка с меткой "label1" компилируется, но код в "label2" дает ошибки. Почему так? И почему я хочу маркировать утверждения, которые не являются "петлями"?
Ответы
Ответ 1
Вы получаете сообщение об ошибке, потому что метка не может быть применена к объявлениям переменных, а именно как языковая грамматика (метка может предшествовать только Statement
, и a LocalVariableDeclarationStatement
не является Statement
). Вероятно, причина в том, что это может вызвать путаницу в отношении области видимости переменной. Это работает:
label1: System.out.println("");
label2: { LabelTest t = new LabelTest(); }
Ответ 2
Чтобы добавить к Майклу Боргвардту ответ, вы можете сделать такие вещи для удобства (я просто обнаружил это на днях, читая исходный код Java rt.jar):
BlockSegment:
if (conditionIsTrue) {
doSomeProcessing ();
if (resultOfProcessingIsFalse()) break BlockSegment;
otherwiseDoSomeMoreProcessing();
// These lines get skipped if the break statement
// above gets executed
}
// This is where you resume execution after the break
anotherStatement();
Теперь это логически эквивалентно:
if (conditionIsTrue) {
doSomeProcessing ();
if (!resultOfProcessingIsFalse()) {
otherwiseDoSomeMoreProcessing();
// More code here that gets executed
}
}
anotherStatement();
Но вы можете пропустить некоторые дополнительные фигурные скобки (и отступы, которые прилагаются с фигурными скобками). Возможно, он выглядит более чистым (на мой взгляд), и есть места, где этот стиль кодирования может быть подходящим и менее запутанным.
Таким образом, вы можете использовать метки за пределами циклов и даже за пределами if
. Например, это допустимый синтаксис Java (и, возможно, вы могли бы придумать причину сделать что-то вроде этого):
statementOne();
statementTwo();
BlockLabel: {
statementThree();
boolean result = statementFour();
if (!result) break BlockLabel;
statementFive();
statementSix();
}
statementSeven();
Если здесь выполняется выполнение break
, то выполнение пропускается до конца блока, обозначенного меткой, а statementFive()
и statementSix()
пропускается.
Полезность этого стиля (без оператора if
) становится более очевидной, когда у вас есть блоки в блоках, где вы должны пропустить. В общем, вы можете выполнить все с достаточно продуманным использованием петель. Однако есть несколько случаев, когда метки без циклов упрощают чтение кода. Например, если вам нужно последовательно проверять параметры, вы можете либо сделать это, либо выбросить исключение. В конечном итоге это вопрос чистоты кода и личного стиля.
Ответ 3
Он не компилируется. Хороший вопрос!
Я только что немного сыграл с вашим фрагментом кода. Кажется, что компилятор ожидает вызова метода или оператора после метки. На данный момент это не позволяет назначать задание.
Я думаю, что тот факт, что ярлык не запрещен перед операторами, отличными от for, while и do, вероятно, является ошибкой (?!) java-компилятора спецификации. Во всяком случае, это не так важно. Меня это не беспокоит (лично).
Ответ 4
Синтаксис Java основан на синтаксисе Си.
В C вы можете поместить метку в любом месте (не только на петлях), а затем использовать goto
, чтобы перевести выполнение в эту строку. Теперь goto
не был реализован на Java, но метки были оставлены, чтобы их можно было использовать в сочетании с break
или continue
.
Это не так важно, поскольку это не стандартное использование меток. Использование меток с continue
или break
достаточно плохо (в большинстве случаев). Использование их свободно также бесполезно.
Ответ 5
Обратитесь к Lable в JLS