一、抽象类
在 Java 中,一个类如果被 abstract 修饰称为抽象类,抽象类中被 abstract 修饰的方法称为抽象方法,抽象方法不用 给出具体的实现体。
1.语法
// 抽象类:被 abstract 修饰的类public abstract class Shape {// 抽象方法:被 abstract 修饰的方法,没有方法体abstract public void draw ();abstract void calcArea ();// 抽象类也是类,也可以增加普通方法和属性public double getArea (){return area ;}protected double area ; // 面积}写完之后,编译器可以看到抽象类 和 抽象方法 的图标
2.抽象类的特性
1. 抽象类不能直接实例化自身对象,只能创建该抽象类的子类2. 抽象方法不能是 private 的3. 抽象方法不能被 fifinal 和 static 修饰,因为抽象方法要被子类重写4. 抽象类必须被继承,并且继承后子类要重写父类中的抽象方法,否则子类也是抽象类,必须要使用 abstract 修饰5. 抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类6. 抽象类中可以有构造方法,供子类创建对象时,初始化父类的成员变量7.如果普通类A继承了抽象类,但不想重写该抽象类Shape的方法,这个普通类A前面就要用abstract修饰,但如果又有一个普通类B继承了这个A,那么B既要重写A的抽象方法,也要重写Shape的抽象方法
例子: 特性都在里面标注了
//抽象类,被abstract修饰的方法
abstract class Shape{
//抽象类当中,可以和普通类一样,定义成员变量 和 成员方法
//抽象类,被abstract修饰的方法
public abstract void draw();
//被final、private、static修饰的抽象方法是不可以的
}
//抽象类就是为了被继承
//当一个普通的类,继承了这个抽象类,那么需要重写这个抽象类中的所有抽象方法!!!
class Cycle extends Shape{
@Override
public void draw() {
System.out.println("圆形");
}
}
class Rect extends Shape{
@Override
public void draw() {
System.out.println("矩形");
}
}
//如果普通类A继承了抽象类,但不想重写该抽象类Shape的方法,这个普通类A前面就要用abstract修饰
//但如果又有一个普通类B继承了这个A,那么B既要重写A的抽象方法,也要重写Shape的抽象方法
abstract class A extends Shape{
public abstract void test();
}
class B extends A{
//重写Shape里的所有抽象方法
@Override
public void draw() {
}
//重写A里的所有抽象方法
@Override
public void test() {
}
}
public class Test {
public static void drawMap(Shape shape){
shape.draw();
}
public static void main(String[] args) {
//抽象类本身不能实例化对象
//Shape shape = new Shape();
//抽象类只能创建该抽象类的子类
Shape shape = new Rect();
Shape shape2 = new Cycle();
drawMap(shape);
drawMap(shape2);
}
}
二、接口
在 Java 中,接口可以看成是:多个类的公共规范,是一种引用数据类型。
1.语法
接口的定义格式与定义类的格式基本相同,将 class 关键字换成 interface 关键字,就定义了一个接口。public interface 接口名称 {// 抽象方法public abstract void method1 (); // public abstract 是固定搭配,可以不写public void method2 ();abstract void method3 ();void method4 ();// 注意:在接口中上述写法都是抽象方法,跟推荐方式 4 ,代码更简洁}
2.接口的使用
接口不能直接使用,必须要有一个 " 实现类 " 来 " 实现 " 该接口,实现接口中的所有抽象方法。public class 类名称 implements 接口名称 {// ...}子类和父类之间是 extends 继承关系,类与接口之间是 implements 实现关系。
4.接口特性
1. 接口类型是一种引用类型,但是不能直接 new 接口的对象2. 接口里只能有抽象方法; dk8中:接口中还可以包含default、static方法。3. 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现,或者使用 static、default修饰的方法 (其中由接口实现的类,必须被重写,因为接口里的方法默认都是 public abstract 所修饰的!!!)(default修饰的可以重写也可以不重写)(static不能重写,可以直接通过类名调用)4. 重写接口中方法时,不能使用默认的访问权限,只能是public(因为子类的访问权限要大于父类)5. 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static fifinal 变量(相当于常量)6. 接口中不能有代码块和构造方法7. 接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是 .class8. 如果类没有实现接口中的所有的抽象方法,则类必须设置为抽象类
//接口
interface IShape{
//接口里的方法默认都是 public abstract 所修饰的!!!
//全称 :public abstract void draw();
void draw();//默认抽象方法
//接口里只能有抽象方法,还有static、default修饰的方法(jdk8引入的)
default public void test(){}
static public void test2(){};
//接口当中的成员变量 默认都是 public static final 修饰的!!!
//实际上就是一个常量,常量一般大写字母表示
int A = 1;
public static int B = 2;
public static final int C = 3;
}
//类实现接口,使用implement
class Rect_i implements IShape{
//需要重写接口的抽象方法
@Override
public void draw() {
System.out.println("矩形");
}
}
class Flower_i implements IShape{
@Override
public void draw() {
System.out.println("花花");
}
}
public class Test2 {
public static void drawMap(IShape iShape){
iShape.draw();
}
public static void main(String[] args) {
//接口不能实例化自身
//IShape iShape = new IShape();
//接口只能创建该抽象类的子类
IShape iShape1 = new Flower_i();
IShape iShape2 = new Rect_i();
drawMap(iShape1);
drawMap(iShape2);
System.out.println("================");
IShape[] iShapes ={new Flower_i(),new Rect_i()};
for (IShape x:iShapes) {
drawMap(x);
}
}
}
4.实现笔记本电脑使用USB鼠标、USB键盘的例子
1. USB 接口:包含打开设备、关闭设备功能2. 笔记本类:包含开机功能、关机功能、使用 USB 设备功能3. 鼠标类:实现 USB 接口,并具备点击功能4. 键盘类:实现 USB 接口,并具备输入功能
package demo2;
public interface USB {
void openDevice();
void closeDevice();
}
package demo2;
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("疯狂点击鼠标。。。。。。。。");
}
}
package demo2;
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("疯狂敲打键盘。。。。。。。。。。。");
}
}
package demo2;
public class Computer {
public void powerOn(){
System.out.println("打开电脑!!");
}
public void powerOff(){
System.out.println("关闭电脑!!");
}
public void useService(USB usb){
usb.openDevice();
//如果usb引用的对象是Mouse,强制类型转换到Mouse
//如果usb引用的对象是KeyBoard,强制类型转换到KeyBoard
if (usb instanceof Mouse){
Mouse mouse = (Mouse) usb;
mouse.click();
} else if (usb instanceof KeyBoard) {
KeyBoard keyBoard = (KeyBoard) usb;
keyBoard.input();
}
usb.closeDevice();
}
}
package demo2;
public class Test {
public static void main(String[] args) {
Computer computer = new Computer();
Mouse mouse = new Mouse();
KeyBoard keyBoard = new KeyBoard();
computer.powerOn();
computer.useService(mouse);
System.out.println("=================");
computer.useService(keyBoard);
computer.powerOff();
}
}
5.实现多个接口 - 解决Java的多继承问题
在 Java 中,类和类之间是单继承的,一个类只能有一个父类,即 Java 中不支持多继承 ,但是 一个类可以实现多个接 口 。下面通过类来表示一组动物 .狗是一种动物 , 具有会跑的特性 .青蛙也是一种动物 , 既能跑 , 也能游泳鸭子也是一种动物 , 既能跑 , 也能游 , 还能飞
package demo3;
abstract class Animal{
public String name;
public int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public abstract void eat();
}
interface IFly{
void fly();
}
interface IRun{
void run();
}
interface ISwim{
void swim();
}
//狗是一个动物,具备跑这个功能
class Dog extends Animal implements IRun{
public Dog(String name, int age) {
super(name, age);
}
@Override
public void run() {
System.out.println(this.name+"正在跑!!!");
}
@Override
public void eat() {
System.out.println(this.name+"吃狗粮");
}
}
class Frog extends Animal implements IRun,ISwim{
public Frog(String name,int age){
super(name,age);
}
@Override
public void run() {
System.out.println(this.name+"正在用4条腿跳着跑!!");
}
@Override
public void swim() {
System.out.println(this.name+"正在蛙泳!!");
}
@Override
public void eat() {
System.out.println(this.name+"吃蛙粮");
}
}
class Duck extends Animal implements IRun,IFly,ISwim{
public Duck(String name, int age) {
super(name, age);
}
@Override
public void run() {
System.out.println(this.name+"正在两只脚 跑!!!");
}
@Override
public void swim() {
System.out.println(this.name+"正在 游泳!!!");
}
@Override
public void fly() {
System.out.println(this.name+"正在用两只翅膀飞!!!");
}
@Override
public void eat() {
System.out.println(this.name+"吃鸭粮");
}
}
public class Test {
public static void func1(Animal animal){
animal.eat();
}
public static void run(IRun iRun){
iRun.run();
}
public static void fly(IFly ifly){
ifly.fly();
}
public static void swim(ISwim iSwim){
iSwim.swim();
}
public static void main(String[] args) {
run(new Duck("唐老鸭",1));
swim(new Duck("唐老鸭",1));
fly(new Duck("唐老鸭",1));
System.out.println("========");
run(new Dog("二狗子",2));
System.out.println("========");
run(new Frog("青蛙王子",3));
swim(new Frog("青蛙王子",3));
}
public static void main1(String[] args) {
// Animal animal = new Duck("唐老鸭",1);
// Animal animal2 = new Dog("二狗子",2);
// Animal animal3 = new Frog("青蛙王子",3);
Animal[] animals = {new Duck("唐老鸭",1),new Dog("二狗子",2),new Frog("青蛙王子",3)};
for (Animal x:animals) {
func1(x);
}
}
}
6.接口间的继承
package demo4extends;
interface A{
void testA();
}
interface B extends A{
void testB();
}
class TestDemo1 implements B{
@Override
public void testA() {
}
@Override
public void testB() {
}
}
public class Test {
}
7.接口的使用实例
1)给定一个学生对象数组, 对这个对象数组中的元素进行排序
方法1:类里重写comparaTo方法(方式固定)
package demo5;
/**
* 方法1:固定比较方式
*/
class Student implements Comparable<Student>{
public String name;
public int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student o) {
if(this.age > o.age){
return 1;
} else if (this.age == o.age) {
return 0;
}else {
return -1;
}
}
}
public class Test {
public static void main(String[] args) {
//两个引用类型比较大小
Student student1 = new Student("zhangsan",10);
Student student2 = new Student("lisi",20);
//System.out.println(student1>student2);无法比较
//因为,student是引用类型,里面存的是地址,无法直接通过大于小于符号比较大小
//不知道拿什么作比较(是姓名还是年龄)
//使用重写后的compareTo
System.out.println(student1.compareTo(student2));
}
public static void main1(String[] args) {
//普通数值比较大小
int a = 10;
int b = 20;
System.out.println(a > b);//false
}
}
方法2:自定义一个类,写比较器(运用灵活)
import java.util.Comparator;
/**
* 方法2:可以根据需求,更改比较的对象
* 比较器
*/
class Student {
public String name;
public int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
//根据年龄比较
class AgeComparator implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
return o1.age- o2.age;
}
}
//根据姓名比较
class NameComparator implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
return o1.name.compareTo(o2.name);
}
}
public class Test {
public static void main(String[] args) {
//两个引用类型比较大小
Student student1 = new Student("zhangsan",10);
Student student2 = new Student("lisi",20);
AgeComparator ageComparator = new AgeComparator();
System.out.println(ageComparator.compare(student1, student2));
NameComparator nameComparator = new NameComparator();
System.out.println(nameComparator.compare(student1, student2));
}
}
2)给students数组排序
package demo5;
import java.util.Arrays;
import java.util.Comparator;
/**
* 方法1:固定比较方式
*/
//class Student implements Comparable<Student>{
// public String name;
// public int age;
//
// public Student(String name, int age) {
// this.name = name;
// this.age = age;
// }
//
// @Override
// public String toString() {
// return "Student{" +
// "name='" + name + '\'' +
// ", age=" + age +
// '}';
// }
//
// @Override
// public int compareTo(Student o) {
// if(this.age > o.age){
// return 1;
// } else if (this.age == o.age) {
// return 0;
// }else {
// return -1;
// }
// }
//}
/**
* 方法2:可以根据需求,更改比较的对象
* 比较器
*/
class Student {
public String name;
public int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
//根据年龄比较
class AgeComparator implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
return o1.age- o2.age;
}
}
//根据姓名比较
class NameComparator implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
return o1.name.compareTo(o2.name);
}
}
public class Test {
public static void main(String[] args) {
// int[] array = {1,2,31,4};
// Arrays.sort(array);
// System.out.println(Arrays.toString(array));
Student[] students = new Student[3];
students[0] = new Student("zhangsan",10);
students[1] = new Student("lisi",4);
students[2] = new Student("abc",5);
System.out.println("排序前:"+Arrays.toString(students));
//方法1:可以用固定方法
//Arrays.sort(students);
//方法2:可以用自定义方法,比较器
AgeComparator ageComparator = new AgeComparator();
NameComparator nameComparator = new NameComparator();
//Arrays.sort(students,ageComparator);
Arrays.sort(students,nameComparator);
System.out.println("排序后:"+Arrays.toString(students));
}
public static void main3(String[] args) {
//两个引用类型比较大小
Student student1 = new Student("zhangsan",10);
Student student2 = new Student("lisi",20);
// AgeComparator ageComparator = new AgeComparator();
// System.out.println(ageComparator.compare(student1, student2));
//
// NameComparator nameComparator = new NameComparator();
// System.out.println(nameComparator.compare(student1, student2));
}
public static void main2(String[] args) {
//两个引用类型比较大小
Student student1 = new Student("zhangsan",10);
Student student2 = new Student("lisi",20);
//System.out.println(student1>student2);无法比较
//因为,student是引用类型,里面存的是地址,无法直接通过大于小于符号比较大小
//不知道拿什么作比较(是姓名还是年龄)
//使用重写后的compareTo
//System.out.println(student1.compareTo(student2));
}
public static void main1(String[] args) {
//普通数值比较大小
int a = 10;
int b = 20;
System.out.println(a > b);//false
}
}
方法1:固定方法
方法2:自定义方法,比较器
根据name排序
根据age排序