如何解决通过示例了解Java枚举方法的实现
因此,我现在正在与几个人一起为学校设计一个项目,其中一个人提交了一些代码,我确实很难解决问题。该项目的基础是创建一个包含歌曲,专辑和播放列表的音乐库。这些播放列表尤其是arraylists
首歌曲,它们需要不同的排序方式,因此他实现了用于排序的比较器。他使用枚举来做到这一点,我从实例的角度来理解这些枚举来表示项目。喜欢
public enum Suit {
SPADES,CLUBS,HEARTS,DIAMONDS
}
代表卡的不同花色。我还了解到您可以在枚举旁边声明方法,这就像他所做的一样。这是属性声明区域和构造函数:
public class Playlist implements Comparator<Song>{
private TotalTime aTotalTime;
private String aName;
private ArrayList<Song> playList;
private Comparator<Song> aComparator;
private enum Method{
SortByTitle(new Comparator<Song> () {
@Override
public int compare(Song o1,Song o2) {
// TODO Auto-generated method stub
return o2.getTitle().compareTo(o1.getTitle());
}
}),SortByArtist(new Comparator<Song>() {
@Override
public int compare(Song o1,Song o2) {
// TODO Auto-generated method stub
return o2.getExpectedTags().getArtist().compareTo(o1.getExpectedTags().getArtist());
}
}),SortByLength(new Comparator<Song>() {
@Override
public int compare(Song o1,Song o2) {
// TODO Auto-generated method stub
return o2.getTotalSeconds()-o1.getTotalSeconds();
}
});
private Comparator<Song> comparator;
Method(Comparator<Song> pComparator){
comparator = pComparator;
}
public Comparator<Song> getComparator(){
return this.comparator;
}
}
// constructor that initializes the the playlist.
public Playlist(String pName,Method aMethod) {
aName = new String(pName);
playList = new ArrayList<Song>();
this.aComparator = aMethod.getComparator();
}
}
我可以这样隐约地了解发生的情况:我们从构造函数开始,该构造函数调用aMethod.getComparator()
,其中aMethod
是枚举实例,然后aMethod.getComparator()
返回{{ 1}}对象,它本身在上面三行声明为this.comparator
。从我的角度来看,这似乎每次都会返回私有private Comparator<Song> comparator
对象,而实际上并没有改变comparator
接口的排序方法。解析所有这些内容的任何帮助将不胜感激。
解决方法
您的分析是正确的。这堂课很奇怪。一些值得注意的地方:
- 为什么播放列表是歌曲的比较器?允许使用“方法”对播放列表进行排序而不是继续进行构造。
- 提供的方法对播放列表中歌曲的顺序没有影响。
- Method枚举可能不应该是私有的。
可能值得重新审视项目中组件的范围。
- 什么是播放列表?如果歌曲顺序已更改,它是否是另一个播放列表?
- 由播放列表决定如何播放播放列表中的歌曲吗?
仅查看枚举定义。
枚举定义定义了3个实际枚举:SortByTitle
,SortByLength
和SortByArtist
-这些是您对此枚举的SPADE,HEARTS,DIAMONDS,CLUBS;
。对于每个值,都使用非零长度的构造函数对其进行初始化,并且传递的对象是比较器的自定义隐式实现,但现在就忘了这一切。
然后枚举值的枚举(heh)结束。为什么?因为是分号。
但是枚举定义还没有结束;那么我们得到private Comparator<Song> comparator;
。
请注意,每个枚举值都将获得该字段的副本。枚举的每个值本身就是该枚举表示的“类”的实例。这里的关键是该字段为SortByArtist
,SortByLength
等持有不同的比较器。
因此,Method.SortByArtist.getComparator();
返回Method
'class'实例的那个字段的值(枚举基本上是类,具有高度受限的构造;每个值仅一个实例,因此这里有3个实例,曾经)。与SortByLength
实例的该字段的值不同。
其余只是匿名内部类。
这是有效的Java,我认为应该很明显地知道,对吧?
class StringByLengthComparator implements Comparator<String> {
public int compare(String a,String b) {
return a.length() - b.length();
}
}
...
Comparator<String> c = new StringByLengthComparator();
但是我们可以使用“匿名内部类”的概念在Java中用更少的字符来编写。当您创建一个类然后打算仅一次使用此定义,然后再也不使用它时,此方法将起作用。假设这个“比较器c = ...;” line是整个代码库中唯一要提及的名称StringByLengthComparator
的位置。然后:
Comparator<String> c = new Conmparator<String>() {
public int compare(String a,String b) {
return a.length() - b.length();
}
};
看起来很时髦,但这表示完全一样。一个区别是仍然存在的此类并未命名为StringByLengthComparator
,但它得到一个您无需担心且永远不会使用的随机名称。没关系-毕竟,这是我们曾经使用过的唯一东西。
Java lambdas 。
请注意,您可以使用lambda语法使此值更短:
Comparator<String> c = (a,b) -> a.length() - b.length();
仍然意味着同一件事(嗯,您获得的对象不再存在,仅当您做非常愚蠢的事情(例如依赖于其对象标识哈希码或锁定比较器本身)时,这才有意义要做的事情。因此,如果您不做任何疯狂的事情,那是同一回事。
这就是代码的作用。与首先定义三个分别实现Comparable<Song>
的类,然后将new SongsByLengthComparer()
作为表达式作为第一个参数传递一样。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。