嵌套类(Nested Classes),简单来说就是:在一个类中定义另一个类,那么在类内被定义的那个类就是嵌套类,最外层的类一般称为封闭类(Enclosing Class)。嵌套类主要分为两种:静态嵌套类和非静态嵌套类,而非静态嵌套类又称为内部类(Inner Classes)。
// 封闭类 class OuterClass { ... // 静态嵌套类 static class StaticNestedClass { ... } // 内部类 class InnerClass { ... } }静态嵌套类可以直接使用封闭的类名称去访问例如:OuterClass.StaticNestedClass x = new OuterClass.StaticNestedClass();,这种使用形式和一般类实例化基本没有区别。
内部类实例的存在必须依赖于封闭类实例的存在,并且内部类可以直接访问封闭类的任意属性和方法,简单来说就是内部类的实例化必须在封闭类实例化之后,并且依赖于封闭类的实例,声明的语法有点奇特:
public class OuterClass { int x = 1; static class StaticNestedClass { } class InnerClass { // 内部类可以访问封闭类的属性 int y = x; } public static void main(String[] args) throws Exception { OuterClass outerClass = new OuterClass(); // 必须这样实例化内部类 - 声明的语法相对奇特 OuterClass.InnerClass innerClass = outerClass.new InnerClass(); // 静态嵌套类可以一般实例化,形式为:封闭类.静态嵌套类 OuterClass.StaticNestedClass staticNestedClass = new OuterClass.StaticNestedClass(); // 如果main方法在封闭类内,可以直接使用静态嵌套类进行实例化 StaticNestedClass x = new StaticNestedClass(); } }内部类中有两种特殊的类型:本地类(Local Classes)和匿名类(Anonymous Classes)。
本地类是一种声明在任意块(block)的类,例如声明在代码块、静态代码块、实例方法或者静态方法中,它可以访问封闭类的所有成员属性和方法,它的作用域就是块内,不能在块外使用。例如:
public class OuterClass { static int y = 1; { // 本地类A class A{ int z = y; } A a = new A(); } static { // 本地类B class B{ int z = y; } B b = new B(); } private void method(){ // 本地类C class C{ int z = y; } C c = new C(); } }匿名类可以让代码更加简明,允许使用者在定义类的同时予以实现,匿名类和其他内部类不同的地方是:它是一种表达式,而不是类声明。例如:
public class OuterClass { interface In { void method(String value); } public void sayHello(){ // 本地类 - 类声明 class LocalClass{ } // 匿名类 - 是一个表达式 In in = new In() { @Override public void method(String value) { } }; } }如果用Java做过GUI开发,匿名类在Swing或者JavaFx的事件回调中大量使用,经常会看到类似这样的代码:
JButton button = new JButton(); button.addActionListener(new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { System.out.println("按钮事件被触发..."); } });嵌套类的类型关系图如下:
Nested Classes - Static Nested Classes - None Nested Classes - Local Classes - Anonymous Classes - Other Inner Classes Lambda表达式下面是来自某搜索引擎百科关于Lambda表达式的定义:
Lambda表达式(Lambda Expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的Lambda抽象(Lambda Abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。
Java中的Lambda表达式(下面称Lambda)表面上和上面的定义类似,本质也是匿名函数,但其实现原理区别于一般的匿名类中的匿名函数实现,她是JDK8引入的一颗新的语法糖。
引入Lambda表达式的初衷如果一个接口只包含一个方法,那么匿名类的语法会变得十分笨拙和不清楚,产生大量的模板代码,归结一下就是:代码冗余是匿名类的最大弊端。在编程的时候,我们很多时候希望把功能作为参数传递到另一个方法,Lambda就是为此而生,Lambda允许使用者将功能视为方法参数,将代码视为数据。引入Lambda带来了如下优势:
简化代码,引入了强大的类型推断和方法引用特性,简单的功能甚至可以一行代码解决,解放匿名类的束缚。
把功能作为参数向下传递,为函数式编程提供了支持。
至此还得出一个结论:Lambda只适用于函数式接口对应唯一抽象方法的实现。
Lambda表达式的语法定义Lambda语法的详细定义如下:
// en_US InterfaceType interfaceObject = [Method Argument List] -> Method Body // zh_CN 接口类型 接口实例 = [方法参数列表] -> 方法体更具体的描述应该是: