本文是針對List<T>
的用法和場景:
舉個例子
你有 一個羊羣 和 一個牛羣。
羊羣和牛羣都會遛彎。
羊會 咩咩叫 和 需要餵養。
牛會 哞哞叫 和 需要餵養。
代碼的樣子
你有 一個羊羣 和 一個牛羣。
public class HerdSheep extends Herd{
/**
* 羊羣
*/
List<Sheep> sheeps;
public List<Sheep> getSheeps() {
return sheeps;
}
public void setSheeps(List<Sheep> sheeps) {
this.sheeps = sheeps;
}
@Override
public String toString() {
return "HerdSheep{" +
"sheeps=" + sheeps +
"} " + super.toString();
}
}
public class HerdCow extends Herd {
/**
* 牛羣
*/
private List<Cow> cows;
public List<Cow> getCows() {
return cows;
}
public void setCows(List<Cow> cows) {
this.cows = cows;
}
@Override
public String toString() {
return "HerdCow{" +
"cows=" + cows +
"} " + super.toString();
}
}
羊羣和牛羣都會遛彎。
public class Herd {
/**
* 遛彎
*/
private String walk;
public String getWalk() {
return walk;
}
public void setWalk(String walk) {
this.walk = walk;
}
@Override
public String toString() {
return "Herd{" +
"walk='" + walk + '\'' +
'}';
}
}
羊會 咩咩叫 和 需要餵養。
public class Sheep {
/**
* 羊叫
*/
private String bleat;
/**
* 是否被餵過
*/
private String fed;
public Sheep(String bleat, String fed) {
this.bleat = bleat;
this.fed = fed;
}
public String getFed() {
return fed;
}
public void setFed(String fed) {
this.fed = fed;
}
@Override
public String toString() {
return "Sheep{" +
"bleat='" + bleat + '\'' +
", fed='" + fed + '\'' +
'}';
}
}
牛會 哞哞叫 和 需要餵養。
public class Cow {
/**
* 牛叫
*/
private String moo;
/**
* 是否被餵過
*/
private String fed;
public Cow(String moo, String fed) {
this.moo = moo;
this.fed = fed;
}
public String getFed() {
return fed;
}
public void setFed(String fed) {
this.fed = fed;
}
@Override
public String toString() {
return "Cow{" +
"moo='" + moo + '\'' +
", fed='" + fed + '\'' +
'}';
}
}
牧羊的孩子要幹活了
如果需要你去把每一隻沒喫飽的牲口餵飽,你怎麼辦?
我是這麼做的:
HerdSheep herdSheep = new HerdSheep();
herdSheep.setWalk("溜過彎了");
Sheep sheep0 = new Sheep("咩咩", "喫飽了");
Sheep sheep1 = new Sheep("咩咩", "沒喫飽");
List<Sheep> sheeps = new ArrayList<>();
sheeps.add(sheep0);
sheeps.add(sheep1);
herdSheep.setSheeps(sheeps);
work(herdSheep);
/**
* 放羊娃幹活:給沒喫飽的牲口餵食
*
* @param herd
*/
public void work(Herd herd) {
if (herd instanceof HerdSheep) {
for (int i = 0; i < ((HerdSheep) herd).getSheeps().size(); i++) {
Sheep sheep = ((HerdSheep) herd).getSheeps().get(i);
if (sheep.getFed().equals("沒喫飽")) {
sheep.setFed("吃了兩頓喫飽了");
}
}
} else if (herd instanceof HerdCow) {
for (int i = 0; i < ((HerdCow) herd).getCows().size(); i++) {
Cow cow = ((HerdCow) herd).getCows().get(i);
if (cow.getFed().equals("沒喫飽")) {
cow.setFed("吃了兩頓喫飽了");
}
}
}
Log.i("yico", herd.toString());
}
結果:
HerdSheep{
sheeps=[
Sheep{
bleat='咩咩',
fed='喫飽了'
},
Sheep{
bleat='咩咩',
fed='吃了兩頓喫飽了'
}
]
}Herd{
walk='溜過彎了'
}
看,第二隻餓着的羊也喫飽了。
但是我們發現work()方法雖然接收的是Herd,但是裏面的操作確實區分 羊羣(HerdSheep) 和 牛羣(HerdCow)來做,並且做的事情都是對牲口 餵養(fed),這讓我很不爽。
那麼我們要怎麼做呢?
- 首先 羊羣(HerdSheep) 和 牛羣(HerdCow)和List要放到Herd內,不然還是沒法對Herd直接操作。
- 其次Sheep和Cow的fed方法要抽象到一個父類(Animal)裏,不然也沒法繞開Sheep和Cow對fed操作。
第一次改造
public class Herd {
/**
* 遛彎
*/
private String walk;
private List<Animal> animals;
public String getWalk() {
return walk;
}
public void setWalk(String walk) {
this.walk = walk;
}
public List<Animal> getAnimals() {
return animals;
}
public void setAnimals(List<Animal> animals) {
this.animals = animals;
}
@Override
public String toString() {
return "Herd{" +
"walk='" + walk + '\'' +
", animals=" + animals +
'}';
}
}
public class HerdSheep extends Herd{
@Override
public String toString() {
return "HerdSheep{} " + super.toString();
}
}
public class Animal {
/**
* 是否被餵過
*/
private String fed;
public Animal(String fed) {
this.fed = fed;
}
public String getFed() {
return fed;
}
public void setFed(String fed) {
this.fed = fed;
}
@Override
public String toString() {
return "Animal{" +
"fed=" + fed +
'}';
}
}
public class Sheep extends Animal{
/**
* 羊叫
*/
private String bleat;
public Sheep(String fed, String bleat) {
super(fed);
this.bleat = bleat;
}
@Override
public String toString() {
return "Sheep{" +
"bleat='" + bleat + '\'' +
"} " + super.toString();
}
}
HerdSheep herdSheep = new HerdSheep();
herdSheep.setWalk("溜過彎了");
Sheep sheep0 = new Sheep("喫飽了", "咩咩");
Sheep sheep1 = new Sheep("沒喫飽", "咩咩");
List<Animal> sheeps = new ArrayList<>();
sheeps.add(sheep0);
sheeps.add(sheep1);
herdSheep.setAnimals(sheeps);
work(herdSheep);
public void work(Herd herd) {
for (int i = 0; i < herd.getAnimals().size(); i++) {
if (herd.getAnimals().get(i).getFed().equals("沒喫飽")) {
herd.getAnimals().get(i).setFed("吃了兩頓喫飽了");
}
}
Log.i("yico",herd.toString());
}
我們發現,這麼改造後,work()方法簡單多了是嗎?
可是構造有問題,我們在構造羊羣的時候,List內是Animal,這個寫法還是很彆扭的。
爲什麼會這麼彆扭呢?
因爲:
hardSheep的setAnimals方法是父類的,但父類的List內是Animal,因此herdSheep.setAnimals(sheeps)的sheeps必須是List<Animal>
類型的,而不能是List<Sheep>
。
那麼我們怎麼辦呢?用 泛型 T 啊!
第二次改造
public class Herd <T extends Animal>{
/**
* 遛彎
*/
private String walk;
private List<T> animals;
public String getWalk() {
return walk;
}
public void setWalk(String walk) {
this.walk = walk;
}
public List<T> getAnimals() {
return animals;
}
public void setAnimals(List<T> animals) {
this.animals = animals;
}
@Override
public String toString() {
return "Herd{" +
"walk='" + walk + '\'' +
", animals=" + animals +
'}';
}
}
public class HerdSheep extends Herd<Sheep>{
@Override
public String toString() {
return "HerdSheep{} " + super.toString();
}
}
HerdSheep herdSheep = new HerdSheep();
herdSheep.setWalk("溜過彎了");
Sheep sheep0 = new Sheep("喫飽了", "咩咩");
Sheep sheep1 = new Sheep("沒喫飽", "咩咩");
List<Sheep> sheeps = new ArrayList<>();
sheeps.add(sheep0);
sheeps.add(sheep1);
herdSheep.setAnimals(sheeps);
work(herdSheep);
public void work(Herd herd) {
for (int i = 0; i < herd.getAnimals().size(); i++) {
if (((Animal) herd.getAnimals().get(i)).getFed().equals("沒喫飽")) {
((Animal) herd.getAnimals().get(i)).setFed("吃了兩頓喫飽了");
}
}
Log.i("yico", herd.toString());
}
結果:
HerdSheep{
}Herd{
walk='溜過彎了',
animals=[
Sheep{
bleat='咩咩'
}Animal{
fed=喫飽了
},
Sheep{
bleat='咩咩'
}Animal{
fed=吃了兩頓喫飽了
}
]
}
諾,是不是舒服多了,Herd和HerdSheep這兩個對象給別人用的時候就不會感覺突兀了。
另外HerdSheep extends Herd<Sheep>
裏這個<Sheep>
不是必寫的,但是寫上可以規範代碼,防止傳入錯誤的數據類型。
比如:
List<Cow> cows = new ArrayList<>();
HerdSheep herdSheep = new HerdSheep();
herdSheep.setAnimals(cows);
如果不寫<Sheep>
的話,上面不會報錯,但這樣你就把牛羣放到羊圈咯,哈哈。
代碼請見:點擊下載
注:sheep單複數同型,上文中用到sheeps是爲了區別羊羣和羊,請注意(⊙o⊙)哦!!!