Глубокое понимание методов Java

Java

Метод (некоторые любят называть его функцией) — это многократно используемый фрагмент кода.

: Notebook: Эта статья была заархивирована под: "blog"

:keyboard: Пример кода в этой статье был заархивирован в: "javacore"

использование метода

определение метода

Формат синтаксиса определения метода:

[修饰符] 返回值类型 方法名([参数类型 参数名]){
    ...
    方法体
    ...
    return 返回值;
}

Пример:

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

Метод состоит из заголовка метода и тела метода. Вот все части метода:

  • модификаторМодификатор - является необязательным и сообщает компилятору, как вызывать метод. Определяет тип доступа для этого метода.
  • тип возвращаемого значения- Тип возвращаемого значения указывает тип данных результата, возвращаемого после выполнения метода. Если нет возвращаемого значения, оно должно быть установлено как void.
  • имя метода- это фактическое название метода. Имя метода и список параметров вместе составляют подпись метода.
  • Тип параметра- Параметр подобен заполнителю. При вызове метода передать значения параметрам. Список параметров относится к типу параметра, порядку и количеству параметров метода. Аргументы необязательны, а методы не могут содержать аргументов.
  • тело метода- Тело метода содержит определенные операторы, определяющие функцию метода.
  • return- Должен возвращать тот же тип данных, что и тип возвращаемого значения при объявлении метода. В методе void оператор return является необязательным, если вы хотите написать return, вы можете толькоreturn;эта форма.

вызов метода

Когда программа вызывает метод, управление программой переходит к вызываемому методу. Вернуть управление программе, когда выполняется инструкция return вызываемого метода или когда достигается закрывающая скобка тела метода.

Java поддерживает два способа вызова методов в зависимости от того, имеет ли метод возвращаемое значение или нет.

  • Метод с возвращаемым значением. Метод с возвращаемым значением обычно используется для присвоения значения переменной или подстановки его в арифметическое выражение для вычисления.
int larger = max(30, 40);
  • Метод без возврата. Метод без возврата может быть только одним оператором.
System.out.println("Hello World");

рекурсивный вызов

Java поддерживает рекурсивный вызов методов (то есть метод вызывает сам себя).

Уведомление:

  • Рекурсивные методы должны иметь явное конечное условие.
  • Старайтесь избегать рекурсивных вызовов. Потому что рекурсивные вызовы могут привести к переполнению стека, если они не обрабатываются должным образом.

Пример последовательности Фибоначчи (типичный рекурсивный алгоритм):

public class RecursionMethodDemo {
    public static int fib(int num) {
        if (num == 1 || num == 2) {
            return 1;
        } else {
            return fib(num - 2) + fib(num - 1);
        }
    }

    public static void main(String[] args) {
        for (int i = 1; i < 10; i++) {
            System.out.print(fib(i) + "\t");
        }
    }
}

параметры метода

В языках программирования, таких как C/C++, передача параметров метода обычно принимает две формы:

  • Передача по значению. Параметры, передаваемые по значению, называются формальными параметрами. Когда значение передается, параметры передаются, модификация в методе не вступит в силу вне метода.
  • Передача по ссылке. Параметры, передаваемые по ссылке, называются фактическими параметрами. При передаче по ссылке переданные параметры, изменения в методе, вступят в силу вне метода.

Итак, как обстоят дела в Java?

В Java есть только передача по значению.

Пример первый:

public class MethodParamDemo {
    public static void method(int value) {
        value =  value + 1;
    }
    public static void main(String[] args) {
        int num = 0;
        method(num);
        System.out.println("num = [" + num + "]");
        method(num);
        System.out.println("num = [" + num + "]");
    }
}
// Output:
// num = [0]
// num = [0]

Пример второй:

public class MethodParamDemo2 {
    public static void method(StringBuilder sb) {
        sb = new StringBuilder("B");
    }

    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("A");
        System.out.println("sb = [" + sb.toString() + "]");
        method(sb);
        System.out.println("sb = [" + sb.toString() + "]");
        sb = new StringBuilder("C");
        System.out.println("sb = [" + sb.toString() + "]");
    }
}
// Output:
// sb = [A]
// sb = [A]
// sb = [C]

проиллюстрировать:

В приведенных выше двух примерах, независимо от того, передается ли в метод базовый тип данных или ссылочный тип, значение, измененное в методе, не действует извне.

Для базовых типов данных Java напрямую копирует значение и передает его методу, для ссылочных типов данных копирует ссылочный адрес текущего объекта, а затем передает адрес, поэтому он также передается по значению.

Дальнейшее чтение:

Иллюстрация передачи параметров в Java

