本文是针对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⊙)哦!!!