一、面向对象编程 & 函数式编程
面向对象编程是对数据进行抽象,而函数式编程是对行为进行抽象。现实世界中,数据和行为并存,程序也是如此,因此这两种编程方式我们都得学。
二、Java 8 Lambda表达式
Java 8 的最大变化是引入了Lambda表达式:一种紧凑、传递行为的方式。Android为按钮控件绑定事件的五种方式中有一种是使用匿名内部类的方式。
- 步骤1:首先需要获取到 layout 中布局页面的Button控件中指定的Id。
- 步骤2:之后为这样按钮绑定监听器,使用匿名内部类的方式,代码如下。
button = (Button)findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this, "按钮被点击了",Toast.LENGTH_SHORT).show();
}
});
在这个例子中,我们创建了一个新对象,它实现了OnClickListener接口。这个接口只有一个方法onClick,当用户点击屏幕上的按钮时,button就会调用这个方法。匿名内部类实现了该方法。
/**
* Interface definition for a callback to be invoked when a view is clicked.
*/
public interface OnClickListener {
/**
* Called when a view has been clicked.
*
* @param v The view that was clicked.
*/
void onClick(View v);
}
这实际上是一个代码即数据的例子——我们给按钮传递了一个代表某种行为的对象
设计匿名内部类的目的,就是为了方便Java程序员将代码作为数据传递。不过,匿名内部类还是不够简便。为了调用一行重要的逻辑代码Toast.makeText,不得不加上4行冗繁的样板代码。尽管如此,样板代码并不是唯一的问题:这些代码还相当难读,因为它没有清楚地表达程序员的意图。我们并不想传入对象,只想传入行为。在Java 8 中,上述代码可以写成一个Lambda表达式
button.setOnClickListener(view -> Toast.makeText(MainActivity.this, "按钮被点击了",Toast.LENGTH_SHORT).show());
使用Lambda表达式将行为和按钮点击进行关联
和传入一个实现某接口的对象不同,我们传入了一段代码块:一个没有名字的函数。view是参数名,和上面匿名内部类示例中的是同一个参数。->
将参数和Lambda表达式的主题分开,而主体是用户点击按钮时会运行的一些代码。Lambda表达式除了基本的形式之外,还有几种变体,如
//无参数
Runnable noArguments = () -> System.out.println("Hello World");
//一个参数
ActionListener onArguments = event -> System.out.println("button clicked");
//Lambda表达式是一段代码块
Runnable multiStatement = () ->{
System.out.print("Hello");
System.out.println("World");
}
//表示包含多个参数的方法
BinaryOperator <Long> add = (x,y) -> x + y;
//显示声明参数类型
BinaryOperator <Long> addExplicit = (Long x, Long y) -> x + y;
三、 Lambda表达式只能针对函数式接口使用
函数式接口
当接口里只有一个抽象方法的时候,就是函数式接口,可以使用注解@FunctionalInterface
强制限定接口是函数式接口,即只能有一个抽象方法。
例如:
public interface Integerface1 {
void test();
}
上面的接口只有一个抽象方法,则默认是函数式接口。
interface Integerface3 {
void test();
void test2();
}
该接口有两个抽象方法,不是函数式接口
@FunctionalInterface
interface Integerface2 {
}
上面这样写编译会报错,因为@FunctionalInterface注解声明了该接口是函数式接口,必须且只能有一个抽象方法。如:
@FunctionalInterface
interface Integerface2 {
void test();
}