JavaRush /Java блог /Random /Кофе-брейк #212. В чем разница между перегрузкой метода и...

Кофе-брейк #212. В чем разница между перегрузкой метода и переопределением метода в Java? Краткое руководство по HTTP-клиенту Java

Статья из группы Random

В чем разница между перегрузкой метода и переопределением метода в Java?

Источник: FreeCodeCamp В этой публикации рассмотрены ключевые правила перегрузки и переопределения методов, а также различия между ними. Кофе-брейк #212. В чем разница между перегрузкой метода и переопределением метода в Java? Краткое руководство по HTTP-клиенту Java - 1В языке Java перегрузка методов и переопределение методов подразумевают создание разных методов с одинаковыми именами. Хотя эти две концепции имеют некоторое сходство, у них разные варианты применения. Если вы хотите обладать прочными базовыми навыками Java, вам важно это понимать.

Что такое перегрузка методов в Java?

Перегрузка метода означает создание другого метода с тем же именем в том же классе, но с другим списком параметров. Существует много ситуаций, когда вам может понадобиться обрабатывать разные типы входных данных для одной и той же операции. Перегрузка методов — один из способов обработки таких ситуаций. Допустим, вы хотите создать метод, выполняющий сложение двух чисел. Этот расчет предназначен для возврата числа в качестве вывода. Если ваш метод обрабатывает параметры типа int, то попытка вызвать его путем передачи значений типа double в качестве аргументов приведет к ошибке компиляции. По этой причине вы можете попытаться перегрузить метод, создав его новую версию, способную обрабатывать другой тип ввода (в данном случае тип double):

public class Calculator {

    public int sum(int a, int b) {
        return a + b;
    }

    public double sum(double a, double b) {
        return a + b;
   }
}
В приведенном выше примере метод sum() перегружен, так как он определен более одного раза в одном классе, но с другим списком параметров. Метод также можно перегрузить, изменив количество параметров. Перед вами примеры того, как метод sum() может быть перегружен, при условии, что методы помещены в один и тот же класс:

public int sum(int a, int b, int c) {
        return a + b + c;
    }
    
protected void sum() {
        System.out.print("Nothing to sum");
    }
Обратите внимание, что, как и в некоторых приведенных выше примерах, вы также можете изменить тип возвращаемого значения или модификатор доступа (но это не обязательно).

Ключевые правила перегрузки методов

  • Перегруженные и перегружаемые методы должны находиться в одном классе (Примечание: сюда относятся любые методы, унаследованные, даже неявно, от суперкласса).
  • Параметры метода должны измениться: либо количество, либо тип параметров должны быть разными в двух методах.
  • Тип возвращаемого значения может быть свободно изменен.
  • Модификатор доступа (public, private и другие) можно свободно изменять.
  • Выброшенные исключения, если таковые имеются, могут быть свободно изменены.

Что такое переопределение метода в Java?

Переопределение метода — это возможность реализации метода в подклассе, который уже существует в суперклассе или родительском классе. Когда вы вызываете переопределенный метод, используя объект типа подкласса, Java использует реализацию метода в подклассе, а не в суперклассе. По этой причине понимание концепции наследования в Java важно для понимания переопределения методов. Любой подкласс обычно может переопределить любой метод из суперкласса, если только метод не помечен ключевыми словами final или static. Метод переопределения не должен изменять имя и список параметров переопределяемого метода. Хотя это и не обязательно, но рекомендуется использовать аннотацию @Override при переопределении метода: эта аннотация проверит правильность переопределения метода и предупредит вас, если это не так. В следующем примере вы увидите класс Car, который расширяет класс Vehicle. Класс Car переопределяет метод move() из суперкласса, и он становится явным с помощью аннотации @Override. Эти два метода по-разному реализованы в теле метода.

class Vehicle {
    public void move() {
        System.out.println("The vehicle is moving");
    }
}

