栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java笔记(6) 接口,内部类,多态 ,lambda表达式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java笔记(6) 接口,内部类,多态 ,lambda表达式

1 接口

序言:我们还延续介绍是抽象类的时候所举的例子,我们知道继承抽象类的所有子类,需要将抽象类中的所有抽象方法进行重写,这样在多态的机制中,就可以将父类修改为抽象类,将draw()方法设置为抽象方法,然后每个子类都重写这个方法来处理。但这又会使代码变的冗余,同样这样的父类局限性很大,也许某个不需要draw()方法的子类也不得不重写draw()方法。如果将draw()方法放置在另一个类中,让那些需要draw()方法的类继承该类,不需要draw()方法的类继承图形类,又会产生新的问题:所有的子类都需要继承图形类,因为这些类是从图形类中导出的,同时某些类还需要draw()方法,而Java中规定类不能同时继承多个父类。为了应对这一个概念,接口的概念便出现了。

总纲: 我们可以把接口当成一种特殊的抽象类。

1.1 接口的组成
接口用关键字interface修饰
public interface 接口名 { }
类实现接口用implements表示
public class 类名 implements 接口名 { }
(1)注意事项:

★接口不能实例化,但我们可以创建接口的实现类对象使用。

★接口的子类:要么重写接口中的所有抽象方法,要么子类也是抽象类。

(2)接口的成员组成:
  • 成员变量:

只能是常量

默认修饰符:public static final

  • 构造方法:

没有,因为接口主要是扩展功能的,而没有具体存在的

  • 成员方法:

只能是抽象方法

默认修饰符:public abstract

(3)代码演示:
接口
public interface Inter {
    public static final int NUM = 10;

    public abstract void show();
}
实现类
class InterImpl implements Inter{

    public void method(){
        // NUM = 20;
        System.out.println(NUM);
    }

    public void show(){

    }
}
测试类
public class TestInterface {
    
    public static void main(String[] args) {
        System.out.println(Inter.NUM);
    }
  
}
1.2类和接口的关系

  • 类与类的关系

继承关系,只能单继承,但是可以多层继承

  • 类与接口的关系

实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口

  • 接口与接口的关系

继承关系,可以单继承,也可以多继承

1.3 接口中默认方法
  • 格式

public default 返回值类型 方法名(参数列表) { }

  • 作用

解决接口升级的问题

范例

public default void show3() { 
}

注意事项

  • 默认方法不是抽象方法,所以不强制被重写。但是可以被重写,重写的时候去掉default关键字

  • public可以省略,default不能省略

  • 如果实现了多个接口,多个接口中存在相同的方法声明,子类就必须对该方法进行重写

1.4接口中静态方法【应用】
  • 格式

public static 返回值类型 方法名(参数列表) { }

  • 范例
public static void show() {
}

注意事项

  • 静态方法只能通过接口名调用,不能通过实现类名或者对象名调用

  • public可以省略,static不能省略

1.5接口中私有方法
  • 私有方法产生原因

Java 9中新增了带方法体的私有方法,这其实在Java 8中就埋下了伏笔:Java 8允许在接口中定义带方法体的默认方法和静态方法。这样可能就会引发一个问题:当两个默认方法或者静态方法中包含一段相同的代码实现时,程序必然考虑将这段实现代码抽取成一个共性方法,而这个共性方法是不需要让别人使用的,因此用私有给隐藏起来,这就是Java 9增加私有方法的必然性

  • 定义格式
格式1:  private 返回值类型 方法名(参数列表) { 
        
        }

案例:  private void show() {  

        }

格式2:  private static 返回值类型 方法名(参数列表) {   

        }

案例:    private static void method() {  

          }
  • 注意事项

默认方法可以调用私有的静态方法和非静态方法

静态方法只能调用私有的静态方法

3.多态 3.1 多态的相关用法 (1)多态的好处与弊端

好处:提高程序的拓展性,定义方法的时候,使用父类型作为参数,在使用的时候,使用具体的子类型参数操作。

弊端:不能使用子类的特有成员。

(2)多态中的转型:

