Функциональное программирование 1. Введение
В математике есть функция от объема ввода, вывода программы расчета, что «что-то сделать, чтобы получить что-то.» В отличие от этого, объектно-ориентированный над
Большое внимание на «объекте должно быть сделано в форме вещей,» и пытается игнорировать идею сложного синтаксиса функционального объектно-ориентированный - подчеркивает, что делать, а не
Какая форма делать.
Объектно-ориентированное мышление: не одно, ищет цель, чтобы решить этот вопрос, вызовите метод объекта, чтобы получить вещи сделано.
Функциональные идеи программирования: пока перейдём к результатам, которые делают, как сделать, это не важно, важен результат, а не обращать внимание на этот процесс.
2. избыточных кодов Runnable
Традиционные письма:
// 当需要启动一个线程去完成任务时,通常会通过 java.lang.Runnable 接口来定义任务内容,并使用 java.lang.Thread 类来启动该线程。代码如下: public class Demo01Runnable { public static void main(String[] args) { // 匿名内部类 Runnable task = new Runnable() { @Override public void run() { // 覆盖重写抽象方法 System.out.println("多线程任务执行!"); } }; new Thread(task).start(); // 启动线程 } } // 本着“一切皆对象”的思想,这种做法是无可厚非的:首先创建一个 Runnable 接口的匿名内部类对象来指定任务内 容,再将其交给一个线程来启动。
Анализ кода:
- класс резьбы необходим интерфейс Runnable в качестве параметра, в котором способ выполняется абстрактный базовый поток, используемый для определения содержания задачи;
- Для того, чтобы задать запуск тела метода, у нас есть необходимость достижения Runnable класса интерфейса;
- Чтобы избавляет определить класс реализации RunnableImpl, мы должны были использовать анонимные внутренние классы;
- Заменяет абстрактный метод должен работать, так что имя метода, параметры метода, метод возвращаемые значения должны писать снова, и не может быть неправильным;
- На самом деле, кажется, что ключ является единственным способом тело.
3. идеи программирования преобразования
Что делать, вместо того, как это сделать
Мы действительно хотим создать анонимный объект внутреннего класса? Нет. Мы просто сделать это и нужно было создать объект. Мы очень надеемся, что нужно сделать, это: код пропуска запуск виво класс резьбы известно.
Передача кусок кода - это наша реальная цель. И создавать объекты ограничены только путем средством объектно-ориентированного синтаксиса и должны были быть приняты.
Это не простой способ? Если мы сосредоточимся от «как это сделать» возвращение к «что» в сущности, до тех пор, как вы найдете больше возможностей для достижения своих целей, процесса и форма не имеет никакого значения
Живой пример
Когда нам нужно из Пекина в Шанхай, вы можете выбрать высокоскоростной железнодорожной, автомобиль, на велосипеде или пешком. Наша реальная цель состоит в том, чтобы достичь Шанхай, Шанхай и как получить вид не важен, поэтому мы исследовали нет лучшего способа, чем высоким содержанием железа - муха.
而现在这种飞机(甚至是飞船)已经诞生:2014年3月Oracle所发布的Java 8(JDK 1.8)中,加入了Lambda表达式的重量级新特性,为我们打开了新世界的大门。
4. 体验Lambda的更优写法
借助Java 8的全新语法,上述 Runnable 接口的匿名内部类写法可以通过更简单的Lambda表达式达到等效:
public class Test {
public static void main(String[] args) {
new Thread(()->System.out.println("多线程任务执行!")).start();
}
}
这段代码和刚才的执行效果是完全一样的,可以在1.8或更高的编译级别下通过。从代码的语义中可以看出:我们启动了一个线程,而线程任务的内容以一种更加简洁的形式被指定。
不再有“不得不创建接口对象”的束缚,不再有“抽象方法覆盖重写”的负担,就是这么简单!
5. Lambda标准格式
- Lambda省去面向对象的条条框框,格式由3个部分组成:
- 一些参数
- 一个箭头
- 一段代码
- 标准格式:
(参数类型 参数名称) ‐> { 代码语句 }
- 格式说明:
- 小括号内的语法与传统方法参数列表一致:无参数则留空;多个参数则用逗号分隔。
->
是新引入的语法格式,代表指向动作。- 大括号内的语法与传统方法体要求基本一致。
- 小括号内的语法与传统方法参数列表一致:无参数则留空;多个参数则用逗号分隔。
6. 练习1:无参数无返回值的代码
题目
给定一个厨子 Cook 接口,内含唯一的抽象方法 makeFood ,且无参数、无返回值。如下:
代码:
public interface Cook { void makeFood(); } // 在下面的代码中,请使用Lambda的标准格式调用 invokeCook 方法,打印输出“吃饭啦!”字样: public class Demo05InvokeCook { public static void main(String[] args) { // TODO 请在此使用Lambda【标准格式】调用invokeCook方法 } private static void invokeCook(Cook cook) { cook.makeFood(); } }
解答:
invokeCook(() ‐> { System.out.println("吃饭啦!"); });
7. 练习2:有参数有返回值的代码
题目:使用数组存储多个Person对象对数组中的Person对象使用Arrays的sort方法通过年龄进行升序排序
下面举例演示
java.util.Comparator<T>
接口的使用场景代码,其中的抽象方法定义为:public abstract int compare(T o1, T o2);
当需要对一个对象数组进行排序时, Arrays.sort 方法需要一个
Comparator
接口实例来指定排序的规则。假设有一个 Person 类,含有 String name 和 int age 两个成员变量:public class Person { private String name; private int age; // 省略构造器、toString方法与Getter Setter }
传统方式:
public class Test { public static void main(String[] args) { // 本来年龄乱序的对象数组 Person[] array = { new Person("古力娜扎", 19), new Person("迪丽热巴", 18), new Person("马尔扎哈", 20) }; // 排序 Arrays.sort(array, new Comparator<Person>() { @Override public int compare(Person o1, Person o2) { return o1.getAge() - o2.getAge(); } }); // 打印 for (int i = 0; i < array.length; i++) { System.out.println(array[i].getName() + "---" + array[i].getAge()); } } } // 这种做法在面向对象的思想中,似乎也是“理所当然”的。其中 Comparator 接口的实例(使用了匿名内部类)代表 了“按照年龄从小到大”的排序规则。
代码分析:下面我们来搞清楚上述代码真正要做什么事情。
- Для сортировки, метод Arrays.sort требует сортировки, т.е. экземпляр интерфейса компаратор, сравните основные абстрактные методы;
- Для того, чтобы сравнить метод указанного тела, у нас есть потребность реализовать компаратор интерфейса класса;
- Для того, чтобы избавляет определение класса реализации ComparatorImpl, мы должны были использовать анонимные внутренние классы;
- Должно быть перезаписаны абстрактными методы сравнения, имя метода, параметры метода, метод возвращаемых значений должны писать снова, и не могут быть неправильно;
- На самом деле, только тело ключевые параметры и методы.
Лямбда образом:
public class Test { public static void main(String[] args) { // 本来年龄乱序的对象数组 Person[] array = { new Person("古力娜扎", 19), new Person("迪丽热巴", 18), new Person("马尔扎哈", 20) }; // 排序 Arrays.sort(array,(Person o1, Person o2) ->{ return o1.getAge()-o2.getAge(); }); // 打印 for (int i = 0; i < array.length; i++) { System.out.println(array[i].getName() + "---" + array[i].getAge()); } } }
8. Лямбда опущен формат
Может быть получена могут быть опущены.
Опустить правила:
- Параметр типа в скобках может быть опущен;
- Если в скобках и только один параметр, круглые скобки могут быть опущены;
- Если фигурные скобки и только один оператор, независимо от того, есть ли возвращаемое значение, то можно опустить фигурные скобки, возвращаемые ключевые слова и точку с запятой.
Код:
// 【练习2代码:】 // 省略前 Arrays.sort(array,(Person o1, Person o2) ->{ return o1.getAge()-o2.getAge(); }); // 省略后 Arrays.sort(array,(o1, o2) ->return o1.getAge()-o2.getAge());
9. Lambda использование помещения
Синтаксис лямбды очень прост, нет объектно-ориентированного сложных ограничений. Но есть несколько вопросов, которые требуют особого внимания при использовании:
Использование Lambda должен иметь интерфейс, и интерфейс и требует только абстрактный метод.
Если JDK встроенный Runnable, интерфейсы Компаратор или пользовательские интерфейсы, только тогда, когда есть абстрактные методы интерфейса и только тогда, когда, можно использовать лямбда.
Использование лямбды должна быть выведен контекстом.
Метод является локальным переменным или аргументом типа должен Лямбда, соответствующий типа интерфейса для использования в качестве примера интерфейса лямбды.
Примечание: Существует только один интерфейс и абстрактный метод, называемый «функции интерфейса.»