class Car extends Vehicle {
    @Override
    public void move() {
        System.out.println("The car is moving");
    }
}
Выбор того, какая версия move() будет вызываться, зависит от типа объекта, для которого вызывается метод. Обратите внимание, что версия вызываемого переопределенного метода определяется во время выполнения и основывается на типе объекта, а не на ссылке на объект. Это показано в следующем примере, особенно в третьем вызове move(): хотя метод вызывается для ссылки на объект типа Vehicle, фактический объект имеет тип Car. Тип объекта здесь определяется во время выполнения, поэтому вызывается версия метода из подкласса Car.

public static void main(String[] args) {
        
        Vehicle vehicle = new Vehicle();
        vehicle.move();     // Вывод: The vehicle is moving

        Car car = new Car();
        car.move();     // Вывод: The car is moving

        Vehicle secondVehicle = new Car();
        secondVehicle.move();     // Вывод: The car is moving
}

Ключевые правила переопределения методов

  • Список параметров не должен меняться: переопределяющий метод должен принимать то же количество и тип параметров, что и переопределяемый метод, иначе вы просто перегрузите метод.
  • Тип возвращаемого значения не должен изменяться (Примечание: если метод возвращает объект, то в качестве типа возвращаемого значения допускается подкласс этого объекта).
  • Модификатор доступа должен быть таким же или менее ограничивающим (например, если переопределяемый метод — protected, вы можете объявить переопределяющий метод как public, но не private).
  • Выброшенные проверенные исключения, если таковые имеются, могут быть удалены или сокращены методом переопределения. Это означает, что переопределяющий метод может генерировать то же проверенное исключение, что и переопределенный метод, или подкласс этого проверенного исключения, но не более широкое исключение. Это ограничение не распространяется на непроверенные исключения.

Заключение

В этой статье мы рассмотрели основные правила перегрузки и переопределения методов в Java. Вы узнали, что основная цель перегрузки метода — изменить список его параметров, чтобы реализовать другое поведение на основе переданных ему аргументов. Переопределение, с другой стороны, относится к реализации того же метода с тем же списком параметров в подклассе, чтобы адаптировать его поведение к потребностям подкласса. Эти концепции взаимосвязаны с некоторыми основными идеями объектно-ориентированного программирования, такими как наследование и полиморфизм, поэтому они являются фундаментальными для освоения Java. Они могут вызвать некоторую путаницу, особенно у новичков, но четкое понимание правил и способов использования этих концепций должно помочь разработчикам писать более эффективный и читаемый код.

Краткое руководство по HTTP-клиенту Java

Источник: Medium Изучив это руководство, вы узнаете, как использовать HTTP-клиент Java для выполнения запросов и его основные функции. HTTP-клиент был представлен в Java 11 (сентябрь 2018 г.) с целью предложить разработчикам более простой способ выполнения HTTP-запросов. Ранее доступный HttpURLConnectionAPI был многословным, сложным и устаревшим. Новый API имеет множество полезных функций, поддерживает синхронное и асинхронное программирование, а также совместим с HTTP/1.1 и HTTP/2.

Выполнение основного запроса

Пример выполнения GET-запроса:

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://example.com/"))
                .build();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
System.out.println("response body: " + response.body());
В этом примере HTTP-клиент основан на классах HttpClient, HttpRequest и HttpResponse.

Создание HttpClient

Для выполнения запроса HttpClient необходим экземпляр. Существует два статических метода для его получения.
  1. HttpClient.newHttpClient() создает значение по умолчанию HttpClient, которое подходит для большинства случаев.
  2. HttpClient.newBuilder() возвращает построитель (билдер, builder) для более конкретных настроек, таких как версия HTTP, политика перенаправления, прокси-сервер, CookieHandler, HTTP-аутентификация и многое другое.

HttpClient client = HttpClient.newBuilder()
        .followRedirects(Redirect.NORMAL)
        .build();

Создание HttpRequest

