- Создание функций на языке Java
- Создание функции, которая возвращает
- Язык программирования Java SE 8. Подробное описание.
- Пользовательские функции Java: как создать функцию в Java?
- Создание функций в Java
- Вызываем функции без параметров
- Создаём функции с параметрами
- Функциональное программирование в Java
- Работа с коллекциями в функциональном стиле
- Работа с коллекциями с помощью Google Collections
- Ссылки
- О чем хотелось бы рассказать еще
Создание функций на языке Java
Функция — это небольшая программа, которая выполняет определённые действия при вызове функции по имени.
В языке Java существуют свои встроенные и готовые к использованию функции, но никто не отменял пользовательских функций.
Пользовательская функция — это функция созданная разработчиком для конкретной задачи.
Написание функций относят к процедурному подходу в программировании.
Чаще всего в функции помещают повторяющийся программный код. Для того, чтобы не писать одни и те же строчки кода, их выносят в отдельный блок, а затем вызывают по имени в основном коде программы когда это необходимо.
Различают два основных вида функций:
Также функции можно разделить на две категории:
Запомните: переменная созданная в функции, умирает после завершения функции и более не существует!
Создание функции, которая возвращает
Данный тип функций является наиболее используемым, так как почти всегда требуется что-то посчитать, произвести некое преобразование и тому подобное, следовательно полученный результат необходимо использовать вне функции. Всё что было создано в функции в конечном счёте умирает в ней же, в связи с этим необходимо вернуть результат в основной код программы.
Сделать это помогает оператор return
Создадим функцию, которая вернёт значение переменной и присвоит переменной в основном коде это значение.
Язык программирования Java SE 8. Подробное описание.
Эта книга написана разработчиками языка Java и является полным техническим справочником по этому языку программирования. В ней полностью описаны новые возможности, добавленные в Java SE 8, включая лямбда-выражения, ссылки на методы, методы по умолчанию, аннотации типов и повторяющиеся аннотации. В книгу также включено множество поясняющих примечаний. В ней четко обозначены отличия формальных правил языка от практического поведения компиляторов.
Java является языком программирования общего назначения, ориентированным на параллельное выполнение и основанным на классах объектно-ориентированным языком. Он специально разрабатывался так, чтобы быть достаточно простым, так что многие программисты могут легко достичь высокой скорости работы.
Язык программирования Java является строго и статически типизированным. В дан ной спецификации четко различаются ошибки времени компиляции, которые могут и должны быть обнаружены во время компиляции, и ошибки, которые происходят во время выполнения.
Язык программирования Java — язык относительно высокого уровня, что проявляется, в частности, в том, что детали представления машинного кода в языке недоступны.
Сюда входят автоматическое управление памятью, обычно с использованием сборщика мусора (чтобы избежать проблем, связанных с явным освобождением памяти. Высокопроизводительные реализации сборки мусора могут ограничиваться работой в паузах выполнения программы, чтобы обеспечить возможность создания системных программ и приложений реального времени.
Язык не включает ни одной небезопасной конструкции, такой как доступ к массиву без проверки диапазонов индексирования, поскольку такие небезопасные конструкции могут приводить к неопределенному поведению программы.
Программа на языке Java обычно компилируется в набор команд байт-кода и бинарный формат, определенный в спецификации виртуальной машины Java The Java Virtual Machine Specification, Java SE 8 Edition.
Пользовательские функции Java: как создать функцию в Java?
Функция представляет собой небольшую программу, выполняющую определённые действия, когда её (функцию) вызывают по имени. В языке программирования Java есть много встроенных и готовых к работе функций, однако никто не мешает создавать пользователю свои функции.
Исходя из вышеизложенного, пользовательской функцией можно назвать функцию, которую создал сам разработчик для решения конкретной задачи. Непосредственный процесс написания функций считается процедурным подходом в программировании.
Что обычно помещают в функции? Как правило, речь идёт о повторяющемся программном коде. Соответственно, чтобы программисту не писать те же самые строчки кода снова и снова, он просто выносит эти строчки в отдельный блок, а потом вызывает этот блок в основном Java-коде программы тогда, когда это нужно.
Идём дальше, в Java выделяют 2 вида функций: 1. Функция, которая что-либо возвращает. 2. Функция, которая не возвращает ничего.
Вдобавок к этому, функция в Джаве может быть с параметрами и без них. Тут следует напомнить важный момент: переменная, которая создана в функции, после завершения этой функции «умирает», то есть больше не существует.
Рассмотрим формулу создания функции в Java:
Создание функций в Java
Для начала создадим пользовательскую функцию, которая что-нибудь возвращает. Этот тип функций используется чаще всего, ведь очень часто нужно что-либо посчитать, выполнить преобразование и т. п., то есть речь идёт о том, чтобы использовать полученный результат вне этой функции. А так как всё, что создано в функции, после её завершения «погибает», нам надо, чтобы в основной код программы вернулся результат работы этой функции. Для это используется оператор return.
Итак, создадим пользовательскую функцию, которая вернёт нам значение переменной, а также присвоит это значение переменной в основном коде.
public class Main < public static int function1()< //идентификатор доступа, функция является статичной, тип возвращаемого значения, имя функции без параметров int a = 5; //создаём переменную со значением return a; //возвращаем значение при вызове данной функции >public static void main(String[] args) < //блок основного кода нашей программы >>Таким образом, создаётся переменная, которая потом возвращается в нужном разработчику месте. Но вообще, в теле пользовательской функции мы можем прописать любой код, например, по созданию массивов, циклов и другой структуры.
Теперь давайте создадим функцию в Java, которая ничего возвращать не будет. Такой тип функции может пригодиться во время работы с глобальными переменными либо если надо что-либо напечатать и вывести на экран.
По большему счёту, особых отличий между написанием функций обоих видов нет. Главное — указать другой тип (void) и не применять return.
public class Main < public static void function2()< System.out.println("Записывайтесь на курсы OTUS!"); //выводим сообщение на экран >public static void main(String[] args) < //основной блок нашей программы >>Вызываем функции без параметров
Чтобы работать с функциями, получая от них какой-либо результат, надо вызвать функцию в нужном месте по имени.
Давайте воспользуемся написанными нами функциями и вызовем их в основном коде.
public class Main < public static int function1()< int a = 5; return a; >public static void function2() < System.out.println("Записывайтесь на курсы OTUS!"); >public static void main(String[] args) < //основной блок программы int b = function1(); //присваиваем переменной значение, которое возвратит первая функция System.out.println(b); //выводим на экран значение нашей переменной function2(); //вызываем по имени вторую функцию >>5 Записывайтесь на курсы OTUS!Следует добавить, что функция, которая что-либо возвращает, обязательно должна вызываться так, как указано в примере, то есть возвращаемое значение должно быть чему-то присвоено.
Создаём функции с параметрами
Иногда надо произвести над значениями какие-нибудь действия. Для этого нужно передать нашей пользовательской функции эти самые значения. Когда значения передаются в нашу функцию, они становятся её аргументами функции.
Итак, давайте создадим функцию с параметрами, а потом вызовем её в основном коде с помощью аргументов. Возведём переменную в определённую степень, а потом вернём значение в переменную.
Необходимые параметры нужно указывать при создании функции (речь идёт о переменных в скобках после имени функции). При этом аргументы надо передать в обязательном порядке, иначе функция попросту не заработает, ведь у неё просто не будет значения, с которым надо взаимодействовать. Аргументы надо указывать при вызове функции (2 целочисленных значения).
public class Main < public static int function3(int var_1, int var_2)< //функция с параметрами int a = 1; //создаём переменную, в которой будет находиться расчётное значение for(int i = 0; i < var_2; i++)< //используем цикл для возведения в степень a = a * var_1; //перемножаем новое значение со старым, возводя тем самым в степень >return a; //возвращаем посчитанное значение > public static void main(String[] args) < //основной блок программы int result = function3(5,3); //вызываем функцию, передав 2 аргумента (возводим 5 в третью степень) System.out.println(result); //выводим значение переменной >>В консоли увидим следующее значение:
Таким образом, в функцию в Java мы можем помещать, что угодно. В нашем же случае, аргументы надо передать обязательно, иначе возникнет ошибка.
Вот и всё, надеемся, что теперь вы разобрались с темой по созданию пользовательских функций на языке Java. Если же интересуют более сложные задачи, добро пожаловать на наш курс для опытных Java-разработчиков!
Функциональное программирование в Java
Что такое функциональное программирование? Если в двух словах, то функциональное программирование — это программирование, в котором функции являются объектами, и их можно присваивать переменным, передавать в качестве аргументов другим функциям, возвращать в качестве результата от функций и т. п. Преимущества, которые раскрывает такая возможность, будут понятны чуть позже. Пока нам надо разобраться, как в Java можно использовать саму конструкцию «функция».
Как известно, в Java нету функций, там есть только классы, методы и объекты классов. Зато в Java есть анонимные классы, то есть классы без имени, которые можно объявлять прямо в коде любого метода. Этим мы и воспользуемся. Для начала объявим такой интерфейс:
public final interface Function
Теперь в коде какого-нибудь метода мы можем объявить анонимную реализацию этого интерфейса:
public static void main() < // Объявляем "функцию", присваиваем ее переменной intToString. FunctionintToString = new Function() < @Override public String apply(Integer from) < return from.toString(); >>; intToString.apply(9000); // Вызываем нашу функцию. Получаем строку "9000". >
Такую реализацию мы и будем называть «анонимной функцией». С точки зрения функционального программирования с ней можно делать все то же самое, что и с функцией из функциональных языков: присваивать переменным, передавать в качестве аргумента другим функциям(и методам классов), получать в качестве результата от функций(и методов классов).
Теперь можно перейти к изложению некоторых базовых паттернов функционального программирования.
Работа с коллекциями в функциональном стиле
Допустим, у нас есть некая коллекция целых чисел. Мы хотим их вывести на экран в виде строки, и каждое число в строке будет разделено через запятую. Нефункциональное решение выглядело бы примерно так:
public String joinNumbers(Collection numbers) < StringBuilder result = new StringBuilder(); boolean first = true; for (Integer number : numbers) < if (first) first = false; else result.append(", "); result.append(number); >return result; >
Для реализации функционального решения нам потребуется сперва подготовить несколько функций и методов. Будем объявлять их в качестве статических полей класса:
public static final Function INT_TO_STRING = . // Уже реализовали выше // Берет поэлементно значения из коллекции from, преобразует их с помощью функции transformer // и возвращает список результатов преобразования в том же порядке. public static List map(Collection from, Function transformer) < ArrayListresult = new ArrayList(); for (F element : from) result.add(transformer.apply(element)); return result; > // Берет коллекцию произвольных элементов и конкатенирует их в строку public static String join(Collection from, String separator) < StringBuilder result = new StringBuilder(); boolean first = true; for (T element : from) < if (first) first = false; else result.append(separator); result.append(element); >return result.toString(); >
Теперь наш метод joinNumbers будет выглядить следующим образом:
public String joinNumbers(Collection numbers)Метод реализован ровно в одну простую строку.
- Методы map и join являются достаточно обобщенными, то есть их можно применять не только для решения данной задачи. Это значит, что их можно было бы выделить в некий утилитный класс, и использовать потом этот класс в разных частях проекта.
- Вместо класса Collection в методе map можно было бы передавать Iterable и возвращать новый Iterable , извлекая из переданной коллекции данные по мере обхода данных в возвращаемой коллекции, то есть извлекать элементы лениво, поэтапно, а не все сразу. Такая реализация, позволит, например, создавать цепочки преобразования данных, выделяя каждый этап преобразования в отдельную простую функцию, при этом эффективность алгоритма будет оставаться порядка O(n):
map(map(numbers, MULTIPLY_X_2), INT_TO_STRING); // каждый элемент умножаем на два и приводим к строке.- Создавая какой-нибудь класс, вы можете создавать для некоторых его методов статические поля, являющиеся функциями-обертками, делегирующими вызов apply на вызов соответствующего метода класса. Это позволит использовать «методы» объектов в функциональном стиле, например, в представленных выше конструкциях.
Работа с коллекциями с помощью Google Collections
- interface Function . Интерфейс, аналогичный приведенному мной выше.
- Iterables.filter . Берет коллекцию и функцию-предикат(функцию, возвращающую булево значение). В ответ возвращает коллекцию, содержающую все элементы исходной, на которые указанная функция вернула true. Удобно, например, если мы хотим отсеить из коллекции все четные числа: Iterables.filter(numbers, IS_ODD);
- Iterables.transform . Делает то же самое, что функция map в моем примере выше.
- Functions.compose . Берет две функции. Возвращает новую функция — их композицию, то есть функцию, которая получает элемент, подает его во вторую функцию, результат подает в первую функцию, и полученный из первой функции результат возвращает пользователю. Композицию можно использовать, например, так: Iterables.transform(numbers, Functions.compose(INT_TO_STRING, MULTIPLY_X_2));
В Google Collections конечно есть еще много других полезных вещей как для функционального программирования, так и для работы с коллекциями в императивном стиле.
Ссылки
- Статья в Википедии о функциональном программировании.
- Google Guava, проект, частью которого является Google Collections.
- Видеопрезентация Google Collections с Joshua Bloch.
- Apache Commons Collections. Решает схожие с Google Collections задачи, но был написан под Java 4, то есть без параметрических типов.
О чем хотелось бы рассказать еще
- Мутабельные и иммутабельные замыкания.
- Pattern-matcher.
- Монады.
- Распараллеливание с использованием функционального подхода.
- Комбинаторы парсеров.