Java之泛型学习笔记

1. 泛型技术的产生背景

1.1 泛型的引出

保存多种数据类型的一堆数据时,我们会考虑Object类型:

  • int自动装箱为Interger,Interger向上转型为Object
  • double自动装箱为Double,Double向上转型为Object
  • String向上转型为Object

注意:向上转型的核心目的在统一操作的参数上,而向下转型的目的是操作子类定义的特殊功能。向下转型是一件非常不安全的操作。

从JDK1.5后增加了泛型技术,而泛型技术的核心意义在于:类在定义的时候,可以使用一个标记,此标记表示表示类中属性或方法参数的类型标记,在使用的时候才动态的设置。

1.2 泛型操作的实现

使用泛型示例:

import java.awt.*;

/*
这是关于泛型的一个Demo。
 */
class Point<T>{
    private T x;
    private T y;

    public void setX(T x) {
        this.x = x;
    }
    public void setY(T y) {
        this.y = y;
    }
    public T getX() {
        return x;
    }
    public T getY() {
        return y;
    }
}
public class Demo {
    public static void main(String[] args) {
        //第一步:设置数据
        Point<String> p=new Point<String>();
        //利用的就是包装类的自动装箱功能
        p.setX("我是");
        p.setY("杨婷婷");
        System.out.println(p.getX()+p.getY());
    }
}

发现使用泛型以后,所有类中属性的类型都是动态设置的,而所有使用泛型标记方法参数类型也发生变化,这就避免了向下转型的问题,从而解决了类转换的安全隐患。

需要特别注意的是,要想使用泛型,那么它能够采用的类型只能是类,即:不能是基本类型,只能是引用类型(String、Double、Integer、List等)。

对于泛型有两点说明:

  • 如果在使用泛型类或者接口时,没有设置泛型的具体类型,那么会出现编译时的警告,将使用Object表示泛型。
  • 从JDK1.7开始可以简化声明泛型。即允许这样定义:
Point<Integer> p=new Point<>();

2. 通配符的使用

2.1 背景

注意:泛型不能作为方法重载的参数。即下列代码不构成重载。

在这里插入图片描述

解决参数传递问题:

import java.awt.*;

/*
这是关于泛型的一个Demo。
 */
class Point<T>{
    private T x;
    private T y;

    public void setX(T x) {
        this.x = x;
    }
    public void setY(T y) {
        this.y = y;
    }
    public T getX() {
        return x;
    }
    public T getY() {
        return y;
    }
}
public class Demo {
    public static void main(String[] args) {
        //第一步:设置数据
        Point<Integer> p=new Point<>();
        Point<String> p1=new Point<>();
        //利用的就是包装类的自动装箱功能
        p.setX(12);
        p.setY(18);
        p1.setX("ytt");
        p1.setY("hello");
        fun(p);
        fun(p1);
    }
    public static void fun(Point p){  //此处不设置泛型,会出现警告
        System.out.println(p.getX()+" "+p.getY());
    }
}

但仍然存在警告。因为只要不设置泛型,就一定存在警告信息。所以现在需要解决的是,需要有一种方式可以接收一个类的任意的泛型,但是不可以修改,只能取出,那么就可以使用“?”来描述。即:

import java.awt.*;

/*
这是关于泛型的一个Demo。
 */
class Point<T>{
    private T x;
    private T y;

    public void setX(T x) {
        this.x = x;
    }
    public void setY(T y) {
        this.y = y;
    }
    public T getX() {
        return x;
    }
    public T getY() {
        return y;
    }
}
public class Demo {
    public static void main(String[] args) {
        //第一步:设置数据
        Point<Integer> p=new Point<>();
        Point<String> p1=new Point<>();
        //利用的就是包装类的自动装箱功能
        p.setX(12);
        p.setY(18);
        p1.setX("ytt");
        p1.setY("hello");
        fun(p);
        fun(p1);
    }
    public static void fun(Point<?> p){
        System.out.println(p.getX()+" "+p.getY());
    }
}

2.2 "?"通配符

  1. 在"?"通配符基础上还会有两个子的通配符:
  • ?extends 类:设置泛型上限,可以在声明上和方法参数上使用。
? extends Number

上述代码意味着可以设置Number类或其子类 (Integer、Double)。

import java.awt.*;

/*
这是关于泛型的一个Demo。
 */
class Point<T extends Number>{  //限定只能使用Number类或其子类
    private T x;
    private T y;

    public void setX(T x) {
        this.x = x;
    }
    public void setY(T y) {
        this.y = y;
    }
    public T getX() {
        return x;
    }
    public T getY() {
        return y;
    }
}
public class Demo {
    public static void main(String[] args) {
        //第一步:设置数据
        Point<Integer> p=new Point<>();  //若设置String类会报错
        Point<Double> p1=new Point<>();
        //利用的就是包装类的自动装箱功能
        p.setX(12);
        p.setY(18);
        p1.setX(11.0);
        p1.setY(28.2);
        fun(p);
        fun(p1);
    }
    public static void fun(Point<? extends Number> p){
        System.out.println(p.getX()+" "+p.getY());
    }
}

  • ?super 类:设置泛型下限,方法参数上使用。
?super String

上述代码意味着只能够设置String或者它的父类Object。

import java.awt.*;

/*
这是关于泛型的一个Demo。
 */
class Point<T>{  //此处不能写 Point<T ? super Double>
    private T x;
    private T y;

    public void setX(T x) {
        this.x = x;
    }
    public void setY(T y) {
        this.y = y;
    }
    public T getX() {
        return x;
    }
    public T getY() {
        return y;
    }
}
public class Demo {
    public static void main(String[] args) {
        //第一步:设置数据
        Point<Number> p=new Point<>();  //若设置String类会报错
        Point<Double> p1=new Point<>();
        //利用的就是包装类的自动装箱功能
        p.setX(12);
        p.setY(18);
        p1.setX(11.0);
        p1.setY(28.2);
        fun(p);
        fun(p1);
    }
    public static void fun(Point<? super Double> p){
        System.out.println(p.getX()+" "+p.getY());
    }
}

3. 泛型接口

3.1 概念

在之前都是将泛型定义在一个类里面,那么泛型也可以在接口上声明,这样的接口称为泛型接口。

3.2 实现

  1. 定义泛型接口
public interface IPoint<T>{
    public void print(T t);
}

  1. 在接口上必须要定义其相应的子类,定义子类有两种形式。
  • 在子类继续设置泛型
public class Demo<T> implements IPoint<T> {
    public void print(T t) {
        System.out.println(t);
    }

    public static void main(String[] args) {
        IPoint<String> iPoint=new Demo<String>();
        iPoint.print("Hello");
    }
}
  • 在子类不设置泛型,为父接口明确定义泛型类型。
public class Demo implements IPoint<String> {
    public void print(String t) {
        System.out.println(t);
    }

    public static void main(String[] args) {
        IPoint<String> iPoint=new Demo();
        iPoint.print("Hello");
    }
}

以上两类代码应该清楚其继承流程。

4. 泛型方法

泛型方法不一定非要定义在支持泛型的类里面。

泛型方法定义:


public class Demo{
    public static void main(String[] args) {
       String str=fun("HELLO");
       System.out.println(str.length());
    }
    //T的类型由传入的参数决定
    public static <T> T fun(T t) {
      return t;
    }
}

5. 总结

  1. 泛型解决的是向下转型所带来的安全隐患,其核心在于在声明类或接口时不设置参数或属性的类型;
  2. “?”通配符可以接收任意的泛型类型,但是只能够取出不能够修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

就是二二二二婷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值