Java基础知识每日总结(10)---Java接口、lambda表达式和内部类

接口、lambda表达式和内部类

1.简介
接口主要用来描述类具有什么功能,而并不给出每个功能的具体实现。
lambda表达式是一种表示可以在将来某个时间点执行的代码块的简洁方法。
内部类定义在另外一个类的内部,其中的方法可以访问包含它们的外部类的域。

2.接口
在Java中,接口不是类,而是对类的一组需求描述,这些类要遵从接口描述的统一格式进行定义。接口中的所有方法都自动地被public修饰,所以在接口中声明方法时,不用写出关键字public。要将类声明为实现某个接口,需要使用关键字implements,语法:class 类名 implements 接口名
注:在接口中的方法都自动为public所以不用指明,但在接口的实现中,必须把方法声明为public。
接口不是类,不能使用new实例化一个接口,但能声明接口类型的变量,且接口变量必须引用实现了接口的类对象。instanceof可以检测一个对象是否属于一个类,也可以检测一个对象是否实现了某个接口。一个接口可以继承另一个接口,接口中可以包含常量,但不能包含实例域或静态方法,接口中的域被自动设定为public static final。
虽然每个类都只能拥有一个父类,但却能实现多个接口,使用逗号将实现的各个接口分隔开。

在Java SE8及以上可以在接口中增加静态方法。
回调是一种常见的程序设计模式,它可以指出某个特定事件发生时应该采取的动作。

3.lambda表达式(闭包)
lambda表达式是一个可传递的代码块,可以在以后执行一次或多次。在数学中,带参数变量的表达式被称为lambda表达式。Java中的一种lambda表达式形式:参数、箭头(–>)和一个表达式,如果代码要完成的计算无法放在一个表达式中,就可以把它们放在{}中,并包含显示的return语句。例,

Arrays.sort(planets, (first,second)-> first.length()-second.length());

即使lambda表达式没有参数,也要提供空括号,就像无参方法一样。如果可以推导出参数的类型就可以在括号内忽略其类型。不需要指出lambda表达式的返回类型。
注:如果lambda表达式在某些分支有返回值,在另外的分支没有返回值,这是不合法的。
lambda表达式可以转换为接口(函数式接口)。

Timer t=new Timer(1000, System.out::println);

在上面的例子中,System.out::println是一个方法引用,它等价于lambda表达式:x ->System.out.println(x)。用::操作符分隔方法名与对象或类名,主要有3种情况:

  • object::instanceMethod
  • Class::staticMethod
  • Class::instanceMethod
    前两种情况方法引用等价于提供方法参数的lambda表达式,对第三种情况第一个参数会成为方法的目标。
    可以在方法引用中使用this参数,也可以使用super。
    使用lambda表达式的重点是延迟执行。常用的函数式接口:
    Java基础知识每日总结(10)---Java接口、lambda表达式和内部类_第1张图片
    基本数据类型的函数式接口:
    Java基础知识每日总结(10)---Java接口、lambda表达式和内部类_第2张图片

4.内部类
内部类是定义在另一个类中的类。内部类可分为成员内部类、局部内部类以及匿名类等。使用内部类的好处:

  • 内部类的方法能够访问所在类的所有数据,包括私有数据;
  • 内部类可以对同一个包中的其他类隐藏起来

①成员内部类
在一个类的内部直接定义的类,称为成员内部类,语法格式:

public class OuterClass{
     
     class InnerClass{
     
     }
}

内部类的实例一定要绑定在外部类的实例上。如果从外部类中初始化一个内部类对象,那么内部类对象就会绑定在外部类对象上。内部类的对象实例化操作必须在外部类或外部类中的非静态方法中实现。
在main()方法中或者其他类中实例化本实例的内部类对象,如果不使用方法返回内部类对象引用,必须在new操作符之前提供一个外部类的引用,例,

public static void main(String[] args){
     
   OuterClass out=new OuterClass();
   OuterClass.innerClass in=out.doit();   //doit方法会返回一个内部类的对象引用
   OuterClass.innerClass in2=out.new innerClass();  //实例化内部类对象

在实例化内部类对象时,不能在new操作符之前使用外部类名称的形式进行实例化内部类对象,而是应该使用外部类的对象来创建其内部类的对象。
注:内部类对象会依赖于外部类对象,除非已经存在一个外部类对象,否则不能创建内部类对象。
如果在外部类中定义的成员变量与内部类的成员变量名称相同,可以使用this关键字。表达式OuterClass.this表示外部类的引用。
内部类中声明的所有静态域都必须是final,且不能有static方法(但并不强制)。如果有静态方法则只能访问外部类的静态域和方法。
②局部内部类
在类的局部位置定义的类称为局部内部类,例如在方法中定义的类,此时,内部类是方法的一部分,并非外部类中一部分,所以在方法的外部不能访问该内部类,但是该内部类可以访问当前代码块的常量,以及此外部类的所有成员。
在方法中定义的内部类只能访问方法中的final类型的局部变量,这是因为在方法中定义的局部变量相当于一个常量,它的生命周期超出方法运行的生命周期,由于该局部变量被设置为final,所以不能在内部类中改变该局部变量的值。
局部内部类不能用public或private访问说明符进行声明,它的作用域被限定在声明这个局部类的块中。局部类对外部世界可以完全地隐藏起来。
③匿名内部类
在创建内部类时,如果并没有指定内部类的名称,则称其为匿名内部类。比较常见的应用是Swing的中事件监听器。这种内部类的宗旨就是创建一个实现外部类接口的匿名类的对象。
在匿名内部类定义结束后,需要加分号标识。
④静态内部类
使用static关键字修饰的内部类称为静态内部类。静态内部类拥有一个最大的特点就是不可以使用外部类的非静态成员。
静态内部类的特点:

  • 如果创建静态内部类的对象,不需要外部类对象的引用
  • 不能从静态内部类的对象中访问非静态外部类的对象

你可能感兴趣的:(CoreJava,java)