文档章节

黑马程序员-JAVA基础-Java 集合之泛型

不最醉不龟归
 不最醉不龟归
发布于 2016/11/22 18:14
字数 2192
阅读 18
收藏 0
点赞 0
评论 0

所谓泛型就是允许在定义类、接口时指定类型形参,这个类型形参将在声明变量、创建对象时确定。增加了泛型支持后的集合,完全可以记住集合中元素的类型,并可以在编译时检查集合中元素的类型。即解决一些安全问题;同时还可以让代码变得更加简洁。

  

一.使用泛型 

  泛型的格式:通过<>来定义要操作的引用数据类型。

复制代码

1 public class GenericDemo {
 2     public static void main(String[] args)
 3     {
 4 //        创建一个只能保存字符串的List 集合
 5         List<String> strList = new ArrayList<String>() ;
 6         strList.add("Generic") ; 
 7 //        如果存放其他对象这回出现编译错误。
 8         System.out.println(strList);
 9     }
10 }

复制代码

 

   使用泛型的好处:

    1、将运行时期出现的ClassCastExcpetion , 转移到了编译时期。方便于程序员解决问题,让运行时期问题减少。

    2、避免了强制转换的麻烦。

  如下代码: 

复制代码

1 class StringDemo
 2 {
 3     String name ; 
 4     public StringDemo(String name )
 5     {
 6         this.name = name ; 
 7     }
 8 }
 9 public class GenericDemo {
10     public static void main(String[] args)
11     {
12         List list = new ArrayList() ;  
13         list.add(new StringDemo("烦烦烦烦烦01")) ; 
14         list.add(new StringDemo("烦烦烦烦烦02")) ; 
15         list.add(new StringDemo("烦烦烦烦烦03")) ; 
16         list.add(new StringDemo("烦烦烦烦烦04")) ; 
17         
18         list.add(1000) ; 
19         MyIterator(list) ; 
20     }
21 //    定义遍历方法:
22     public static void MyIterator(List list)
23     {
24         Iterator it = list.iterator() ; 
25         while (it.hasNext() )
26         {
27             StringDemo s = (StringDemo) it.next() ; 
28             System.out.println(s.name);
29         }
30     }
31 }

复制代码

 

}

  在调用MyIterator(List list) 方法时会发生ClassCastException 异常。而且在编译时是不会有任何提示,只有运行时会出现,所以使的程序存在安全隐患。

  如果使用泛型则会在编译时提示错误,而且在遍历时不需要强制转换。如: 

复制代码

1 class StringDemo
 2 {
 3     String name ; 
 4     public StringDemo(String name )
 5     {
 6         this.name = name ; 
 7     }
 8 }
 9 public class GenericDemo {
10     public static void main(String[] args)
11     {
12         List<StringDemo> list = new ArrayList<StringDemo>() ;  
13         list.add(new StringDemo("烦烦烦烦烦01")) ; 
14         list.add(new StringDemo("烦烦烦烦烦02")) ; 
15         list.add(new StringDemo("烦烦烦烦烦03")) ; 
16         list.add(new StringDemo("烦烦烦烦烦04")) ; 
17         
18 //        下面一行代码在编译时会出错:
19         list.add(1000) ; 
20         MyIterator(list) ; 
21     }
22 //    定义遍历方法:
23     public static void MyIterator(List list)
24     {
25         Iterator<StringDemo> it = list.iterator() ; 
26         while (it.hasNext() )
27         {   
28             System.out.println( it.next().name);
29         }
30     }
31 }

复制代码

  注意:在使用Java提供的对象时,什么时候写泛型呢?

  只要见到<> (<>就是用来接收类型的。),就要定义泛型。当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。

二.了解泛型

  ArrayList<E> 类定义和ArrayList<Integer> 类引用中涉及的术语:

  > 整个称为ArrayList<E> 泛型类型。

  > ArrayList<E> 中的E称为类型变量或类型参数。

  > 整个ArrayList<Integer> 称为参数化的类型。

  > ArrayList<Integer> 中的Integer 称为类型参数的实例或实际类型参数。

  > ArrayList<Integer> 中的<> 念着typeof

  > ArrayList 称为原始类型

  参数化类型不考虑类型参数的继承:

  > Vector<String> v = new Vector<Object>() ; //错误

  > Vector<Object> v = new Vector<String>() ; //也错误

  创建数组实例时,数组的元素不能使用参数化的类型:

  > Vector<Integer> vectorList[] = new Vector<Integer>[10] ; //错误

 

 

