一、lambda表达式的定义:
Lambda流式操作是Java8中重要的特性,lambda表达式核心概念为 函数式接口、::、-> 等基本语法,可以大大减少代码量的编写,使代码更加优雅
1、只有一个抽象函数的接口,就是函数式接口
2、:: 可以称之为域运算符,主要是用来获取方法
3、-> 的语法为: (变量或参数)->{代码体}。也叫变量和代码的分隔符
4、当只获取一个方法属性的时候 :: 和 -> 可以通用
二、接口:
1、接口可以定义在另一个类的内部
2、接口中的方法都是抽象方法
3、接口中的常量都是静态常量
三、函数式接口:
1、定义:只有一个抽象方法的接口就是函数式接口。
2、函数式接口与lambda表达式的关系:在java8中,lambda表达式就是一个函数式接口的实例,也就是说,只要一个对象是函数式接口的实例,那么该对象就可以用lambda表达式来表示。
3、java内置函数式接口。
四、四大核心函数式接口
函数式接口 | 称谓 | 传入方法参数类型 | 用途 | 理解 |
Comsumer<T> | 消费型接口 | T |
对类型为 T 的对象应用操作,包含方法:
void accept(T t)
| 没有返回值,可以用来对对象进行操作,可供消费 |
Supllier<T> | 供给型接口 | 无 |
返回类型为 T 的对象,包含方法:
T get()
| 无论怎样他都会供给使用者一个对象 |
Function<T,R> | 函数型接口 | T |
对类型为 T 的对象应用操作,并返回结果。 结果是 R 类型的对象。包含方法:R
apply(T t)
| 就像y=x+1这种函数表达式一样,传入一个x返回一个y结果 |
Predicate<T> | 判断型接口 | T |
确定类型为 T 的对象是否满足某约束,并返 回 boolean 值。包含方法:boolean
test(T t)
| 根据用途和返回值很明显是判断型 |
五、类
(一)类可以定义在另一个类的内部
1、把类定义在另一个类的内部,该类就被称为内部类。如果在类 Outer 的内部再定义一个类 Inner,此时类 Inner 就称为内部类(或称为嵌套类),而类 Outer 则称为外部类(或称为宿主类)。
2、内部类一般来说包括这四种:成员内部类、静态内部类、局部内部类、private修饰的内部类、匿名内部类。
(二)成员内部类
//成员内部类
public class Outer {
//Outer是外部类
private int age=20;
//Inner是处于成员的位置,是成员内部类
class Inner{
public void show(){
System.out.println(age);//成员内部类可以访问外部类的成员变量
}
}
}
class Test{
public static void main(String[] args) {
Outer.Inner oi=new Outer().new Inner();
oi.show();
}
}
运行结果如下:
(三)静态内部类
public class Outer3 {
int age=10;
static int age1=20;
//静态内部类,不能使用外部类的非static的成员变量和成员方法。
static class Inner{//有static修饰的类就是静态内部类
public void method(){
System.out.println(age1);//这里如果输出的是age就会出错
}
}
}
class Test3{
public static void main(String[] args) {
//内部类相当于外部类的成员
Outer3.Inner inner=new Outer3.Inner();
inner.method();
}
}
运行结果如下:
(四)局部内部类
//局部内部类:定义在一个方法或一个作用域里面的类
public class Out4 {
private int n=10;
//外部类的方法
public int SumN(){
//for循环,n从10加到19,
for (int i=0;i<10;i++){
n++;
//局部内部类
//不能有private、public、protected和static等修饰符,与局部变量类似。
//只能在定义局部内部类的方法或者作用域中实例化
//如果局部内部类访问了一个局部变量,那么该局部变量必须使用final修饰
class DemoInner{
//局部内部类的方法
public void AddN(){
//判断n是否是偶数;如果是偶数的话就减一
if (n%2==0){
n--;
}
}
}
}
return n;
}
}
class Test4{
public static void main(String[] args) {
Out4 inner=new Out4();
int n1=inner.SumN();
System.out.println(n1);//这里输出的结果是20.如果局部内部类没有实例化的话,里面的代码是不会运行得到的
}
}
运行结果如下:
(五)private修饰的内部类
import java.util.Scanner;
public class Outer2 {
//private修饰的内部类,外部不能通过创建对象的方法来访问内部类,只有通过创建专门访问的方法
private class Inner{
public void show(){
System.out.println("密码是:12345678");
}
}
//创建专门的访问方法
public void getInner(){
new Inner().show();
}
}
class Test2{
public static void main(String[] args) {
Outer2 outer=new Outer2();
//设置访问限制
System.out.println("请输入密码提示:");
Scanner in=new Scanner(System.in);
String passwordTip=in.next();
if ("123".equals(passwordTip)){
outer.getInner();
}
}
}
运行结果如下:
(六)匿名内部类:
public interface Inner {
public abstract void show();
}
/*本质:匿名内部类会隐式的继承一个类或者实现一个接口,或者说,
匿名内部类是一个继承了该类或者实现了该接口的子类匿名对象。
匿名内部类必须借助接口和父类
*/格式:new 类名/接口名/抽象类名(){}
class Outer5{
public void method(){
/*从以下程序可以看出,new后面就是接口名,本身接口是不可以new的,Inner后面又有花括号,有接口的方法重写,可见这里new的是接口实现类,
只是这个实现类在这里是没有名字的。所以是匿名内部类。
*/
new Inner(){
public void show(){
System.out.println("实现了函数式接口");
}
}.show();//类对象调用自己的方法
}
}
class Test5{
public static void main(String[] args) {
Outer5 O=new Outer5();
O.method();
}
}
运行结果如下:
(七)内部类的特点:
1、内部类仍然是一个独立的类,在编译之后内部类会编译成独立的.class文件,但是前面会冠以外部类的类名和$符号。 2、内部类不能以普通的方式访问。 3、内部类是外部类的一个成员,因此内部类可以自由的访问外部类成员变量。但是有两种内部类例外:静态内部类和局部内部类
六、lambda表达式的用法
import java.util.Comparator;
import java.util.function.Consumer;
public class Lambda {
/*1、lambda表达式是一个可传递的代码块,可以在以后执行一次或多次
2、lambda表达式形式:(参数)->表达式
3、可使用lambda表达式代替匿名内部类的代码.
*/
//语法格式1:无参数无返回值
public void lambdaTest(){
Runnable r1=new Runnable(){
@Override
public void run() {
System.out.println("这里是匿名内部类");
}
};
r1.run();
/*用lambda表达式代替
1、声明的变量不变:Runnable r1=
2、凡是确定了的都可以省略:匿名函数对象new Runnable()确定了的省略,这个函数式接口Runnable()只有一个run方法也是确定了的省略,只剩下
需要传递参数的();
*/
Runnable r2=()->{
System.out.println("这里是匿名内部类");
};
r2.run();
//语法格式2:有一个参数,无返回值
Consumer<String> con=new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
con.accept("这是一个函数式接口!");
//使用lambda表达式代替,传入方法的参数类型可以省略,只有一个参数时括号也可以省略,只有一条语句时,大括号可省略
Consumer<String> con2=s-> System.out.println(s);
//格式3:lambda表达式需要传入两个及以上的参数。
//未使用lambda表达式前:
Comparator<Integer> com1=new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
}
};
System.out.println(com1.compare(12,26));
//使用lambda表达式后:
Comparator<Integer> com2=(Integer o3, Integer o4)->{
System.out.println(o3);
System.out.println(o4);
return o3.compareTo(o4);
};
System.out.println(com1.compare(30,40));
}
}
class Test6{
public static void main(String[] args) {
Lambda l1=new Lambda();
l1.lambdaTest();
}
}
运行结果如下:
弄懂这些,lambda表达式也就差不多了。