day15_JAVAOOP
课程目标
1. 【理解】什么是泛型 2. 【掌握】泛型的基本使用 3. 【理解】什么是Collections工具类 4. 【理解】什么是File类 5. 【掌握】File类的常用功能 6. 【掌握】打印多级目录案例 7. 【掌握】文件搜索案例
泛型
泛型概述
在前面学习集合时,我们都知道集合中是可以存放任意对象的,只要把对象存储集合后,那么这时他们都会被提升成Object类型。当我们在取出每一个对象,并且进行相应的操作,这时必须采用类型转换。
大家观察下面代码:
public class GenericDemo { public static void main(String[] args) { Collection coll = new ArrayList(); coll.add("abc"); coll.add("cba"); coll.add(5);//由于集合没有做任何限定,任何类型都可以给其中存放 Iterator it = coll.iterator(); while(it.hasNext()){ //需要打印每个字符串的长度,就要把迭代出来的对象转成String类型 String str = (String) it.next(); System.out.println(str.length()); } } }
程序在运行时发生了问题java.lang.ClassCastException。为什么会发生类型转换异常呢? 我们来分析下:由于集合中什么类型的元素都可以存储。导致取出时强转引发运行时 ClassCastException。
- 怎么来解决这个问题呢?
集合中可以存储各种对象,但实际上通常集合只存储同一类型对象。例如都是存储字符串对象。因此在JDK5之后,新增了泛型(Generic)语法,让你在设计API时可以指定类或方法支持泛型,这样我们使用API的时候也变得更为简洁,并得到了编译时期的语法检查。 - 泛型:可以在类或方法中预支地使用未知的类型。
tips:一般在创建对象时,将未知的类型确定具体的类型。当没有指定泛型时,默认类型为Object类型。
使用泛型的好处
泛型带来了哪些好处呢?
- 将运行时期的ClassCastException,转移到了编译时期变成了编译失败。
- 避免了类型强转的麻烦。
通过我们如下代码体验一下:
public class GenericDemo2 { public static void main(String[] args) { Collection<String> list = new ArrayList<String>(); list.add("abc"); list.add("cba"); // list.add(5);//当集合明确类型后,存放类型不一致就会编译报错 // 集合已经明确具体存放的元素类型,那么在使用迭代器的时候,迭代器也同样会知道具体遍历元素类型 Iterator<String> it = list.iterator(); while(it.hasNext()){ String str = it.next(); //当使用Iterator<String>控制元素类型后,就不需要强转了。获取到的元素直接就是String类型 System.out.println(str.length()); } } }
tips:泛型是数据类型的一部分,我们将类名与泛型合并一起看做数据类型。
泛型的定义与使用
泛型:是一种把类型明确的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型。参数化类型,把类型当作参数一样的传递。
我们在集合中会大量使用到泛型,这里来完整地学习泛型知识。泛型,用来灵活地将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数进行传递。
通常情况下,T,E,K,V,?是这样约定的:
- ?表示不确定的 java 类型
- T (type) 表示具体的一个java类型
- K V (key value) 分别代表java键值中的Key Value
- E (element) 代表Element
泛型类
- 定义格式
<数据类型> 此处的数据类型只能是引用类型。
好处:
A:把运行时期的问题提前到了编译期间
B:避免了强制类型转换
- 自定义泛型类
/* * 泛型类:把泛型定义在类上 */ public class ObjectTool<T> { private T obj; public T getObj() { return obj; } public void setObj(T obj) { this.obj = obj; } }
- 如何使用泛型类
使用泛型: 即什么时候确定泛型。
在创建对象的时候确定泛型
/* * 泛型类的测试 */ public class ObjectToolDemo { public static void main(String[] args) { ObjectTool<String> ot = new ObjectTool<String>(); ot.setObj(new String("江一燕")); String s = ot.getObj(); System.out.println("姓名是:" + s); ObjectTool<Integer> ot2 = new ObjectTool<Integer>(); ot2.setObj(27); Integer i = ot2.getObj(); System.out.println("年龄是:" + i); } }
泛型方法
- 定义格式
修饰符 <代表泛型的变量> 返回值类型 方法名 (参数){ }
- 定义泛型方法
/* * 泛型方法:把泛型定义在方法上 */ public class ObjectTool { public <T> Object show(T t) { //System.out.println(t); return t; } //定义一个泛型方法 //返回类型不应该明确,因为泛型方法的类型都不明确 //建议: Object 或者 T(泛型) public <T> T show(T t){ System.out.println(t); return t; } }
- 泛型方法的使用
调用方法时,确定泛型的类型
public class ObjectToolDemo { public static void main(String[] args) { // 定义泛型方法后 ObjectTool ot = new ObjectTool(); String s = (String) ot.show("hello"); Integer i = (Integer) ot.show(200); Boolean b = (Boolean) ot.show(true); System.out.println(s); System.out.println(i); System.out.println(b); ObjectToolMethod otm = new ObjectToolMethod(); String aa = otm.show("aa"); Integer show = otm.show(11); System.out.println(aa); System.out.println(show); } }
泛型接口
- 定义格式
修饰符 interface接口名<代表泛型的变量> { }
- 定义泛型接口
/* * 泛型接口:把泛型定义在接口上 */ public interface Inter<T> { public abstract void show(T t); }
- 泛型接口的使用
实现类
//实现类在实现接口的时候 //第一种情况:已经知道该是什么类型的了 public class InterImpl implements Inter<String> { @Override public void show(String t) { System.out.println(t); } } //第二种情况:还不知道是什么类型的 public class InterImpl<T> implements Inter<T> { @Override public void show(T t) { System.out.println(t); } }
- 测试
public class InterDemo { public static void main(String[] args) { //第一种情况:实现类已经明确类型,实例化对象时必须与实现类中的类型一致 InterDemo i = new InteImpl();//我在实现的时候,已经明确类型–String i.show(“aaa”); i.show(“bbb”);
//第二种情况:实现类也没有明确类型 InterDemo<Integer> ii = new InteImpl2<>();//我在实现的时间也没有给出明确 ii.show(11); ii.show(22); InterDemo<String> ii2 = new InteImpl2<>();//我在实现的时间也没有给出明确 ii2.show("11"); ii2.show("22"); }
}
## 泛型通配符-了解 ### 什么是泛型通配符 当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示。但是一旦使用泛型的通配符后,只能使用Object类中的共性方法,集合中元素自身方法无法使用。 ### 通配符基本使用 泛型的通配符:**不知道使用什么类型来接收的时候,此时可以使用?,?表示未知通配符。** 此时只能接受数据,不能往该集合中存储数据。 ### 通配符高级使用 ```java /* * 泛型高级(通配符) * ?:任意类型,如果没有明确,那么就是Object以及任意的Java类了 * ? extends E:向下限定,E及其子类 * ? super E:向上限定,E极其父类 */ public class GenericDemo { public static void main(String[] args) { // 泛型如果明确的写的时候,前后必须一致 Collection<Object> c1 = new ArrayList<Object>(); // Collection<Object> c2 = new ArrayList<Animal>(); // Collection<Object> c3 = new ArrayList<Dog>(); // Collection<Object> c4 = new ArrayList<Cat>(); // ?表示任意的类型都是可以的 Collection<?> c5 = new ArrayList<Object>(); Collection<?> c6 = new ArrayList<Animal>(); Collection<?> c7 = new ArrayList<Dog>(); Collection<?> c8 = new ArrayList<Cat>(); // ? extends E:向下限定,E及其子类,表示包括E在内的任何子类; // Collection<? extends Animal> c9 = new ArrayList<Object>(); Collection<? extends Animal> c10 = new ArrayList<Animal>(); Collection<? extends Animal> c11 = new ArrayList<Dog>(); Collection<? extends Animal> c12 = new ArrayList<Cat>(); // ? super E:向上限定,E极其父类,表示包括E在内的任何父类; Collection<? super Animal> c13 = new ArrayList<Object>(); Collection<? super Animal> c14 = new ArrayList<Animal>(); // Collection<? super Animal> c15 = new ArrayList<Dog>(); // Collection<? super Animal> c16 = new ArrayList<Cat>(); } } public class Animal { } public class Dog extends Animal { } public class Cat extends Animal { }
JAVA零基础小白入门上手教程day15-泛型&File(二)https://developer.aliyun.com/article/1433761