You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 8使用Clip播放音频抛出NullPointerException问题求助

Java Clip类播放背景音乐时出现NullPointerException的解决方法

问题根源分析

NullPointerException出现在AudioSystem.getAudioInputStream(inputStream),说明inputStream为null——也就是getClassLoader().getResourceAsStream没有找到指定的音频文件。另外你的代码还有两个潜在问题:

  • DataLine.Info指定的是SourceDataLine.class,但你要获取的是Clip,强制转换会引发ClassCastException
  • 调用audioClip.start()后立刻关闭Clip和流,音频还没开始播放就会被终止

分步解决

1. 正确加载资源文件

ClassLoader.getResourceAsStream()的路径是相对于类路径根目录的,不能带./前缀,也不需要加resources/(如果resources已经被设为类路径的话):

  • 如果项目结构是:
    src/
      ├─ java/
      └─ resources/
         └─ Sounds/
            └─ facilityIndoors.wav
    
    正确路径写法为"Sounds/facilityIndoors.wav"
  • 也可以用getClass().getResourceAsStream(),此时路径以/开头代表类路径根,比如"/Sounds/facilityIndoors.wav"

2. 修正Clip的获取逻辑

把DataLine.Info的目标类型改成Clip.class,避免强制转换错误:

DataLine.Info info = new DataLine.Info(Clip.class, audioFormat);
Clip audioClip = (Clip) AudioSystem.getLine(info);

3. 避免提前关闭资源

Clip.start()是异步执行的,直接在start后调用close会终止播放。对于背景音乐场景,建议:

  • 设置循环播放:audioClip.loop(Clip.LOOP_CONTINUOUSLY);
  • 不在playSound方法内直接关闭资源,而是在需要停止播放时(比如游戏退出)再调用close

修正后的完整Sound类

import java.io.IOException;
import java.io.InputStream;
import javax.sound.sampled.*;

public class Sound implements LineListener {
    
    boolean isPlaybackCompleted;
    int playMode;
    private Clip audioClip; // 保存Clip实例,方便后续停止播放

    public Sound(int mode) {
        playMode = mode; // 0 = background music
    }
    
    @Override
    public void update(LineEvent event) {
        if (LineEvent.Type.START == event.getType()) {
            isPlaybackCompleted = false;
            System.out.println("Playback started.");
        } else if (LineEvent.Type.STOP == event.getType()) {
            isPlaybackCompleted = true;
            System.out.println("Playback completed.");
            // 非背景音乐(单次播放)完成后自动关闭资源
            if (playMode != 0) {
                closeResources();
            }
        }
    }
    
    public void playSound(String soundName) throws LineUnavailableException, IOException, UnsupportedAudioFileException {
        // 加载指定路径的音频资源
        InputStream inputStream = getClass().getClassLoader().getResourceAsStream(soundName);
        if (inputStream == null) {
            throw new IOException("无法找到音频文件: " + soundName);
        }
        AudioInputStream audioStream = AudioSystem.getAudioInputStream(inputStream);
        AudioFormat audioFormat = audioStream.getFormat();
        DataLine.Info info = new DataLine.Info(Clip.class, audioFormat);
        audioClip = (Clip) AudioSystem.getLine(info);
        audioClip.addLineListener(this);
        audioClip.open(audioStream);
        
        if (playMode == 0) {
            // 背景音乐循环播放
            audioClip.loop(Clip.LOOP_CONTINUOUSLY);
        } else {
            // 单次播放
            audioClip.start();
        }
    }
    
    // 提供外部调用的停止播放方法
    public void stopSound() {
        if (audioClip != null && audioClip.isRunning()) {
            audioClip.stop();
            closeResources();
        }
    }
    
    private void closeResources() {
        if (audioClip != null) {
            audioClip.close();
        }
    }
}

资源排查技巧

  • 检查编译后的输出目录(比如target/classes或bin目录),确认Sounds/facilityIndoors.wav是否存在
  • 如果是IDE项目,确保resources文件夹被标记为资源根目录(比如IntelliJ右键文件夹选Mark Directory as -> Resources Root)
  • 文件名和路径区分大小写,确认拼写完全一致(比如WAV和wav是不同的)

内容的提问来源于stack exchange,提问作者Kayla Clayton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 04:16:38