• 【从零开始的Java开发】1-6-2 泛型:概述、泛型作为方法参数、自定义泛型、自定义泛型方法


    泛型概述

    为什么要有泛型
    在Java增加泛型之前,泛型程序设计使用继承来实现。

    坏处:

    • 需要强制转换
    • 可向集合中添加任意类型的对象,存在风险

    泛型的使用:如,在尖括号里,限制在list中只能添加String内容
    Listlist=new ArrayList();

    Java SE7及以后的版本中,构造方法中可以省略泛型类型。即:Listlist=new ArrayList<>();

    多态与泛型
    变量声明的类型必须匹配传递给实际对象的类型,即前后尖括号内的要一致,如下例是错的:

    class Aniaml{}
    class Cat extends Animal{}
    List<Animal>list=new ArrayList<Cat>();
    
    • 1
    • 2
    • 3

    下例也是错的:

    List<Object>list=new ArrayList<String>();
    List<Number>numbers=new ArrayList<Integer>();
    
    • 1
    • 2

    泛型作为方法参数

    案例:

    • 定义一个抽象类Goods,包含抽象方法sell()
    • 分别定义类BookClothesShoes继承Goods,并实现sell(),输出一句话
    • 定义一个商品销售类GoodsSeller,模拟销售,包括方法public void sellGoods(Listgoods),循环调用List对象的sell方法
    • 测试

    Goods类:

    public abstract class Goods {
    	public abstract void sell();
    }
    
    • 1
    • 2
    • 3

    Book类:

    public class Book extends Goods {
    
    	@Override
    	public void sell() {
    		System.out.println("Book sell");
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    Clothes类:

    public class Clothes extends Goods {
    
    	@Override
    	public void sell() {
    		System.out.println("Clothes sell");
    
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Shoes类:

    public class Shoes extends Goods {
    	@Override
    	public void sell() {
    		System.out.println("Shoes sell");
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    GoodsSeller类:

    public class GoodsSeller {
    	// 参数是Goods或其子类都可以
    	public void sellGoods(List<? extends Goods> goods) {
    		// 调用集合中的sell方法
    		for (Goods g : goods) {
    			g.sell();
    		}
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    测试类:

    public class GoodsTest {
    
    	public static void main(String[] args) {
    
    		// 定义Book相关的List:参数类型一定要一致,不然会报错
    		List<Book> book = new ArrayList<Book>();
    		book.add(new Book());
    		book.add(new Book());
    
    		// 定义Clothes相关的List
    		List<Clothes> clothes = new ArrayList<Clothes>();
    		clothes.add(new Clothes());
    		clothes.add(new Clothes());
    
    		// 定义Shoes相关的List
    		List<Shoes> shoes = new ArrayList<Shoes>();
    		shoes.add(new Shoes());
    		shoes.add(new Shoes());
    
    		GoodsSeller goodsSeller = new GoodsSeller();
    		goodsSeller.sellGoods(book);
    		goodsSeller.sellGoods(clothes);
    		goodsSeller.sellGoods(shoes);
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    输出:

    Book sell
    Book sell
    Clothes sell
    Clothes sell
    Shoes sell
    Shoes sell
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    注意public void sellGoods(List goods)表示参数是Goods或其子类都可以。

    自定义泛型

    一个参数

    举个例子:

    //自定义泛型类
    public class NumGeneric<T> {
    	private T num;
    
    	public T getNum() {
    		return num;
    	}
    
    	public void setNum(T num) {
    		this.num = num;
    	}
    
    	// 测试
    	public static void main(String[] args) {
    		NumGeneric<Integer> intNum = new NumGeneric<>();
    		intNum.setNum(100);
    		System.out.println(intNum.getNum());
    
    		NumGeneric<Float> floatNum = new NumGeneric<>();
    		floatNum.setNum(10.2f);
    		System.out.println(floatNum.getNum());
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    输出:

    100
    10.2
    
    • 1
    • 2

    两个参数

    public class TwoNumGeneric<T, X> {
    	private T num1;
    	private X num2;
    
    	public void setNum(T num1, X num2) {
    		this.num1 = num1;
    		this.num2 = num2;
    	}
    
    	public T getNum1() {
    		return num1;
    	}
    
    	public X getNum2() {
    		return num2;
    	}
    
    	public void setNum1(T num1) {
    		this.num1 = num1;
    	}
    
    	public void setNum2(X num2) {
    		this.num2 = num2;
    	}
    
    	// 测试
    	public static void main(String[] args) {
    		TwoNumGeneric<Integer, Double> num = new TwoNumGeneric<>();
    		num.setNum(1, 20.0);
    		System.out.println(num.getNum1() + " " + num.getNum2());
    
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    输出:1 20.0

    跟上一个差不多。

    自定义泛型方法

    泛型方法不一定要写到泛型类中

    类似C++的模板:

    public class GenericMethod {
    	public <T> void printValue(T t) {
    		System.out.println(t);
    	}
    
    	public static void main(String[] agrs) {
    		GenericMethod gm = new GenericMethod();
    		gm.printValue("hello,world!");
    		gm.printValue(123);
    		gm.printValue(12.34);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    输出:

    hello,world!
    123
    12.34
    
    • 1
    • 2
    • 3

    如果只想要Number和它的子类:

    public class GenericMethod {
    	public <T extends Number> void printValue(T t) {
    		System.out.println(t);
    	}
    
    	public static void main(String[] agrs) {
    		GenericMethod gm = new GenericMethod();
    		gm.printValue(123);
    		gm.printValue(12.34);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    输出:

    123
    12.34
    
    • 1
    • 2

    总结

    为什么使用泛型

    • 不用进行强制类型转换
    • 避免运行时异常的安全隐患

    注意:变量声明的类型必须匹配传递给实际对象的类型,即前后尖括号的内容要一致

    泛型作为方法参数

    参数是Goods类及其子类:public void A(List)
    PS:extends后也可以跟接口interface的名字

    参数是Goods及Goods的超类:public void A(List)

    自定义泛型自定义泛型方法

  • 相关阅读:
    树莓派系统的安装教程
    【八股】计算机网络-HTTP和HTTPS的区别、HTTPS加密传输原理
    SQLSERVER基础--存储过程
    【入门篇】1.4 redis 客户端 之 Lettuce 详解
    Java面向对象(二)
    ununtu中vim的使用
    基于WMI更新Windows系统信息采集程序sysInfo的一些收获
    [附源码]SSM计算机毕业设计置地房屋租赁信息系统JAVA
    牛客P21546 莫比乌斯反演+杜教筛
    李白最经典的20首诗排行榜
  • 原文地址:https://blog.csdn.net/karshey/article/details/126227068