Generic 泛型

为什么需要泛型?

集合容器再设计阶段/声明阶段不能确定这个容器实际存储的是什么类型的对象

JDK5 以前只能把元素设计为Object基类 在JDK5之后用泛型来约束对象类型

除了元素类型不能确定,但是其他是可以确定的,如何保存,如何管理

把对象的类型设置成一个参数,这个参数的类型就叫做泛型

<E> 元素的类型  看起来就像一个标签对吧

泛型的概念

允许在定义类、接口时通过一个标识表示类中的某个属性的类型或者时某个方法的返回类型或者参数类型

这个类型将在使用时继承或者实现这个接口,用这个类型声明遍历,创建对象时确定实际传入的类型参数,称为类型实参

当我声明了String泛型时,如果再填入其他类型的元素,编译将提示错误,类型不和String匹配

使用了泛型声明String之后,迭代器返回的对象,自动确定了String类型

Foreach遍历可以直接写String类型的变量接受

 1 public class CollectionTest {
2 public static void main(String[] args) {
3 List<String> list = new ArrayList<>();
4
5 list.add("阿伟");
6 list.add("杰哥");
7 list.add("阿强");
8
9 Iterator<String> iterator = list.iterator();
10
11 while (iterator.hasNext()){
12 String next = iterator.next();
13 System.out.println(next);
14 }
15
16 for (String str : list) {
17 System.out.println( str );
18 }
19 }
20 }

Map的泛型:

public class CollectionTest {
public static void main(String[] args) {
// 映射接口的泛型
Map<String, Integer> map = new HashMap<>(); map.put("K1",1001);
map.put("K2",1002);
map.put("K3",1003);
map.put("K4",1004);
map.put("K5",1005);
map.put("K6",1006); // Set的泛型是Map里面的Entry的KV泛型,范中范,泛型嵌套
Set<Map.Entry<String, Integer>> entrySet = map.entrySet(); Iterator<Map.Entry<String, Integer>> iterator = entrySet.iterator();
while (iterator.hasNext()){
// 返回Entry类型
Map.Entry<String, Integer> next = iterator.next();
// key类型 和 value类型
String key = next.getKey();
Integer value = next.getValue();
// 打印查看
System.out.println("K = " + key + " : " + " V = " + value);
}
}
}

- JDK5.0的集合容器都修改成带泛型的结构

- 实例化具体集合类的时候可以指名元素的泛型类型

- 集合内部所有定义了使用泛型的方法,属性,都将变成指名的类型

- 泛型的类型必须是引用类型,不能是基本类型,通过包装类实现

- 不使用泛型并不影响使用,类型将默认为Object类型

- JDK7的新特性,实例化的对象不再强制要求写泛型

自定义泛型的使用

public class CollectionTest {
public static void main(String[] args) {
// 使用泛型实例化
Generic<String,Integer> generic1 = new Generic<>("阿伟",22); // 不使用泛型实例化 ,类型都默认Object
Generic generic2 = new Generic("杰哥",28);
}
} class Generic<T,C>{// 在类名旁声明一个泛型,可以声明多个类型
T name; // 使用时只需要将T 作为一个类型使用
C age; public Generic(T name, C age) { // 作为参数的类型使用
this.name = name;
this.age = age;
} public T getName() { // 作为方法的返回类型使用
return name;
} public C getAge() {
return age;
}
}

- 有泛型就一定要使用泛型初始化

子类继承父类时的泛型

class SubGeneric extends Generic<Integer,String>{ // 在继承父类是声明确定的类型

    public SubGeneric(Integer name, String age) { // 下面所调用的泛型全都默认此泛型的指明类型
super(name, age);
} @Override
public Integer getName() {
return super.getName();
} @Override
public String getAge() {
return super.getAge();
}
}

或者不指明类型继续泛型

class SubGeneric<T,C> extends Generic<T,C>{ // 或者不指明类型继续泛型化
public SubGeneric(T name, C age) {
super(name, age);
}
}

- 泛型的个数没有限制,可允许多个泛型声明

- 实例化泛型的类之后必须指明泛型的具体类型

- 编译器可以区分 list<String> list<Integer> 但是实际JVM运行中,只有一个Object类型

- 不指定泛型按Object处理,但不等价于Object? 要么一路使用,要么都不用

- 如果接口和抽象类使用泛型声明,则不可以初始化泛型的实例,还是必须要实现的实现类或继承的子类来泛型实例化

- 泛型可以嵌套泛型的泛型,例如声明A类泛型为T,B类又泛型C,组合关系可以A<B<A<B>>>如此嵌套

关于泛型之后的类型串用

public class CollectionTest {
public static void main(String[] args) { List<Object> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>(); // list1 = list2; 编译报错,String并不是Object类
// list2 = list1; 编译报错,String并不是Object类 // 也就是说 List<T1> List<T2> 是并行关系
// 但是A 是 B 的父类, A<G> 是 B<G> 的父类,就可以使用继承关系
}
}

我们可以让泛型也实现继承关系!

public class CollectionTest {
public static void main(String[] args) { List<Object> list1 = new ArrayList<>();
list1.add(1);
list1.add(2);
list1.add(3);
list1.add(4);
list1.add(5);
list1.add(6); List<String> list2 = new ArrayList<>();
list2.add("11");
list2.add("12");
list2.add("13");
list2.add("14");
list2.add("15");
list2.add("16"); // list1 = list2; 编译报错,String并不是Object类
// list2 = list1; 编译报错,String并不是Object类 // 也就是说 List<T1> List<T2> 是并行关系
// 但是A 是 B 的父类, A<G> 是 B<G> 的父类,就可以使用继承关系 // 使用通配符泛型建立父子类关系
// 通配符 ? 表示任何泛型类型的公共父类
List<?> list3 = new ArrayList<>(); // 都可以使用
list3 = list1; // Object 是 ? 的子类
printEach(list3); list3 = list2; // String 也是 ? 的子类
printEach(list3);
} static void printEach(List<?> list){
Iterator<?> iterator = list.iterator();
while (iterator.hasNext()){
Object o = iterator.next();
System.out.println(o);
}
}
}

使用通配符之后的注意事项

- 该泛型化的集合不能再添加元素,或者说只能添加为null的元素

- 允许读取,和删除,修改也不允许了

通配符的有限制条件的说明

< ? extends T >  只允许泛型的类型是T 和他的子类的引用调用【无穷小, T】

< ? super T >   只允许泛型的类型是T和他的父类的引用调用【T, 无穷大】

【Java】Generic 泛型的更多相关文章

  1. [改善Java代码]Java的泛型是类型擦除的

    泛型可以减少强制类型的转换,可规范集合的元素类型,还可以提高代码的安全性和可读性,正是因为有了这些优点,自从Java引入泛型之后,项目的编码规则上便多了一条,优先使用泛型. Java泛型(Generi ...

  2. Java中泛型 类型擦除

    转自:Java中泛型是类型擦除的 Java 泛型(Generic)的引入加强了参数类型的安全性,减少了类型的转换,但有一点需要注意:Java 的泛型在编译器有效,在运行期被删除,也就是说所有泛型参数类 ...

  3. 【Java】泛型学习笔记

    参考书籍 <Java核心技术:卷1> 泛型, 先睹为快 先通过一个简单的例子说明下Java中泛型的用法: 泛型的基本形式类似于模板, 通过一个类型参数T, 你可以"私人定制&qu ...

  4. 【译】9. Java反射——泛型

    原文地址:http://tutorials.jenkov.com/java-reflection/generics.html ===================================== ...

  5. Java“禁止”泛型数组

    Java“禁止”泛型数组 原文:https://blog.csdn.net/yi_Afly/article/details/52058708 1. 泛型定义泛型编程是一种通过参数化的方式将数据处理与数 ...

  6. java基础-泛型举例详解

    泛型 泛型是JDK5.0增加的新特性,泛型的本质是参数化类型,即所操作的数据类型被指定为一个参数.这种类型参数可以在类.接口.和方法的创建中,分别被称为泛型类.泛型接口.泛型方法. 一.认识泛型 在没 ...

  7. Java学习——泛型

    Java学习——泛型 摘要:本文主要介绍了什么是泛型,为什么要用泛型,以及如何使用泛型. 部分内容来自以下博客: https://www.cnblogs.com/lwbqqyumidi/p/38376 ...

  8. Java 之 泛型

    一.泛型概述 集合中是可以存放任意对象的,只要把对象存储集合后,那么这时他们都会被提升成 Object 类型.当我们取出一个对象,并且进行相应的操作,这时必须采用类型转换. 先观察下面代码: publ ...

  9. java 关于泛型的一些知识点

    public class Generic <T>{ private T ob; public Generic(T ob){ this.ob=ob; } public T GetOb(){ ...

  10. java generic type

    java generic type: 类型安全.类型参数化.不需要强制转换

随机推荐

  1. vue 的时间格式化

    大江东去,浪淘尽,千古风流人物.故垒西边,人道是,三国周郎赤壁.乱石穿空,惊涛拍岸,卷起千堆雪.江山如画,一时多少豪杰.遥想公瑾当年,小乔初嫁了,雄姿英发.羽扇纶巾,谈笑间,樯橹灰飞烟灭.故国神游,多 ...

  2. 从数据库设计到性能调优,全面掌握openGemini应用开发最佳实践

    本文分享自华为云社区<DTSE Tech Talk × openGemini :从数据库设计到性能调优,全面掌握openGemini应用开发最佳实践>,作者:华为云开源. 在本期<从 ...

  3. MySql 增、删、改、查数据库

    前言 之前几天写了MySql 的GROUP BY 语句和 JOIN 语句,今天补一下创建数据库.表的语句.首先假设已经暗转好MySQL 数据库,然后创建数据库.表. 创建数据库 create data ...

  4. python selenium.remote远程连接时间达10分钟

    问题: 在机器A搭建了selenium-grid的环境,hub以4444端口号启动,并在4444下注册了子node,端口4445,浏览器配置chrome 使用代码进行远程连接,并创建会话: 传入的se ...

  5. Win10任务栏图标居中

    win+q键搜索并打开字符映射表 点击第五行的空白字符,然后先后点击下方的选择以及复制 在桌面新建一个文件夹,然后重命名,将刚才复制的空白字符粘贴进去,如图,这样我们就拥有了一个空白名称的文件夹 在任 ...

  6. 带有ttl的Lru在Rust中的实现及源码解析

    TTL是Time To Live的缩写,通常意味着元素的生存时间是多长. 应用场景 数据库:在redis中我们最常见的就是缓存我们的数据元素,但是我们又不想其保留太长的时间,因为数据时间越长污染的可能 ...

  7. Android案例分享,基于瑞芯微RK3568国产平台!

    开发环境说明 Windows开发环境:Windows7 64bit.Windows10 64bit 虚拟机:VMware15.5.5 AndroidSDK编译环境:Ubuntu18.04.4 64bi ...

  8. HTTP事务理解

    借图: 首先三次握手理解: TCP三次握手好比两个对话, 第一次握手:甲给乙一直发送信息,乙没有回应,甲不知道乙有没有收到信息 第二次握手:乙收到信息,然后再给甲回信息,此时甲知道乙收到信息,但乙不知 ...

  9. [UG 二次开发 python] 导出BOM表(包含图片)

    只导出最底层的零件,零件的属性已经设置好,零件的截图生成后,放在零件的同一个文件夹下 用到了 xlsxwriter # nx: threaded # 导出BOM表 __version__ = &quo ...

  10. 分布式文件系统 FastDFS 整理

    1.FastDFS 1.1.了解基础概念 1.1.1.什么是分布式文件系统? 全称:Distributed File System,即简称的DFS 这个东西可以是一个软件,也可以说是服务器,和tomc ...