java基础知识--类和接口

  普通类和抽象类

  类:是一组相关属性和行为的集合。(内部封装了成员变量、构造方法、成员方法)

    对象:是一类事物的具体体现。对象是类的实例,必然具备该类事物的属性和行为。

  类和对象的关系:类是对象的抽象,对象是类的实体。

  构造方法<作用>:初始化成员变量。

 

  普通类:没有被abstract修饰,没有抽象方法的类。

  抽象类:被abstract修饰,可能含有抽象方法的类。

  两者的区别:

      ① 含有抽象方法的类,一定是抽象类;

      ② 抽象类有构造器,但不能被实例化;(因为抽象方法没有方法体,不需要实现。)

      ③ 抽象类被abstract修饰,而普通类没有;

      ④ 抽象类的子类,必须重写父类中的所有抽象方法。除非子类也是抽象类。

 抽象类的好处:我们设计抽象类,是为了更好的去支持多态。

 抽象的应用:模板方法设计模式(①解决方法中存在重复代码的问题。②使用final关键字修饰,以免被子类重写,失去模板意义。)。

 

  内部类:将一个类A定义在类B或者方法C里面,类A即为内部类。在JDK16之前的版本,内部类中不能定义静态成员。

内部类获取外部类对象:外部类.this

    作用:①方便代码编写  ②使得多继承机制变得更加完善  ③省去实现类的定义

    补充:内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号。比如,Person$Heart.class(内部类编译文件)

  成员内部类:定义在类中、方法外的类。

    格式如下

1
2
3
4
5
class 外部类 {
    class 内部类 {
        //
    
}

    访问特点

  •  内部类可以直接访问外部类的成员,包括私有成员和静态成员。
  •  外部类要访问内部类的成员,必须要建立内部类的对象。(创建成员内部类对象格式:外部类名.内部类名 对象名= new 外部类型().new 内部类型();
  •  当成员内部类拥有和外部类同名的成员变量和方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员,如果想访问外部类的成员,则需要以下形式进行访问:
            • 外部类.this.成员变量/成员方法

  局部内部类:定义在方法中、代码块中、构造器等执行体中的类。

    鸡肋语法,了解即可。

  静态内部类:也是定义在一个类里面的类,用static修饰,不需要依赖于外部类,并且不能使用外部类的非static成员访问,因为外部类的非static成员必须依附于具体的对象。

         创建静态内部类对象格式:外部类名.内部类名 对象名= new 外部类名.内部类名();

  匿名内部类:没有名字的内部类,是内部类的简化写法,是唯一一种没有构造器的类

    匿名内部类本质就是一个子类,写出来就会产生一个匿名内部类的对象(子类对象)。(匿名内部类对象类型相当于是new Xxx的子类类型)

    实现前提:必须继承一个父类或者实现了一个父接口。

    作用:方便创建子类对象,最终目的为了简化代码编写。

    使用场景:通常作为一个方法的传参。

    格式:

1
2
3
4
5
6
7
8
// 把这个匿名内部类编译成一个子类,然后会立即创建一个子类对象。
new 父类名或者接口名(...) {
  //方法重写
  @override
  public void method( ) {
        //执行语句
  }
}

    举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 抽象类
public abstract class FlyAble{
    public abstract void fly();
}
 
//demo
public class demo {
    public static void main( string[]args) {
      /*
      *    创建匿名内部类,直接传递给showFly(FlyAble f)
      */
      showFly(  
          new FlyAble(){
              public void fly() {
                  system.out.println("我飞了~~~" );
              }
          }
      );
 
      public static void showFly(FlyAble f) {
          f.fly();
      }<br>    }
}

  

 

接口

  概念:是java语言中的一种引用类型,是方法的集合(封装了方法),包含抽象方法(JDK7及以前),默认方法和静态方法(JDK8),私有方法(JDK9,供默认方法和静态方法调用)。

    ① 类对接口可以多实现,使用implements关键字;接口对接口可以多继承,使用extends关键字;

      多实现中,实现类必须重写所有的抽象方法,如果抽象方法有重名,只需要重写一次 ;

      多实现、多继承中,如果多个接口中或接口与类中存在方法签名冲突,则此时不支持多实现、多继承。

    ② 继承了接口的默认方法,可以使用子类的对象直接调用,也可以重写默认方法;

      多实现中,如果默认方法有重名,必须重写一次;

      子接口重写默认方法时,default关键字可以保留。
      子类重写默认方法时,default关键字不可以保留。

    ③ 静态与.class文件相关,只能使用接口名调用,不可以通过实现类的类名或者实现类的对象调用;

    ④ 私有方法的调用:

      a.私有方法:只有默认方法可以调用;

      b.私有静态方法:默认方法和静态方法都可以调用;

    ⑤ 接口中,存在同名的静态方法并不会冲突,原因是只能通过各自接口名访问静态方法;

    ⑥ 优先级的问题:当一个类,既继承一个父类,又实现若干个接口时,父类中的成员方法与接口中的默认方法重名,子类就近选择执行父类的成员方法;

    ⑦ 接口中,无法定义成员变量,但是可以定义静态常量,其值不可以改变,默认使用public static final修饰;

    ⑧ 接口中,没有构造方法,不能创建对象;

    ⑨ 接口中,没有静态代码块。

 JDK8开始,接口中为啥要新增默认、静态、私有等方法?

==》为了增强接口的能力,更便于项目的扩展和维护。

抽象类和接口的对比

a) 语法层面的区别

参数

抽象类

接口

默认的方法实现

它可以有默认的方法实现

所有的方法都是抽象的。

实现

子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现。

子类使用关键字implements来实现接口。它需要提供接口中所有声明的方法的实现

构造器

抽象类有构造器,用于子类初始化

接口不能有构造器

普通类

除了不能实例化抽象类之外,它和普通Java类没有任何区别

接口是完全不同的类型

访问修饰符

抽象方法可以有publicprotecteddefault这些修饰符

接口方法默认修饰符是public。不可以使用其它修饰符。

main方法

抽象方法可以有main方法并且我们可以运行它

接口没有main方法,因此我们不能运行它。

多继承

抽象方法可以继承一个类和实现多个接口

接口只可以继承一个或多个其它接口

速度

它比接口速度要快

接口是稍微有点慢的,因为它需要时间去寻找在类中实现的方法。

添加新方法

如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。

如果你往接口中添加方法,那么你必须改变实现该接口的类。

b) 设计层面上的区别

抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。举个简单的例子,飞机和鸟是不同类的事物,但是它们都有一个共性,就是都会飞。那么在设计的时候,可以将飞机设计为一个类Airplane,将鸟设计为一个类Bird,但是不能将 飞行 这个特性也设计为类,因此它只是一个行为特性,并不是对一类事物的抽象描述。此时可以将 飞行 设计为一个接口Fly,包含方法fly( ),然后AirplaneBird分别根据自己的需要实现Fly这个接口。然后至于有不同种类的飞机,比如战斗机、民用飞机等直接继承Airplane即可,对于鸟也是类似的,不同种类的鸟直接继承Bird类即可。从这里可以看出,继承是一个 "是不是"的关系,而 接口 实现则是 "有没有"的关系。如果一个类继承了某个抽象类,则子类必定是抽象类的种类,而接口实现则是有没有、具备不具备的关系,比如鸟是否能飞(或者是否具备飞行这个特点),能飞行则可以实现这个接口,不能飞行就不实现这个接口。

设计层面不同,抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。什么是模板式设计?最简单例子,大家都用过ppt里面的模板,如果用模板A设计了ppt Bppt Cppt Bppt C公共的部分就是模板A了,如果它们的公共部分需要改动,则只需要改动模板A就可以了,不需要重新对ppt Bppt C进行改动。而辐射式设计,比如某个电梯都装了某种报警器,一旦要更新报警器,就必须全部更新。也就是说对于抽象类,如果需要添加新的方法,可以直接在抽象类中添加具体的实现,子类可以不进行变更;而对于接口则不行,如果接口进行了变更,则所有实现这个接口的类都必须进行相应的改动。

posted @   九点的太阳  阅读(359)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示