Java学习Day04------内部类和Lambda表达式

内部类

1、概念
  在一个类中 定义一个类
2、访问特点
  内部类可以直接访问外部类成员,包括私有的
  外部类要访问内部类的成员,必须要创建对象
3、定义位置:
  局部内部类:位于局部位置(也就是成员方法内部)
  成员内部类:位于成员位置,也就是跟成员变量一个位置
    格式: 外部类名.内部类名 对象名 = 外部类对象.内部类对象;
4、定义格式

public class Outer {
    class Inner {
    }
}

4、创建内部类对象的格式
  外部类名.内部类名 对象名 = new 外部类名().new 内部类名();

私有成员内部类

1、定义格式

public class Outer {
    private class Inner {
    }
}

2、访问
  在自己所在的外部类中创建对象进行访问

静态成员内部类

1、定义格式

public class Outer {
    static class Inner {
    }
}

2、访问格式
  外部类名.内部类名 对象名 = new 外部类.内部类();

局部内部类

1、定义位置
  方法中定义的类
2、访问方式特点
  (1)外界无法直接使用,需要方法内部创建对象并使用
  (2)可以直接访问外部类的成员,也可以访问方法内的局部变量
  示例

class Outer {
    private int num = 10;
    public void method() {
        int num2 = 20;
        class Inner {
            public void show() {
                System.out.println(num);
                System.out.println(num2);
            }
        }
        Inner i = new Inner();
        i.show();
    }
}
public class OuterDemo {
    public static void main(String[] args) {
        Outer o = new Outer();
        o.method();
    }
}

匿名内部类

1、使用前提
  存在一个类或者接口,这里的类可以是具体类也可以是抽象类
2、格式
  new 类名(){ 重写方法}
  new 接口名(){ 重写方法}

// Inter是一个接口
new Inter() {
    @Override
    public void method(){
    }
}

3、本质
  是一个继承了该类或者实现了该接口的子类匿名对象
4、匿名内部类可以通过多态的形式接受

Inter i = new Inter(){
  @Override
    public void method(){
    }
}

5、匿名内部类可以直接调用方法

interface Inter{
    void method();
}
class Test{
    public static void main(String[] args){
        new Inter(){
            @Override
            public void method(){
                System.out.println("我是匿名内部类");
            }
        }.method();    // 直接调用方法
    }
}

Lambda表达式

1、组成三要素
  形式参数  箭头  代码块
  示例:(形式参数) -> { 代码块 }
  形式参数:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可
  ->:由英文中画线和大于符号组成,固定写法。代表指向动作
  代码块:是我们具体要做的事情,也就是以前我们写的方法体内容
2、使用前提
  (1)必须是接口所对应的匿名内部类
  (2)接口必须只有一个抽象方法,也就是必须是函数式接口,如果要省略大括号,那么抽象方法的实现只有一句话(如果一个接口里面只有一个抽象方法,就叫做函数式接口)
  示例:

public interface Inter {
    void show();
}
public class Test {
    public static void main(String[] args) {
        Inter inter = new Inter() {
            @Override
            public void show() {
                System.out.println("匿名类");
            }
        };
        inter.show();
        // 使用lambda表达式,代码块有多行代码
        Inter inter1 =() -> {
            System.out.println("匿名类");
            System.out.println("匿名类");
        };
        inter1.show();
        // 使用lambda表达式,代码块只有一行代码
        Inter inter2 =() -> System.out.println("匿名类");
        inter2.show();
}

3、使用
  (1)无参无返回值
    ()->{ 重写方法代码 }
    案例:

//接口
public interface Eatable {
    void eat();
}
//实现类
public class EatableImpl implements Eatable {
    @Override
    public void eat() {
        System.out.println("一天一苹果,医生远离我");
    }
}
//测试类
public class EatableDemo {
    public static void main(String[] args) {
        //在主方法中调用useEatable方法
        Eatable e = new EatableImpl();
        useEatable(e);
        //匿名内部类
        useEatable(new Eatable() {
            @Override
            public void eat() {
                System.out.println("一天一苹果,医生远离我");
            }
        });
        //Lambda表达式
        useEatable(() -> {
            System.out.println("一天一苹果,医生远离我");
        });
    }
    private static void useEatable(Eatable e) {
        e.eat();
    }
}

  (2)有参无返回值
    (参数列表)->{ 重写方法代码 }
    案例:

public interface Flyable {
    void fly(String s);
}
public class FlyableDemo {
    public static void main(String[] args) {
        //在主方法中调用useFlyable方法
        //匿名内部类
        useFlyable(new Flyable() {
            @Override
            public void fly(String s) {
                System.out.println(s);
                System.out.println("飞机自驾游");
            }
        });
        System.out.println("--------");
        //Lambda
        useFlyable((String s) -> {
            System.out.println(s);
            System.out.println("飞机自驾游");
        });
    }
    private static void useFlyable(Flyable f) {
        f.fly("风和日丽,晴空万里");
    }
}

  (3)无参有返回值
    ()->{ 重写方法代码,带return语句 }
  (4)有参有返回值
    (参数列表)->{ 重写方法代码,带return语句 }
    案例:

public interface Addable {
    int add(int x,int y);
}
public class AddableDemo {
    public static void main(String[] args) {
        //在主方法中调用useAddable方法
        useAddable((int x,int y) -> {
            return x + y;
        });
    }
    private static void useAddable(Addable a) {
        int sum = a.add(10, 20);
        System.out.println(sum);
    }
}

4、表达式省略模式
  (1)参数的类型可以省略。但是参数列表里面是多个参数,那么不能只省略一个,要么所有参数类型都省略,要么都不省略(例如:(a,b)->{重写代码})
  (2)如果只有一个参数,那么小括号也可以省略(例如:a->{重写代码})
  (3)如果代码块的语句只有一条,那么可以省略左边的大括号和分号以及return关键字(例如:(a,b)-> a+b)
  案例:

public interface Addable {
    int add(int x, int y);
}
public interface Flyable {
    void fly(String s);
}
public class LambdaDemo {
    public static void main(String[] args) {
//        useAddable((int x,int y) -> {
//            return x + y;
//        });
        //参数的类型可以省略
        useAddable((x, y) -> {
            return x + y;
        });
//        useFlyable((String s) -> {
//            System.out.println(s);
//        });
        //如果参数有且仅有一个,那么小括号可以省略
//        useFlyable(s -> {
//            System.out.println(s);
//        });
        //如果代码块的语句只有一条,可以省略大括号和分号
        useFlyable(s -> System.out.println(s));
        //如果代码块的语句只有一条,可以省略大括号和分号,如果有return,return也要省略掉
        useAddable((x, y) -> x + y);
    }
    private static void useFlyable(Flyable f) {
        f.fly("风和日丽,晴空万里");
    }
    private static void useAddable(Addable a) {
        int sum = a.add(10, 20);
        System.out.println(sum);
    }
}

5、Lambda表达式和匿名内部类的区别
  (1)、 所需类型不同
    匿名内部类:可以是接口,也可以是抽象类,还可以是具体类
    Lambda表达式:只能是接口
  (2)、 使用限制不同
    如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类
    如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式
  (3)、 实现原理不同
    匿名内部类:编译之后,产生一个单独的.class字节码文件
    Lambda表达式:编译之后,没有一个单独的.class字节码文件。对应的字节码会在运行的时候动态生成

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值