Java编程——对于向下转型的理解

通过一个小Demo,来学习下向下转型,了解下这种特性的意义和使用场景。

新建一个饼干接口,(对于接口不了解的小伙伴,可以阅读这篇文章Java编程——对于接口的理解

package com.shenqi.xiaobaiyang;
/*
 * 新建一个饼干接口
 */
public interface Biscuits {}

新建一个曲奇饼干类,并实现饼干接口

package com.shenqi.xiaobaiyang;
/*
 * 新建一个曲奇饼干类,并实现饼干接口
 */
public class Cookies implements Biscuits {

	public String rawMaterialcookies() {
		
		return "曲奇饼干:以小麦粉、糖、乳制品为主要原料,"
				+ "加入疏松剂和其他辅料,以和面,采用挤注、挤条、"
				+ "钢丝节割等方法中的一种形式成型,烘烤制成的具有立体花纹"
				+ "或表面有规则波纹、含油脂高的酥化焙烤食品。";
		
	}
	
}

新建一个夹心饼干类,并实现饼干接口

package com.shenqi.xiaobaiyang;
/*
 * 新建一个夹心饼干类,并实现饼干接口
 */
public class SandwichBiscuit implements Biscuits {

	public String rawMaterialSandwichBiscuit() {
		
		return "夹心饼干:在两块饼干之间添加糖、"
				+ "油脂或果酱为主要原料的各种夹心料的夹心焙烤食品。";
		
	}
	
}

新建一个酥性饼干类,并实现饼干接口

package com.shenqi.xiaobaiyang;
/*
 * 新建一个酥性饼干类,并实现饼干接口
 */
public class ShortBiscuit implements Biscuits {

	public String rawMaterialShortBiscuit() {
		
		return "酥性饼干,以小麦粉、糖、油脂为主要原料,"
				+ "加入疏松剂和其他辅料,经冷粉工艺调粉、辊压、辊印或者冲、"
				+ "烘烤制成的造型多为凸花的,断面结构呈现多孔状组织,口感疏松的烘焙食品。";
		
	}
	
}

这里子类很多,但是里面只有一个方法,返回自己类型饼干的原料。

我一般在外面超市买饼干的时候,都会背个包去。那么,一个用来装东西的类就出来了。新建一个包类。

package com.shenqi.xiaobaiyang;

import java.util.ArrayList;
import java.util.List;

/**
 * 
 * @author xiaobaiyang
 * 功能:可以知道包中有多少盒饼干,可以拿出对应的饼干类型以供小白阳【这个吃货】享用。
 *
 */

public class Bag {
	
	//饼干数量
	private static int Size = 0;

	private List<Biscuits> mlist = new ArrayList<Biscuits>();
	
	/**
	 * 用于将类型饼干的实例添加到List集合中。
	 * 
	 * @param biscuits	向上转型——子类实例在传进去的过程中进行了向上转型
	 */
	public void add(Biscuits biscuits){
		mlist.add(biscuits);
		Size++;
	}
	/**
	 * 
	 * @return	返回包中有多少盒饼干。
	 */
	public int getSize(){
		return Size;
	}
	/**
	 * 通过item参数来获取相对应的饼干类型。
	 * 
	 * @param item	对应参数
	 * @return	返回与对应参数item相对应的类型饼干
	 */
	public Biscuits getTypesOfBiscuits(int item){
		Size--;
		return mlist.get(item);
	}
	
}

包中的List集合存放类型饼干。add()方法用于将类型饼干添加到List集合中。并以向上转型的方式进行加入。使用泛型<Biscuits>,为什么要使用泛型<Biscuits>,而不是<Cookies>呢?那咱们反向思维一下,如果泛型放的是<Cookies>,那惨淡了呢,我的包里只能放入曲奇饼干,其他类型的饼干不能放入。编译期间不通过呀。那我只能吃曲奇饼干,这岂不是很惨的呢。只有一种口味的呢。所以,我绝对不允许这种情况的发生,嘿嘿,一开始我就写了一个Biscuits饼干接口,提供了一个Biscuits标准,然后让每一个Biscuits子类都去实现这个接口。这里就使用到向上转型的知识点,【向上转型】此时包中存放的子类实例对象,由于向上转型Biscuits,已经丢失了子类独有的方法,取上面的Cookies类来进行分析,Cookies丢失了rawMaterialcookies()原料方法,但是如果我们使用Cookies类的时候,肯定不希望这种情况的方法。

下面我们写一个测试Test类。

package com.shenqi.xiaobaiyang;

public class Test {

	public static final int Cookies = 0;
    public static final int SandwichBiscuit = 1;
    public static final int ShortBiscuit = 2;

	
	public static void main(String[] args) {
		// 从超市买完饼干后,将饼干放入包中
		Bag bag = new Bag();
		bag.add(new Cookies());
		bag.add(new SandwichBiscuit());
		bag.add(new ShortBiscuit());
		
		//包中饼干数量
		System.out.println("包中饼干数量:" + bag.getSize());
		
		//开始享用曲奇饼干,查看它的原料
		Cookies cookies =
				(com.shenqi.xiaobaiyang.Cookies) bag.getTypesOfBiscuits(Cookies);
		System.out.println("开始享用曲奇饼干。" + cookies.rawMaterialcookies());
		
		//查看包中剩余饼干数量(盒)
		System.out.println("包中剩余饼干数量(盒):" + bag.getSize());

	}

}

测试结果如下:

包中饼干数量:3
开始享用曲奇饼干。曲奇饼干:以小麦粉、糖、乳制品为主要原料,加入疏松剂和其他辅料,以和面,采用挤注、挤条、钢丝节割等方法中的一种形式成型,烘烤制成的具有立体花纹或表面有规则波纹、含油脂高的酥化焙烤食品。
包中剩余饼干数量(盒):2

对上述代码进行分析:

//开始享用曲奇饼干,查看它的原料
		Cookies cookies =
				(com.shenqi.xiaobaiyang.Cookies) bag.getTypesOfBiscuits(Cookies);
		System.out.println("开始享用曲奇饼干。" + cookies.rawMaterialcookies());

bag.getTypesOfBiscuits(Cookies)这句代码是获取到Biscuits类型的实例。不是Cookies的实例。

通过向下转型,赋值给子类引用

Cookies cookies =
				(com.shenqi.xiaobaiyang.Cookies) bag.getTypesOfBiscuits(Cookies);
		System.out.println("开始享用曲奇饼干。" + cookies.rawMaterialcookies());

这样子类实例又重新获得了因为向上转型而丢失的方法rawMaterialcookies()。

通过这个小Demo,可以看出,我们有的时候需要的各种类型的类,但是我们又想把它放在一个集合中,而不是每种类型都给一个集合存放,那样就太浪费资源了。这就需要使用向下转型,向上转型来进行编写代码。把很多种类的子类实例对象全部放入到存放父类实例的集合中。放入时,使用向上转型,子类实例赋值给父类引用,这样,完成向上转型后,子类丢失了自己独特的方法,然后通过向下转型的特性,将父类引用强转为子类实例对象。这样,子类又重新拥有了自己的独特的方法。 

猜你喜欢

转载自blog.csdn.net/shenqixiayang/article/details/79332974