java泛型笔记

我们最精彩用java泛型是在集合类中。比如List<String> list = new ArrayList<String>();

1.不使用泛型时一个很严重的问题是会有可能出现java.lang.ClassCastException的异常。看下面一段代码:

List list = new ArrayList();
		list.add("123");
		list.add(344);
		for(int i = 0 ;i < list.size();i++){
			String tmp = (String)list.get(i);
			System.out.println(tmp);
		}
</pre>运行时会抛出类型转换异常,不使用泛型时:List list = new Array();声明的list装入的集合对象是Object,当我们把int型强转为String会抛出异常。<p></p><p>而泛型的出现就很好的解决了这个问题。</p><p></p><pre name="code" class="java">List<String> list2 = new ArrayList<String>();
		list2.add("aaa");
		list2.add(123);
<span style="white-space:pre">		for(String  tmp : list2){
<span style="white-space:pre">			</span>System.out.println(tmp);
<span style="white-space:pre">		</span>}</span>
我们在list2.add(123);时,在编译阶段就会报错。因为我们采用泛型声明了list2。在这个集合中仅允许我们在集合中放入String类型的对象,如果我们放入其他类型就会报错。这样就避免了在出现运行时抛出的java.lang.ClassCastException的异常。

2.自定义泛型类

我们自定义一个泛型类,来看看泛型是怎么回事。

public class test1 {

	public static void main(String[] args) {

		/**
		 * 使用自定义泛型类Box<T>声明两个对象box,box2.
		 * 并分别指定,T的类型,其实box,box2还是一个Box对象
		 * 我们可以把T看做一个类型参数,在Box类中T被赋予什么类型,
		 * setT()就只能接收什么类型的参数
		 * 在获取赋值的对象时,返回的就是T类型的一个对象,也就无需进行类型转换
		 */
		Box<String> box = new Box<String>();
		box.setT("小明");
		System.out.println(box.getT());
		
		Box<Integer> box2 = new Box<Integer>();
		box2.setT(123);
		System.out.println(box2.getT());
		
	}
}

/**
 * 
 * 自定义泛型类:
 * 我们可以将<T>看做一个类型参数,对于这个T我们可以在声明的时候传入任何一种类型。
 * 
 * @param <T>
 */
class Box<T> {
	
	//t是类型为T的一个对象,T的类型是在使用这个类的时候赋予的,比如String,Interger等各种类型都可以
	private T t;

	/**
	 * 返回数据类型为T的一个对象t,比如如果类型是String,则返回一个字符串
	 * @return
	 */
	public T getT() {
		return t;
	}
	/**
	 * 将一个类型为T的对象赋给t,比如如果类型是String,则返回一个字符串
	 * @return
	 */
	public void setT(T t) {
		this.t = t;
	}

}

3.泛型接口

package com.lql.demo;

/**
 * 定义泛型接口
 * @author Administrator
 *
 */
public interface MyCompare<Anytype> {

	public boolean compareTo(Anytype t);
}

package com.lql.demo;

//未使用泛型的接口
public interface MyCompare2 {

	public boolean compareTo2(Object o);
}

package com.lql.demo;

/**
 * 定义泛型接口的好处:我们在使用这个接口时,更加灵活安全
 * 在使用这个泛型接口时,我们只需要将这个泛型的类型给指定了
 * 在使用时就很方便安全
 * @author Administrator
 * 
 * Message方法实现了两个接口,一个是泛型接口MyCompare
 * 另一个是普通接口MyCompare2
 * 
 */
public class Message implements MyCompare<Message>,MyCompare2{

	//Message类中没有使用泛型,那我就把类中可以赋值的字段写死了
	//只能保存String类型的字段
	private String msg;

	public String getMsg() {
		return msg;
	}

	public void setMsg(String msg) {
		this.msg = msg;
	}

	/**
	 * 非泛型接口方法
	 * 我们必须要进行强制类型转换,更重要的是这时很危险的
	 * 如果传递过来的Object参数不是Message类型,就会
	 * 抛出类型转换异常,不安全
	 */
	@Override
	public boolean compareTo2(Object o) {
		// TODO Auto-generated method stub
		Message message = (Message) o;
		if(msg!=null&&msg!=""&&msg.equals(message.msg)){
			return true;
		}
		return false;
	}

	/**
	 * 泛型接口的方法
	 * 不用进行类型转换
	 * 如果compareTo的参数不是Message类型,在编译阶段就不会通过
	 * 更加安全
	 */
	@Override
	public boolean compareTo(Message t) {
		// TODO Auto-generated method stub
		if(msg!=null&&msg!=""&&msg.equals(t.msg)){
			return true;
		}
		return false;
	}
}

4.通配符?在泛型中的使用

定义一个Shape类,一个Square类,和一个Circle类,Shape是Square和Circle的父类。

package com.lql.demo;

public class Shape {

	public double area(){
		return 0;
	}
}

package com.lql.demo;

public class Square extends Shape {

	private int width;
	private int height;
	
	public int getWidth() {
		return width;
	}

	public void setWidth(int width) {
		this.width = width;
	}

	public int getHeight() {
		return height;
	}

	public void setHeight(int height) {
		this.height = height;
	}

	@Override
	public double area() {
		return height * width;
	}

}

package com.lql.demo;

public class Circle extends Shape {

	private final static float PI = 3.14f;
	private float r;
	
	public float getR() {
		return r;
	}

	public void setR(float r) {
		this.r = r;
	}

	@Override
	public double area() {
		// TODO Auto-generated method stub
		return PI * r * r;
	}

}

有一个计算面积的工具类

package com.lql.demo;

import java.util.Collection;

public class Area {

	public static double totleArea(Collection<Shape> list){
		double area = 0;
		for(Shape s : list){
			area += s.area();
		}
		return area;
	}
	
	//通配符可以使Shape子类的集合对象的引用赋值给Collection<? extends Shape>的一个引用,
<span style="white-space:pre">	</span>//使用通配符意思是指,如果集合是一个Shape子类的集合,也可以作为参数进行传递
	public static double totleArea2(Collection<? extends Shape> list){
		double area = 0;
		for(Shape s : list){
			area += s.area();
		}
		return area;
	}
}

建一个单元测试进行测试

public void  mtest3(){
		Collection<Shape> list = new ArrayList<Shape>();
		for(int i = 0 ; i < 3 ; i++){
			Shape shape = new Shape();
			list.add(shape);
		}
		Square square = new Square();
		square.setHeight(2);
		square.setWidth(3);
		list.add(square);
		Circle circle = new Circle();
		circle.setR(2);
		list.add(circle);
		double area = Area.totleArea(list);
		System.out.println(area);
		
		Collection<Square> squares = new ArrayList<Square>();
		squares.add(square);
		//如果将squares作为totleArea的参数,编译时就会报错
		//Square是Shape的子类,但Collection<Square>不是Collection<Shape>的子类,
		//直接将Collection<Square>的一个引用赋给Collection<Shape>的引用是不合法的
		Area.totleArea(squares);//这句是无法通过编译的
		
		
		Area.totleArea2(squares);//这个可以通过编译,totleArea2使用了通配符
	}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值