当前位置: 首页 > news >正文

抽象类和接口(全)

一、抽象类

1.概念:如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象,这样的类就是抽象类。

                像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法,包含抽象⽅法的类我们称为抽象类。

2.语法

在Java中,⼀个类如果被 abstract 修饰称为抽象类,抽象类中被abstract 修饰的⽅法称为抽象⽅法,抽象⽅法不⽤给出具体的实现体。

public abstract class Shape {//抽象方法:被abstract修饰的方法,没有方法体abstract public void draw();abstract void calcArea();//抽象类也是类,也可以增加普通方法和属性public double getArea(){return area;}protected double area;//面积
}

#注:抽象类也是类,内部可以包含普通方法和属性,甚至构造方法

3.抽象类的特性

(1)抽象类不能直接实例化对象

Shape sahpe = new Shape();//编译错误
Error:(30, 23) java: Shape是抽象的; ⽆法实例化

(2)抽象方法不能是private的,也不能被final和static修饰(抽象类注定要被继承,内部的抽象方法要被重写)

(3)抽象类必须被继承,并且继承后子类要重写父类中的抽象方法,否则子类也是抽象类,必须要使用abstract修饰(如果子类也是抽象类,那么它的子类要重写其父类和父类的父类的抽象方法)

//抽象类:被abstract修饰的类
public abstract class Shape {//抽象方法:被abstract修饰的方法,没有方法体abstract public void draw();abstract void calcArea();//抽象类也是类,也可以增加普通方法和属性public double getArea(){return area;}protected double area;//面积
}public class Rect extends Shape{private double length;private double width;public Rect(double length, double width) {this.length = length;this.width = width;}public void draw(){System.out.println("矩形:length="+length+"width="+width);}public void calcArea(){area = length*width;}}public class Circle extends Shape{private double r;final private static double PI = 3.14;public Circle(double r){this.r = r;}public void draw(){System.out.println("圆:r = "+r);}public void calcArea(){area = PI*r*r;}
}public class Triangle extends Shape{private double a;private double b;private double c;@Overridepublic void draw() {System.out.println("三⻆形: a = "+a + " b = "+b+" c = "+c);}@Overridevoid calcArea() {}
}

(4).抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类

(5).抽象方法中可以有构造方法,供子类创建对象时初始化父类的成员变量

4.抽象类的作用

抽象类的使用相当于是多了一重编译器的校验。

在上述代码中,实际工作是由子类完成的,那么如果误用成了父类,普通的类编译器不会报错,但是父类是抽象类就会在实例化的时候提示错误,尽早发现问题。

二、接口

1.概念

在Java中,接口可以看成是多个类的公共规范,是一种引用数据类型

2.语法

