Я пойду, заявление о переключении, которое вы написали, слишком старомодно

Java

Вчера утром я удаленно просматривал код двух новых коллег, большая часть кода красиво написана, строга и хорошо прокомментирована, что меня очень устраивает. Но когда я увидел заявление о переключении, написанное одним из них, я не мог не закричать: «Чёрт возьми, Сяо Ван, заявление о переключении, которое вы написали, слишком старомодно!»

Давайте взглянем на код, написанный Сяо Ваном. Не ругайте меня за то, что я притворяюсь после его прочтения.

private static String createPlayer(PlayerTypes playerType) {
    switch (playerType) {
        case TENNIS:
            return "网球运动员费德勒";
        case FOOTBALL:
            return "足球运动员C罗";
        case BASKETBALL:
            return "篮球运动员詹姆斯";
        case UNKNOWN:
            throw new IllegalArgumentException("未知");
        default:
            throw new IllegalArgumentException(
                    "运动员类型: " + playerType);

    }
}

Прочитав приведенный выше код, вы чувствуете себя так - "Код написан хорошо, проблем нет!" Вы думаете, что я не делаю ничего плохого и вините Сяо Вана! Но в этот момент я хочу послать цитату из Великого Гэтсби:

Моя старшая еще светлая, когда я не могу ее прочитать, отец научил меня слову, я все еще должна думать об этом. «Каждый раз, когда вы хотите критиковать кого-либо, — сказал он мне, — вы помните, что все люди в этом мире не имеют таких лучших условий, как вы».

Ха-ха, это предложение не только для вас, но и для меня. Пора успокоиться и поговорить о старомодном вопросе оператора switch выше.

Посмотрите на картинку выше, когда вы случайно удалите оператор по умолчанию, компилятор сообщит об ошибке, подсказав: «Нет оператора возврата», чтобы решить эту проблему, мы можем создать новую переменную игрока в качестве возвращаемого результата, например следующее:

private static String createPlayer(PlayerTypes playerType) {
    String player = null;
    switch (playerType) {
        case TENNIS:
            player = "网球运动员费德勒";
            break;
        case FOOTBALL:
            player = "足球运动员C罗";
            break;
        case BASKETBALL:
            player = "篮球运动员詹姆斯";
            break;
        case UNKNOWN:
            throw new IllegalArgumentException("未知");
    }

    return player;
}

Когда добавляется переменная player, в оператор case необходимо добавить ключевое слово break; кроме того, после завершения оператора switch возвращается игрок. В это время компилятор не выдаст никакой ошибки, указывая на то, что оператор по умолчанию в этом случае можно опустить.

Начиная с JDK 12 (в этом примере используется JDK 13), оператор switch был обновлен не только как условное суждение, как традиционный оператор switch, но и как прямой результат возврата. Давайте изменим код Xiao Wang следующим образом:

private static String createPlayer(PlayerTypes playerType) {
   return switch (playerType) {
        case TENNIS -> "网球运动员费德勒";
        case FOOTBALL -> "足球运动员C罗";
        case BASKETBALL -> "篮球运动员詹姆斯";
        case UNKNOWN ->  throw new IllegalArgumentException("未知");
    };
}

Это достаточно модно? Не только ключевое слово return добавляется перед ключевым словом switch, но и видно в случаеЛямбда-выраженияТень , тире и стрелка заменяют двоеточие, что означает, что код справа от стрелки просто выполняется без перерыва.

Более того, заявление по умолчанию стало необязательным, необязательным, вы верите в это? Вы тоже попробуйте.

Новый оператор switch достаточно умен, помимо трех вышеперечисленных преимуществ, он также может проверять условия типа перечисления. Если в PlayerTypes добавлен новый тип PINGPANG (шарик для пинг-понга):

public enum PlayerTypes {
    TENNIS,
    FOOTBALL,
    BASKETBALL,
    PINGPANG,
    UNKNOWN
}

В этот момент компилятор выдает следующее предупреждение:

Это означает, что условие case в переключателе не полностью покрывает возможные значения в перечислении. Хорошо, давайте добавим условие PINGPANG. Взгляните на полный код:

public class OldSwitchDemo {
    public enum PlayerTypes {
        TENNIS,
        FOOTBALL,
        BASKETBALL,
        PINGPANG,
        UNKNOWN
    }

    public static void main(String[] args) {
        System.out.println(createPlayer(PlayerTypes.BASKETBALL));
    }

    private static String createPlayer(PlayerTypes playerType) {
        return switch (playerType) {
            case TENNIS -> "网球运动员费德勒";
            case FOOTBALL -> "足球运动员C罗";
            case BASKETBALL -> "篮球运动员詹姆斯";
            case PINGPANG -> "乒乓球运动员马龙";
            case UNKNOWN -> throw new IllegalArgumentException("未知");
        };
    }
}

Оператор switch становится мощным выражением switch, и это здорово! Что, если бы спортсмен мог играть и в баскетбол, и в настольный теннис?

private static String createPlayer(PlayerTypes playerType) {
    return switch (playerType) {
        case TENNIS -> "网球运动员费德勒";
        case FOOTBALL -> "足球运动员C罗";
        case BASKETBALL,PINGPANG -> "牛逼运动员沉默王二";
        case UNKNOWN -> throw new IllegalArgumentException("未知");
    };
}

Как и в приведенном выше коде, просто используйте английскую запятую "," для разделения условий, 666 ах!

Не убежден? Выражения переключения еще более эффективны,->Правая сторона также может быть{}Блок кода, заключенный в круглые скобки, как лямбда-выражение.

private static String createPlayer(PlayerTypes playerType) {
    return switch (playerType) {
        case TENNIS -> {
            System.out.println("网球");
            yield "网球运动员费德勒";
        }
        case FOOTBALL -> {
            System.out.println("足球");
            yield "足球运动员C罗";
        }
        case BASKETBALL -> {
            System.out.println("篮球");
            yield "篮球运动员詹姆斯";
        }
        case PINGPANG -> {
            System.out.println("乒乓球");
            yield "乒乓球运动员马龙";
        }
        case UNKNOWN -> throw new IllegalArgumentException("未知");
    };
}

Внимательные одноклассники найдут ключевое слово, которое никогда раньше не встречалиyield, в чем разница между ним и традиционным возвратом и разрывом?

Давайте сначала посмотрим на официальное объяснение:

A yield statement transfers control by causing an enclosing switch expression to produce a specified value.

Это означает, что оператор yield передает управление, заставляя охватывающее его выражение switch возвращать указанное значение. Узнать большеyieldключевое слово, мы можем декомпилировать байт-код:

private static String createPlayer(NewSwitchDemo3.PlayerTypes playerType) {
    String var10000;
    switch(playerType) {
        case TENNIS:
            System.out.println("网球");
            var10000 = "网球运动员费德勒";
            break;
        case FOOTBALL:
            System.out.println("足球");
            var10000 = "足球运动员C罗";
            break;
        case BASKETBALL:
            System.out.println("篮球");
            var10000 = "篮球运动员詹姆斯";
            break;
        case PINGPANG:
            System.out.println("乒乓球");
            var10000 = "乒乓球运动员马龙";
            break;
        case UNKNOWN:
            throw new IllegalArgumentException("未知");
        default:
            throw new IncompatibleClassChangeError();
    }

    return var10000;
}

Когда компилятор генерирует байт-код,yieldКлючевые слова автоматически экранируются и преобразуются в традиционные операторы break. Это теперь ясно?

Однако, сказав это, те коды, которые кажутся модными, просто передают часть шоу-работы компилятору, и могут быть проблемы несовместимости со старыми версиями и недружественность к тиммейтам - код такой же грязный, как и он. , Это может быть наиболее практичным.

«Извините, я извиняюсь перед вами за то, что вчера утром был высокомерным…» Я отправил Сяо Вану сообщение.

Что ж, мои дорогие читатели и друзья, вышеизложенное и есть все содержание этой статьи, надеюсь завоевать вашу благосклонность. Кстати, у меня есть еще одна маленькая просьба: оригинальность непроста, если сочтете это полезным, пожалуйста, не скупитесь на рукикаксила — потому что это будет самой сильной мотивацией для моего письма.