модификатор метода

Как упоминалось ранее, модификаторы для методов Java являются необязательными и сообщают компилятору, как вызывать метод. Определяет тип доступа для этого метода.

Методы Java имеют несколько модификаторов, давайте познакомимся с ними по порядку:

модификатор контроля доступа

Уровень контроля доступа, от наиболее привилегированного до наименее привилегированного, выглядит следующим образом:

public > protected > 包访问权限(没有任何关键字)> private
  • public- представляет доступ к любому классу;
  • 包访问权限- Доступ к пакету без каких-либо ключевых слов. Это означает, что все остальные классы в текущем пакете доступны, но классы из других пакетов недоступны.
  • protected- Указывает, что подклассы могут получить доступ, кроме того, другие классы в том же пакете также могут получить доступ, даже если эти классы не являются подклассами.
  • private- означает, что никакой другой класс не может получить к нему доступ.

static

одеялоstaticДекорированные методы называются статическими методами.

По сравнению с обычными методами экземпляра статические методы имеют следующие отличия:

  • При вызове внешнего статического метода вы можете использовать类名.方法名способ, вы также можете использовать对象名.方法名Путь. Метод экземпляра имеет только последний способ. То есть,Вы можете вызывать статические методы без создания объекта.

  • Когда статический метод обращается к членам этого класса, доступ разрешен только к статическим членам.(то есть, статические переменные-члены и статические методы), но не разрешая доступ к переменным-членам экземпляра и методам экземпляра; методы экземпляра не имеют этого ограничения.

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

final

одеялоfinalМодифицированные методы не могут быть переопределены подклассами.

Пример окончательного метода:

public class FinalMethodDemo {
    static class Father {
        protected final void print() {
            System.out.println("call Father print()");
        };
    }

    static class Son extends Father {
        @Override
        protected void print() {
            System.out.println("call print()");
        }
    }

    public static void main(String[] args) {
        Father demo = new Son();
        demo.print();
    }
}
// 编译时会报错

проиллюстрировать:

В приведенном выше примере родительский класс Отец определяетfinalметодprint(), то его подкласс не может переопределить этот последний метод, иначе он скомпилирует ошибку.

default

Начиная с JDK8, поддержка в интерфейсеInterfaceопределено вdefaultметод.defaultМетоды могут появляться только в интерфейсахInterfaceсередина.

в интерфейсеdefaultИзмененный метод называется методом по умолчанию.Если класс, который реализует этот интерфейс, не переопределяет этот метод, он напрямую наследует этот метод, и реализация этого метода больше не является обязательной.

Синтаксис метода по умолчанию, по-видимому, добавляет новые функциональные возможности к тысячам существующих классов библиотеки классов Java без необходимости переделывать эти классы. Например, в JDK8CollectionВ классе очень удобноstream()метод, модифицированный какdefault, многие подклассы List и Set класса Collection напрямую наследуют этот метод I, поэтому нет необходимости уделять внимание добавлению этого метода для каждого подкласса.

defaultПример метода:

public class DefaultMethodDemo {
    interface MyInterface {
        default void print() {
            System.out.println("Hello World");
        }
    }


    static class MyClass implements MyInterface {}

    public static void main(String[] args) {
        MyInterface obj = new MyClass();
        obj.print();
    }
}
// Output:
// Hello World

abstract

одеялоabstractДекорированные методы называются абстрактными методами, и методы не могут иметь сущности. Абстрактные методы могут появляться только в абстрактных классах.

Абстрактные методы Пример:

public class AbstractMethodDemo {
    static abstract class AbstractClass {
        abstract void print();
    }

    static class ConcreteClass extends AbstractClass {
        @Override
        void print() {
            System.out.println("call print()");
        }
    }

    public static void main(String[] args) {
        AbstractClass demo = new ConcreteClass();
        demo.print();
    }

}
// Outpu:
// call print()

synchronized

synchronizedдля параллельного программирования.одеялоsynchronizedДекорированный метод позволяет одновременно выполнять только один поток.

В контейнерах синхронизации Java (Vector, Stack, HashTable) вы увидите множество синхронизированных методов. Однако помните: в параллельном программировании на Java синхронизированный метод не является хорошим выбором, в большинстве случаев мы выберем более легкую блокировку.

специальный метод

В Java есть несколько специальных методов, которые используются в особых сценариях.

основной метод

Основной метод в Java — это особый вид статического метода, потому что все Java-программы создаютсяpublic static void main(String[] args)метод начинает выполняться.

Есть много новичков, которые постоянно используют метод main, но не знают, для чего нужны аргументы в методе main. На самом деле, это используется для получения входных аргументов командной строки.

