目录
一、抽象类
1、1抽象类概念
1.2 抽象类语法
1.3 抽象类特性
1.4 抽象类的作用
二、接口
2、1接口的概念
2、2接口的语法规则
2、3接口使用
2、4接口特性
2.5 实现多个接口
2.6 接口间的继承
2、7抽象类和接口的区别
2、8 Object类
一、抽象类
1、1抽象类概念
1.2抽象类语法
// 抽象类:被abstract修饰的类 public abstract class Shape { // 抽象方法:被abstract修饰的方法,没有方法体 abstract public void draw(); abstract void calcArea(); // 抽象类也是类,也可以增加普通方法和属性 public double getArea(){ return area; } protected double area; // 面积 }1.3抽象类特性
1.抽象类不能直接实例化对象2.抽象方法不能是private的3.抽象方法不能被final和static修饰,因为抽象方法要被子类重写4.抽象类必须被继承,并且继承后子类要重写父类中的抽象方法,否则子类也是抽象类,必须要使用abstract修饰5.抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类6.抽象类中可以有构造方法,供子类创建对象时,初始化父类的成员变量
1.4抽象类的作用
抽象类本身不能被实例化,要想使用,只能创建该抽象类的子类.然后让子类重写抽象类中的抽象方法.有些同学可能会说了,普通的类也可以被继承呀,普通的方法也可以被重写呀,为啥非得用抽象类和抽象方法呢?确实如此.但是使用抽象类相当于多了一重编译器的校验.使用抽象类的场景就如上面的代码,实际工作不应该由父类完成,而应由子类完成.那么此时如果不小心误用成父类了,使用普通类编译器是不会报错的.但是父类是抽象类就会在实例化的时候提示错误,让我们尽早发现问题.很多语法存在的意义都是为了"预防出错",例如我们曾经用过的final也是类似.创建的变量用户不去修改,不 就相当于常量嘛?但是加上final能够在不小心误修改的时候,让编译器及时提醒我们. 充分利用编译器的校验,在实际开发中是非常有意义的.
二、接口
2、1接口的概念
2、2接口的语法规则
public interface 接口名称{ // 抽象方法 public abstract void method1(); // public abstract 是固定搭配,可以不写 public void method2(); abstract void method3(); void method4(); // 注意:在接口中上述写法都是抽象方法,跟推荐方式4,代码更简洁 }提示:1.创建接口时,接口的命名一般以大写字母I开头.2.接口的命名一般使用"形容词"词性的单词.3.阿里编码规范中约定,接口中的方法和属性不要加任何修饰符号,保持代码的简洁性.
2、3接口使用
public class类名称implements接口名称{// ...}
// USB接口 public interface USB { void openDevice(); void closeDevice(); } // 鼠标类,实现USB接口 public class Mouse implements USB { @Override public void openDevice() { System.out.println("打开鼠标"); } @Override public void closeDevice() { System.out.println("关闭鼠标"); } public void click(){ System.out.println("鼠标点击"); } } // 键盘类,实现USB接口 public class KeyBoard implements USB { @Override public void openDevice() { System.out.println("打开键盘"); } @Override public 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(); } }2、4接口特性
public class TestUSB { public static void main(String[] args) { USB usb = new USB(); } } // Error:(10, 19) java: day20210915.USB是抽象的;无法实例化public interface USB { void openDevice(); // 编译失败:因为接口中的方式默认为抽象方法 // Error:(5, 23) java: 接口抽象方法不能带有主体 void closeDevice(){ System.out.println("关闭USB设备"); } }public interface USB { void openDevice(); // 默认是public的 void closeDevice(); // 默认是public的 } public class Mouse implements USB { @Override void openDevice() { System.out.println("打开鼠标"); } // ... } // 编译报错,重写USB中openDevice方法时,不能使用默认修饰符 // 正在尝试分配更低的访问权限; 以前为public2.5实现多个接口
2.6接口间的继承
2、7抽象类和接口的区别
(重要)抽象类和接口都是 Java 中多态的常见使用方式.都需要重点掌握.同时又要认清两者的区别(重要!!!常见面试题).核心区别:抽象类中可以包含普通方法和普通字段,这样的普通方法和字段可以被子类直接使用(不必重写),而接口中 不能包含普通方法,子类必须重写所有的抽象方法.如之前写的Animal例子.此处的Animal中包含一个name这样的属性,这个属性在任何子类中都是存在的.因此此处的 Animal只能作为一个抽象类,而不应该成为一个接口.再次提醒: 抽象类存在的意义是为了让编译器更好的校验,像Animal这样的类我们并不会直接使用,而是使用它的子类. 万一不小心创建了 Animal的实例,编译器会及时提醒我们.
2、8 Object类
class Person{} class Student{} public class Test { public static void main(String[] args) { function(new Person()); function(new Student()); } public static void function(Object obj) { System.out.println(obj); } } //执行结果: Person@1b6d3586 Student@4554617c2、8、1获取对象信息
// Object类中的toString()方法实现: public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }2、8、2对象比较equals方法
在Java中,==进行比较时:a.如果==左右两侧是基本类型变量,比较的是变量中值是否相同b.如果==左右两侧是引用类型变量,比较的是引用变量地址是否相同c.如果要比较对象中内容,必须重写Object中的equals方法,因为equals方法默认也是按照地址比较的:
// Object类中的equals方法 public boolean equals(Object obj) { return (this == obj); // 使用引用中的地址直接来进行比较 } class Person{ private String name ; private int age ; public Person(String name, int age) { this.age = age ; this.name = name ; } } public class Test { public static void main(String[] args) { Person p1 = new Person("gaobo", 20) ; Person p2 = new Person("gaobo", 20) ; int a = 10; int b = 10; System.out.println(a == b); // 输出true System.out.println(p1 == p2); // 输出false System.out.println(p1.equals(p2)); // 输出false } } //Person类重写equals方法后,然后比较: class Person{ ... @Override public 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 ; } }结论:比较对象中内容是否相同的时候,一定要重写equals方法。