三.定义泛型类

  除了Java提供了一些类增加了泛型支持外,我们可以定义泛型支持的类。那么在什么时候定义泛型类呢?

  当类中操作的引用数据类型不确定时可以定义泛型类。

  格式如下:

class Tools<T>
{
}

 

  具体操作:

复制代码

1 //定义一个工具类Tools
 2 //因为不知道要操作的类型是什么所增加泛型支持
 3 class Tools<T>
 4 {
 5 //    包含输出函数:
 6     public void sop(T t)
 7     {
 8         System.out.println("sop:"+t);
 9     } 
10 }
11 //定义一个Books 类
12 class Books
13 {
14     private String name ;
15     public Books(String name)
16     {
17         this.name = name  ; 
18     } 
19 //    重写toString 方法
20     public String toString()
21     {
22         return "name = " + name ;  
23     }
24 }
25 public class GenericText 
26 {
27     public static void main(String[] args)
28     { 
29     //    创建一个Tools 实例tool ,定义 tool 要操作的数据类型为Books 
30         Tools<Books>  tool = new Tools<Books>() ;  
31     //    tool 可以操作 Books 类型,还可以操作Integer 类型和String类型。
32         tool.sop(new Books("诛仙")); 
33     }
34 }

复制代码

 

   定义一个Tools 类 用来完成打印操作,但是应为不知道要操作的数据类型是什么,所以可以定义成泛型类。

 

 三.泛型方法

  泛型类定义的泛型,在整个类中有效,如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。为了让不同方法可以操作不同类型,而且类型还不确定,

那么可以将泛型定义在方法上。

  定义泛型方法格式如下:

public <T> void show(T t) 注意:<>放在修饰符后面,返回值前面
        {
        }

  具体操作如下:

复制代码

1 //定义一个工具类Tools
 2 //因为不知道要操作的类型是什么所增加泛型支持
 3 class Tools<T>
 4 {
 5 //    包含输出函数:
 6     public void sop(T t)
 7     {
 8         System.out.println("sop:"+t);
 9     } 
10 //    定义的泛型方法:
11     public <T> void show (T t)
12     {
13         System.out.println("show:"+t);
14     }
15 }
16 //定义一个Books 类
17 class Books
18 {
19     private String name ;
20     public Books(String name)
21     {
22         this.name = name  ; 
23     } 
24 //    重写toString 方法
25     public String toString()
26     {
27         return "name = " + name ;  
28     }
29 }
30 public class GenericText 
31 {
32     public static void main(String[] args)
33     { 
34     //    创建一个Tools 实例tool ,定义 tool 要操作的数据类型为Books 
35         Tools<Books>  tool = new Tools<Books>() ;  
36     //    tool 可以操作 Books 类型,还可以操作Integer 类型和String类型。
37         tool.sop(new Books("诛仙")); 
38         tool.show(new Books("诛仙")) ; 
39 //        下面的方法编译时会报错》、:
40         tool.sop(1000) ;
41         tool.sop("String") ;
42         
43 //        但下面却不会报错,并且正常运行。
44         tool.show(1000) ; 
45         tool.show("String") ;
46     }
47 }

复制代码

 

   通过上面的代码,可以知道泛型类和泛型方法可以同时定义,且不冲突。但是也有特殊情况:静态方法不可以访问定义类上的泛型,如:

复制代码

class Tools<T>
        {
            public static void method(T t)
            {
            }
        }
        上面的书写是错误的,

复制代码

  如果静态方法操作的引用数据类型不确定,可将泛型定义在方法上:

class Tools<T>
        {
            public static <T> void method(T t)
            {
            }
        }

  

  

四.泛型限定和通配符

  4.1 通配符

  类型通配符是一个问号(?):问号作为类型实参传给List 集合写作:List<?>。

复制代码

1 //定义一个Books 类
 2 class Books
 3 {
 4     private String name ;
 5     public Books(String name)
 6     {
 7         this.name = name  ; 
 8     } 
 9 //    重写toString 方法
10     public String toString()
11     {
12         return "name = " + name ;  
13     }
14 }
15 public class GenericText 
16 {
17     public static void main(String[] args)
18     {
19 //        创建一个只能存储 Books 类型元素的 List 集合。
20         List<Books> bookList = new ArrayList<Books>() ;  
21         bookList.add(new Books("诛仙")) ;
22         bookList.add(new Books("笑傲江湖")) ; 
23         
24 //        创建一个只能存储String 类型元素的List 集合
25         List<String> strList = new ArrayList<String>() ;
26         strList.add("Generic001") ;
27         strList.add("Generic002") ;
28         
29         MyIterator(strList) ; 
30         MyIterator(bookList) ;
31         
32     }
33 //    定义个遍历List 集合的方法。
34     public static void MyIterator(List<?>  strList)
35     {
36         Iterator<?> it = strList.iterator() ;
37         while(it.hasNext())
38         {
39             System.out.println(it.next());
40         }
41     }
42 }

