泛型-通配符,受限泛型(上限和下限)

掌握通配符“?”的使用。

掌握受限泛型的设置。

掌握泛型与子类继承的限制。

具体内容

1.1匹配任意类型的通配符

  在开发中对象的引用传递(向上向下传递)是最常见的,但是,在泛型的操作中,在进行引用传递的时候泛型类型必须匹配才可以传递,否则不能传递。

  例如,如下没有进行泛型类型匹配,一个是String,一个是Object类型。

package Thread1;
class Info<T>{
    private T var ;        // 定义泛型变量
    public void setVar(T var){
        this.var = var ;
    }
    public T getVar(){
        return this.var ;
    }
    public String toString(){    // 直接打印
        return this.var.toString() ;
    }
};
public class demo1{
    public static void main(String args[]){
        Info<String> i = new Info<String>() ;        // 使用String为泛型类型
        i.setVar("MLDN") ;                            // 设置内容
        fun(i) ;                    //把String泛型类型的i对象传递给Object泛型类型的temp。
    }
    public static void fun(Info<Object> temp){        // 接收Object泛型类型的Info对象
        System.out.println("内容:" + temp) ;
    }
};

  编译发生错误。

Exception in thread "main" java.lang.Error: Unresolved compilation problem:
    The method fun(Info<Object>) in the type demo1 is not applicable for the arguments (Info<String>)

    at Thread1.demo1.main(demo1.java:18)

  泛型对象进行引用传递的时候,类型必须一致,如果非要传递,则可以将fun方法中Info参数的泛型取消掉(变成 void fun(Info temp)。、

  以上确实改进了功能,但是似乎不是很妥当,毕竟之前指定过泛型。

  以上程序在fun()方法中使用"Info<?>"的代码形式,表示可以使用任意的泛型类型对象,这样的话fun()方法定义就合理了,但是使用以上方法也有需要注意的地方,

即:如果使用“?“接收泛型对象的时候,则不能设置被泛型指定的内容

class Info<T>{
    private T var ;        // 定义泛型变量
    public void setVar(T var){
        this.var = var ;
    }
    public T getVar(){
        return this.var ;
    }
    public String toString(){    // 直接打印
        return this.var.toString() ;
    }
};
public class GenericsDemo14{
    public static void main(String args[]){
        Info<String> i = new Info<String>() ;        // 使用String为泛型类型
        i.setVar("MLDN") ;                            // 设置内容
        fun(i) ;
    }
    public static void fun(Info<?> temp){        // 可以接收任意的泛型对象
        System.out.println("内容:" + temp) ;
    }
};

  如果使用”?“意味着可以接收任意的内容,但是此内容无法直接使得用”?“修饰的泛型的对象进行修改。如下就会出问题:

package Thread1;
class Info<T>{
    private T var ;        // 定义泛型变量
    public void setVar(T var){
        this.var = var ;
    }
    public T getVar(){
        return this.var ;
    }
    public String toString(){    // 直接打印
        return this.var.toString() ;
    }
};
public class demo1{
    public static void main(String args[]){
        Info<?> i = new Info<String>() ;        // 使用String为泛型类型
        i.setVar("MLDN") ;                            // 设置内容,这里会出错,因为”?“通配符修饰的对象只能接收,不能修改,也就是不能设置。
    }
};

  运行结果:

Exception in thread "main" java.lang.Error: Unresolved compilation problem:
    The method setVar(capture#1-of ?) in the type Info<capture#1-of ?> is not applicable for the arguments (String)

    at Thread1.demo1.main(demo1.java:17)

  在使用”?“只能接收,不能修改。

1.2受限泛型

  之前设置泛型的时候,实际上是可以任意设置的,只要是类就可以设置。但是在JAVA的泛型中可以指定一个泛型的上限和下限。

  

设置上限

class Info<T>{
    private T var ;        // 定义泛型变量
    public void setVar(T var){
        this.var = var ;
    }
    public T getVar(){
        return this.var ;
    }
    public String toString(){    // 直接打印
        return this.var.toString() ;
    }
};
public class GenericsDemo17{
    public static void main(String args[]){
        Info<Integer> i1 = new Info<Integer>() ;        // 声明Integer的泛型对象
        Info<Float> i2 = new Info<Float>() ;            // 声明Float的泛型对象
        i1.setVar(30) ;                                    // 设置整数,自动装箱
        i2.setVar(30.1f) ;                                // 设置小数,自动装箱
        fun(i1) ;
        fun(i2) ;
    }
    public static void fun(Info<? extends Number> temp){    // 只能接收Number及其Number的子类
        System.out.print(temp + "、") ;
    }
};

  运行成功。但是,如果传人的泛型类型为String的话就不行,因为String不是Number子类。

  在类中使用泛型上限。

package Thread1;
class Info<T extends Number>{    // 此处泛型只能是数字类型
    private T var ;        // 定义泛型变量
    public void setVar(T var){
        this.var = var ;
    }
    public T getVar(){
        return this.var ;
    }
    public String toString(){    // 直接打印
        return this.var.toString() ;
    }
};
public class demo1{
    public static void main(String args[]){
        Info<Integer> i1 = new Info<Integer>() ;        // 声明Integer的泛型对象
    }
};

  如果在使用Info的时候设置成String类型,则编译的时候将会出现错误(String不是Number子类):

设置下限

  

class Info<T>{
    private T var ;        // 定义泛型变量
    public void setVar(T var){
        this.var = var ;
    }
    public T getVar(){
        return this.var ;
    }
    public String toString(){    // 直接打印
        return this.var.toString() ;
    }
};
public class GenericsDemo21{
    public static void main(String args[]){
        Info<String> i1 = new Info<String>() ;        // 声明String的泛型对象
        Info<Object> i2 = new Info<Object>() ;        // 声明Object的泛型对象
        i1.setVar("hello") ;
        i2.setVar(new Object()) ;
        fun(i1) ;
        fun(i2) ;
    }
    public static void fun(Info<? super String> temp){    // 只能接收String或Object类型的泛型,String类的父类只有Object类
        System.out.print(temp + "、") ;
    }
};

  Object类和String类都是String的父类,所有运行成功,但是如果此时用Integer则会出错,因为integer并不是String父类。

1.3解释:泛型与子类继承的限制。

  一个类的子类可以通过对象多态性,为其父类实例化,但是在泛型操作中,子类的泛型类型是无法使用父类的泛型类型接收的。例如:Info<String>不能使用Info<Object>

接收。

  例如,以下肯定出错。

class Info<T>{
    private T var ;        // 定义泛型变量
    public void setVar(T var){
        this.var = var ;
    }
    public T getVar(){
        return this.var ;
    }
    public String toString(){    // 直接打印
        return this.var.toString() ;
    }
};
public class GenericsDemo23{
    public static void main(String args[]){
        Info<String> i1 = new Info<String>() ;        // 泛型类型为String
        Info<Object> i2 = null ;
        i2 = i1 ;                  //这里因为对象泛型类型不同,而出错。
    }
};

  Object肯定比String大。

总结

  1)使用?可以接收任意泛型对象。

  2)泛型的上限:?extends 类型。

  3)泛型的下限:?super 类型。相对了解一些就可。

  4)了解为什么泛型子类之间的继承无法直接转换的原因。

时间: 2024-10-19 01:38:59

泛型-通配符,受限泛型(上限和下限)的相关文章

java中泛型上限,下限应用

import java.util.*; class Person implements Comparable<Person>{ String name; int age; Person(){ name = ""; age = 0; } Person(String name, int age){ this.name = name; this.age = age; } public String toString(){ return name + "...."

Java知多少(42)泛型通配符和类型参数的范围

本节先讲解如何限制类型参数的范围,再讲解通配符(?). 类型参数的范围 在泛型中,如果不对类型参数加以限制,它就可以接受任意的数据类型,只要它是被定义过的.但是,很多时候我们只需要一部分数据类型就够了,用户传递其他数据类型可能会引起错误.例如,编写一个泛型函数用于返回不同类型数组(Integer 数组.Double 数组等)中的最大值: 1 public <T> T getMax(T array[]){ 2 T max = null; 3 for(T element : array){ 4 m

java泛型通配符和类型参数的范围

本节先讲解如何限制类型参数的范围,再讲解通配符(?). 类型参数的范围 在泛型中,如果不对类型参数加以限制,它就可以接受任意的数据类型,只要它是被定义过的.但是,很多时候我们只需要一部分数据类型就够了,用户传递其他数据类型可能会引起错误.例如,编写一个泛型函数用于返回不同类型数组(Integer 数组.Double 数组等)中的最大值: public <T> T getMax(T array[]){ T max = null; for(T element : array){ max = ele

使用通配符增强泛型

利用泛型类型参数<T>,可以将类.方法或接口的类型限制为T类型.但是这种方式显然不够灵活.例如,<T extends Number>可以将类型限制为Number的一种子类型,一旦指定了该类型,就不能再修改了.而如果使用通配符就会让代码更加灵活.本实例演示如何在泛型方法中使用通配符,实例运行效果如图 泛型中使用"?"作为通配符.通配符的使用与普通的类型参数类似,如通配符也可以利用extends关键字来设置取值上限.<? extends Number>表

自定义泛型_无多态_通配符无泛型数组_jdk7泛型使用

通配符 T, K, V, E 等泛型字母为有类型, 类型参数赋予具体的值 ? 未知类型 类型参数赋予不确定值, 任意类型 只能用在 声明类型上,方法参数上, 不能用在定义泛型类上 上限 extends, 指定类型必须是继承某个子类. 或者实现某个接口 (不是用 implements), 即 <= 如 ? extends Fruit ? extends List 不能添加信息 存在以下规则, 如 List<Fruit> 满足 List<? extends Fruit> List

Java学习之道:简述泛型通配符&lt;? extends T&gt;和&lt;? super T&gt;

<? extends T>和<? super T>含有JAVA5.0的新的概念.由于它们的外表导致了很多人误解了它们的用途: 1.<? extends T>首先你很容易误解它为继承于T的所有类的集合,这是大错特错的,相信能看下去你一定见过或用过List<? extends T>吧?为什么我说理解成一个集合是错呢?如果理解成一个集合那为什么不用List<T>来表示?所以<? extends T>不是一个集合,而是T的某一种子类的意思,记

【Java】java 中的泛型通配符——从“偷偷地”地改变集合元素说起

一直没注意这方面的内容,想来这也算是基础了,就写了这个笔记. 首先java的通配符共有三种----先别紧张,现在只是粗略的过一下,看不看其实无所谓 类型 介绍 <?> 无限定通配符,等价于 <? extends Object> <? extends Number> 上限通配符,表示参数类型只能是 Number 或是 Number 的子类. <? super Number> 下限通配符,表示参数类型只能是 Number 或是 Number 的父类. 然后再让我

通用集合遍历 泛型通配符

创建Person父类 package com.oracle.demo02; public class Person { private String name; private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String

Java泛型通配符学习 —— Java Generic&#39;s Wildcards

Java Generic's wildcards is a mechanism in Java Generics aimed at making it possible to cast a collection of a certain class, e.g A, to a collection of a subclass or superclass of A. This text explains how. 理解:Java的泛型通配符机制旨在实现集合的类型转换.例如集合A,转换为A的子类集合或