ClassCast创建 javax.sound.sampled.Clip 时抛出异常

ClassCastException thrown when creating a javax.sound.sampled.Clip

提问人:cpliu338 提问时间:8/3/2023 最后编辑:Hendrikcpliu338 更新时间:8/4/2023 访问量:78

问:

我想在 Java Swing 应用程序中播放声音。我参考了 https://www.baeldung.com/java-play-sound 并像这样修改:

模块信息.java

module sound {
    requires java.desktop;
}

源文件位于同一文件夹 [mydomain]/desktopproject/sound 中。有一个带有 JButton 的 Swing JFrame,当我按下按钮时,以下代码片段会一直运行,直到最后一行抛出 ClassCastException:

audioStream = AudioSystem.getAudioInputStream(new BufferedInputStream(
    new FileInputStream(new File("/path-to-my.wav"))
));
AudioFormat audioFormat = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
Clip audioClip = (Clip) AudioSystem.getLine(info);

异常消息如下所示:

Exception in thread "AWT-EventQueue-0"
java.lang.ClassCastException: class com.sun.media.sound.DirectAudioDevice$DirectSDL
   cannot be cast to class javax.sound.sampled.Clip
   (com.sun.media.sound.DirectAudioDevice$DirectSDL
   and javax.sound.sampled.Clip are in module java.desktop
   of loader 'bootstrap')

我不确定问题出在哪里。我使用 openjdk 版本“11.0.20”2023-07-18,当我运行时,我得到:java --list-module

[email protected]
java swing javasound java模块

评论

3赞 gthanop 8/3/2023
而不是你能试试吗?DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);DataLine.Info info = new DataLine.Info(Clip.class, audioFormat);
0赞 cpliu338 8/3/2023
是的,这行得通,谢谢。如果你把这当作一个答案,我会接受的。

答:

1赞 gthanop 8/3/2023 #1

根据文档(此处),您使用的构造函数的第一个参数是:DataLine.Info

Info 对象描述的数据行的类

然后,根据 's 方法的文档(这里):AudioSystemgetLine

获取与指定对象中的描述匹配的行。Line.Info

此外,是一个 ,因此我认为 的文档也适用于 。我的假设主要来自OOP继承和对实现的信任。DataLine.InfoLine.InfogetLineDataLine.Info

最后,错误是 ,它指示(并声明)返回的对象不是 的类型。ClassCastExceptiongetLineClip

从文档和对错误的观察中,如果假设为真,并且在搜索类似的用法以获得灵感之后,人们可能会得出结论,构造函数的第一个参数应该是 返回的对象类型。这就是为什么我在问题的评论中建议尝试以下解决方案:DataLine.InfogetLine

更改以下代码行:

DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);

自:

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

为了获得 的实例 (这是 ,这是 )。ClipDataLineLine

我没有尝试过,我对包不是很熟悉(因此最初是一条评论),但是由于您报告它有效,我认为这是一个答案并写在这里。javax.sound.sampled

3赞 VGR 8/4/2023 #2

我不知道为什么人们仍然相信Baeldung的家伙是Java专家。他不是。

您可以只替换以下行:

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

有了这个:

Clip audioClip = AudioSystem.getClip();

自 Java 1.5 以来,getClip() 方法就已经可用,因此 2023 年的一篇文章没有理由声称可以帮助 Java 程序员忽略它。

评论

0赞 gthanop 8/4/2023
所以在打开时会确定用?那么这是一个更好的答案。audioFormatAudioInputStreamClip
0赞 VGR 8/4/2023
是的。随意编写一个测试程序来向自己证明它有效。(或者我可以在我的答案中添加这样一个程序;它很短。