RX-java的按引用传递或按值传递? [英] Rx-java pass by reference or pass by value?

查看:304
本文介绍了RX-java的按引用传递或按值传递?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Java方法一切都是通过传值,所以我可以改变传递给方法的对象的属性和期望,原来的对象属性被更改。但在这种方法我得到不同的结果:

In java methods everything is passed-by-value so i can change the object attributes passed to the method and expect that the original object attributes are changed. but in this method i get different result:

我有这样的方法:

public Observable<Menu> makeMenu(Menu menu, NumberSettingChanges.MenuChanges changes) {
    // Start flow with added and edited extensions
    return Observable.from(changes.added.entrySet())
            .mergeWith(Observable.from(changes.edited.entrySet()))
                    //Upload announcement voices or do nothing if extension is not an announcement
            .flatMap(e -> {
                        if (AppTypeContract.APP_TYPE_ANNOUNCEMENT.equals(e.getValue().type)) {
                            return mMediaManager.uploadAsync(e.getValue().config.localPrompt)
                                    .doOnNext(response -> {
                                        //Update extension prompt with the storage path.
                                        menu.config.extensions.get(e.getKey()).config.prompt = response.mPath;
                                        menu.config.extensions.get(e.getKey()).config.localPrompt = "";
                                    })
                                    .flatMap(response -> Observable.just(e));
                        } else {
                            return Observable.just(e);
                        }
                    }
            )
}

和我操作菜单中的属性flatmap:

and i manipulate menu attributes in the flatmap:

menu.config.extensions.get(e.getKey()).config.localPrompt = "";

我把在同一类中的方法:

I call the method in the same class:

public Observable<NumberSetting> saveSettings(NumberSetting o, NumberSetting n) {
    NumberSettingChanges changes = compareNumberSetting(o, n);

    return makeMenu(n.day, changes.day)
            .mergeWith(makeMenu(n.night, changes.night));
    }

最后:

saveSettings(ns, mNumberSettingNew).subscribe();

我所想到的是, mNumberSettingNew.menu.config.extensions.get(e.getKey())。config.prompt 被改变,但没有改变发生后,该呼叫和 mNumberSettingNew 的变化都没有。

What i expect is that the mNumberSettingNew.menu.config.extensions.get(e.getKey()).config.prompt is changed but no change is happening after this call and the mNumberSettingNew has no change at all.

请注意,我相信,改变提示线调试完成。

Note that i am sure that changing prompt line is done in the debug.

推荐答案

我不认为我可以解释Java的参数语义比任何(甚至一半好),你在你的第一个段落引用链接更好,所以我赢了T尝试。主要的一点是:在Java中一切都按值传递(即复制。),但什么物体复制不是的对象本身,而是参照对象的。因此,换句话说基准是按值传递

I don't think I could explain Java's parameter semantics any better than (or even half as good as) the link you referenced in your first paragraph so I won't try. The main point is: Everything in Java is passed by value (i. e. copied) but with objects what is copied is not the object itself but the reference to the object. So in other words the reference is passed by value.

所以,对于您的具体问题:是的,如果你传递一个引用可变对象一些RX-java的code,提及将指向对象的同一个实例。如果发生变异实例,然后调用者code也将能够看到的变化,因为他们在的相同的实例的制作。这是因为RX-java的仍然只有Java和不能改变该级别语言的语义。

So with respect to your particular problem: Yes, if you pass a reference to a mutable object to some rx-java code that reference will point to the same instance of the object. If you mutate the instance then the caller code will also be able to see the changes because they were made on the same instance. That's because rx-java is still only Java and cannot change the language semantics on that level.

在没有看到整个code,我不能确定这可能是这里的问题...当你检查是否 mNumberSettingsNew 其实有你在做的改变你的 doOnNext ?如果立即检查后 saveSettings(NS,mNumberSettingNew).subscribe(); 你的 uploadAsync 可能还没有返回。你可以尝试在增加实际用户你的订阅并检查结果在那里。

Without seeing the whole code I am unsure what could be the problem here... When are you checking whether mNumberSettingsNew actually has the changes you were making in your doOnNext? If you check that immediately after saveSettings(ns, mNumberSettingNew).subscribe(); your uploadAsync may not have returned yet. You could try adding an actual Subscriber in your subscribe and check the result there.

在更广泛的说明,我想你应该尽量避免副作用,像这样的东西,你可以使用RX-java的时候。你的情况 - 以一个输入对象,应用一组(可能是异步)切换到那个对象,并等待改变的输出对象 - 是有点棘手,但我认为这可能与扫描<完成/ code>。也许隐约的东西是这样的:

On a more general note, I think you should try to avoid side-effects like this as much as you can when using rx-java. Your case - taking an input object, applying a set of (possibly asynchronous) changes to that object, and waiting for the changed output object - is a bit tricky, but I think it could be done with scan. Maybe something vaguely like this:

Observable.from(changes.added.entrySet())
    .mergeWith(Observable.from(changes.edited.entrySet()))
    .scan(menuBeforeAnyChanges, new Func2<Menu, Change, Menu>() {

        public Menu call(final Menu previousVersionOfTheMenu, final Change nextChange) {
            // since I don't know of a version of scan that can return 
            // an Observable you would I think you would have to adapt
            // your code in here to be fully synchronous - but of
            // course the scan itself could run asynchronously
            final newVersionOfTheMenu = previousVersionOfTheMenu.applyChange(nextChange);
            return newVersionOfTheMenu;
        }
     )

这将采取菜单的原始版本,依次从添加应用所有更改编辑和/发射/菜单的每个更新版本。所以,你不会有任何副作用,但只要订阅该观察到了认购&LT;菜单&gt; ,然后采取最后一个()菜单,这将是一个与所有的更改。

This would take the original Version of the menu, consecutively apply all the changes from added and edited and /emit/ every updated version of menu. So you would not have any side effects but simply subscribe to that observable with a Subscriber<Menu> and then take the last() Menu and that would be the one with all changes applied.

修改:哦,我刚才看到有所谓的另一种方法减少的做到了这一点:首先扫描然后末页 takeLast

EDIT: Oh, I just saw that there is another method called reduce that does just that: first scan and then last or takeLast.

这篇关于RX-java的按引用传递或按值传递?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