美文网首页Java练级
对于内部类和Lambda的理解

对于内部类和Lambda的理解

作者: 拜仁的月饼 | 来源:发表于2019-11-26 17:41 被阅读0次

1. 内部类

如何理解内部类呢?

1.1 内部类的定义及使用方法

内部类的定义及使用

使用:"类中类",类的嵌套。

例:
包:com.TestInnerClass

文件1: innerClass.java

package com.TestInnerClass;

public class innerClass {
    private Contents c;
    private Desti d;

    public innerClass(){} // 一个空的初始化方法

    class Contents{ // 内部类Contents
        private int value;
        public Contents(int value){
            this.value = value;
        }
        public int getValue(){
            return value;
        }
    }

    class Desti{ // 内部类Desti
        private String whereTo;
        public Desti(String whereTo){
            this.whereTo = whereTo;
        }
    }
}

文件2: Test.java

package com.TestInnerClass;

public class Test {
    public static void main(String[] args) {
        innerClass p = new innerClass();

        // 内部类调用方法:
        // 外部类名.内部类名 变量名 = 已经实例化的外部类.new 内部类名(参数);
        innerClass.Contents c = p.new Contents(33);
        innerClass.Desti d = p.new Desti("Tianjin");
    }
}

1.2 如何在内部类中使用外部类成员?

这个问题值得一说。

在内部类中如何使用外部类的成员

规则如下:

  • 内部类可以直接访问外部类的字段及方法
  • 如果内部类有和外部类同名的字段和方法,则:
    • 外部类名.this.字段及方法

例:
IC2.java

package com.TestInnerClass;

public class IC2 {
    private int s = 111;

    public class IIC{ // 内部类IIC
        private int s = 222;
        public void mb(int s){
            System.out.println(s); // 形参
            System.out.println(this.s); // 内部类的s
            System.out.println(IC2.this.s); // 外部类的s
        }
    }
}

Test.java

package com.TestInnerClass;

public class Test {
    public static void main(String[] args) {
        IC2 run = new IC2();

        IC2.IIC tst = run.new IIC();

        tst.mb(2);
    }
}

1.3 内部类的修饰符

内部类也可以使用修饰符如下:

  • static
  • protected
  • private
  • default (默认,一般不写)
  • final
  • abstract

注:外部类只能用public及默认(default)来修饰

例: static

static的使用方法

根据上图的PPT,我们可知:一旦内部类用static修饰之后便与外部类的实例无关了,可以认为成转换为实质上的外部类

访问规则只需要记得两点:

  1. static内部类在使用时不需要预先初始化一个外部类;
  2. static内部类只能访问static字段及方法。

1.4 局部类

定义:方法中的内部类,即“方法中的类”。

可以访问外部类的成员,但不能访问内部类中的成员,除非被final修饰。

1.5 匿名类

一次性使用的类。

例:
MetCls.java

package com.TestInnerClass;

public class MetCls {
    private int sz = 5;

    public Object makeTheInner(int v){
        final int fl = 99;
        return new Object(){
            final int finalLocalVar = 100;
            @Override
            public String toString(){
                return ("InnerSize= " + sz + " FinalLocalVar =" + finalLocalVar);
            }
        };
    }
}

Test.java

package com.TestInnerClass;

public class Test {
    public static void main(String[] args) {
        MetCls ms = new MetCls();

        var k = ms.makeTheInner(8);

        System.out.println(k);
    }
}

2. Lambda表达式

当被问及Java 8新特性时,Lambda表达式应该属于其中之一。

Lambda表达式在其他语言中(尤其是Python)也叫匿名函数,及即没有具体名称的函数,它允许快速定义单行函数。

在Java中,例如Arrays.sort()方法中,除了数组参数,还可以传入一个方法(method)参数来指定排序方法。这个方法参数就可以快速地用lambda表达式来做。

然而,对于Java这样的完全意义上的面向对象语言(一切皆对象)要如何实现呢?

2.1 实现方法

Lambda表达式

