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基础回顾-泛型的更多相关文章

  1. day1 java基础回顾- 文件路径

    绝对路径 以根目录或某盘符开头的路径(或者说完整的路径) 例如: l  c:/a.txt (Windows操作系统中) l  c:/xxx/a.txt (Windows操作系统中) l  /var/x ...

  2. day1 java基础回顾-内省

    为什么要学内省? 开发框架时,经常需要使用java对象的属性来封装程序的数据,每次都使用反射技术完成此类操作过于麻烦,所以sun公司开发了一套API,专门用于操作java对象的属性. 内省是用于操作j ...

  3. day1 java基础回顾- Properties类与配置文件

    Properties配置文件说明 Properties类对应.properties文件.文件内容是键值对,键值对之间使用"="或空格隔开.开头是"#"的表示注释 ...

  4. day1 java基础回顾-Junit单元测试

    Junit单元测试框架的基本使用 一.搭建环境: 导入junit.jar包(junit4) 二.写测试类: 0,一般一个类对应一个测试类. 1,测试类与被测试类最好是放到同一个包中(可以是不同的源文件 ...

  5. day1 java基础回顾-多线程

    启动线程方式 方式一:继承Thread. 1. 自定义一个类继承Thread类. 2. 重写Thread的run方法,把自定义线程的任务代码定义在run方法上. 3. 创建Thread子类的对象,并且 ...

  6. day1 java基础回顾-IO流

    IO流的分类 注:这几个类都是抽象类. IO解决问题: 解决设备与设备之间 的数据传输问题. 比如: 硬盘--->内存 内存----->硬盘 字节流: 输入字节流:---------| I ...

  7. day1 java基础回顾-集合

    1.集合 1.1 集合的类型与各自的特性 ---|Collection: 单列集合 ---|List: 有存储顺序, 可重复 ---|ArrayList: 数组实现, 查找快, 增删慢 由于是数组实现 ...

  8. 四、Android学习第四天——JAVA基础回顾(转)

    (转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 四.Android学习第四天——JAVA基础回顾 这才学习Android的 ...

  9. 黑马程序员:Java基础总结----泛型(高级)

    黑马程序员:Java基础总结 泛型(高级)   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 泛型(高级) 泛型是提供给javac编译器使用的,可以限定集合中的输入类型 ...

随机推荐

  1. Android 关于软键盘

    一..弹出的时候显示Editext框 添加布局replay_input <?xml version="1.0" encoding="utf-8"?> ...

  2. 基于Flume的美团日志收集系统 架构和设计 改进和优化

    3种解决办法 https://tech.meituan.com/mt-log-system-arch.html 基于Flume的美团日志收集系统(一)架构和设计 - https://tech.meit ...

  3. VC调用Delphi DLL

    别的没什么,是一定可以调用成功的.但是意外的是,ShowMessage函数在DLL里也可以轻易被调用.此外,Delphi里的var 相当于VC里的引用,需要在函数原型里正确标识,否则传递普通变量甚至常 ...

  4. SAP FI 科目代码

    资产类 现金 银行存款 其他货币资金 短期投资 短期投资跌价准备 应收票据 应收股利 应收利息 应收账款 其他应收款 坏账准备 预付账款 应收补贴款 物料采购 原材料 包装物 低值易耗品 材料成本差异 ...

  5. Java for LeetCode 102 Binary Tree Level Order Traversal

    Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, ...

  6. hashMap的线程不安全

    hashMap是非线程安全的,表现在两种情况下: 1 扩容: t1线程对map进行扩容,此时t2线程来读取数据,原本要读取位置为2的元素,扩容后此元素位置未必是2,则出现读取错误数据. 2 hash碰 ...

  7. P4474 王者之剑

    P4474 王者之剑 题目大意 n*m的带权网格,任意选择起点开始时刻为0秒.以下操作,每秒按顺序执行 在第i秒开始的时候,在方格(x,y)上,获得(x,y)的值 在偶数秒,周围四格的值清零 每秒可选 ...

  8. 3D特效焦点图

    在线演示 本地下载

  9. Spring Boot2.0之全局捕获异常

    全局捕获异常,很明显的错误404返回给客户,很不好呀.整个web请求项目全局捕获异常,比如空指针直接返回给客户啊,那多操蛋呀~ 看这几个常用的注解: @ExceptionHandler 表示拦截异常 ...

  10. [干货]兼容HTML5的Placeholder属性-更新版v0.10102013

    HTML5对Web Form做了许多增强,比如input新增的type类型.Form Validation等.Placeholder是HTML5新增的另一个属性,当input或者textarea设置了 ...