是由抽象类衍生出来的恶一个概念,并由此产生了一种编程方式:面向接口编程。
1、能够最大限度实现解耦合,降低程序耦合性。
2、使程序易于扩展。
3、有利于程序后期维护
面向接口编程就是将程序中的业务模块进行分离,以接口的形式去对接不同的业务模块。
**面向接口编程的优点:**当用户需求变更时,只需要切换不同的实现类,而不需要修改串联模块的接口,减小对系统的影响。
耦合度太高:鼠标直接固定在电脑上而不是通过usb口连接,不灵活,更换不方便。
如何使用接口?接口在java中时独立存在的一种结构,和类相似,需要创建一个接口文件,用interface来标识接口,基本语法:
public interface 接口名{ public 返回值方法名(参数列表) }
接口其实就是一个极度抽象的抽象类。抽象类:一个类中存在没有具体实现的抽象方法时,那么该类就必须定位为抽象类,同时抽象类允许存在非抽象方法。
**接口:**不能存在非抽象方法,必须全部是抽象方法。
因为全是抽象方法,所以修饰抽象方法的关键字abstract可以省略。
接口允许定义成员变量,但有如下要求:
- 只能定义public和默认访问权限修饰符的成员变量,不能定义private和protected修饰的成员变量
- 接口中成员变量在定义时就必须完成初始化。
- 接口中的成员变量都是静态常量,即可以直接通过接口访问,同时值不能被修改。
public interface MyInterface { public int ID = 0; String NAME = "张三"; public void test(); }
使用接口时,不能直接实例化接口对象,而必须实例化其实现类对象,实现类对象本身就是一个普通的java类,创建实现类的代码如下所示:
public class MyInterfaceImpl implements MyInterface{ @Override public void test() { } }
通过Implements关键字来指定实现类具体要实现的接口,在实现类的内部需要对接口的所有抽象方法进行实现,同时要求访问权限修饰符、返回值类型、方法名和参数列表必须完全一致。
接口和继承:java只支持单继承,但是接口可以多实现(一个实现类可以同时实现多个接口)
public interface MyInterface { public int ID = 0; String NAME = "张三"; public void run(); }
public interface MyInterface2 { public void fly(); }
package com.southwind.test; public class MyInterfaceImpl implements MyInterface, MyInterface2{ @Override public void run() { System.out.println("实现了跑的方法"); } @Override public void fly() { System.out.println("实现了飞的方法"); } }
package com.southwind.test; public class Test { public static void main(String[] args) { MyInterfaceImpl myInterface = new MyInterfaceImpl(); myInterface.fly(); myInterface.run(); } }面向接口编程的实际应用
场景
某工厂生产产品A,产品A主要是由设备A来完成生产,用程序模拟生产过程。
产品B是由设备B来生产的。
public class EquipmentA { public void work(){ System.out.println("设备A运行,生产产品A"); } }
public class Factory { private EquipmentA equipmentA; public EquipmentA getEquipmentA() { return equipmentA; } public void setEquipmentA(EquipmentA equipmentA) { this.equipmentA = equipmentA; } public void work(){ System.out.println("开始生产..."); this.equipmentA.work(); } }
public class Test { public static void main(String[] args) { // MyInterfaceImpl myInterface = new MyInterfaceImpl(); // myInterface.fly(); // myInterface.run(); //初始化工厂 Factory factory = new Factory(); EquipmentA equipmentA = new EquipmentA(); factory.setEquipmentA(equipmentA); //开始工作 factory.work(); } }
当需求发生改变时,就要频繁修改类的内部结构方式是需要避免的,因为扩展性很差,如何修改?使用面向接口编程即可。
1、创建接口Equipmentpublic interface Equipment { public void work(); }2、创建Equipment实现类
public class EquipmentA implements Equipment { public void work(){ System.out.println("设备A运行,生产产品A"); } }
public class EquipmentB implements Equipment { public void work(){ System.out.println("设备B运行,生产产品B"); } }3、创建Factory类
public class Factory { private Equipment equipment; public Equipment getEquipment() { return equipment; } public void setEquipment(Equipment equipment) { this.equipment = equipment; } public void work(){ System.out.println("开始生产..."); this.equipment.work(); } }4、Test
public class Test { public static void main(String[] args) { // MyInterfaceImpl myInterface = new MyInterfaceImpl(); // myInterface.fly(); // myInterface.run(); //初始化工厂 Factory factory = new Factory(); EquipmentA equipmentA = new EquipmentA(); EquipmentB equipmentB = new EquipmentB(); factory.setEquipment(equipmentB); //开始工作 factory.work(); } }2、异常
- 什么是异常?
java中的错误大致分为两类:
一类是编译时错误,一般是指语法错误。
另一类是运行时错误
try-catch-finally
try{ //可能会抛出异常的代码 }catch(Exception e){ //对异常进行处理 }finally{ //一定会执行的代码 }异常类
- Error:系统错误,程序无法处理。
- Exception:程序运行时出现的错误,错误可以处理。
Error和 Exception都是Throwable 的子类,Throwable、Error、Exception都是存放在java.lang包中。
Error常见的子类:VirtualMachineError、AWTError、IOError。
VirtualMachineError的子类: StackOverflowError、OutOfMemoryError,用来描述内存溢出等系统问题。
Exception常见的子类:IOException和 RuntimeException
IOException存放在java.io包中,RuntimeException存放在java.lang 包中。
lOException 常见的子类:FileLockInterruptionException、FileNotFoundException、FilerException,这些异常通常都是处理通过IO流进行文件传输的时候发生的错误。
RuntimeException常见的子类:
-
ArithmeticException:表示数学运算异常。
-
ClassNotFoundException:表类未定义异常。
-
IllelArgumentException:表示参数格式错误。
-
ArraylndexOutOfBounds:表示数组下标越界。
-
NullPointException:表示空指针异常。
-
NoSuchMethodException:表示方法未定义异常。
-
NumberFormatException:表示将其他数据类型转为数值类型发生的类型不匹配异常。
两个常用关键字,都可以用来抛出异常,但是使用的方式和表示的含义完全不同。
Java中抛出异常有3种方式:
- 自动捕获try-catch
- 使用throw是开发者主动抛出异常,即读到 throw代码就一定抛出异常,基本语法:throw newException(),是一种基于代码的逻辑而主动抛出异常的方式。
package com.southwind.test.exception; public class Test { public static void main(String[] args) { int[] array = {1,2,3}; test(array,2); } public static void test(int[] array,int index){ if (index >= 3 || index <0){ try { throw new Exception(); } catch (Exception e) { e.printStackTrace(); } }else { System.out.println(array[index]); } } }
- try-catch和throw都是作用于具体的逻辑代码,throws是作用于方法的,用来描述方法可能会抛出的异常。如果方法 throws的是RuntimeException 异常或者其子类,外部调用时可以不处理,JVM会处理。
如果方法 throws的是Exception 异常或者其子类,外部调用时必须处理,否则报错。
public class Test { public static void main(String[] args) throws Exception{ test("123"); } public static void test(String str) throws Exception{ int num = Integer.parseInt(str); } }自定义异常
除了使用java异常外,也可以根据需求来自定义异常
public class MyNumException extends Exception{ public MyNumException(String error){ super(error); } }
package com.southwind.exception; public class Test { public static void main(String[] args) throws Exception{ Test test = new Test(); System.out.println(test.add("a")); } public int add(Object object) throws MyNumException{ if (object instanceof Integer){ int num = (int) object; return ++num; }else { String error = "传入的参数不为整数"; MyNumException myNumException = new MyNumException(error); throw myNumException; } } }综合练习
封装、继承、多态、抽象、接口、异常完成一个汽车查询系统。
需求描述:共有3种类型的汽车:小轿车、大巴车、卡车,其中小轿车的座位数是4座,大巴车座位数是5座,卡车座位数是2座,要求使用封装、继承、抽象来完成车辆的定义。
可以对车辆信息进行修改,卡车可以运货但是载重量不能超过12吨,使用自定义异常来处理错误,小轿车和大巴车没有此功能,要求使用接口来实现。
car
package com.southwind.car; public abstract class Car { private String name; private String color; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public Car(String name, String color) { this.name = name; this.color = color; } public abstract String seatNum(); }
Sedan
package com.southwind.car; public class Sedan extends Car{ public Sedan(String name, String color) { super(name, color);//父类是带参构造,子类也要 } @Override public String seatNum() { return "4座"; } }
Bus
package com.southwind.car; public class Bus extends Car{ public Bus(String name, String color) { super(name, color); } @Override public String seatNum() { return "53座"; } }
Truck
package com.southwind.car; public class Truck extends Car implements Container{ private int weight; public Truck(String name, String color, int weight) { super(name, color); this.weight = weight; } @Override public String seatNum() { return "2座"; } @Override public int getweight() { return this.weight; } }
Container
package com.southwind.car; public interface Container { public int getweight(); }
CarException
package com.southwind.car; public class CarException extends Exception{ public CarException(String error){ super(error); } }
Test
package com.southwind.car; import java.util.Scanner; public class Test { private static Scanner scanner; private static Sedan sedan; private static Bus bus; private static Truck truck; private static Car[] cars; static { scanner = new Scanner(System.in); sedan = new Sedan("小轿车","黑色") ; bus = new Bus("大巴车","绿色"); truck = new Truck("卡车","蓝色",2); cars = new Car[3]; cars[0] = sedan; cars[1] = bus; cars[2] = truck; } public void showCars(){ System.out.println("欢迎使用本汽车管理系统"); System.out.println("车辆名称tt车辆颜色tt座位数tt载重量"); for (Car car:cars){ if (car instanceof Truck){ Truck truck = (Truck)car; System.out.println(car.getName()+"ttt"+car.getColor()+"ttt"+car.seatNum()+"ttt"+truck.getweight()); }else { System.out.println(car.getName()+"tt"+car.getColor()+"tt"+car.seatNum()+"tt不能拉货"); } } System.out.println("1.小轿车t2.大巴车t3.卡车"); System.out.print("请选择要修改的车辆"); int num = scanner.nextInt(); switch (num){ case 1: update("sedan"); break; case 2: update("bus"); break; case 3: update("truck"); break; default: System.out.println("输入的车辆不存在"); break; } } public void update(String type){ String name = null; String color = null; if (type.equals("sedan")){ System.out.print("输入车辆名称"); name = scanner.next(); System.out.print("输入车辆颜色"); color = scanner.next(); Sedan sedan = new Sedan(name,color); cars[0] = sedan; } if (type.equals("bus")){ System.out.print("输入车辆名称"); name = scanner.next(); System.out.print("输入车辆颜色"); color = scanner.next(); Bus bus = new Bus (name,color); cars[1] = bus; }if (type.equals("truck")){ System.out.print("输入车辆名称"); name = scanner.next(); System.out.print("输入车辆颜色"); color = scanner.next(); System.out.print("输入载重量"); int weight = scanner.nextInt(); if (weight > 12){ CarException carException = new CarException("卡车的载重量不超过12吨"); try { throw carException; } catch (CarException e) { e.printStackTrace(); return; } } Truck truck = new Truck(name,color,weight); cars[2] = truck; } showCars(); } public static void main(String[] args) { Test test = new Test(); test.showCars(); } }
- 讲解了面向对象的高级部分,包括Object类、包装类、接口和异常。其中Object类是所有Java类的父类,定义了Java体系的基础资料,通过继承传递给Java的每一个类,通过方法重写和多态让整个Java体系具有很强的灵活性。
- 包装类是Java为基本数据类型提供封装的一组类,通过包装类我们可以将基本数据类型转为对象,这一点在面向对象编程中很重要。
- 接口是抽象类的扩展,是Java中实现多态的重要方式,可以降低程序的耦合性,让程序变得更加灵活多变。接口就相当于零件,我们可以自由地将这些零件进行组装、整合。
- 异常是Java中处理错误的一种机制,同样是基于面向对象的思想,将错误抽象成对象然后进行处理,这里需要关注的是对异常相关的几个关键字的使用,try、catch、finally、throw、throws。l