有如下两种方法:

  • (parameters) -> {a method};,即在小括号中写明需要的参数,在花括号中写明实现方法。参数的类型可写可不写,因为编译器可以自动推断。
  • () -> {method;},在无参数时可以这样写,只是单纯实现一个方法 。

例:

package com.lambda;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;

/**
 * This programme demonstrates the use of lambda expressions.
 * @version 1.0 2019-11-27
 * @author Allen Bayern
 * */

public class LambdaTestf {
    public static void main(String[] args) {
        String[] planets = new String[]{"Mercury", "Venus", "Earth", "Mars", "Jupyter", "Saturn", "Uranus", "Neptune"};
        System.out.println(Arrays.toString(planets));
        System.out.println("Sorted in dictionary order:");
        Arrays.sort(planets);
        System.out.println(Arrays.toString(planets));
        System.out.println("Sorted by length:");
        // Lambda below:
        Arrays.sort(planets, (first, second) -> first.length() - second.length());
        System.out.println(Arrays.toString(planets));

        Timer timer = new Timer(1000, (event) -> System.out.println("The time is" + new Date()));
        timer.start();

        // keep programme running until user selects "OK".
        JOptionPane.showMessageDialog( null, "Quit Programme?" );
        System.exit(0);
    }
}

2.2 函数式接口

那么什么样的方法可以被写成Lambda表达式呢?通常只有一个抽象方法的接口更易实现为Lambda表达式。

Lambda的实质

从上图可看出,Lambda函数的实质是接口函数的简写,即不单独占用一行来实现接口,而是放到传参里直接实现。

函数式接口

能写成Lambda函数的接口只能有一个,且至多一个抽象方法。最好在前面加上@FunctionalInterface注解。例如:
@FunctionalInterface
interface Fun{ double fun(double x); }

2.3 举例:Comparator接口

这是一个系统自带的单方法接口,所以可以写成Lambda表达式。上例代码中就用到了该接口。

源码如下:

public interface Comparator<T>{
  int copare(T first, T second);
}

回到上面的代码,我们发现了这么一行:

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

如果不用Lambda表达式的话,我们要这样写:

// 下面的代码与上面的Lambda形式等效
class LenComparator implements Comparator<String>{
  public int compare(String first, String second){
    return (first.length() - second.length());
  }
}

Arrays.sort(planets, new LenComparator());

这样一看,是不是Lambda简洁了许多?

相关文章

  • 对于内部类和Lambda的理解

    1. 内部类 如何理解内部类呢? 1.1 内部类的定义及使用方法 使用:"类中类",类的嵌套。 例:包:com.T...

  • 《深入理解Java函数式编程》系列文章

    《深入理解Java函数式编程》系列文章 目录 Lambda表达式和匿名内部类(I),展示如何使用Lambda表达式...

  • 2020-07-04【Lambda】

    Lambda标准格式 Lambda省略模式 Lambda注意事项 Lambda表达式和匿名内部类的区别

  • Kotlin之Lambda表达式和成员引用

    Lambda介绍:作为函数参数的代码块 用匿名内部类实现监听器 现在用Kotlin的Lambda表达式来替换匿名内...

  • Android Java8新特性之Lambda表达式详解

    1、Lambda 表达式是使用内部类来实现的? Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一...

  • 内部类

    成员内部类 局部内部类(定义在方法内和定义在作用域内的类) 匿名内部类

  • Lambda表达式-03-02

    外部类实现线程接口: 内部类实现线程接口: 匿名内部类: jdk8的Lambda表达式:

  • Lambda表达式和匿名内部类-001

    前言 Java Lambda表达式是匿名内部类的语法糖,它可以简化和取代匿名内部类,JVM内部是通过invoked...

  • Java 内部类

    内部类包括成员内部类、方法内部类、*静态内部类、匿名内部类*。 内部类的作用 由于内部类的实现和外部类没有关系,内...

  • Lambda表达式

    本章节主要介绍lambda表达式简化匿名内部类的写法,但lambda表达式不能取代所有的匿名内部类,只能用来取代函...

网友评论

    本文标题:对于内部类和Lambda的理解

    本文链接:https://www.haomeiwen.com/subject/weijwctx.html