向上转型与向下转型
1.当把子类对象赋给父类对象引用变量时,称为向上转型。
上转型型中只是在编译时变量的类型是父类,具体执行时表现子类的行为方式
2.把父类对象赋给子类引用变量时,则需要强制类型转换。
public class Test
{
private Object b;
public Object getB(){
return b;
}
public void setB(Object b){
this.b=b;
}
public static void main(String []args){
Test t=new Test();
t.setB(new Boolean(true));
//向上转型 Boolean->Obejct
Float f=(Float)(t.getB());
//向下转型 Object->Float
}
}
向上转型是安全的,而向下转型操作时如果强制类型转换出现错误或者未执行该操作,便会报异常。
为解决下转型可能出现的问题,引入泛型机制。
泛型机制语法:类名 < T >
public class OverClass<T>
{
private T over;
public T getOver(){
return Over;
}
public void setOver(T over){
this.over=over;
}
public static void main(String []args){
OverClass<Boolean> over1=new OverClass<Boolean>();//实例化Boolean对象
OverClass<Float> over2=new OverClass<Float>();
over1.setOVer(true);
over2.setOver(12.3f);
Boolean b=over1.getOver();
Float f=over2.getOver();
}
}
泛型的用法:
1.定义时声明多个类型: NameClass< T1,T2 >
2.定义时声明数组类型
public class ArrayClass< T >
{
private T[] arr;
//不能用泛型建立数组的实例 private T[] arr=new T[10];
}
3.集合类声明容器的元素
集合类 泛型定义
ArrayList ArrayList<E>
HashMap HashMap<K,V>
HashSet HashSet<E>
Vector Vector<E>
public class HashClass<K,V>
{
public Map<K,V> m=new HashMap<K,V>();
public void put(K k,V v){
m.put(k,v);
}
public static void main(String []args){
HashClass<Integer,String> hc=new HashClass<Integer,String>();
}
}
4.限制泛型可用类型: class 类名称//anyClass代表某个类或者接口
使用泛型限制后,泛型类的类型必须实现或继承了anyclass这个接口或者类,在泛型限制必须使用extends
public class LimitClass<T extends List>
{
public static void main(String []args){
//可实例化已实现List接口的类
LimitClass<ArrayList> l=new LimitClass<ArrayList>();
//Err,HashMap没有实现List()接口
LimitClass<HashMap> hm=new LimitClass<HashMap>();
}
}
5.继承泛型类与实现泛型接口
定义为泛型的类和接口亦可以被继承与实现
//泛型类
public class ExtendClass<T1>{
}
public SubClass<T1,T2,T3> extends ExtendClass<T1>{
}
//泛型接口
interface i<T1>{
}
class SubClass<T1,T2,T3> implements i<T1>{
}
6.使用类型通配符
泛型类名称<? extends List> a=null;
//向下限制
泛型类名称<? super List> a=null;
//向上限制,对象a只接受List接口或者上层父类类型,如a=new A<Obejct>();
主要在创建一个泛型类对象时限制这个泛型类的类型实现或者继承某个接口或类的子类
//实例化一个限制泛型类型的实例
A<? extends List> a=null;
a=new A<ArrayList>();
a=new A<LinkedList>();
如果Foo是Bar的一个子类型(子类或者接口),而G是具有泛型声明的类或接口,
G<Foo>并不是G<Bar>的子类型。如List<String>不是List<Obejct>的子类。
为了表示各种泛型List的父类,使用类型通配符。
public void test(List<?> c){
//此写法可适应任何支持泛型声明的类或接口Set<?>
System.out.println(c.get(0));
}
/*
可以使用任何类型的List来调用,程序依然可以访问集合c中的元素,其类型是Object
这永远是安全的,因为不管List的真实类型是什么,它包含的都是Object。
但是List<?>仅表示其是各种类型的父类,并不能把元素加入其中,如下。
*/
List<?> c=new ArrayList<String>();
//Err,因为不知道c集合里元素的类型,所以不能向其中添加对象。
-----------------------------------------------------------
public abstract class Shape
{
public abstract void draw(Canvas c)
}
public class Circle extends Shape
{
public void draw(Canvas c){
syso("Circle");
}
}
public class Rect extends Shape
{
public void draw(Canvas c){
syso("Rect");
}
}
public class Canvas
{
public void draw(List<shape> shapes){
for(Shape s:shapes){
s.draw(this);
}
}
}
List<Circle> circleList=new ArrayList<>();
Canvas c=new Canvas();
c.draw(circleList);
//Err,因为List<Cirlce>并不是List<Shape>的子类型
//为解决不是子类型的问题,可使用List<?>,即:
public class Canvas
{
public void draw(List<?> shapes){
for(Object obj:shapes){
Shape s=(Shape)obj;//强制类型转换
s.draw(this);
}
}
}
//为了避免上述强制类型转换,可用List<? extends Shape>
public class Canvas
{
public void draw(List<? extends Shape> shapes){
for(Shape s:shapes){
s.draw(this);
}
}
}