向上转型:当有子类对象赋值给父类应用时,便是向上转型。多态本身就是向上转型的过程。

向下转型:一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类引用转为子类引用,这个过程是向下转型。(注意前提是有向上转型的子类对象,如果是直接创建父类对象是无法向下转型的)。

为什么要有向下转型:

这是由于多态的弊端,通过向上转型不能使用子类的特有功能。

如果就想使用子类的特有功能,怎么做?

A:最原始的创建对象调用方法呗。(但是很多时候不合理。而且建了太多对象会占内存)

B: 把父类的引用强制转换为子类的引用。(向下转型)

(3)我们最好理解下这里的方法重写,以及继承的意义就会很好理解
public class fu {
    int age =42;
  public void teach(){
      System.out.println("我是一名教Java的老师");
  }
}

public class zi extends fu {
    int age =19;
    public void teach(){
        System.out.println("我也会教Java,我从我爸那学的");
    }
    public void student(){
        System.out.println("我还是一名学生");
    }
}

public class Test01 {
    public static void main(String[] args) {
        //向上转型  (只能调出子类的重写方法)
        fu f= new zi();
        f.teach();       //我也会教Java,我从我爸那学的
        System.out.println(f.age);    /
        swimming.swim();
    }
}
5 Lambda表达式

★函数式接口:仅包含一个抽象方法的接口。

★lambda表达式不能独立执行,因此必须实现函数式接口,并且会返回一个函数式接口的对象。

★lambda表达式的理解:

( ) -> {代码块}

这个方法 按照 这样的代码来执行

5.1 lambda表达式调用无参抽象方法

无参抽象方法在lambda表达式中使用“()”表示

//通过多态的形式
public interface Eatable {
    void eat();
}
public class EatableDemo {
    public static void main(String[] args) {
       useEatable(() -> {
            System.out.println("一天一苹果,医生远离我");
        });
    }
//lambda表达式不能独立执行,因此必须实现函数式接口,并且会返回一个函数式接口的对象(子类)。
    private static void useEatable(Eatable e) {
        e.eat();
    }
}
//***************************************************************
//通过创建对象的形式
public interface Eatable {
    void eat();
}
public class EatableDemo {
    public static void main(String[] args) {
     Eatable e =  () -> {
            System.out.println("一天一苹果,医生远离我");
        };
    }
    System.out.println(e.eat());
}
5.2 lambda表达式实现有参抽象方法
public interface Addable {
    int add(int x,int y);
}
public class AddableDemo {
    public static void main(String[] args) {
        useAddable((int x,int y) -> {
            return x + y;
        });
    }
    private static void useAddable(Addable a) {
        int sum = a.add(10, 20);
        System.out.println(sum);
    }
}
5.3 lambda表达式调用外部变量

(1)lambda表达式无法更改局部变量(注意局部变量的定义)

interface defin{
void method();
}
public class s2{
public static void main(String[] args) {
  int value =100;             //创建局部变量
  defin v=()->{                   
  int num =value -90;
  value =12;                 //更改局部变量,报错
  };
}
}

(2)lambda 表达式可以更改类成员变量

interface  face2{
    void method();
}
public class Server {
 int value =100;
 public void action(){
     face2 v =()->{
         value =-12;
     };
     System.out.println("运行前"+value);  //100
     v.method();
     System.out.println("运行后"+value);  //-12
 }

    public static void main(String[] args) {
        Server d =new Server();
        d.action();
    }
}

总结:

lambda表达式只是描述了函数式接口的抽象方法是如何实现的,在抽象方法没有调用前,lambda表达式中的代码并没有被执行

5.4 lambda表达式和匿名内部类的区别
  • 所需类型不同
    • 匿名内部类:可以是接口,也可以是抽象类,还可以是具体类
  • Lambda表达式:只能是接口
  • 使用限制不同
    • 如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类
  • 如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式
  • 实现原理不同
    • 匿名内部类:编译之后,产生一个单独的.class字节码文件
  • Lambda表达式:编译之后,没有一个单独的.class字节码文件。对应的字节码会在运行的时候动态生成
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/831755.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号