复制代码

  在 MyIterator 方法中使用了类型通配符 ? ,好处是只写一个 遍历方法便可操作List 集合的遍历,缺点是不能调用元素中的特定方法。

   

  4.2 泛型限定:

    1、 ? extends E : 可以接收E类型或者E的子类型。上限定。

    2、? super E : 可以接收E类型或者E的父类型。下限定。

    

复制代码

1 class Books
 2 {
 3     String name ;
 4     public Books(String name)
 5     {
 6         this.name = name  ; 
 7     }  
 8     public String toString()
 9     {
10         return "name:" + name ; 
11     }
12 }
13 class ComicBooks extends Books
14 { 
15     public ComicBooks(String name) {
16         super(name); 
17     } 
18 }
19 class Person_1 
20 {
21     String name ; 
22     public Person_1 (String name)
23     {
24         this.name = name ;
25     }
26 }
27 public class GenericTreeSet {
28     
29     public static void main(String[] args)
30     {
31 //        定义 TreeSet 集合 ,并且里面只存储ComicBooks类型元素,切按照自已的比较规则排序
32         TreeSet<ComicBooks> bookTree = new TreeSet<ComicBooks>(new MyComparable()) ;
33         
34         bookTree.add(new ComicBooks("aaaaaa")) ;
35         bookTree.add(new ComicBooks("aaa3gfaaa")) ;
36         bookTree.add(new ComicBooks("afdfef")) ;
37         bookTree.add(new ComicBooks("asdffefq")) ;
38 //        调用
39         MyIterator(bookTree) ; 
40         
41 //        下面代码编译会出现异常
42         TreeSet<Person_1> p = new TreeSet<Person_1>(new MyComparable()) ;
43     }
44 //    定义遍历方法:只能操作Books 类型或者 Books的子类型
45     public static void MyIterator(TreeSet<? extends Books> bookTree)
46     {
47         Iterator<? extends Books> it =  bookTree.iterator()  ;
48         while(it.hasNext())
49         {
50             System.out.println(it.next().toString());
51         }
52     }
53 }
54 //定义比较器 :按倒序排序且该比较器只适用于 Books 类型或者 Books的子类型
55 class MyComparable implements Comparator<Books>
56 { 
57     public int compare(Books o1 , Books o2)
58     {  
59         return o2.name.compareTo(o1.name);
60     } 
61 }

复制代码

  所以,当我们定义的某些方法只作用与某些类与其子类时,可以通过泛型限定来实现。

本文转载自:http://www.cnblogs.com/jbelial/archive/2013/03/30/2990935.html

共有 人打赏支持
不最醉不龟归
粉丝 12
博文 415
码字总数 435155
作品 0
深圳
程序员
理解Java 泛型 : 和

在工作中使用<? extends T>是很常见的。那么在使用add方法的时候(List <? extends T>),是不是发现在编译的时候就会报错。为什么,这是我和同事同时发出的疑问。这看来还是我们对JAVA的泛...

jishuai
2017/11/06
0
0
Kotlin语言中的泛型设计哲学

Kotlin语言的泛型设计很有意思,但并不容易看懂。关于这个部分的官方文档,我反复看了好几次,终于弄明白Kotlin语言泛型设计的背后哲学。这篇文章将讲述Kotlin泛型设计的整个思考过程及其背后...

欧阳锋
04/16
0
0
从java程序员到CTO的成长路线图

很多新人不知道从事java开发,具体的发展路径是怎么样的,甚至很多人都不能区分程序猿和攻城师的区别。包括不少小白,从事java开发都半年,甚至1年了,对职业发展还没有清晰的认证。这非常不...

6pker
2013/10/24
0
2
【转】Java语法糖的味道:泛型与类型擦除

泛型是JDK 1.5的一项新特性,它的本质是参数化类型(Parameterized Type)的应用,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类...

mj4738
2011/11/29
0
0
黑马程序员.bobo.DAY.1

