JavaRush /Java блог /Random UA /Оператор return в Java
Viacheslav
3 рівень

Оператор return в Java

Стаття з групи Random UA

Вступ

Як ми знаємо, мова Java є об'єктно-орієнтованою мовою програмування. Тобто базова концепція, т.к. сказати основа основ, у тому, що є об'єкт. Об'єкти описуються за допомогою класів. Оператор return в Java - 1У свою чергу, у класів є стан і поведінка. Наприклад, банківський рахунок може мати стан як кількість грошей на рахунку і мати поведінки збільшення і зменшення балансу. Поведінка Java реалізується за допомогою методів. Те, як описувати методи, наводиться на початку шляху вивчення Java. Наприклад, в офіційному tutorial від Oracle: " Defining Methods ". Тут можна виділити два важливі аспекти:
  • Кожен метод має сигнатуру. Сигнатура складається з імені методу та його вхідних параметрів;
  • Для методів має бути зазначений тип значення, що повертається (return type);
  • Тип значення, що повертається, не входить у сигнатуру методу.
Знову ж таки, це наслідок того, що Java мова строго типізована і компілятор хоче заздалегідь розуміти, які типи і де використовуються на стільки, наскільки це можливо. Знову ж таки, щоб уберегти нас від помилок. Загалом, все на благо. Ну і нам це ще раз прищеплює культуру поводження з даними, як мені здається. Отже, для методів зазначається тип значення. А щоб повернути це саме значення з методів, використовується ключове слово return.

Ключове слово оператор return в Java

Ключове слово оператор returnвідноситься до виразів "керування ходом виконання", про що зазначено в oracle tutorial " Control Flow Statements ". Про те, як потрібно повертати значення можна також прочитати в офіційному tutorial: «Returning a Value from a Method ». Компілятор ретельно стежить, наскільки у нього вистачає сил, за тим, щоб значення, що повертається з методу, відповідало зазначеному у методу типу значення, що повертається. Скористаємося для прикладу Online IDE від tutorialspoint. Подивимося на початковий приклад:
public class HelloWorld {
    public static void main(String []args) {
        System.out.println("Hello World");
    }
}
Як бачимо, тут виконується mainметод, що є точкою входу у програму. Рядки коду виконуються зверху донизу. Наш mainметод не може повертати значення, інакше ми отримаємо помилку: « Error: Main method must return a value of type void». Тому метод просто виконає виведення на екран. Давайте тепер винесемо отримання рядка в окремий спосіб отримання повідомлення:
public class HelloWorld {

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

    public static String getHelloMessage() {
        return "Hello World";
    }

}
Як бачимо, за допомогою ключового слова returnми вказали значення, що повертається, яке використовували далі в методі println. В описі (визначенні) методу getHelloMessageми вказали, що він поверне нам String. Це дозволяє компілятор перевірити, що дії методу узгоджуються з тим, яким чином він оголошений. Природно, тип значення, що повертається, зазначеного у визначенні методу, може бути ширшим ніж тип значення, що повертається з коду, тобто. головне, щоб типи наводабося один до одного. А якщо ні, то ми отримаємо помилку під час компіляції: « error: incompatible types». До речі, напевно відразу постало питання: Чому returnналежить до операторів управління ходом виконання програми. А тому, що він може порушувати звичайний хід виконання програми "згори донизу". Наприклад:
public class HelloWorld {

    public static void main(String []args){
        if (args.length == 0)  {
            return;
        }
        for (String arg : args)  {
            System.out.println(arg);
        }
    }

}
Як видно з прикладу, ми перериваємо виконання методу mainв тому випадку, якщо програма java наша викликана без параметрів. Важливо пам'ятати, що якщо у вас returnє код, він стає недоступним. І це побачить наш розумний компілятор і не дасть вам запустити таку програму. Наприклад, цей код не скомпілюється:
public static void main(String []args) {
        System.out.println("1");
        return;
        System.out.println("2");
 }
Є один «брудний хак» для такого обходу. Наприклад, для цілей налагодження чи ще чомусь. Вище зазначений код можна полагодити обернувши returnв ifблок:
if (2==2)  {
    return;
}

Оператор Return під час обробки помилок

Є одна дуже хитра обставина – ми можемо використовувати returnразом із обробкою помилок. Відразу хочеться сказати, що використання returnв catchблоці це дуже поганий тон, тому варто цього уникати. Але ж нам потрібен приклад? Ось він:
public class HelloWorld  {

    public static void main(String []args) {
        System.out.println("Value is: " + getIntValue());
    }

    public static int getIntValue()  {
        int value = 1;
        try {
            System.out.println("Something terrible happens");
            throw new Exception();
        } catch (Exception e) {
            System.out.println("Catched value: " + value);
            return value;
        } finally {
            value++;
            System.out.println("New value: " + value);
        }
    }

}
На перший погляд здається, що має повернутися 2, адже finallyвиконується завжди. Але ні, значення буде 1, а зміна змінної finallyбуде проігноровано. Більше того, якби valueмістила б об'єкт і ми finallyсказали б value = null, то з catchповернулася б все одно посилання на об'єкт, а не null. А ось із блоку finallyоператор returnспрацював би правильно. Колеги за такий подарунок явно не подякують.
Що ще почитати:

Оператор return

void.class

Ну і насамкінець. Можна написати дивну конструкцію виду void.class. Здавалося б, навіщо й у чому сенс? Насправді, в різних фреймворках і хитрих випадках, коли використовується Java Reflection API , це може знадобитися. Наприклад, можна перевіряти, який тип повертає метод:
import java.lang.reflect.Method;

public class HelloWorld {

    public void getVoidValue() {
    }

    public static void main(String[] args) {
        for (Method method : HelloWorld.class.getDeclaredMethods()) {
            System.out.println(method.getReturnType() == void.class);
        }
    }
}
Це може бути корисним у тестових фреймворках, де необхідно підміняти реальний код методів. Але для цього потрібно розуміти, як цей метод поводиться (тобто які типи повертає). Є ще другий спосіб реалізації методу mainіз коду вище:
public static void main (String[] args) {
        for (Method method : HelloWorld.class.getDeclaredMethods()) {
            System.out.println(method.getReturnType() == Void.TYPE);
        }
 }
Досить цікаве обговорення різниці між ними можна прочитати на stackoverflow: What is the difference between java.lang.Void and void? #Viacheslav
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