day1 java基础回顾-泛型
2、泛型(Generic)
当集合中存储的对象类型不同时,那么会导致程序在运行的时候的转型异常
1 import java.util.ArrayList;
2 import java.util.Iterator;
3
4 public class Demo5 {
5 public static void main(String[] args) {
6 ArrayList arr = new ArrayList();
7 arr.add(new Tiger("华南虎"));
8 arr.add(new Tiger("东北虎"));
9 arr.add(new Sheep("喜羊羊"));
10 System.out.println(arr);
11 Iterator it = arr.iterator();
12 while (it.hasNext()) {
13 Object next = it.next();
14 Tiger t = (Tiger) next;
15 t.eat();
16 }
17
18 }
19 }
20 class Tiger {
21 String name;
22
23 public Tiger() {
24
25 }
26
27 public Tiger(String name) {
28 this.name = name;
29 }
30
31 @Override
32 public String toString() {
33
34 return "Tiger@name:" + this.name;
35 }
36
37 public void eat() {
38 System.out.println(this.name + "吃羊");
39 }
40 }
41
42 class Sheep {
43 String name;
44
45 public Sheep() {
46
47 }
48
49 public Sheep(String name) {
50 this.name = name;
51 }
52
53 @Override
54 public String toString() {
55 return "Sheep@name:" + this.name;
56 }
57
58 public void eat() {
59 System.out.println(this.name + "吃青草");
60 }
61 }
原因 :发现虽然集合可以存储任意对象,但是如果需要使用对象的特有方法,那么就需要类型转换,如果集合中存入的对象不同,可能引发类型转换异常.
[Tiger@name:华南虎, Tiger@name:东北虎, Sheep@name:喜羊羊]
华南虎吃羊
东北虎吃羊
Exception in thread "main" java.lang.ClassCastException: cn.itcast.gz.map.Sheep cannot be cast to cn.itcast.gz.map.Tiger
at cn.itcast.gz.map.Demo5.main(Demo5.java:17)
出现问题:
存入的是特定的对象,取出的时候是Object对象,需要强制类型转换,可能诱发类型转换异常.
无法控制存入的是什么类型的对象,取出对象的时候进行强转时可能诱发异常.而且在编译时期无法发现问题.
虽然可以再类型转换的时候通过if语句进行类型检查(instanceof),但是效率较低.(例如吃饭的时候,还需要判断米饭里有没有沙子,吃饭效率低).可以通过给容器加限定的形式规定容器只能存储一种类型的对象.
就像给容器贴标签说明该容器中只能存储什么样类型的对象。
所以在jdk5.0后出现了泛型
泛型应用
格式
1. 集合类<类类型> 变量名 = new 集合类<类类型>();
1 public class Demo5 {
2 public static void main(String[] args) {
3 // 使用泛型后,规定该集合只能放羊,老虎就进不来了.
4 ArrayList<Sheep> arr = new ArrayList<Sheep>();
5 arr.add(new Sheep("美羊羊"));
6 arr.add(new Sheep("懒洋洋"));
7 arr.add(new Sheep("喜羊羊"));
8 // 编译失败
9 // arr.add(new Tiger("东北虎"));
10 System.out.println(arr);
11 Iterator<Sheep> it = arr.iterator();
12 while (it.hasNext()) {
13 // 使用泛型后,不需要强制类型转换了
14 Sheep next = it.next();
15 next.eat();
16 }
17
18 }
19 }
优点
1. 将运行时的异常提前至编译时发生。
2. 获取元素的时候无需强转类型,就避免了类型转换的异常问题
格式 通过<> 来指定容器中元素的类型.
什么时候使用泛型:当类中操作的引用数据类型不确定的时候,就可以使用泛型类.
JDK5.0之前的Comparable
package java.lang;
public interface Comparable { public int compareTo(Object o);
}
JDK5.0之后的Comparable
package java.lang;
public interface Comparable<T> { public int compareTo(T o);
}
这里的<T>表示泛型类型,随后可以传入具体的类型来替换它.
细节一:声明好泛型类型之后,集合中只能存放特定类型元素
1 public class Demo6 {
2 public static void main(String[] args) {
3 //创建一个存储字符串的list
4 ArrayList<String> arr=new ArrayList<String>();
5 arr.add("gz");
6 arr.add("itcast");
7 //存储非字符串编译报错.
8 arr.add(1);
9 }
10 }
细节二:泛型类型必须是引用类型
1 public class Demo6 {
2 public static void main(String[] args) {
3 // 泛型类型必须是引用类型,也就是说集合不能存储基本数据类型
4 // ArrayList<int> arr2=new ArrayList<int>();
5
6 // 使用基本数据类型的包装类
7 ArrayList<Integer> arr2 = new ArrayList<Integer>();
8
9
10 }
11 }
细节三: 使用泛型后取出元素不需要类型转换.
1 public class Demo6 {
2 public static void main(String[] args) {
3
4 ArrayList<String> arr = new ArrayList<String>();
5 arr.add("gzitcast");
6 arr.add("cditcast");
7 arr.add("bjitcast");
8 //使用泛型后取出元素不需要类型转换.
9 String str=arr.get(0);
10 System.out.println();
11 }
12 }
泛型方法
需求:写一个函数,调用者传递什么类型的变量,该函数就返回什么类型的变量?
实现一:
由于无法确定具体传递什么类型的数据.那么方法的形参就定义为Object类型.返回值也就是Object类型.但是使用该函数时需要强制类型转换.
private Object getDate(Object obj) {
return obj;
}
当不进行强制类型转换能否写出该功能.?
目前所学的知识无法解决该问题
就需要使用泛型类解决
使用的泛型的自定义来解决以上问题。
泛型: 就是将类型当作变量处理。规范泛型的定义一般是一个大写的任意字母。
1. 函数上的泛型定义
当函数中使用了一个不明确的数据类型,那么在函数上就可以进行泛型的定义。
public <泛型的声明> 返回值类型 函数名( 泛型 变量名 ){
}
public static void main(String[] args) {
int[] arr = { 1, 2, 3, 4, 5 };
new Demo6().getData(5);
}
public <T> T getData(T data) {
return data;
}
细节:
使用泛型方法前需要进行泛型声明,使用一对尖括号 <泛型>,声明的位置在static后返回值类型前。
当一个类中有多个函数声明了泛型,那么该泛型的声明可以声明在类上。
泛型类
格式
2. 类上的泛型声明 修饰符 class 类名<泛型>{ }
1 import java.util.Arrays;
2
3 public class Demo6<T> {
4 public static void main(String[] args) {
5 // 使用泛型类,创建对象的时候需要指定具体的类型
6 new Demo6<Integer>().getData(5);
7 }
8
9 public T getData(T data) {
10 return data;
11 }
12
13 // 反序任意类型数组
14 public void reverse(T[] arr) {
15 int start = 0;
16 int end = arr.length - 1;
17 for (int i = 0; i < arr.length; i++) {
18 if (start < end) {
19 T temp = arr[start];
20 arr[start] = arr[end];
21 arr[end] = temp;
22 }
23 }
24
25 }
1 import java.util.Arrays;
2
3 public class Demo6<T> {
4 public static void main(String[] args) {
5 // 使用泛型类,创建对象的时候需要指定具体的类型
6 new Demo6<Integer>().getData(5);
7 }
8
9 public T getData(T data) {
10 return data;
11 }
12
13 // 反序任意类型数组
14 public void reverse(T[] arr) {
15 int start = 0;
16 int end = arr.length - 1;
17 for (int i = 0; i < arr.length; i++) {
18 if (start < end) {
19 T temp = arr[start];
20 arr[start] = arr[end];
21 arr[end] = temp;
22 }
23 }
24
25 }
在泛型类中定义一个静态方法
public class Demo6<T> {
public static void main(String[] args) {
System.out.println(getData2(100));
}
public T getData(T data) {
return data;
}
//静态方法
public static T getData2(T data) {
return data;
}
}

注意:静态方法不可以使用类中定义的泛型
因为类中的泛型需要在对象初始化时指定具体的类型,而静态优先于对象存在。那么类中的静态方法就需要单独进行泛型声明,声明泛型一定要写在static后,返回值类型之前
泛型类细节:
1、创建对象的时候要指定泛型的具体类型
2、创建对象时可以不指定泛型的具体类型(和创建集合对象一眼)。默认是Object,例如我们使用集合存储元素的时候没有使用泛型就是那么参数的类型就是Object
3、类上面声明的泛型只能应用于非静态成员函数,如果静态函数需要使用泛型,那么
需要在函数上独立声明。
4、如果建立对象后指定了泛型的具体类型,那么该对象操作方法时,这些方法只能操作一种数据类型。
5、所以既可以在类上的泛型声明,也可以在同时在该类的方法中声明泛型。
泛型练习:
定义泛型成员
public class Demo7 {
public static void main(String[] args) {
Father<String> f = new Father<String>("jack");
System.out.println(f.getT());
Father<Integer> f2 = new Father<Integer>(20);
System.out.println(f2.getT());
}
}
class Father<T> {
private T t;
public Father() {
}
public Father(T t) {
super();
this.t = t;
}
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
如果Father类有子类,子类该如何实现
public class Demo7 {
public static void main(String[] args) {
Father<String> f = new Father<String>("jack");
System.out.println(f.getT());
Father<Integer> f2 = new Father<Integer>(20);
System.out.println(f2.getT());
}
}
class Father<T> {
private T t;
public Father() {
}
public Father(T t) {
super();
this.t = t;
}
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
//子类指定了具体的类型
class Son extends Father<String>{
}
//子类也需要使用泛型
class Son3<T> extends Father<T>{
}
//错误写法,父类上定义有泛型需要进行处理
class Son2 extends Father<T>{
}
泛型接口
public class Demo8 {
public static void main(String[] args) {
MyInter<String> my = new MyInter<String>();
my.print("泛型");
MyInter2 my2 = new MyInter2();
my.print("只能传字符串");
}
}
interface Inter<T> {
void print(T t);
}
// 实现不知为何类型时可以这样定义
class MyInter<T> implements Inter<T> {
public void print(T t) {
System.out.println("myprint:" + t);
}
}
//使用接口时明确具体类型。
class MyInter2 implements Inter<String> {
@Override
public void print(String t) {
System.out.println("myprint:" + t);
}
}
day1 java基础回顾-泛型的更多相关文章
- day1 java基础回顾- 文件路径
绝对路径 以根目录或某盘符开头的路径(或者说完整的路径) 例如: l c:/a.txt (Windows操作系统中) l c:/xxx/a.txt (Windows操作系统中) l /var/x ...
- day1 java基础回顾-内省
为什么要学内省? 开发框架时,经常需要使用java对象的属性来封装程序的数据,每次都使用反射技术完成此类操作过于麻烦,所以sun公司开发了一套API,专门用于操作java对象的属性. 内省是用于操作j ...
- day1 java基础回顾- Properties类与配置文件
Properties配置文件说明 Properties类对应.properties文件.文件内容是键值对,键值对之间使用"="或空格隔开.开头是"#"的表示注释 ...
- day1 java基础回顾-Junit单元测试
Junit单元测试框架的基本使用 一.搭建环境: 导入junit.jar包(junit4) 二.写测试类: 0,一般一个类对应一个测试类. 1,测试类与被测试类最好是放到同一个包中(可以是不同的源文件 ...
- day1 java基础回顾-多线程
启动线程方式 方式一:继承Thread. 1. 自定义一个类继承Thread类. 2. 重写Thread的run方法,把自定义线程的任务代码定义在run方法上. 3. 创建Thread子类的对象,并且 ...
- day1 java基础回顾-IO流
IO流的分类 注:这几个类都是抽象类. IO解决问题: 解决设备与设备之间 的数据传输问题. 比如: 硬盘--->内存 内存----->硬盘 字节流: 输入字节流:---------| I ...
- day1 java基础回顾-集合
1.集合 1.1 集合的类型与各自的特性 ---|Collection: 单列集合 ---|List: 有存储顺序, 可重复 ---|ArrayList: 数组实现, 查找快, 增删慢 由于是数组实现 ...
- 四、Android学习第四天——JAVA基础回顾(转)
(转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 四.Android学习第四天——JAVA基础回顾 这才学习Android的 ...
- 黑马程序员:Java基础总结----泛型(高级)
黑马程序员:Java基础总结 泛型(高级) ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 泛型(高级) 泛型是提供给javac编译器使用的,可以限定集合中的输入类型 ...
随机推荐
- 基于zookeeper或redis实现分布式锁
前言 在分布式系统中,分布式锁是为了解决多实例之间的同步问题.例如master选举,能够获取分布式锁的就是master,获取失败的就是slave.又或者能够获取锁的实例能够完成特定的操作. 目前比较常 ...
- python 基础 7.1 datetime 获得时间
一 datatime 的使用 object timedeta tzinfo time data dat ...
- php字符串中 转义字符 “ ’‘ ” ’ “” ‘ " \’ ' ' \‘ " " \" '' \ " " 使用
<?php echo $str_string1='甲问:"你在哪里学的PHP?"'; echo "<br />"; echo $str_str ...
- linux rz sz命令
rz是receive zmodem的缩写,sz是send zmodem的缩写. 传输文件使用的是zmodem协议,所以叫zmodem. r和s是以服务器为主体的,服务器接收就是r,服务器发送就是s.
- mysqldump的--master-data参数
mysqldump导出数据时,当这个参数的值为1的时候,mysqldump出来的文件就会包括CHANGE MASTER TO这个语句,CHANGE MASTER TO后面紧接着就是file和posit ...
- 流畅python学习笔记:第十七章:并发处理二
本章讨论python3.2引入的concurrent.futures模块.future是中文名叫期物.期物是一种对象,表示异步执行的操作 在很多任务中,特别是处理网络I/O.需要使用并发,因为网络有很 ...
- UITableViewCell的多选操作
版权声明:本文为博主原创文章.未经博主同意不得转载,转载需加上原博客链接. https://blog.csdn.net/panyong4627/article/details/37902207 - ( ...
- Django+ajax+jsonp实现借口调用文本处理
首页 提交 <script src="/static/jquery-2.1.4.min.js"></script> <script type=&quo ...
- nginx日志输出参数记录
摘自: http://www.cnblogs.com/LoveJulin/p/5082363.html nginx服务器日志相关指令主要有两条,一条是log_format,用来设置日志格式,另外一条是 ...
- Hadoop- 分布式资源管理YARN架构讲解
YARN是分布式资源管理,每一台机器都要去管理该台计算机的资源,Yarn负责为MapReduce程序分配运算硬件资源.每一台机器的管理者叫 NodeManager,整个集群的管理者管理着整个集群的No ...