Java 重复剪辑

Posted

技术标签:

【中文标题】Java 重复剪辑【英文标题】:Java duplicate clip 【发布时间】:2019-03-26 06:37:10 【问题描述】:

我发现了很多建议和讨论克隆的主题,但我一直无法真正实现可以复制我的 Clip 对象的方法。

这是我尝试过的:

// ... setting up class ...

MyClip GunClip = new MyClip();

GunClip.set(Audiosystem.getClip());

AudioInputStream inputStream = AudioSystem.getAudioInputStream(new BufferedInputStream(getClass().getResourceAsStream("/Resources/sound/Laser.wav")));

GunClip.dummy.open(inputStream);
// ...

然后当触发事件时,我想重复播放该声音。所以我尝试复制它:

class MyClip implements Cloneable 

    Clip dummy;

    public MyClip() 

    

    public Clip get() 
        return dummy;
    

    public void set(Clip c) 
        this.dummy = c;
    

    @Override
    protected Object clone() throws CloneNotSupportedException 
        return super.clone();
    


我按照this 主题中的建议实现了 Cloneable 类。

然后我在播放之前克隆它:

MyClip c = (MyClip) GunClip.clone();

c.dummy.setFramePosition(0);
c.dummy.start();

但即使现在它也不起作用......

编辑:我已经弄清楚为什么它不起作用,这是因为它不是深度克隆,并且原始 GunClip 使用的 InputStream 没有被克隆。但由于 Clip 是一个抽象接口,因此克隆它可能比正常情况下更难。

【问题讨论】:

您的代码中没有显示任何“克隆”,只有糟糕的代码。在您的代码中,您将永远无法创建 MyClip 的实例,除非您已经拥有 MyClip 的实例。让 MyClip 实现 Cloneable 接口,然后实现它。 我也试过了,但它总是说clone() has protected access in Object,我写的代码是我在答案#1 ***.com/questions/869033/…中找到的代码的副本 你是怎么尝试的?你应该展示你尝试过的东西 在那个问题中,您已经使用 Clone 构造函数选择了答案。是的,您可以这样做,但您至少应该为您的类设置一个其他构造函数,否则您的代码将毫无用处。如果您想要一个如何正确使用 Cloneable 接口的示例:检查相同的线程,但 Bhasker Tiwari 发布的答案 已编辑但仍无法正常工作。我想知道为什么? 【参考方案1】:
class MyClip implements Cloneable 

    Clip dummy;

    public MyClip() 

    

    public Clip get() 
        return dummy;
    

    public void set(Clip c) 
        this.dummy = c;
    

    @Override
    protected Object clone() throws CloneNotSupportedException 
        return super.clone();
        

如果您编写这样的代码,您基本上是在说“Object 类了解我的自定义类的所有信息,包括如何构建它”。当然不是这样的。

您需要根据需要调整克隆方法:

class MyClip implements Cloneable 

    Clip dummy;

    public MyClip() 

    

    public Clip get() 
        return dummy;
    

    public void set(Clip c) 
        this.dummy = c;
    

    @Override
    protected Object clone() throws CloneNotSupportedException 
        MyClip clone = new MyClip(); // create a new instance of your class
        clone.set(this.dummy);       // make sure it has the same value for 'dummy'
                                     // I would suggest improvement on your setter and getter name, though
        return clone;  // This returns an instance of MyClip, which has the exact same
                       // state as your current, but is a clone, and not the same instance.
    


为了调用它,你需要这样的东西:

public void getClone(MyClip original) 
  MyClip Clone = (MyClip)original.clone();

编辑: 根据您的问题,原始的“虚拟”也被感染,如果您想防止这种情况,只需让您的 Clip 类也实现 Cloneable,并将您的克隆方法变成这样:

@Override
        protected Object clone() throws CloneNotSupportedException 
            MyClip clone = new MyClip(); 
            clone.set(this.dummy == null ? null : this.dummy.clone());     
            return clone;                            
        

【讨论】:

非常感谢。这是有道理的,但是,克隆仍然无法正常工作? 好的,我让你的班级使用字符串(而不是剪辑)我将看看我是否可以向后工作以使剪辑也工作 定义“不能正常工作”,你期望它做什么? 当我克隆字符串并修改生成的对象时,它也不会修改原始对象。有了剪辑,它似乎仍在这样做。 这并不意味着克隆不起作用。我会编辑我的答案【参考方案2】:

我喜欢在我的对象中编写一个复制构造函数。这给了我一种克隆对象的方法,而不必强制转换结果。您可以使用该构造函数以干净的方式实现 Cloneable ,因此您的对象仍然支持该接口。这就是我的意思,包括以这两种方式克隆对象的示例代码:

static class MyClip implements Cloneable 

    Clip dummy;

    public MyClip() 

    

    public MyClip(MyClip toCopy) 
        dummy = toCopy.dummy;
    

    public Clip get() 
        return dummy;
    

    public void set(Clip c) 
        this.dummy = c;
    

    @Override
    public Object clone() 
        return new MyClip(this);
    



public static void main(String... args) 
    MyClip original = new MyClip();
    MyClip clone1 = (MyClip)original.clone();
    MyClip clone2 = new MyClip(original);

编写复制构造函数来复制对象的另一个好处是,通过使用“super(toCopy);”调用其复制构造函数,可以自然地让超类参与复制操作。首先,然后复制您自己的子类中的字段。这不适用于这里,因为您正在实现一个接口,但如果您正在扩展另一个类,这很重要。

【讨论】:

谢谢!我已经实现了这一点,但是当我修改 clone2 时,它也在修改原始版本。有没有办法避免这种情况? 为什么要修改原版?我的代码不会。它所做的只是在 dummy = toCopy.dummy; 行中引用副本的虚拟值。 clone2.dummy.start() -> 当我打印该行时, original 和 clone2 都已开始。我相信这可能是因为原件加载了一个inputStream,这可能是通过引用传递的? 当我意识到你在谈论一个定义良好的 Clip 接口时,我放弃了这一点。由于 Clip 只是一个接口,因此我无法以这种方式克隆它。它似乎也没有“克隆”方法,所以我不知道如何克隆剪辑。 是的。无论如何,如果无法克隆剪辑,您可能必须这样做,并且您需要有两个唯一的剪辑对象。关键是要使用此代码进行深层复制,您需要将以下行: dummy = toCopy.dummy; 更改为复制 toCopy.dummy 的行b> 对象,而不是仅仅复制对它的引用。

以上是关于Java 重复剪辑的主要内容,如果未能解决你的问题,请参考以下文章

在moviepy中组合音频剪辑时的音频帧重复

编辑重复的影片剪辑会影响原始剪辑 - Flash CS

使用javascript播放声音剪辑[重复]

删除重复电影剪辑的最佳方法?

尽管设置为“剪辑”,但背景图像仍重复

SwiftUI 列表正在使用 .navigationBarItems 进行剪辑 [重复]