public interface 接口名称{//抽象方法public abstract void method1();// public abstract是固定搭配,可以不写public void method2();abstract void method3();void method4();//注意:在接口中上述写法都是抽象方法,但是更推荐方式4,代码更加简洁}

#注:

(1)创建接口时,接口的命名一般是以大写的字母I开头

(2)接口的命名一般使用形容词性的单词(后面+able)

(3)阿里编码规范中约定,接口中的方法和属性不要加任何修饰符号,保持代码的简洁性。

3.接口的使用

接口不能直接使用,必须要有一个“实现类”来“实现”该接口,实现接口中所有的抽象方法。

public class 类名 implements 接口名称{//...
}

#注:子类和父类之间是extends继承关系,类与接口之间是implements实现关系

//鼠标类,实现USB接口
public class Mouse implements USB{@Overridepublic void openDevice() {System.out.println("打开鼠标");}@Overridepublic void closeDevice() {System.out.println("关闭鼠标");}public void click(){System.out.println("鼠标点击");}
}//键盘类,实现USB接口
public class KeyBoard implements USB {@Overridepublic void openDevice() {System.out.println("打开键盘");}@Overridepublic void closeDevice() {System.out.println("关闭键盘");}public void inPut(){System.out.println("键盘输入");}
}//笔记本类:使用USB设备
public class Computer {public void powerOn(){System.out.println("打开笔记本电脑");}public void powerOff(){System.out.println("关闭笔记本电脑");}public void useDevice(USB usb){usb.openDevice();if(usb instanceof Mouse){Mouse mouse = (Mouse)usb;mouse.click();} else if (usb instanceof KeyBoard) {KeyBoard keyBoard = (KeyBoard) usb;keyBoard.inPut();}usb.closeDevice();}
}//测试类
public class TestUSB {public static void main(String[] args) {Computer computer = new Computer();computer.powerOn();//使用鼠标设备computer.useDevice(new Mouse());//使用键盘设备computer.useDevice(new KeyBoard());computer.powerOff();}
}

instanceof是用于检查比较的,避免出现ClassCastException异常

4.特性

(1)接口是一种引用类型,但是不能直接new接口的对象

(2)即接⼝中的⽅法会被隐式的指定为public  abstract

(3)接口中的方法不能在接口中实现,只能由实现接口的类来实现

(4)重写接口中的方法时,不能使用默认的访问权限

(5)接口中可以含有变量,但是接口中的变量会被隐式的指定为public static final变量

(6)接口中不能有静态代码块和构造方法

(7)接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是.class

(8)如果类没有实现接口中的所有抽象方法,则类必须设置为抽象类

5.实现多个接口

Java中不⽀持多继承,但是⼀个类可以实现多个接⼝。

public class Animal {protected String name;public Animal(String name) {this.name = name;}}public interface IFlying {void fly();
}public interface IRunning {void run();
}public interface ISwimming {void swim();
}public class Duck extends Animal implements IRunning,ISwimming,IFlying{public Duck(String name) {super(name);}@Overridepublic void fly() {System.out.println(this.name+"正在用翅膀飞");}@Overridepublic void run() {System.out.println(this.name+"正在用两条腿跑");}@Overridepublic void swim() {System.out.println(this.name+"正在漂在水上");}}

这样设计可以让程序员不必关注具体类型,而是只关注某个类是否具备某种能力

6.接口之间的继承

在Java中,类和类之间是单继承的,⼀个类可以实现多个接⼝,接⼝与接⼝之间可以多继承。即:⽤ 接⼝可以达到多继承的⽬的。

接⼝可以继承⼀个接⼝,达到复⽤的效果. 使⽤extends关键字.

7.接⼝使⽤实例

例:对象之间进⾏⼤⼩关系⽐较

(1)使⽤Comparable接⼝

public class Student implements Comparable<Student>{private String name;private int score;public Student(String name, int score) {this.name = name;this.score = score;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", score=" + score +'}';}@Overridepublic int compareTo(Student o) {
//        Student s = (Student) o;
//        if(this.score > s.score){
//            return -1;
//        } else if (this.score > s.score) {
//            return 1;
//        }else {
//            return 0;
//        }return this.score-o.score;//return this.name.compareTo(o.name);}
}public class Test {public static void main(String[] args) {Student s1 = new Student("zhangsan",10);Student s2 = new Student("lisi",20);System.out.println(s1.compareTo(s2));}
}

(2)使⽤Comparator接⼝

public class ScoreComparator implements Comparator<Student> {@Overridepublic int compare(Student o1, Student o2) {return o1.getScore()-o2.getScore();}
}public class NameComparator implements Comparator<Student> {@Overridepublic int compare(Student o1, Student o2) {return  o1.getName().compareTo(o2.getName());}
}public class Test {public static void main(String[] args) {Student s1 = new Student("zhangsan",10);Student s2 = new Student("lisi",20);//根据分数进行比较ScoreComparator scoreComparator = new ScoreComparator();System.out.println(scoreComparator.compare(s1,s2));//根据姓名比较NameComparator nameComparator = new NameComparator();System.out.println(nameComparator.compare(s1,s2));}
}

8.Clonable 接⼝和深拷⻉

Java 中内置了⼀些很有⽤的接⼝,Clonable就是其中之⼀.

Object 类中存在⼀个clone⽅法,调⽤这个⽅法可以创建⼀个对象的"拷⻉".但是要想合法调⽤clone ⽅法,必须要先实现Clonable接⼝,否则就会抛出CloneNotSupportedException异常.

public class Animal implements Cloneable{private String name;public Animal clone(){Animal o = null;try{o = (Animal) super.clone();}catch(CloneNotSupportedException e){e.printStackTrace();}return o;}
}public class Test {public static void main(String[] args) {Animal animal = new Animal();Animal animal2 = animal.clone();System.out.println(animal == animal2);}
}

#注:try-catch用来处理克隆过程中可能出现的异常的(try尝试调用并执行父类Object的clone方法,catch则是捕获异常,是一种校验)

(1)浅拷贝

public class Person implements Cloneable{public Money money = new Money();@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}}public class Money {public double m = 99.99;
}public class TestDemo3 {public static void main(String[] args) throwsCloneNotSupportedException {Person person1 = new Person();Person person2 = (Person) person1.clone();System.out.println(" 通过 person2 修改前的结果 ");System.out.println(person1.money.m);System.out.println(person2.money.m);person2.money.m = 13.6;System.out.println("通过person2 修改后的结果 ");System.out.println(person1.money.m);System.out.println(person2.money.m);}
}

就像是上面的代码,只是拷贝了Person,它的Money没有被拷贝,这就叫做浅拷贝

(2)深拷贝(在浅拷贝的基础上连同Money一起拷贝)

protected Object clone()throws CloneNotSupportedException {//return super.clone();Person tmp = (Person)super.clone();tmp.m = (Money) this.m.clone();return tmp;}
}

9.抽象类和接口的区别

核⼼区别:抽象类中可以包含普通⽅法和普通字段,这样的普通⽅法和字段可以被⼦类直接使⽤(不必重写), ⽽接⼝中不能包含普通⽅法,⼦类必须重写所有的抽象⽅法.

三、Object类

Object是Java默认提供的⼀个类。Java⾥⾯除了Object类,所有的类都是存在继承关系的。默认会继 承Object⽗类。即所有类的对象都可以使⽤Object的引⽤进⾏接收

Object类也存在有定义好的⼀些⽅法,我们主要来熟悉这⼏个⽅法:equals()⽅法,hashcode()⽅法。

1.equals⽅法

equals⽅法默认是按照地址⽐较,如果要⽐较对象中内容,必须重写Object中的equals⽅法

class Person{...@Overridepublic boolean equals(Object obj) {if (obj == null) {return false ; }if(this == obj) {return true ; }// 不是Person类对象 if (!(obj instanceof Person)) {return false ; }Person person = (Person) obj ; // 向下转型,⽐较属性值 return this.name.equals(person.name) && this.age==person.age ; }
}

2.hashcode⽅法

了hashCode()这个⽅法,他帮我算了⼀个具体的对象位置,这⾥⾯涉及数据结构,但是还没学数据结构,没法讲述,所以只能说它是个内存地址。然后调⽤Integer.toHexString()⽅法, 将这个地址以16进制输出。

像重写equals⽅法⼀样,我们也可以重写hashcode()⽅法。

