所以我有一个名为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类?
谢谢!
对的,这是可能的。我想到了两种选择。
选项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,它将简化不可变的实现,并具有一些整洁的性能优势。两个设计备注:
Album
的一个实例不会被垃圾收集,除非你也从listOfAllAlbumsCreated
中删除它。这可能是也可能不是你想要的。你可以做的是使用WeakReference
s,以便允许垃圾收集对象,如果只存在WeakReference
s这个对象。你会把listOfAllAlbumsCreated
改为List<WeakReference<Album>>
。作为回报,这会导致某些引用在您调用null
时返回get()
的情况。您可以尝试通过覆盖finalize()
方法来解决这个问题,但这是非常气馁的。Album
s提供了某种簿记,则可以实施Factory Method Pattern或Builder Pattern以防止创建重复项。有关此更完整的示例,您可能需要查看Integer.valueOf(int value)
的实现。我想你在这里混淆了一些概念。
“不可变”的东西意味着它一旦创建就无法更改。看来你不希望你的ArrayList是不可变的 - 只是保护谁可以访问它。
为了保护谁可以访问您的数据(或调用您的方法),您应该更改其access modifiers - public
,protected
,package-private
或private
之一。
截至目前,除了Album类之外,没有人能够实际更改listOfAllAlbumsCreated
ArrayList的内容,因为该变量是私有的,似乎没有任何方法可以更改其内容。 getListOfAllAlbumsCreated
是公共的,这意味着任何类都可以调用此方法并查看ArrayList中的内容。
如果您只希望播放列表能够调用此方法,则需要重构一下(除非播放列表将是您的包中唯一的其他类...这是不太可能的)。然而,专辑和播放列表之间似乎没有任何关系 - 使播放列表成为专辑的子类似乎不是一个合理的解决方案。我想知道listOfAllAlbumsCreated
是否真的需要在Album类中。对于专辑来说,了解所有存在的其他专辑似乎有点奇怪;这可能不是好设计。我要么将相册的ArrayList存储在另一个类中(可能是Playlist类,因为你想限制对这个类的访问),或者可能创建一个AlbumList类。
我能想到的唯一方法是使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
真的没有意义,但它确实完全符合你的要求。