我有這 3 節課:
第一
private List<Domino> pile = new ArrayList<Domino>();
public DominoPile(List<Domino> list) {
this.pile = list;
}
public List<Domino> getList(){
return List.copyOf(pile);
}
public void getOutLastOne() {
pile.remove(this.getLast(0));
}
public Domino getLast(int nbr) {
return nbr == 0 || nbr > this.getSize() ? pile.get(pile.size() - 1) : pile.get(pile.size() - 1 - nbr);
}
public int getSize() {
return pile.size();
}
}
第二個
public class KingdominoGameFactory {
private List<Player> pl;
private List<Domino> dom;
private int selected;
private DominoPile pile;
private int nbrPl;
public KingdominoGameFactory(List<Player> p, List<Domino> d) {
// TODO Auto-generated constructor stub
this.setPl(List.copyOf(p));
this.setDom(List.copyOf(d));
}
public List<Player> getPl() {
return pl;
}
public void setPl(List<Player> pl) {
this.pl = pl;
}
public List<Domino> getDom() {
return dom;
}
public void setDom(List<Domino> dom) {
this.dom = dom;
}
public int getSelected() {
return selected;
}
public void setSelected(int selected) {
this.selected = selected;
}
public int getNbrPl() {
return nbrPl;
}
public void setNbrPl() {
if(selected == 0) this.nbrPl = 2;
else if(selected == 1) this.nbrPl = 3;
else this.nbrPl = 4;
}
public DominoPile getPile() {
return pile;
}
private void setPile(DominoPile pile) {
this.pile = pile;
}
public void nbrDomFinal() {
if(this.getNbrPl() == 2) this.setPile(new DominoPile(this.getDom().subList(0, 24)));
else if(this.getNbrPl() == 3) this.setPile(new DominoPile(this.getDom().subList(0, 36)));
else this.setPile(new DominoPile(this.getDom()));
}
public void nbrPlFinal() {
if(this.getNbrPl() == 2) this.setPl(this.getPl().subList(0, 2));
else if(this.getNbrPl() == 3) this.setPl(this.getPl().subList(0, 3));
else this.setPl(this.getPl());
}
第三個
public class Game {
private List<Player> players;
private DominoPile pile;
private DrawLine actual = new DrawLine(new TreeSet<Domino>());
private final int nbrDraw;
public Game(KingdominoGameFactory kg){
this.nbrDraw = kg.getNbrPl() == 3 ? 3 : 4;
this.pile = new DominoPile(List.copyOf(kg.getPile().getList()));
this.players = this.getListPlayers();
}
private void addActual(){
actual.add(pile.getLast(0));
}
public int getNbrDraw() {
return nbrDraw;
}
public List <Player> getListPlayers(){
return players;
}
public void setDrawActual() {
actual.clear();
for(int i = 0; i < nbrDraw; i) {
this.addActual();
pile.getOutLastOne();
}
}
public DrawLine getActual() {
return actual;
}
public DominoPile getPile() {
return pile;
}
}
然后我讓我做這個測驗
@BeforeEach
void setup() {
List<Domino> liste = new ArrayList<Domino>();
liste.add(new Domino(1, new Tile(Terrain.CASTLE, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(2, new Tile(Terrain.CASTLE, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(3, new Tile(Terrain.CASTLE, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(4, new Tile(Terrain.EMPTY, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(5, new Tile(Terrain.EMPTY, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(6, new Tile(Terrain.EMPTY, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(7, new Tile(Terrain.EMPTY, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(8, new Tile(Terrain.EMPTY, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(9, new Tile(Terrain.EMPTY, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(10, new Tile(Terrain.EMPTY, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(11, new Tile(Terrain.EMPTY, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(12, new Tile(Terrain.EMPTY, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(13, new Tile(Terrain.EMPTY, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(14, new Tile(Terrain.EMPTY, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(15, new Tile(Terrain.EMPTY, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(16, new Tile(Terrain.EMPTY, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(17, new Tile(Terrain.EMPTY, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(18, new Tile(Terrain.EMPTY, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(19, new Tile(Terrain.EMPTY, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(20, new Tile(Terrain.EMPTY, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(21, new Tile(Terrain.EMPTY, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(22, new Tile(Terrain.EMPTY, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(23, new Tile(Terrain.EMPTY, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(24, new Tile(Terrain.EMPTY, 2), new Tile(Terrain.CASTLE, 1)));
liste.add(new Domino(25, new Tile(Terrain.EMPTY, 2), new Tile(Terrain.CASTLE, 1)));
List<Player> liste2 = new ArrayList<Player>();
liste2.add(new Player("Jeff", "366"));
liste2.add(new Player("Jeff", "366"));
liste2.add(new Player("Jeff", "366"));
liste2.add(new Player("Jeff", "366"));
kg = new KingdominoGameFactory(liste2, liste);
kg.setSelected(0);
kg.setNbrPl();
kg.nbrDomFinal();
kg.nbrPlFinal();
game = new Game(kg);
}
@Test
void setActual() {
game.setDrawActual();
assertEquals(game.getActual().getSize(), 4);
}
然后我有這個錯誤
java.lang.UnsupportedOperationException
at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:72)
at java.base/java.util.ImmutableCollections$AbstractImmutableCollection.remove(ImmutableCollections.java:79)
at kingdomino.domains.DominoPile.getOutLastOne(DominoPile.java:23)
at kingdomino.domains.Game.setDrawActual(Game.java:35)
at kingdomino.domains.GameTest.setActual(GameTest.java:87)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
我不知道為什么我不能從 Game 類中洗掉,因為 DominoPile 的測驗都是成功的,這是唯一有問題的測驗,我不知道如何解決這個問題我試圖改變我的收藏型別,我也嘗試改變我的方法“getOutLastOne”
uj5u.com熱心網友回復:
List.copyOf
這使您傳遞給它的任何內容都成為不可變(即:只讀)副本。復制它沒有進一步的意義(事實上,我相信如果你在其中傳遞一個已經不可變的串列,它只會逐字回傳它;復制無法修改的東西沒有意義)。
創建 DominoPile 物件時,將結果傳遞List.copyOf給其建構式,這意味著pileDominoPile 中的欄位現在是這些不可變串列之一。稍后,您的代碼呼叫getOutLastOnewhich 修改(更改)該pile欄位參考的串列,這不起作用,因為它不能被修改。正如例外所述。
那就是問題所在。您可以使用 3 種不同的策略來解決問題。概括地說:
- 傳入串列的建構式中的檔案
DominoPile是逐字記錄的,并將按原樣修改,這意味著:它不能是不可變的(現在呼叫者有責任閱讀檔案并按照它所說的去做),以及任何影響由 DominoPile 引起的串列(例如洗掉最后一個)回顯到最初用于創建 DominoPile 物件的串列。
完成后(基本上,您需要做的就是添加一些 javadoc),然后呼叫者(您當前擁有的位置new DominoPile(List.copyOf(kg....)))需要停止傳遞不可變串列。這很容易 - 替換List.copyOf(X)為new ArrayList<>(X)- 也可以制作副本,但是是可變的。
或者,您也可以選擇稍微不同的設計:讓 DominoPile 僅將提供的串列視為模板,從而讓 DominoPile 建構式創建一個新的(可變的!)串列,它是它的副本。換句話說,
this.pile = pile在建構式和set方法中都用this.pile = new ArrayList<>(pile)替換。setPile但如果發生這種情況,我有點不喜歡這個名字。DominoPile 變得不可變,所有設定的方法都需要消失,所有資料結構都變得不可變,并且類似的方法
.getOutLastOne實際上并沒有洗掉任何東西(它不能 - 一切都不能修改),而是創建了一個全新的 DominoPile 物件自己的克隆,除了移除了一個多米諾骨牌。現在,您的串列是不可變的這一事實(如果有的話)是一個好處。這是……我認為在相當大的程度上過度設計了事情。
這些選項按我如何做的順序列出 - 所以,除非你有一個緊迫的理由為什么第一個選項對你來說聽起來很糟糕,否則我會選擇第一個,在這里。基于您的 API 設計(例如擁有一個set方法,這意味著您似乎并不特別渴望不變性)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/469976.html