Пример:

public class MainMethodDemo {
    public static void main(String[] args) {
        for (String arg : args) {
            System.out.println("arg = [" + arg + "]");
        }
    }
}

выполнять последовательно

javac MainMethodDemo.java
java MainMethodDemo A B C

Консоль выведет выходные параметры:

arg = [A]
arg = [B]
arg = [C]

Метод строительства

Любой класс имеет конструктор, и функция конструктора заключается в установке состояния экземпляра при инициализации экземпляра класса.

У каждого класса есть конструктор. Если для класса явно не определен конструктор, компилятор Java предоставит для класса конструктор по умолчанию.

При создании объекта должен быть вызван хотя бы один конструктор. Имя конструктора должно совпадать с именем класса, а класс может иметь несколько конструкторов.

public class ConstructorMethodDemo {

    static class Person {
        private String name;

        public Person(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    public static void main(String[] args) {
        Person person = new Person("jack");
        System.out.println("person name is " + person.getName());
    }
}

Обратите внимание, что в дополнение к использованию public конструктор также может быть изменен с помощью private В этом случае класс не может вызывать этот конструктор для создания экземпляра объекта, который часто используется в шаблоне singleton в шаблоне проектирования.

Метод переменных параметров

Начиная с JDK5, Java поддерживает передачу переменных параметров одного типа в метод. В объявлении метода добавьте многоточие после указания типа параметра..... В методе может быть указан только один переменный параметр, и он должен быть последним параметром метода. Любой нормальный параметр должен быть объявлен перед ним.

Пример вариативного метода:

public class VarargsDemo {
    public static void method(String... params) {
        System.out.println("params.length = " + params.length);
        for (String param : params) {
            System.out.println("params = [" + param + "]");
        }
    }

    public static void main(String[] args) {
        method("red");
        method("red", "yellow");
        method("red", "yellow", "blue");
    }
}
// Output:
// params.length = 1
// params = [red]
// params.length = 2
// params = [red]
// params = [yellow]
// params.length = 3
// params = [red]
// params = [yellow]
// params = [blue]

метод завершения()

finalizeВызывается перед уничтожением (восстановлением) объекта сборщиком мусора для очистки восстановленного объекта.

finalizeвjava.lang.ObjectОпределенный в, то есть каждый объект имеет такой метод. Этот метод вызывается при запуске GC и сборе объекта.

finalizer() обычно непредсказуем, опасен и вообще не нужен. Использование финализаторов может привести к нестабильному поведению, снижению производительности и проблемам с переносимостью.

Помните: этого следует избегать, насколько это возможно.finalizer(). Никогда не используйте его в качестве деструктора в C/C++. Причина в следующем:Поток Finalizer будет конкурировать с нашим основным потоком, но поскольку он имеет более низкий приоритет и получает меньше процессорного времени, он никогда не догонит основной поток. Таким образом, в конце концов может произойти ошибка OutOfMemoryError.

Дальнейшее чтение:

Следующие две статьи более подробно описывают проблемы и причины, которые может вызвать finalizer().

Переопределение и перегрузка

Переопределение означает, что подкласс определяет метод с тем же именем, что и родительский класс, но при переопределении метода необходимо учитывать права доступа.Переопределяемый подклассом метод не может иметь более строгие права доступа, чем родительский класс.

Метод, который будет переопределен подклассом. Если вы хотите получить доступ к методу родительского класса, вы можете использоватьsuperключевые слова.

Пример переопределения:

public class MethodOverrideDemo {
    static class Animal {
        public void move() {
            System.out.println("会动");
        }
    }
    static class Dog extends Animal {
        @Override
        public void move() {
            super.move();
            System.out.println("会跑");
        }
    }

    public static void main(String[] args) {
        Animal dog = new Dog();
        dog.move();
    }
}
// Output:
// 会动
// 会跑

Перегрузка метода означает, что имя метода то же, но типы параметров или количество параметров разные. Вызовы методов с различными функциями могут быть выполнены путем передачи количества и типов параметров.

Уведомление:

Перегрузка должна быть в том, что параметры метода не совсем совпадают. Если параметры метода точно такие же, отличается только возвращаемое значение, Java не скомпилируется.

Пример перегрузки:

public class MethodOverloadDemo {
    public static void add(int x, int y) {
        System.out.println("x + y = " + (x + y));
    }

    public static void add(double x, double y) {
        System.out.println("x + y = " + (x + y));
    }

    public static void main(String[] args) {
        add(10, 20);
        add(1.0, 2.0);
    }
}
// Output:
// x + y = 30
// x + y = 3.0

резюме



использованная литература