Запрос, который необходимо выполнить, представлен классом HttpRequest. Он создается построителем запросов, и с его помощью мы определяем URI, метод запроса, тело, заголовки, время ожидания запроса и версию HTTP. Метод HttpRequest.newBuilder() создает построитель (билдер). В качестве альтернативы есть вариант HttpRequest.newBuilder(URI uri), который уже принимает URI для более короткого кода.

Настройка заголовка запроса

Заголовок можно настроить с помощью header(String name, String value) метода построителя запросов.

HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create("https://example.com/api/products"))
        .header("Authorization", "Bearer 6f0e91f1-b237-45dc-a462-5b6bd1bf9747")
        .build();

Настройка метода HTTP и тела запроса

Для настройки метода HTTP для запроса в билдере есть методы с эквивалентным названием: GET, POST, PUT и DELETE. Тело запроса передается как параметр в файле BodyPublisher. Для создания экземпляра BodyPublisher у класса BodyPublishers есть статические методы, такие как ofString(String body), ofByteArray(byte[] buf) и другие. Также есть статический метод noBody() для выполнения запроса без тела.

HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create("https://example.com/api/products"))
        .header("Content-Type", "application/json")
        .POST(BodyPublishers.ofString("{\"message\": \"Test.\"}"))
        .build();
У построителя также есть method(String method, BodyPublisher bodyPublisher), который принимает имя метода HTTP как String.

HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create("https://example.com/api/products/1"))
        .header("Content-Type", "application/json")
        .method("POST", BodyPublishers.ofString("{\"message\": \"Test.\"}"))
        .build();

Время ожидания запроса

У построителя HttpRequest есть метод timeout, который принимает показатель времени в виде файла java.time.Duration. Время можно получить такими методами, как Duration.ofMinutes(2) и Duration.ofSeconds(45). Если время ожидания истекло до получения ответа, то используется HttpTimeoutException.

HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create("https://example.com/api/products"))
        .timeout(Duration.ofMinutes(2))
        .build();
Учтите, что без установки тайм-аута клиент будет бесконечно ждать ответа.

Реализации BodyHandler

BodyHandler — это интерфейс, который определяет, как будет управляться тело ответа на запрос. Методы HttpClient, выполняющие запросы, принимают файл BodyHandler. Класс BodyHandlers имеет статические методы, которые предлагают BodyHandler такие реализации, как ofString(), ofByteArray(), ofInputStream() и другие.

HttpResponse<String> response1 = client.send(request, HttpResponse.BodyHandlers.ofString());
HttpResponse<byte[]> response2 = client.send(request, HttpResponse.BodyHandlers.ofByteArray());

Асинхронный запрос

HttpClient имеет метод sendAsync(HttpRequest request, BodyHandler<T> responseBodyHandler), который возвращает CompletableFuture и выполняет запрос асинхронно. CompletableFuture — это класс, предназначенный для асинхронного программирования. Он представляет собой результат операции, выполняемой асинхронно, и предлагает полезные методы для обработки успешных результатов и ошибок.

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder(URI.create("https://example.com/api/products")).build();
CompletableFuture<HttpResponse<String>> future = client.sendAsync(request, BodyHandlers.ofString());
future.thenAccept(response -> System.out.println("response body: " + response.body()));
Метод thenAccept(Consumer<? super T> action) выполнит полученный Consumer после успешного завершения запроса.

HttpResponse

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

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder(URI.create("https://example.com/")).build();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
System.out.println("status code: " + response.statusCode());
System.out.println("headers: " + response.headers());
System.out.println("response body: " + response.body());

Более короткий код со статическим импортом

HTTP-клиент намного проще, чем старые классы и методы, но на самом деле он все еще многословен. И при частом использовании, например, в тестовом коде endpoint, проблема усугубляется. Однако код все же можно сделать более кратким, используя статический импорт.

var response = newHttpClient().send(newBuilder(URI.create("https://example.com/api/products")).build(),
        BodyHandlers.ofString());
System.out.println("response body: " + response.body());

Заключение

В этом руководстве мы узнали, как использовать HTTP-клиент Java для выполнения запросов, а также его основные функции.
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