试图保持ArrayList不变

问题描述 投票:1回答:3

所以我有一个名为Album的类,它包含一个名为'listOfAllAlbumsCreated'的静态ArrayList。

   public class Album {
    private static ArrayList<Album> listOfAllAlbumsCreated= new ArrayList<>();

           public Album(String albumTitle) {
                this.albumTitle = albumTitle;
                listOfAllAlbumsCreated.add(this);

    }


public static ArrayList<Album> getListOfAllAlbumsCreated() {
        return listOfAllAlbumsCreated;
    }// I only want PlayList Class to Access this!

}

基本上,每当创建一个Album对象时,'listOfAllAlbumsCreated'就会将该对象添加到它。然后,我创建了一个PlayList类,它应该可以访问所有创建的专辑 - 通过获取'listOfAllAlbumsCreated'并为其分配另一个ArrayList。

 public class PlayList {
    private static ArrayList<Album> allExistingAlbums = Album.getListOfAllAlbumsCreated();

 public PlayList(String playListName) {
        this.playListName = playListName;
    }

}

但是,这允许其他类中的任何人只调用Album.getListOfAllAlbumsCreated并可能更改我显然不想创建的所有专辑的内容。那么我怎样才能保持listOfAllAlbumsCreated的安全;即只能访问我的PlayList类?

谢谢!

java list mutable
3个回答
2
投票

对的,这是可能的。我想到了两种选择。

选项1:通过访问修饰符限制访问。

Oracle tutorial on access control有一个简洁的表概述了不同的访问修饰符做什么(表生成与Senseful):

╔═════════════╦═══════╦═════════╦══════════╦═══════╗
║  Modifier   ║ Class ║ Package ║ Subclass ║ World ║
╠═════════════╬═══════╬═════════╬══════════╬═══════╣
║ public      ║ Y     ║ Y       ║ Y        ║ Y     ║
║ protected   ║ Y     ║ Y       ║ Y        ║ N     ║
║ no modifier ║ Y     ║ Y       ║ N        ║ N     ║
║ private     ║ Y     ║ N       ║ N        ║ N     ║
╚═════════════╩═══════╩═════════╩══════════╩═══════╝

根据您的描述,private修饰符(仅授予当前类中的访问权限),no modifier(仅授予来自当前类和同一包中的类的访问权限)或protected修饰符(从当前类中授予访问权限,类在同一个包中并派生类)可能就是你要找的东西。该示例显示没有修饰符。

static ArrayList<Album> getListOfAllAlbumsCreated() {
    return listOfAllAlbumsCreated;
}

选项2:返回列表的不可修改的视图。

通过List返回你的Collections.unmodifiableList(...)的不可修改的视图。您的代码将如下所示:

public static ArrayList<Album> getListOfAllAlbumsCreated() {
    return Collections.unmodifiableList(listOfAllAlbumsCreated);
}

关于不可修改清单的两个警告词:

  • 在您调用List之后对原始getListOfallAlbumsCreated()所做的更改将不会反映在不可修改的视图中。不可修改的视图仅是您创建不可修改视图时的列表视图。
  • 虽然返回的List是不可修改的,但List中的条目不是。 Java没有像C ++那样的const对象的概念。为了实现真正的不变性,你需要设计你的Album类是不可变的。在未来,我们很可能会有value types,它将简化不可变的实现,并具有一些整洁的性能优势。

两个设计备注:

  • 你正在做的是基本上重新创建Java - 相当于内存泄漏。 Album的一个实例不会被垃圾收集,除非你也从listOfAllAlbumsCreated中删除它。这可能是也可能不是你想要的。你可以做的是使用WeakReferences,以便允许垃圾收集对象,如果只存在WeakReferences这个对象。你会把listOfAllAlbumsCreated改为List<WeakReference<Album>>。作为回报,这会导致某些引用在您调用null时返回get()的情况。您可以尝试通过覆盖finalize()方法来解决这个问题,但这是非常气馁的。
  • 如果您已经为Albums提供了某种簿记,则可以实施Factory Method PatternBuilder Pattern以防止创建重复项。有关此更完整的示例,您可能需要查看Integer.valueOf(int value)的实现。

2
投票

我想你在这里混淆了一些概念。

“不可变”的东西意味着它一旦创建就无法更改。看来你不希望你的ArrayList是不可变的 - 只是保护谁可以访问它。

为了保护谁可以访问您的数据(或调用您的方法),您应该更改其access modifiers - publicprotectedpackage-privateprivate之一。

截至目前,除了Album类之外,没有人能够实际更改listOfAllAlbumsCreated ArrayList的内容,因为该变量是私有的,似乎没有任何方法可以更改其内容。 getListOfAllAlbumsCreated是公共的,这意味着任何类都可以调用此方法并查看ArrayList中的内容。

如果您只希望播放列表能够调用此方法,则需要重构一下(除非播放列表将是您的包中唯一的其他类...这是不太可能的)。然而,专辑和播放列表之间似乎没有任何关系 - 使播放列表成为专辑的子类似乎不是一个合理的解决方案。我想知道listOfAllAlbumsCreated是否真的需要在Album类中。对于专辑来说,了解所有存在的其他专辑似乎有点奇怪;这可能不是好设计。我要么将相册的ArrayList存储在另一个类中(可能是Playlist类,因为你想限制对这个类的访问),或者可能创建一个AlbumList类。


0
投票

我能想到的唯一方法是使Playlist静态内部类Album,失去吸气剂并单独访问listOfAllAlbumsCreated内部的Playlist

public class Album {
    private static ArrayList<Album> listOfAllAlbumsCreated= new ArrayList<>();

    public Album(String albumTitle) {
        this.albumTitle = albumTitle;
        listOfAllAlbumsCreated.add(this);
    }

    public static class PlayList {

        public PlayList(String playListName) {
            this.playListName = playListName;
        }

        public someMethod() {
            listOfAllAlbumsCreated.get(0);
        }
    }
}

这可能不是一个好的解决方案,因为在Playlist类中声明Album真的没有意义,但它确实完全符合你的要求。

© www.soinside.com 2019 - 2024. All rights reserved.