簡體   English   中英

Java8 - “有效最終”

[英]Java8 - “effectively final”

我正在使用RxVertx這是一種RxJava和Java8,我有一個編譯錯誤。

這是我的代碼:

public rx.Observable<Game> findGame(long templateId, GameModelType game_model, GameStateType state) {

return context.findGame(templateId, state)
    .flatMap(new Func1<RxMessage<byte[]>, rx.Observable<Game>>() {

        @Override
        public Observable<Game> call(RxMessage<byte[]> gameRawReply) {

            Game game = null;

            switch(game_model) {

                case SINGLE: {

                    ebs.subscribe(new Action1<RxMessage<byte[]>>() {

                        @Override
                        public void call(RxMessage<byte[]> t1) {

                            if(!singleGame.contains(0) {
                                game = new Game();       // ERROR is at this line
                                singleGames.put(0, game);
                            } else {
                              game = singleGames.get(0); // ERROR is at this line
                            }
                        }
                    });
                }
            }

            return rx.Observable.from(game);
        }
    });
}

編譯錯誤是:“在封閉范圍內定義的局部變量游戲必須是最終的或有效的最終”

我無法將'游戲'定義為最終,因為我在分配\\ set並在函數結束時返回它。

我怎樣才能編譯這段代碼?

謝謝。

我有一個Holder類,我用於這種情況。

/**
 * Make a final one of these to hold non-final things in.
 *
 * @param <T>
 */
public class Holder<T> {
  private T held = null;

  public Holder() {
  }

  public Holder(T it) {
    held = it;
  }

  public void hold(T it) {
    held = it;
  }

  public T held() {
    return held;
  }

  public boolean isEmpty() {
    return held == null;
  }

  @Override
  public String toString() {
    return String.valueOf(held);
  }

}

然后你可以做以下事情:

final Holder<Game> theGame = new Holder<>();
...

theGame.hold(myGame);
...
{
  // Access the game through the `final Holder`
  theGame.held() ....

由於您不需要修改對象的引用,因此您可以將Game包裝在其他內容中。

最快(但很難看)修復是使用大小為1的數組,然后稍后設置數組的內容。 這是有效的,因為數組實際上是最終的,數組中包含的內容不一定是。

@Override
    public Observable<Game> call(RxMessage<byte[]> gameRawReply) {

        Game[] game = new Game[1];

        switch(game_model) {

            case SINGLE: {

                ebs.subscribe(new Action1<RxMessage<byte[]>>() {

                    @Override
                    public void call(RxMessage<byte[]> t1) {

                        if(!singleGame.contains(0) {
                            game[0] = new Game();       
                            singleGames.put(0, game[0]);
                        } else {
                          game[0] = singleGames.get(0);
                        }
                    }
                });
            }
        }

        return rx.Observable.from(game[0]);
    }

另一個類似的選項是創建一個具有Game字段的新類,然后再設置該字段。

CyclopsMutableLazyImmutable對象來處理這個用例。 Mutable是完全可變的,並且LazyImmutable設置一次。

 Mutable<Game> game = Mutable.of(null);

 public void call(RxMessage<byte[]> t1) {

                        if(!singleGame.contains(0) {
                           game.mutate(g -> new Game());       
                            singleGames.put(0, game.get());
                        } else {
                          game[0] = game.mutate(g->singleGames.get(0));
                        }
               }

LazyImmutable可用於懶惰地設置一次值:

LazyImmutable<Game> game = LazyImmutable.def();

public void call(RxMessage<byte[]> t1) {

     //new Game() is only ever called once
     Game g = game.computeIfAbsent(()->new Game());
}

你不能。 至少不是直接的。 你可以使用包裝類:只需定義一個以游戲為屬性的類“GameContainer”,然后改為對該容器進行最終引用。

@ dkatzel的建議很好,但還有另一種選擇:將關於檢索/創建Game的所有內容提取到幫助方法中,然后聲明final Game game = getOrCreateGame(); 我認為這比最終的陣列方法更清晰,盡管最終的陣列方法肯定會有效。

雖然其他方法看起來可以接受,但我想提一下,你不能確定訂閱ebs會是同步的,你可能最終總是從內部函數返回null。 由於你依賴於另一個Observable,你可以簡單地通過以下方式編寫它:

public rx.Observable<Game> findGame(
        long templateId, 
        GameModelType game_model, 
        GameStateType state) {

    return context.findGame(templateId, state)
    .flatMap(gameRawReply -> {
        switch(game_model) {
        case SINGLE: {
            return ebs.map(t1 -> {
                Game game;
                if (!singleGame.contains(0) {
                    game = new Game();
                    singleGames.put(0, game);
                } else {
                    game = singleGames.get(0);
                }
                return game;
            });
        }
        }

        return rx.Observable.just(null);
    });
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM