标题

  • 1. 泛型语法
    • 1.1 泛型的引出
    • 1.2 泛型介绍
    • 1.3 泛型语法
    • 1.4 泛型使用细节
    • 1.5 练习题
  • 2.自定义泛型
    • 2.1自定义泛型-类
    • 2.2自定义泛型-接口
    • 2.3自定义泛型-方法
    • 2.4练习题
  • 3.范型继承和通配符
    • 3.1JUnit单元测试框架
    • 3.2练习题

1. 泛型语法

1.1 泛型的引出

  1. 传统方法不能对加入到集合中的数据类型进行约束;
  2. 对集合遍历的时候需要进行类型转换,效率低;
public class Generic01 {public static void main(String[] args){ArrayList arrayList = new ArrayList();arrayList.add(new Dog("scott",4));arrayList.add(new Dog("jack",5));arrayList.add(new Dog("mary",6));for(Object o : arrayList) {Dog dog = (Dog) o;//获取对象的名字System.out.println(dog.getName());}}
}
class Dog {private String name;private int age;public Dog(String name, int age) {this.name = name;this.age = age;}public void setName(String name) {this.name = name;}public String getName() {return name;}public void setAge(int age) {this.age = age;}public int getAge() {return age;}
}
  1. 引出:new ArrayList<Dog>(),表示存放到ArrayList 集合中的元素是Dog类型
  2. 优点
    • 如果编译器发现添加的类型不满足要求,就会报错,即编译时编译器会检查添加元素的类型,提高安全性;
    • 遍历时,可以直接取出Dog类型,而不是Object类型,减少了类型转换的次数;
public class Generic01 {public static void main(String[] args){ArrayList arrayList = new ArrayList<Dog>();arrayList.add(new Dog("scott",4));arrayList.add(new Dog("jack",5));arrayList.add(new Dog("mary",6));//arrayList.add(new Cat("招财猫",3));for(Dog dog : arrayList) {System.out.println(dog.getName());}}
}

不使用泛型:放入到ArrayList会先转成Object,在取出时,再转换成Dog;
使用泛型:放入和取出时,不需要类型转换;

不使用泛型 使用泛型
放入到ArrayList会先转成Object,在取出时,再转换成Dog; 放入和取出时,不需要类型转换;

1.2 泛型介绍

  1. 泛型是可以表示数据类型的一种数据类型;
  2. 泛型又称为参数化类型,是jdk5.0出现的新特性,可以解决数据类型的安全性问题;
  3. 在类声明或者实例化的时候只需要指定需要的具体类型即可;
  4. Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生ClassCastException的异常;同时,代码更简洁、健壮。
  5. public class ArrayList<E> ,相当于把Dog赋给了E,Dog->E
  6. 泛型的作用是: 可以在类声明时通过一个标识符表示类中某个属性的类型,或者是某个方法的返回值的类型,或者是参数类型。
    - 参数的类型
    - 类中方法返回值的类型
    - 属性的类型
泛型 Generic
参数的类型 $1600
类中方法返回值的类型 $12
属性的类型 $1
  1. 在这里,E的类型一定要清楚的知道,可以通过getClass()方法得到;
  2. 注意:E具体的数据类型在定义Person对象时指定,即在编译期间就已确定类型;

1.3 泛型语法

  1. interface 接口<T> {} 和 class 类<K,V>{}
  • 说明:

    • T、K、V不代表值,而是表示类型;
    • 任意字母都可以,常用T表示,T是Type的缩写
  1. 泛型的实例化:要在类名后面指定类型参数的值(类型),如:

    • (1)List<String> stringList = new ArrayList<\String>();
    • (2)Interator<\Dog> iterator = dog.iterator();

1.4 泛型使用细节

  1. interface List<T> {}, public class HashSet<E> {};
    T,E只能是引用类型,不能用基本数据类型;(Type argument cannot be of primitive type)
  2. 在给泛型指定具体类型后,可以传入该类型或其子类类型;
  3. 泛型的简写形式:省略构造器处的泛型表示,编译器会进行类型推断;
    List<Pig> list = new ArrayList<>();
  4. 如果没有指定泛型,默认泛型是Object;
    Map hashMap = new HashMap();
    等价于
    Map<Object, Object> hashMap = new HashMap<>();

1.5 练习题


改进后:封装后代码复用性更高;

2.自定义泛型

2.1自定义泛型-类

  1. 基本语法:class 类名<T,R…> {} 可以有多个泛型
  2. 普通成员可以使用泛型(属性、方法);
  3. 使用泛型的数组不能初始化;
  4. 静态成员中不能使用类的泛型;
  5. 泛型类的类型,是在创建对象时确定的;(因为在创建对象时,需要指定类型)
  6. 如果在创建对象时,没有指定类型,默认为Object;
public class CustomGeneric {public static void main(String[] args) {//T是Double,R是String,M是IntegerTiger<Double, String, Integer> tiger = new Tiger<>("john~~");tiger.setT(3.2);//OKSystem.out.println(tiger);Tiger tiger1 = new Tiger("john");//tiger.setT("yy");因为T是Object,"yy"是 Object子类,类型不对}
}
//1.Tiger后面有泛型,所以我们把Tiger 称为自定义泛型类
//2.T, R, M 泛型的标识符,一般是单个大写字母
//3.泛型的标识符可以有多个
//4.普通成员可以使用泛型 (属性、方法)
//5.使用泛型的数组,不能初始化
class Tiger<T, R, M> {String name;T t;//属性使用到泛型M m;R r;public Tiger(String name) {this.name = name;}//Type parameter 'T' cannot be instantiated directly//T[] ts = new T[8];类型不能确定,无法分配空间,因为数组在new的时候不能确定T的类型,就无法在内存开辟空间public Tiger(T t, M m, R r) {//构造器使用泛型this.t = t;this.m = m;this.r = r;}//因为静态是和类相关的,在类加载时,对象还没有创建//所以,如果静态方法和静态属性使用了泛型,JVM就无法完成初始化/*static R r2;public static void m1(M m) {//cannot be referenced from a static context}*///方法使用泛型public String getName() {return name;}public void setName(String name) {this.name = name;}public T getT() {return t;}public void setT(T t) {this.t = t;}public M getM() {return m;}public void setM(M m) {this.m = m;}public R getR() {//返回类型可以使用泛型return r;}public void setR(R r) {//方法使用到泛型this.r = r;}
}

2.2自定义泛型-接口

基本语法:interface 接口名 <T, R…> {}

  1. 接口中静态成员也不能使用泛型;(和泛型类规定一样)
  2. 泛型接口的类型,在继承接口或者实现接口时确定;
  3. 如果没有指定类型,默认为Object;(不规范,建议指定<Object>)
  4. 方法参数列表中的泛型直接给值,类定义时的泛型给类型;
/*** 泛型接口使用说明* 1.接口中,静态成员不能使用泛型* 2.泛型接口的类型是在继承接口或者实现接口时实现的*///1.在继承接口时,指定泛型接口的类型
interface IA extends IUsb<String, Double> {}
//当我们去实现IA接口时,因为IA在继承IUsb接口时,指定了U为String,R为Double
// 因此在实现IUsb接口方法时,使用String替换U,Double替换R
class AA implements IA {@Overridepublic Double get(String s) {return null;}@Overridepublic void hi(Double aDouble) {}@Overridepublic void run(Double r1, Double r2, String u1, String u2) {}
}
//2.实现接口时,直接指定泛型接口的类型
//给U指定了Integer, 给R指定了Float
//所以当实现IUsb接口方法时,会使用Integer替换U,Float替换R
class BB implements IUsb<Integer, Float> {@Overridepublic Float get(Integer integer) {return null;}@Overridepublic void hi(Float aFloat) {}@Overridepublic void run(Float r1, Float r2, Integer u1, Integer u2) {}
}//3.没有指定泛型,就默认为Object
//等价于class CC implements IUsb<Object, Object> {}, 但是不规范
class CC implements IUsb {@Overridepublic Object get(Object o) {return null;}@Overridepublic void hi(Object o) {}@Overridepublic void run(Object r1, Object r2, Object u1, Object u2) {}}
interface IUsb<U, R> {//U=Integer, R=Float//接口中普通方法,可以使用泛型R get(U u);int n = 10;//U name = "3e";静态成员不能使用泛型void hi(R r);void run(R r1, R r2, U u1, U u2);//在jdk8以后,可以在接口中使用默认方法,在默认方法中可以使用泛型default R method(U u) {return null;}
}

2.3自定义泛型-方法

基本语法:修饰符[空格]<T, R> 返回类型 方法名(参数列表) {}

  1. 泛型方法,可以定义在普通类中,也可以定义在泛型类中;
  2. 当泛型方法被调用时,泛型类型就会确定,否则调用不起来;
  3. public void ear(E e) {},修饰符后面没有 <T, R…>, 那么eat方法就不是泛型方法,只是使用了泛型;
  4. 泛型方法可以使用类声明的泛型,也可以使用自己声明的泛型;
public class CustomMethodGeneric_ {public static void main(String[] args) {Car car = new Car();//2. 当泛型方法被调用时,泛型类型就会确定,否则调用不起来;car.fly("宝马",1200);//当调用方法时,传入参数,编译器就会确定类型System.out.println("===========");car.fly(2.2,1200);//当调用方法时,传入参数,编译器就会确定类型System.out.println("===========");//T:Sring, R:ArrayListFish<String, ArrayList> fish = new Fish<>();//K:Floatfish.hello(new ArrayList(), 2.1f);}
}
//1.泛型方法,可以定义在普通类中
class Car {//普通类public void run() {//普通方法}//说明:泛型方法// <T, R> 就是泛型// 提供给fly方法使用的public <T, R> void fly(T t, R r) {//泛型方法System.out.println(t.getClass());//StringSystem.out.println(r.getClass());//Integer}
}
//2.泛型方法,也可以定义在泛型类中
class Fish<T, R> {//泛型类public void run() {//普通方法}public <U, M> void fly(U u, M m) {//泛型方法}//说明//  hi()方法不是一个泛型方法//  只是hi()方法使用了类声明的泛型public void hi(T e) {}//泛型方法,可以使用类声明的泛型,也可以使用自己声明的泛型public <K> void hello(R r, K k) {System.out.println(r.getClass());//ArrayListSystem.out.println(k.getClass());//Float}
}

2.4练习题

public class CustomMethodGenericExercise {public static void main(String[] args) {//T:String, R:Integer, M:DoubleApple<String, Integer, Double> apple = new Apple<>();apple.fly(10);//泛型都是引用类型,所以10自动装箱,输出:Integerapple.fly(new Dog());//输出:Dog}
}class Apple<T, R, M> {public <E> void fly(E e) {//.getClass():显示包名+类名; //.getClass().getSimpleName():只显示类名System.out.println(e.getClass().getSimpleName());}//public void eat(U u) {} //错误,U没有声明public <U> void eat(U u) {} //改正public void run(M m) {}}
class Dog {}

3.范型继承和通配符

  1. 泛型不具备继承性;
    List<Object> list = new ArrayList<String> ();//这样写是错误的
  2. 通配符起到约束作用;
通配符 作用
List<?> c 表示可以接收任意范型类型
List<? extends A> c 表示可以接收A类或者A类的子类,规定泛型上限
List<? super A> c 表示可以接收A类或者A类的父类(不限于直接父类),规定泛型下限
@SuppressWarnings({"all"})
public class GenericExtends {public static void main(String[] args) {//范型没有继承性//List<Object> list = new ArrayList<String>();//举例说明下面三个方法的使用;List<Object> list1 = new ArrayList<>();List<String> list2 = new ArrayList<>();List<AA> list3 = new ArrayList<>();List<BB> list4 = new ArrayList<>();List<CC> list5 = new ArrayList<>();//1.如果是 List<?> c, 可以接收任意的范型类型printCollection1(list1);printCollection1(list2);printCollection1(list3);printCollection1(list4);printCollection1(list5);//2.如果是 List<? extends AA> c, 可以接收AA或者AA的子类//printCollection2(list1);//printCollection2(list2);printCollection2(list3);printCollection2(list4);printCollection2(list5);//3.如果是 List<? super AA> c, 可以接收AA,AA的父类但不限于直接父类printCollection3(list1);//正确//printCollection3(list2);printCollection3(list3);//printCollection3(list4);//printCollection3(list5);}public static void printCollection1(List<?> c) {for (Object object : c) {//通配符,取出时就是ObjectSystem.out.println(object);}}public static void printCollection2(List<? extends AA> c) {for (AA object : c) {System.out.println(object);}}//List<?> 表示任意范型类型都可以接收//List<? extends AA> 表示的是上限,可以接收 AA或AA的子类//List<? super AA> 表示的是下线,可以接收 AA或者AA的父类,不限于直接父类public static void printCollection3(List<? super AA> c) {for (Object object : c) {System.out.println(object);}}
}
class AA {}
class BB extends AA {}
class CC extends BB {}

3.1JUnit单元测试框架

shortcuts: Alt+Enter/option+Enter
可以直接运行一个方法,JUnit测试框架;

public class JUnit_ {public static void main(String[] args) {//new JUnit_().m1();//new JUnit_().m2();}@Testpublic void m1() {System.out.println("m1()方法");}@Testpublic void m2() {System.out.println("m2()方法");}
}

3.2练习题

public class Homework01 {public static void main(String[] args) {}@Testpublic void test() {//这里我们给泛型T指定的类型是UserDAO<User> userDAO = new DAO<>();userDAO.save("No1", new User(1, 22));userDAO.save("No2", new User(2, 23));userDAO.save("No3", new User(3, 23));List<User> list = userDAO.list();userDAO.update("No3", new User(3, 18));list = userDAO.list();userDAO.delete("No3");list = userDAO.list();User user = userDAO.get("No2");System.out.println(list);System.out.println(user.getAge());}
}class DAO<T> {private Map<String, T> map = new HashMap<>();public void save(String id, T entity) {map.put(id, entity);}public T get(String id) {return map.get(id);}public void update(String id, T entity) {map.put(id, entity);}public List<T> list() {List<T> arrayList = new ArrayList<>();Set<String> keySet = map.keySet();Iterator<String> iterator = keySet.iterator();while (iterator.hasNext()) {String key = iterator.next();arrayList.add(get(key));}return arrayList;}public void delete(String id) {map.remove(id);}
}
class User {private int id;private int age;public User(int id, int age) {this.id = id;this.age = age;}public int getId() {return id;}public void setId(int id) {this.id = id;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "\nUser{" +"id=" + id +", age=" + age +'}';}
}

泛型「generic」讲解相关推荐

  1. 「 机器人学 」“IMU惯性传感器”讲解

    一.前言 惯性传感器(IMU)能够测量传感器本体的角速度和加速度,被认为与相机传感器具有明显的互补性,而且十分有潜力在融合之后得到更完善的SLAM系统. 二.IMU工作特点 IMU虽然可以测得角速度和 ...

  2. 万字长文讲解:什么是「抽象」?

    编译 | bluemin 编辑丨陈彩娴 1 抽象 计算思维以设计问题的抽象模型为中心,应用计算步骤和高效算法解决问题--这一概念不仅服务于计算机科学(CS),而且逐渐渗透到科学和日常生活中. 「抽象」 ...

  3. 变量不合法的表达式JAVA_Java8中lambda表达式的语法,别人都会的,你还不会吗?「一」...

    函数式编程 函数式编程是一种编程方式,它将电脑运算视为函数的计算.函数编程语言最重要的基础是λ演算(lambda calculus),λ演算的函数可以接受函数当作输入(参数)和输出(返回值). 函数式 ...

  4. 如何直观地理解「协方差矩阵」?

    如何直观地理解「协方差矩阵」? Xinyu Chen Urban Traffic Data Analytics 372 人赞同了该文章 协方差矩阵在统计学和机器学习中随处可见,一般而言,可视作方差和协 ...

  5. 消除左递归实验代码_「leetcode」108. 构造二叉搜索树【递归】【迭代】详解!

    构造二叉搜索树,一不小心就平衡了 ❞ 108.将有序数组转换为二叉搜索树 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树. 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树 ...

  6. 86岁还在录网课:MIT教授Gilbert Strang最新「线性代数」课程上线

    机器之心报道 参与:张倩.Jamin.Raccon X 讲 MIT 线性代数经典课程的 Gilbert Strang 教授已经 86 岁高龄了.他的书被清华选作教材,课程吸引了国内外大批学子.如今疫情 ...

  7. 33个神经网络「炼丹」技巧

    点击上方"视学算法","星标"或"置顶" 关键时刻,第一时间送达 本文转载自:机器之心     作者:Andrej Karpathy 特斯拉 ...

  8. 字节「大力」做教育,依然技术思维,1万员工参与,三年不考虑盈利

    鱼羊 发自 凹非寺 量子位 报道 | 公众号 QbitAI 字节跳动搞教育,现在终于官方明确了. 名字和品牌也非常有意思:大力教育. 该品牌会承接字节跳动所有教育产品及业务. 而曾任今日头条CEO的字 ...

  9. 被「卡脖子」的尖端技术该如何前行?刘明张亚勤等院士大咖为你解惑 | CNCC2020...

    金磊 郑集杨 发自 CNCC现场  量子位 报道 | 公众号 QbitAI 距离世界顶尖,中国「芯」还差多远?又该如何发展? 数字化3.0的浪潮下,该如何突破三大定律的瓶颈? -- 这些大家所关心和讨 ...

最新文章

  1. Redis 笔记系列(十一)——Redis的发布和订阅机制
  2. python开发环境安装
  3. Windows cmd(DOS)命令窗口中echo命令ANSI转义显示彩色字或背景
  4. STL源码剖析学习七:stack和queue
  5. Spring Boot + Oracle 处理Blob/Clob类型字段实例
  6. GTK 4.0 图形工具包正式发布
  7. poj Risk 1603 floyd基础题!!
  8. [转]ffmpeg库音频解码示例
  9. 视易精通收银服务器自动关机,视易收银系统总汇
  10. java实现多表代替密码(维吉尼亚密码)
  11. 2018年下半年软件设计师下午真题及答案解析
  12. HTTP协议报文头部结构和Web相关工具
  13. stress模拟CPU使用100%
  14. 3.0.0 alpha 重磅发布!九大新功能、全新 UI 解锁调度系统新能力
  15. QCC3040---peer UI module
  16. dedecms图片绝对路径(附件绑定域名)的设置方法
  17. JAVA练习97-网格照明
  18. Castle Monorail 缓存
  19. 水滴筹-商业模式画布
  20. XP下如何共享文件,及开启相应的服务

热门文章

  1. C语言 二级 通过率,2019计算机二级通过率是多少 考试科目有哪些
  2. css3宽度变大动画_14种动画让你轻松掌握各种流量计工作原理
  3. C++中的out-of-line虚函数
  4. google Reader快捷键
  5. java aws s3 下载文件_使用send_file从Amazon S3下载文件?
  6. Adobe Flash CS5中文版经典教程 下载地址
  7. db dbm dbw dbi
  8. 从零开始的游戏运营数据分析生活?如何构建数据分析的逻辑框架?
  9. 推荐几本有关软件测试的书籍
  10. Orin 10G PHY网络分析