【Java】异常处理

有风险的代码
import javax.sound.midi.*;

public class Test{
    public void play(){
        Sequencer sequencer = MidiSystem.getSequencer();
        System.out.println("We got a sequencer");
    }
    public static void main(String[] args){
        Test test = new Test();
        test.play();
    }
}

在这里插入图片描述
编译器提示,有异常未处理,因为getSequencer()可能会在执行期间出问题。

try/catch

IDEA中使用快捷键,Alt+Enter,可以帮助纠正代码。
把有风险的代码放到try/catch里,编译器会放心许多。在这里插入图片描述

import javax.sound.midi.*;

public class Test{
    public void play(){
        try {
            Sequencer sequencer = MidiSystem.getSequencer();
        } catch (MidiUnavailableException e) {
            e.printStackTrace();
        }
        System.out.println("We got a sequencer");
    }
    public static void main(String[] args){
        Test test = new Test();
        test.play();
    }
}
  • 声明有风险的方法时,使用throws抛出异常
  • 调用有风险的方法时,方法放到try块里,异常处理程序放到catch块里
  • 编译器不检查运行时异常,大部分运行时异常是因为代码逻辑有问题
  • 异常也是对象
    在这里插入图片描述
try/catch/finally

finally,无论如何都会执行的部分,即使try或者catch中有return,也会finally,最后才return

import javax.sound.midi.*;

public class Test{
    public String play(){
        try {
            Sequencer sequencer = MidiSystem.getSequencer();
            System.out.println("executing code in try");
            return "executing return of try";
        } catch (MidiUnavailableException e) {
            e.printStackTrace();
            System.out.println("executing code in catch");
        }finally{
            System.out.println("executing code in finally");
        }
        return "";
    }
    public static void main(String[] args){
        Test test = new Test();
        String res = test.play();
        System.out.println(res);
    }
}

在这里插入图片描述

多重异常
多重异常的声明
//ClothingException.java
public class ClothingException extends Exception {
}
//PantsException.java
public class PantsException extends ClothingException {
}

//ShirtException.java
public class ShirtException extends ClothingException {
}

一个方法可以抛出多个异常,逐个抛出,就像下面这样,

//Laundry.java
public class Laundry {
    public void doLaundry() throws PantsException,ShirtException{

    }
}

前面讲过,异常也是对象,因此可以使用多态。
如果两个或两个以上的异常有共同的父类,也可以只声明父类,就像这样,

//Laundry.java
public class Laundry {
    public void doLaundry() throws ClothingException{

    }
}
多重异常的处理

可以依次catch每个可能的异常。唯一要注意的是,有多个catch块时,要从小到大排列。

//Test.java
public class Test{
    public static void main(String[] args){
        Laundry laundry = new Laundry();
        try {
            laundry.doLaundry();
        } catch (PantsException e) {
            e.printStackTrace();
        } catch (ShirtException e) {
            e.printStackTrace();
        }
    }
}

也可以只catch它们的父类。

//Test.java
public class Test{
    public static void main(String[] args){
        Laundry laundry = new Laundry();
        try {
            laundry.doLaundry();
        } catch (ClothingException e) {
            e.printStackTrace();
        } 
    }
}
声音播放程序
import javax.sound.midi.*;

//Test.java
public class Test{
    public static void main(String[] args){
        Test t = new Test();
        t.play();
    }
    public void play(){
        Sequencer player = null;
        try {
            //1.打开播放器
            player = MidiSystem.getSequencer();
            player.open();

            //2.制作CD盘
            Sequence seq = new Sequence(Sequence.PPQ,4);

            //3.制作单曲,单曲烧至CD盘
            Track track = seq.createTrack();

            //4.给单曲添加音符
            ShortMessage a = new ShortMessage();
            a.setMessage(144,1,44,100);
            MidiEvent noteOn = new MidiEvent(a,1);
            track.add(noteOn);

            ShortMessage b = new ShortMessage();
            b.setMessage(128,1,44,100);
            MidiEvent noteOff = new MidiEvent(b,16);
            track.add(noteOff);

            //5.CD盘插入播放器,播放盘中唯一单曲
            player.setSequence(seq);
            player.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • ShortMessage
    ShortMessage实例描述了要做什么。
    • setMessage(command,channel,data1,data2)
      • command
        命令类型。
        144代表开启;
        128代表关闭;
        192代表更换乐器。
      • channel
        代表频道 。
      • data1
        代表使用哪个音符,范围在 0~127之间。
      • data2
        代表音道。
        0,代表几乎没有声音
        100,音量还可以
  • MidiEvent
    MidiEvent实例决定了什么时候做。
    • new MidiEvent(message,tick)
      • tick
        代表音长。
        new MidiEvent(a,1),意思是在第一拍启动a这个message。

在这里插入图片描述
现在我们把这两个步骤,8行代码通过一个静态方法来实现,如下,

    public static MidiEvent makeEvent(int command,int channel,int data1,int data2,int tick){
        MidiEvent event = null;
        try {
            ShortMessage message = new ShortMessage();
            message.setMessage(command,channel,data1,data2);
            event = new MidiEvent(message,tick);
        } catch (InvalidMidiDataException e) {
            e.printStackTrace();
        }
        return event;
    }

使用静态makeEvent方法实现了一个新的声音播放器,运行试试看。

//Test.java
import javax.sound.midi.*;

public class Test{
    public static void main(String[] args){
        try {
            Sequencer player = MidiSystem.getSequencer();
            player.open();

            Sequence sequence = new Sequence(Sequence.PPQ,4);
            Track track = sequence.createTrack();

            for(int i=5;i<61;i+=4){
                track.add(makeEvent(144,1,i,100,i));
                track.add(makeEvent(128,1,i,100,i+2));
            }

            player.setSequence(sequence);
            player.start();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    public static MidiEvent makeEvent(int command,int channel,int data1,int data2,int tick){
        MidiEvent event = null;
        try {
            ShortMessage message = new ShortMessage();
            message.setMessage(command,channel,data1,data2);
            event = new MidiEvent(message,tick);
        } catch (InvalidMidiDataException e) {
            e.printStackTrace();
        }
        return event;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值