一.接口
1.1什么是接口?
Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的特征的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
定义了接口就相当于定义了调用对象的标准。我们一台电脑上有多个usb接口,它可以提供数据传输,供电系统的标准。
1.2接口的基本语法
1.2.1基本语法(一)
a.使用interface定义;
b.接口当中的方法都是抽象方法;
c.接口当中的方法都是public权限;
可以用以下的代码,来直观的理解一下:
...
interface USB{
public void read();
public void write();
}
...
我们需要注意的是接口中全为抽像方法,抽象函数,即抽象类是不能生成对象,不能new一个对象。因此要使用接口可以采用两种方法:(1)继承抽象类;(2)复写抽象方法。
...
class USBphone implements USB{ //继承接口USB;
public void read(){ //对接口中的抽象方法进行复写;
system.out.println("usbphone read");
}
public void write(){
system.out.println("usbphone write");
}
...
public class Test{
public static void main(String[] args){
Usbphone usbphone = new Usbphone();
Usb usb = usbphone; //将子类的对象向上转型为父类的引用
usb.read();
usb.write();
}
}
...
1.2.2基本语法(二)
a.实现接口使用implements关键字;
b.一个类可以实现多个接口;
c.一个接口可以继承多个接口;
实现和继承是有一定的区别的,区别如下:
C implements A,B 需要将A,B中的方法进行复写;
C extends A,B 继承:假设C 中有func,A中有funA,B中有funB,若C继承了A,B,则C中funA, funB,funC。
...
public interface Usb{
public void read();
public void write();
}
...
public interface Wifi{
public void open();
public void close();
}
public class UsbPhone implements Usb,Wifi{ //一个类可以继承多个接口;
public void read(){ //子类对于接口中的抽象方法进行复写;
System.out.println("UsbPhone read");
}
public void write(){
System.out.println("UsbPhone write");
}
public void open(){
System.out.println("Wifi open");
}
public void close(){
System.out.println("Wifi close");
}
}
...
public class Test{
public static void main(String[] args){
UsbPhone usbphone = new UsbPhone();
Usb usb = UsbPhone; //向上转型:将子类的对象赋值给父类的引用;
usb.read();
usb.write();
Wifi wifi = new Wifi();
Wifi wifi = Usbphone;
wifi.open();
wifi.write();
}
}
从以上的代码可以看出:一个类可以继承多个接口,一个接口可以继承多个接口,只需要创建一个类UsbPhone来继承接口Usb和Wifi即可,在子类中对接口的抽象方法进行复写,在主函数中,创建一个子类对象,再利用向上转型,就可以调用接口中的抽象方法。
1.3接口的应用
1.3.1为什么要使用接口?
在学习面向对象的程序设计中有三个特点:继承性,封装性,多态性;我们知道Java中的继承只允许单继承,假设创建一个printer类,其拥有开机,关机,打印的功能,再创建两个子类,分别为HPPrinter,CanonPrinter,来继承父类中的开机,关机,打印功能。
这样会出现一个问题:两个子类的开机,关机,打印是不可能完全一样的,此时的继承是远远不能满足需求的,因此使用接口来解决这个问题,接口实质上是定义了一种标准。
1.3.2工厂方法模式
静态工厂模式:顾名思义就是将生成对象的代码或者使用new来调用构造函数将其封装在工厂类中。
为了解决上述的问题,采取工厂模式。
应用场景:
假设父类为打印机,子类为HPPrinter,CanonPrinter,两者的打印功能不可能完全一样,此时如果出现其他品牌的打印机,那么就必须创建许多的子类,这样就会出现许多的重复代码,引进工厂模式,定义一个参数,来判断是那种品牌的打印机,在调用接口中的打印功能。具体代码如下:
...
public interface Printer {
public void open();
public void close();
public void print();//定义三个抽象方法,即方法体为空;
}
...
public class HPPrinter implements Printer{
public void open(){
System.out.println("HP open");
}
public void close(){
System.out.println("HP close");
}
public void print(){
System.out.println("HP print");
}
}
...
public class CanonPrinter implements Printer{
public void open(){
System.out.println("Canon open");
}
public void clean(){
System.out.println("clean");
}
public void close(){
this.clean();
System.out.println("Canon close");
}
public void print(){
System.out.println("Canon print");
}
}
...
public class XXXPrinter implements Printer{
public void open(){
System.out.println("XXX open");
}
public void close(){
System.out.println("XXX close");
}
public void print(){
System.out.println("XXX print");
}
}
...
public class PrinterFactory {//如果出现其他品牌的打印机,则此时在主函数中需要再生成new+构造函数,如果在打印机工厂中获取一个打印机方法,将参数传入其中;
public static Printer getPrinter(int flag){
Printer printer = null;
if(flag ==0){
printer = new HPPrinter();
}
else if(flag==1){
printer = new CanonPrinter();
}
else if (flag==2){
printer = new XXXPrinter();
}
return printer;
}
}
...
/*
继承只允许单继承
一个类可以实现多个接口,一个接口可以继承多个接口;
此时会出现一个问题:两个打印机的开机,关机,打印功能不可能完全一样,因此要使用接口(接口实质上就是定义了一个标准)*/
public class Test {
public static void main(String[] args) {
/*根据用户的需求,生成相应的打印机类型;
向上转型(将子类的对象赋值给父类的引用)为Printer,调用打印机的方法;
*/
Printer printer = null;
int flag=0;
/* if(flag ==0){
printer = new HPPrinter();
}
else{
printer = new CanonPrinter();
}*/
//若需求中再出现其他的打印机,此时需要修改打印机中的部分代码,此时创建一个打印机工厂的类,来判断选择用那种打印机;*/
printer= PrinterFactory.getPrinter(flag);
printer.open();
printer.close();
printer.print();
}
}
...
二.java中的异常
2.1什么是异常以及异常的分类
异常顾名思义是:中断了正常指令流的事件。
2.2利用try...catch...finally结构来处理异常
try{
存放可能出现的异常
}
catch{
处理异常
}
finally{
清理资源/释放资源
}
...
public class Test {
public static void main(String args[]){
System.out.println(1);
try{
//打开文件的代码;若int i = 1/0;出现异常,那么此时就不执行关闭文件代码,将执行catch结构体;
System.out.println(2);
int i = 1 / 1;//uncheck exception;//try结构体中可能会出现的异常;若出现异常,则此时代码将跳入catch中
System.out.println(3);
//关闭文件的代码;
}
catch(Exception e){//e代表虚拟机产生的异常对象,在catch中使用这个对象;
e . printStackTrace (); //调用这个方法,是用来打印这个栈的异常追踪信息;
System.out.println(4);
//关闭文件的代码;若在try中不出现错误,则不执行catch中的代码;
}finally{
System.out.println("finally");
//为避免上面的两种情况,则将关闭文件的代码放在finally中。
}
System.out.println(5);
}
}
/*try catch 结构是为了解决异常出现的情况,若出现异常,此时直接跳到查catch中,继续执行catch下面的程序,若没有异常出现,此时catch结构中的程序将不执行,结构体以外的程序可以执行
*/
2.3如何来捕捉异常
throw的作用是:捕捉一个异常对象(java虚拟机不能识别的异常);
throws的作用:声明一个异常(主要是函数可能会产生的异常,而是在调用这个函数时处理异常);
throws:处理异常(在一个函数里,有可能会产生异常:check Exception)
...
public class User {
private int age;
public void setAge(int age) throws Exception{//声明一个异常,异常由调用的这个函数来处理,此时在setAge()需要利用try......catch进行处理;
if(age<0){
Exception e = new Exception("年龄不能为负数");
throw e;
}
this.age = age;
}
}
...
public class Test {
public static void main(String[] args) {
User user = new User();
try{
user.setAge(-20);
}
catch(Exception e){
System.out.println(e);
}
}
}