zoukankan      html  css  js  c++  java
  • Java 内部类、Lambda表达式

    外部类、接口只能使用public、abstract、final修饰,不能使用private、protected、static修饰,就是说外部类、接口的访问权限只能是默认、public。

    局部变量不能使用static修饰,但可以使用final修饰。

    内部类提供了更好的封装,可以把内部类隐藏在外部类之内。


    普通内部类

    修饰符 class Outer{
      修饰符 class Inner{
        .......
      }
    }
    普通内部类相当于外部类的一个成员,可以使用任何修饰成员的修饰符。内部类中可以有构造函数、初始化块、成员变量、成员方法。

    内部类内(内部类成员级、内部类方法体中均)可以直接访问外部类的成员。

    在外部类中访问内部类的成员:
    外部类的成员方法中不能直接访问内部类中的成员,需要new Inner()创建内部类对象,再通过内部类对象访问内部类的成员。

    在外部类外访问内部类的成员:
    外部类类名.内部类名  变量名=外部类实例对象.new   内部类(参数表); //需要先创建内部类实例,再通过内部类实例访问内部类的成员
    外部类类名.内部类名  变量名=new  外部类(参数表) .new 内部类(参数表); //内部类是public、要访问的内部类成员时public才可以访问
    内部类的完整类名是:外部类类名.内部类类名,有时候还需要加前缀包名。


    会编译为两个.class文件,内部类一个,外部类一个。
    创建外部类对象时,在heap中会有两个对象,一个外部类的,一个内部类的,二者分开存储,但内部类中保存了对应的外部类的引用。

    当外部类成员、内部类成员、内部内的局部变量同名时,在内部类的方法体中:
    this 表示当前内部类对象
    外部类类名.this 表示当前外部类对象


    静态内部类

    修饰符 class Outer{
      static class Inner{
      .......
      }
    }
    该内部类属于外部类本身,不属于外部类的任何一个实例。静态内部类也是外部类的一个成员。
    静态内部类中可以包含静态成员,也可以包含普通成员。static只是表示此内部类是外部类的类成员,并不是说此内部类只能包含静态成员。
    静态内部类中只能访问外部类的静态成员,不能访问外部内的非静态成员,但可以访问内部类自身的所有成员。

    在外部类中访问内部类的成员:
    需要先 new 内部类类名(参数表) 创建内部类对象,再通过该对象来访问。
    内部类的静态成员可通过内部类类名直接访问。

    在外部类外访问内部类的成员:
    外部类.内部类 变量名=new 外部类.内部类(参数表); //通过外部类类名直接调用内部类的构造函数(内部类使用static修饰),参数表是内部类构造函数的参数表
    内部类的静态成员可直接通过 外部类类名.内部类类名.静态成员 调用。
    外部类.内部类 也是一种数据类型,表示内部类。


    局部内部类

    定义在方法体中的内部类,和局部变量一个级别。

    局部变量不能使用任何访问权限、static修饰,但可以使用final来修饰,所以局部内部类也不能使用这些来修饰,但局部内部类可以使用final来修饰。

    局部内部类中的成员,和正常的成员一样,可以使用一切修饰符。

    局部内部类的上一级程序单元是所在方法,不是类。

    在局部内部类中,只能访问所在方法体中的局部变量(只能在成员一级访问,比如用来给内部类的成员变量赋值,不能在内部类的方法中访问),不能访问外部类的成员。


    匿名内部类

    new 接口名|父类构造器(实参表){
    ........
    }
    匿名内部类没有类名,只能使用一次。会在定义处创建该类的一个实例。
    实质还是定义一个类,要实现一个接口,或继承+重写一个父类。但最多只能实现一个接口,或继承+重写一个父类。
    因为没有类名,所以没有构造函数,但可以有初始化块。

    如果匿名内部类是外部类的成员级,则内部类中可以访问外部类的成员,比如:
    private ActionListener al=new ActionListener{
    .............
    }

    如果匿名内部类是局部变量级的,则匿名内部类中不能访问外部内的成员,比如:
    public void xxx(){
      ........
      btn.addActionListener(new ActionListener{
      .......
      });
    }


    注意:

    外部类成员级的内部类,在内部类的成员级、方法体内均可直接访问外部类的成员。

    局部变量级的内部类,只能在内部类的成员级访问外部类的成员,在内部类的方法体内不能访问外部类的成员。


    Lambda表达式

    函数式接口:

    只包含一个抽象方法的接口。函数式接口可以包含多个默认方法、类方法,但只能包括一个抽象方法。

    Java8提供了@FunctionalInterface注解,该注解放在接口定义前面,表示该接口是函数式接口,编译时会检查该接口是否符合函数式接口的要求。

    Lambda表达式可以实现函数式接口,并在实现处创建一个对象,和匿名内部类相似。

    区别:匿名内部类可以实现任何接口、抽象类,但Lambda表达式只能实现函数式接口。Lambda表达式相当于一种特殊的匿名内部类,但Lambda表达式比匿名内部类更加简洁。

    Lambda表达式只是语法糖,编译时会被替换为常规的代码。

    Lambda表达式语法:

    (形参表) -> {

      .......//抽象方法的实现部分

    }

    无形参时,写为();只有一个形参时,可以缺省()。

    代码块中只有一条语句时,可以缺省{};代码块中只有一条return语句时,可以缺省{}和return关键字(要缺省,必须同时缺省return关键字和{})。

    参数表只写形参变量名,不写形参类型。

    示例:

     1 package test;
     2 
     3 interface  Interface1{
     4     //无形参、无返回值
     5     void print();
     6 }
     7 
     8 interface Interface2{
     9     //有形参
    10     void print(String str);
    11 }
    12 
    13 interface Interface3 {
    14     //有返回值
    15     String getString();
    16 }
    17 
    18 public class Test {
    19     public static void main(String[] args) {
    20         Interface1 interface1=()->{
    21             System.out.println("接口1 ok");
    22         };
    23         interface1.print();
    24 
    25         //只有一个形参时,可以缺省();代码块只有一条语句时,可以缺省{}
    26         Interface2 interface2=str-> System.out.println(str);
    27         interface2.print("接口2 ok");
    28 
    29         //方法体中只有一条return语句时,可以同时缺省{}和return关键字,要缺省就必须同时缺省这两部分
    30         Interface3 interface3=()-> "接口3 ok";
    31         String str=interface3.getString();
    32         System.out.println(str);
    33     }
    34 }

    Lambda表达式会在该处创建一个该接口的示例,并返回这个实例,即Lambda表达式的值是对应接口的实例。

    可以将Lambda表达式作为实参传递给方法:

     1 package test;
     2 
     3 interface Interface3 {
     4     //有返回值
     5     String getString();
     6 }
     7 
     8 public class Test {
     9     public static void main(String[] args) {
    10         //可以将Lambda表达式作为实参传递给方法。Lambda表达式的值是对应接口的实例,并不是所实现抽象方法的返回值String。Lambda表达式比匿名内部类更简洁。
    11         printStr(()->"ok");
    12     }
    13 
    14     public static void printStr(Interface3 interface3){
    15         System.out.println(interface3.getString());
    16     }
    17 }

    Java中的很多接口都是函数式接口,比如ActionListener接口、Runnable接口。

    Lambda表达式可访问的变量和匿名内部类可访问的变量完全一致,但Lambda表达式不能调用接口中定义的默认方法,匿名内部类则可以。

  • 相关阅读:
    IntelliJ IDEA 2017 反向代理工具新方法激活
    如何去掉idea里mybatis的.xml文件 sql 语句背景色
    eclipse、idea切换大小写的快捷键
    pageHelper没有分页效果的问题
    springboot使用thymeleaf 解析异常
    SpringBoot发送简单文本邮件
    IDEA中使用git详细步骤
    解决 git branch -a 无法全部显示远程的分支,只显示master分支
    git常用命令
    异常处理
  • 原文地址:https://www.cnblogs.com/chy18883701161/p/10852628.html
Copyright © 2011-2022 走看看