java泛型代码_JAVA泛型入门代码

让我们来写一段实际代码来了解,泛型设计代码如何写。

下面是设计一个游戏中的npc管理器。

[code]//npc

public abstract class Npc{

//...

}

//士兵,继承了npc

public class Soldier extends Npc{

public void goAttack(Location loc){

//...

}

}

//野兽,继承了npc

public class Beast extends Npc{

public void goAttack(Location loc){

//...

}

}

public class NpcManager {

private LinkedList npcs= new LinkedList();

public T spawnNpc(Class npcType) {

T npc=null;

try {

npc= npcType.newInstance();

} catch (InstantiationException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

}

npcs.add(npc);

return npc;

}

//示例,运行正常,生成Soldier对象

public Soldier spawnSoldier(){

Soldier soldier= this.spawnNpc(Soldier.class);

return soldier;

}

//示例,运行正常,生成Beast对象

public Beast spawnBeast(){

Beast beast= this.spawnNpc(Beast.class);

return beast;

}

//报错,因为spawnNpc方法只能接受父类是Npc的类。

public NpcManager spawnSomeshit(){

NpcManager shit= this.spawnNpc(NpcManager.class);

return shit;

}

}

我们可以看到有三个类,Npc、Soldier、NpcManager。NpcManager管理着所有npc,但在游戏里npc种类有很多呀,比如小兵、野怪,他们都是npc所以继承同一个Npc抽象类。以后还可能有更多游戏中的npc种类例如交易商人Trader等,我们想创建npc并且让这个npc受NpcManager管理,是一种工厂模式,怎么办呢?给NpcManager设置一个生成npc的生产方法。

在接触泛型之前,我们可能会把写这样一个生产方法:

[code]public Npc spawnNpc(NpcType type){

Npc npc=null;

if(NpcType.SOLDIER.equal(type)){

npc= new Soldier();

}else if(NpcType.MONSTER.equal(type)){

npc= new Monster();

}else if(NpcType.TRADER.equal(type)){

npc= new Trader();

}

//....

return npc;

}

public enum NpcType {

SOLDIER,

MONSTER,

TRADER,

//....

}

这样的话,是可行,但是它增加了一项工作,就是需要创建一个枚举类添加每个新写的Npc子类,这样是多余的,繁琐容易出错。每当以后创建一个Npc子类都得在NpcType枚举类里添加一个这样的类型,并且还需要在spawnNpc(type)方法中加入对这个类型的生成支持代码,实属繁琐。

用了泛型以后呢,我们不需要这个NpcType枚举类了,传递进去新出的Npc子类的类型即可。

不管以后游戏更新出多少种Npc,我们都无需为生成这种npc再多写代码,还是那个泛型方法spanwNpc(type)。这就是泛型的好处。

再深入一些

泛型中,针对不确定的类型的对象,可以用T、?来替补,并且可以指定父类,用extends,例如

[code]public T spawnNpc(Class npcType) ;

其中可以理解为对T这个代码变量的修饰符,修饰它为Npc类的子类。默认是Object的子类。

在方法声明一行中:

T是不确定类型的对象。

T就像是编写代码时的变量,而不是运行时变量。

可以在方法声明中多次声明T,出现的三个T都是同一个类型。起到类型关联的作用。

T泛型如果要指定父类,要在声明处(例如方法声明处)用extends并用<>套起来。

T的泛型主要用于不确定类型多处关联的地方,例如方法的参数类型和返回结果类型。

T泛型不仅可以用在方法声明上,还可以类的声明上,我们常见的List、Set就是使用了这样的泛型特性。

除了T之外,还有成对出现、键值的泛型变量可以用,例如Map的实现。个人暂时用不到。

Note: Class是泛型类,所以可以写为Class>

那么还有一种写法,是用?问号替换T,例如

[code]private List super Npc> npcs;

public void register(Npc npc){

npcs.add(npc);

}

?问号的泛型使用总结:

?是不确定的类型,并非对象。

不具关联性,只对输入限定类型为某类子类,而没有且不与输出类型关联;如果一行声明出现多个?,那么每个?都没有关联,都是独立的。

只能用于声明泛型变量的类型。不可独立出现,因为,它代表一个未知类型,而不是T这样的一个未知类型的对象。

如果要指定父类,要在?后面加上 super加上父类名。

实用性:能让我们在写代码时,限制一个泛型变量的赋值必须为某类子类,或干脆直接完全未知,不限制父类。

但在读取使用未知类型的时候,取出来类型是Object,如果要使用子类特性,还需要仔细检查类型并需要强制转换。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值