C:Program Files (x86)NVIDIA CorporationPhysXCommon;<span style="background:rgb(255,0,0)">%JAVA8HOME%bin;%JAVA8HOME%jrebin;</span>D:oracleproduct10.2.0db_1bin;C:Program Files (x8......

BobbyLou
2015/05/14
0
0
【目录导航】JAVA零基础进阶之路

【JAVA零基础入门系列】(已完结)导航目录 Day1 开发环境搭建 Day2 Java集成开发环境IDEA Day3 Java基本数据类型 Day4 变量与常量 Day5 Java中的运算符 Day6 Java字符串 Day7 Java输入与输出...

MFrank
06/21
0
0
Kotlin 泛型 VS Java 泛型

建议先阅读我的上一篇文章 -- Java 泛型 和 Java 泛型一样,Kotlin 泛型也是 Kotlin 语言中较难理解的一个部分。Kotlin 泛型的本质也是参数化类型,并且提供了编译时强类型检查,实际上也是伪...

JohnnyShieh
06/11
0
0
Java 8新特性探究(六)泛型的目标类型推断

简单理解泛型 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。通俗点将就是“类型的变量”。这种类型变量可以用在类、接口和方法的创建中。...

OSC闲人
2013/12/14
0
3
Java编程学习之泛型方法的了解 java开发

Java泛型方法和泛型类支持程序员使用一个方法指定一组相关方法,或者使用一个类指定一组相关的类型。 Java泛型是JDK 5中引入的一个新特性,泛型提供了编译时类型安全检测机制,该机制允许程序...

老男孩Linux培训
05/29
0
0
Java 8新特性探究 前言

自2013年6月13日,oracle就已经发布的Java 8特性完备版本(M7),但最终GA版本将在2014年3月18日(已第二次跳票,原计划今年9月发布的,据官网宣称是为了解决安全问题......),相信大家多多...

OSC闲人
2013/11/05
0
17

没有更多内容

加载失败,请刷新页面

加载更多

下一页

expect脚本同步文件、expect脚本指定host和要同步的文件、构建文件分发系统

expect脚本同步文件 更改权限 执行脚本 查看执行结果 expect eof需要加上,作用是等脚本命令执行完再进行退出 expect脚本指定host和要同步的文件 更改权限,执行脚本 构建文件分发系统 需求背...

Zhouliang6
27分钟前
1
0
Hive应用:外部分区表

Hive应用:外部分区表 介绍 Hive可以创建外部分区表。创建表的时候,分区要在建表语句中体现。建完之后,你不会在表中看到数据,需要进行分区添加,使用alter语句进行添加。然后数据才会显示...

星汉
37分钟前
0
0
点击Enter登录

1. 效果 2. 实现过程(记得引入jq文件) //6.回车事件 登录 $(function() { document.onkeydown = function(event) { var e = event || window.event || arguments.callee.caller.arguments......

Lucky_Me
42分钟前
1
0
点击菜单内容切换

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .menu{ height: 38px; background-color: #eeeeee; line-height: 38px; } .mao{ ......

南桥北木
今天
1
0
OSChina 周六乱弹 —— 妹子和游戏哪个更好玩

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @andonny :分享唐朝乐队的单曲《国际歌》 《国际歌》- 唐朝乐队 手机党少年们想听歌,请使劲儿戳(这里) @举个栗子- :日常祈雨 邪恶的大祭...

小小编辑
今天
508
6
流利阅读笔记32-20180721待学习

“人工智能”造假:只有人工,没有智能 Lala 2018-07-21 1.今日导读 当今社会,擅长单个方面的人工智能已经盛行,手机借助 AI 智慧防抖技术帮助大家拍出清晰照片,谷歌研发的 AI 助手将可以帮...

aibinxiao
今天
7
0
我的成长记录(一)

今天突然精神抖擞,在我的博客下新开一项分类>成长记录,专门记录每隔一段时间我的一点感悟吧。因为今天才专门花时间新开这样一个分类,所以以前有过的一些感悟没有记录下来,现在已经想不起...

dtqq
今天
1
0
机器学习管理平台 MLFlow

最近工作很忙,博客一直都没有更新。抽时间给大家介绍一下Databrick开源的机器学习管理平台-MLFlow。 谈起Databrick,相信即使是不熟悉机器学习和大数据的工程湿们也都有所了解,它由Spark的...

naughty
今天
13
0
idea tomcat 远程调试

tomcat 配置 编辑文件${tomcat_home}/bin/catalina.sh,在文件开头添加如下代码。    CATALINA_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=7829" Idea端配......

qwfys
今天
2
0
遍历目录下的文件每250M打包一个文件

#!/usr/bin/env python # -*- utf-8 -*- # @Time : 2018/7/20 0020 下午 10:16 # @Author : 陈元 # @Email : abcmeabc@163.com # @file : tarFile.py import os import tarfile import thr......

寻爱的小草
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部