 class Person {public String name;public int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic int hashCode() {return Objects.hash(name, age);}}public class TestDemo4 {public static void main(String[] args) {Person per1 = new Person("gaobo", 20) ;Person per2 = new Person("gaobo", 20) ;System.out.println(per1.hashCode());System.out.println(per2.hashCode());}}//执⾏结果460141958460141958

相关文章:

  • 土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
  • 学习记录之nestjs---基本认识
  • QT开发技术【ffmpeg EVideo录屏软件 一】
  • vue+cesium示例:3D热力图(附源码下载)
  • pkg-config --cflags --libs opencv4详细解释
  • LangGraph基础知识(Graph-GraphState)
  • Ansible 错误处理:确保高效自动化
  • 大模型——基于Docker+DeepSeek+Dify :搭建企业级本地私有化知识库超详细教程
  • 河南建筑安全员C证考试常见题及答案解析
  • MyBatis中关于缓存的理解
  • stm32进入Infinite_Loop原因(因为有系统中断函数未自定义实现)
  • 门静脉高压——检查
  • FreeRTOS学习01_移植FreeRTOS到STM32(图文详解)
  • 从0到1构建我的AI星逻系统: LLM智能控制 + Streamlit前端实战
  • Netty
  • 简繁体智能翻译软件
  • ThreadLocal 源码
  • 7种分类数据编码技术详解:从原理到实战
  • 学习日记-day25-6.9
  • ArcGIS应用与FLUS模型预测:从安装到土地利用建模,数据管理、地图制作、遥感解译、空间分析、地形分析及案例分析攻略
  • wordpress发送邮件插件/seo网络营销招聘
  • 北京好用的h5建站/app拉新推广平台渠道商
  • 做b2b网站项目技巧/推广注册app拿佣金平台
  • 商务网站建设试题/网络营销的常用工具
  • 做淘客网站用备案/百度最新推广产品
  • wordpress自动获取标签/seo专员工资一般多少