java 泛型 通配符

实现了参数化类型的概念 通过泛型解耦类的方法与所使用的类型之间的约束

参数化类型 指定一个类型作为实参 由修改该类的代码所提供的类型 来将该类进行参数化

具体类型实例化 插入一个实际的java类型作为参数

用途举例

  • 创造容器类: 用来指定容器类要持有什么类型的对象,而且由编译器来保证类型的正确性
  • 实现元组 (将一组对象直接打包存储于其中的一个单个对象),允许读取其中的元素,但不允许修改
  • 实现堆栈类
  • 实现生成器

泛型类  语法:  可见修饰符 class 类名 <类型参数> [extends | implement] ..   <类型参数>添加在类名之后)

public class TwoTuple <A,B>{
    public final A first;
    public final B second;
    public TwoTuple(A a,B b){
        first = a;
        second = b;
    }
}
//通过继承机制 实现长度更长的元组
public class ThreeTuple <A,B,C> extends TowTuple{
    public final D third;
    public ThreeTuple(A a,B b,C c){
        super(A a,B b;
        third = c;
    }
}
  • 非泛型子类: 必须 填充父类型的参数类型

  • class DateList extends ArrayList<Date>{ }
     
    DataList dataList = new DateList();
    dateList.add( new Date() );
    List<Date> ld = dateList;
  • 泛型子类

  •           和父类共享类型变量 该类型变量通过向上传递可以对父类进行实例化
  • class AjustableTrap<T> extends Trap<T>{ }

    使用泛型类

  • List <String> words = new LinkedList<String>();
    //JDK7之后可以 在声明引用时指定类型 创建对象时不用再写类型
    List <String> words = new LinkedList<>();

    泛型接口接口名 <类型参数> [implement ] .. <类型参数>添加在接口名之后)

public interface Generator<T> { //习惯上以单个大写字母表示 类型参数
    T next();
}

 泛型方法 语法:  可见修饰符 <类型参数> 返回类型 (形参) ..<类型参数>添加在返回类型之前)

  1.  方法的泛型与类的泛型没有必然联系,尽量用方法的泛型取代类的泛型

  2. 若方法的泛型与类的泛型 类型参数 重名,则在该方法内 方法的泛型将覆盖类型的参数

  3. static方法无法访问泛型类的类型参数, 但static方法可以成为泛型方法

  4. 实现泛型方法时,可以不指明参数声明 编译器会为我们找出具体的类型 称类型参数推断 (泛型类和泛型接口必须指名参数声明)   类型参数推断仅对赋值操作有效

1.显示的类型说明 

在泛型方法中可以显示的指明类型,在点操作符与方法名之间插入尖括号<>,然后把类型置于尖括号之间

对象.<类型参数>方法名()

2.若在定义该方法的内部则

this.<类型参数>方法名() 

 3.泛型方法为静态static时

 类名.<类型参数>方法名() 

 4.可变参数与泛型方法能很好的共存

//<T>为泛型方法的声明 必须  List<T>为返回值   (List<T>中T的使用是在声明了泛型的情况下) 
public static <T> List<T> makeList(T...args){ 
    List<T> result = new ArrayList<T>();
    for(T item : args)
        result.add(item);
    return result;
}//将多个类型为T的参数args 存储在List<T> 中并将其返回 

调用 类名.<String>makeList()

泛型也可以应用于内部类以及匿名内部类

泛型与异常

例如 实际使用的是Throwsable的一个类型  <T extends Throwable>

ExceptionTester<T extends Throwable>{
       public void test(T exception) throws T{    throw exception;    }
}
try{
      new ExceptionTester<ClassNotFoundException>(),test(new ClassNotFoundException() );
} catch( ClassNotFountException e){..}

不能使用泛型来创建新的异常类型 


通配符

  • 定义            ?     通配符自身称为 无界限通配符  

           <? extends 类> 称为 有界限通配符 

  •  还可以扩展一个或多个接口 用&间隔 同样的 类必须在最左边 <T extends Comparable& Serializable &Iterable>
  • 对于无方法体的接口应排在后面(因为 切换限定)

  • 使用

    • <?> 使用?代替一个实际的参数类型 表示该类型可以被赋予泛型类型可能的实例化范围中的一种 

  • 意义: 通配符实例化允许我们在参数类型上实现多态 

    • 通配符表示一种对象或者可能的对象的一个集合

  • 通配符实例化充当了一个变量的类型 不能使用通配符创建一个类的实例 即和new关键字来使用

  • 通配符捕获: 指泛型方法可以操作的参数 其类型为一个类型的通配符实例 就好像已知类型一样

  • 通配符捕获意义: 可以将通配符实例作为参数传入一个真正的泛型中,来避免通配符实例仅能读/写的局限

List<?> anyList = new ArrayLsit<Date>();

 可靠类型:指未被擦除修改过的类型 包括 java具体类 基本类型 无界限通配符实例

边界

对参数类型设置边界

上边界

  • 扩展一个类或接口<T extends Employee>

  • 扩展多个接口      多个 <T extends Ranked & Printable>

  • 扩展一个类和多个接口 <T extends 类 & 接口1 &接口2> 类必须出现在最左边

类型变量也可以引用声明其他类型变量

class Foo <A, B extends A>

读 与 写 

把一个对象的一个方法获得具体类型的返回值 称为读取一个类型

传递具体类型的参数给对象的方法 称为将对象写入一个类型

List<Date> 可以被读成Date类型 可以写入Date的子类型

通配符实例化 与边界 

List<? extends Date> someDateList = new ArrayList<MyDate>();
Date date = someDateList.get(0); //通配符实例化上边界  仅可读
List<? super MyDate> superMydate = new ArrayList<Date>;
superMydate.add( new MyDate() );//通配符实例化上边界  仅可写

下边界

<? super MyDate>  ?必须是MyDate 或MyDate的父类

只有通配符实例语法可以使用super关键字来表示下界 在泛型类的声明中 类型变量的边界时不能有霞姐的

擦除使用上界来替换其所有的引用 因此运行时类型无法保证这种契约

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值