目录
前言:栈的定义
数据先进后出
一,泛型的应用场景
在一种数据结构下,在传入不同数据类型时要改变其数据结构的类型,为了方便使用不同的数据类型的数据引入了泛型的概念。
(1)在不使用泛型的情况下构建一个栈
public class Stack { // 定义数组 private int[] arr; private int i = -1; public Stack(int size) { arr = new int[size]; } // 添加数据 public void add(int value) { i++; arr[i] = value; } // 输出数据 public int get() { return arr[i--]; } }
其在创建对象传参时,栈里的数据只会是int型,如果想传入其他类型的数据如String则需要更改如下
public class StringStack { private String[] arr; private int i = -1; public StringStack(int size) { arr = new String[size]; } // 添加数据 public void add(String value) { i++; arr[i] = value; } // 输出数据 public String get() { return arr[i--]; } }
现在需要考虑把数组的类型换成string,重写一个属于string类型的栈模拟程序,这样可以解决问题。但是如果每一个数据类型都需要写一个栈,这么做时间复杂度高且代码很冗余。
由此,引出泛型,下面用泛型解决此问题。
(2)在使用泛型的情况下构建一个栈
栈的泛型类
public class Stack<T> { // 假设泛型类型参数T // 定义数组 private T[] arr; private int i = -1; public Stack(int size) { arr = (T[]) new Object[size]; // Object类是所有类的父类 } // 添加数据 public void add(T value) { i++; arr[i] = value; } // 输出数据 public T get() { return arr[i--]; } }
测试类
public class Test { public static void main(String[] args) { // 整数类型的栈操作示例 Stack<Integer> stack = new Stack<>(10); //Integer类是包装类 stack.add(1); stack.add(2); stack.add(3); System.out.println(stack.get()); System.out.println(stack.get()); System.out.println(stack.get()); // 字符串类型的栈操作示例 Stack<String> stack1 = new Stack<>(10); stack1.add("保定"); stack1.add("石家庄"); stack1.add("北京"); System.out.println(stack1.get()); System.out.println(stack1.get()); System.out.println(stack1.get()); } }
输出结果
拓展:甚至于在同一个栈中不同数据类型的数据也能存储 ,但前提是没有给泛型设置类型
Stack<String> stack1 = new Stack<>(10);
//Stack <设置泛型里存储数据的类型> 变量名 = new Stack<可写可不写>(传参);
二,泛型类
(1)使用语法
类名<具体的数据类型> 对象名 = new 类名<具体的数据类型>();
(2)泛型类的定义语法
class 类名称 <泛型标识、泛型标识,...> { private 泛型标识 变量名; ...... }
常用的泛型标识 T、E、K、V
(3)注意事项
- 泛型类,如果没有指定具体的数据类型,此时,操作类型是Object
- 泛型的类型参数只能是类类型,不能是基本数据类型
- 泛型类型在逻辑上可以看成是多个不同的类型,但实际上是相同类型
- java 1.7以后,后边的<>中具体的数据类型可以省略不写
类名<具体的数据类型> 对象名 = new 类名<>();
-
统一类型,在确定方形类型后,添加不同类型的数据会报错
三,父子类当中的泛型类
(1)子类是泛型类
子类和父类的泛型类型要保持一致,父类不指定泛型类型的话默认为Object,和子类指定不同数据类型就会报错
class ChildGeneric<T> extends Generic<T>
(2)子类不是泛型类
父类要明确泛型类的数据类型
class ChildGeneric extends Generic<String>
四,泛型的实例
public class Test { public static void main(String[] args) { ProducGetter<String> stringProducGetter = new ProducGetter<>(); String[] strPro = {"uhuh","uhuh","asd"}; for(int i = 0;i<strPro.length;i++){ stringProducGetter.addProduct(strPro[i]); } String product = stringProducGetter.getProduct(); System.out.println(product); ProducGetter<Integer> integerProducGetter = new ProducGetter<>(); int[] intPro = {12,34,5,6,78,8}; for(int i = 0;i<strPro.length;i++){ integerProducGetter.addProduct(intPro[i]); } int product1 = integerProducGetter.getProduct(); System.out.println(product1); } }
import java.util.ArrayList; import java.util.Random; public class ProducGetter<T>{ private T product; ArrayList<T> products = new ArrayList<>(); public void addProduct(T t){ products.add(t); } Random random = new Random(); public T getProduct(){ product = products.get(random.nextInt(products.size())); return product; } }
arraylist也是一个数组,使用数组作为泛型的容器,在main方法里是给定一个数组将其按照for循环输入到泛型里面去,random是一个随机数,随机出现一个不超过数组大小的数字i然后输出a[i].
输出结果: