Почему я не могу создать метод в методе main(...)? Мне не нужно это, просто хочу узнать почему я не могу это сделать?)

Доброго времени суток всем! Недавно начал осваивать Java по курсу на Udemy. Там есть домашка в которой сказано создать метод averageGrade (Student st) в классе StudentTest, который выводит среднюю оценку студента.

    public class Student {
    int studentId;
    String name;
    String surname;
    int course;
    double mathAver;
    double economyAver;
    double languageAver;
}
class StudentTest {
    double averageGrade (Student st) {
        double averGrade = (st.economyAver + st.languageAver + st.mathAver) / 3;
        System.out.println("Средняя оценка студента " + st.name + " = " + averGrade);
        return averGrade;
    }
    public static void main(String[] args) {
        Student st1 = new Student();
        st1.studentId = 2234;
        st1.name = "Vasya";
        st1.surname = "Sidorov";
        st1.course = 1;
        st1.mathAver = 5;
        st1.economyAver = 6;
        st1.languageAver = 8;
        StudentTest st4 = new StudentTest();
        st4.averageGrade(st1);
    }
}

Почему я не могу создать этот метод в методе main()? Мне не нужно обязательно создавать его в меттоде main(), просто интересно где об этом почитать, что посмотреть по теме и т.д.? Заранее благодарен!


Ответы (1 шт):

Автор решения: Alex Rudenko

Вложенные методы в Java не допускаются в соответствии со спецификацией языка. Однако, допускается создание в методе локальных классов, со своими собственными методами, которые будут иметь доступ к аргументам / переменным, определённым во внешнем методе.

public static void main(String... args) {
    int[] a = {0};
    class Foo {
        int x = 0;
        
        void bar() {
            System.out.println(x++ + "; " + a[0]++);
        }
    }
    
    Foo f = new Foo();
    f.bar();                     // -> 0; 0
    System.out.println(f.x);     // -> 1
    System.out.println(a[0]);    // -> 1
}

Кроме того, начиная с Java 8, в методе можно определять функции при помощи лямбда-выражений, которые по своей сути представляют экземпляры, реализующие функциональные интерфейсы и очень близки поэтому к анонимным внутренним (anonymous inner) классам.

В данном случае можно было бы определить average как функцию от экземпляра Student, возвращающую значение Double (для возврата примитивного типа double нужно использовать интерфейс ToDoubleFunction):

Function<Student, Double> avg1 = (st) -> (st.economyAver + st.languageAver + st.mathAver) / 3.0;

ToDoubleFunction<Student> avg2 = (st) -> (st.economyAver + st.languageAver + st.mathAver) / 3.0;

Double res1 = avg1.apply(st);
double res2 = avg2.applyAsDouble(st);
→ Ссылка