问题引入
package cn.itcast_01;
import java.util.ArrayList;
import java.util.Iterator;
/*
* ArrayList存储字符串并遍历
*
* 我们按照正常的写法来写这个程序, 结果确出错了。
* 为什么呢?
* 因为我们开始存储的时候,存储了String和Integer两种类型的数据。
* 而在遍历的时候,我们把它们都当作String类型处理的,做了转换,所以就报错了。
* 但是呢,它在编译期间却没有告诉我们。
* 所以,我就觉得这个设计的不好。
* 回想一下,我们的数组
* String[] strArray = new String[3];
* strArray[0] = "hello";
* strArray[1] = "world";
* strArray[2] = 10;
* 集合也模仿着数组的这种做法,在创建对象的时候明确元素的数据类型。这样就不会在有问题了。
* 而这种技术被称为:泛型。
*/
public class GenericDemo {
public static void main(String[] args) {
// 创建
ArrayList<String> array = new ArrayList<String>();
// 添加元素
array.add("hello");
array.add("world");
array.add("java");
// array.add(new Integer(100));
//array.add(10); // JDK5以后的自动装箱
// 等价于:array.add(Integer.valueOf(10));
// 遍历
Iterator<String> it = array.iterator();
while (it.hasNext()) {
// ClassCastException
// String s = (String) it.next();
String s = it.next();
System.out.println(s);
}
// 看下面这个代码
// String[] strArray = new String[3];
// strArray[0] = "hello";
// strArray[1] = "world";
// strArray[2] = 10;
}
}
概述
泛型:是一种把类型明确的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型。
参数化类型,把类型当作参数一样的传递。
格式
<数据类型> (注意:此处的数据类型只能是引用类型)
好处:
A:把运行时期的问题提前到了编译期间
B:避免了强制类型转换
C:优化了程序设计,解决了黄色警告线
使用的地方及案例
泛型在哪些地方使用呢?
看API,如果类,接口,抽象类后面跟的有<E>就说要使用泛型。一般来说就是在集合中使用。
案例一:泛型存储字符串并遍历
package cn.itcast_02;import java.util.ArrayList;import java.util.Iterator;/* * 泛型在哪些地方使用呢? * 看API,如果类,接口,抽象类后面跟的有<E>就说要使用泛型。一般来说就是在集合中使用。 */public class ArrayListDemo { public static void main(String[] args) { // 用ArrayList存储字符串元素,并遍历。用泛型改进代码 ArrayList<String> array = new ArrayList<String>(); array.add("hello"); array.add("world"); array.add("java"); Iterator<String> it = array.iterator(); while (it.hasNext()) { String s = it.next(); System.out.println(s); } System.out.println("-----------------"); for (int x = 0; x < array.size(); x++) { String s = array.get(x); System.out.println(s); } }}
案例二:泛型存储自定义学生对象并遍历
package cn.itcast_02;import java.util.ArrayList;import java.util.Iterator;/* * 需求:存储自定义对象并遍历。 * * A:创建学生类 * B:创建集合对象 * C:创建元素对象 * D:把元素添加到集合 * E:遍历集合 */public class ArrayListDemo2 { public static void main(String[] args) { // 创建集合对象 // JDK7的新特性:泛型推断。 // ArrayList<Student> array = new ArrayList<>(); // 但是我不建议这样使用。 ArrayList<Student> array = new ArrayList<Student>(); // 创建元素对象 Student s1 = new Student("曹操", 40); // 后知后觉 Student s2 = new Student("蒋干", 30); // 不知不觉 Student s3 = new Student("诸葛亮", 26);// 先知先觉 // 添加元素 array.add(s1); array.add(s2); array.add(s3); // 遍历 Iterator<Student> it = array.iterator(); while (it.hasNext()) { Student s = it.next(); System.out.println(s.getName() + "---" + s.getAge()); } System.out.println("------------------"); for (int x = 0; x < array.size(); x++) { Student s = array.get(x); System.out.println(s.getName() + "---" + s.getAge()); } }}
package cn.itcast_02;/** * 这是学生描述类 * * @author 风清扬 * @version V1.0 */public class Student { // 姓名 private String name; // 年龄 private int age; public Student() { super(); } public Student(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; }}
泛型类:把泛型定义在类上
package cn.itcast_04;/* * 泛型类:把泛型定义在类上 */public class ObjectTool<T> { private T obj; public T getObj() { return obj; } public void setObj(T obj) { this.obj = obj; }}
package cn.itcast_04;/* * 泛型类的测试 */public class ObjectToolDemo { public static void main(String[] args) { // ObjectTool ot = new ObjectTool(); // // ot.setObj(new String("风清扬")); // String s = (String) ot.getObj(); // System.out.println("姓名是:" + s); // // ot.setObj(new Integer(30)); // Integer i = (Integer) ot.getObj(); // System.out.println("年龄是:" + i); // ot.setObj(new String("林青霞")); // // ClassCastException // Integer ii = (Integer) ot.getObj(); // System.out.println("姓名是:" + ii); System.out.println("-------------"); ObjectTool<String> ot = new ObjectTool<String>(); // ot.setObj(new Integer(27)); //这个时候编译期间就过不去 ot.setObj(new String("林青霞")); String s = ot.getObj(); System.out.println("姓名是:" + s); ObjectTool<Integer> ot2 = new ObjectTool<Integer>(); // ot2.setObj(new String("风清扬"));//这个时候编译期间就过不去 ot2.setObj(new Integer(27)); Integer i = ot2.getObj(); System.out.println("年龄是:" + i); }}
泛型方法:把泛型定义在方法上
package cn.itcast_05;//public class ObjectTool<T> {// // public void show(String s) {// // System.out.println(s);// // }// //// // public void show(Integer i) {// // System.out.println(i);// // }// //// // public void show(Boolean b) {// // System.out.println(b);// // }//// public void show(T t) {// System.out.println(t);// }// }/* * 泛型方法:把泛型定义在方法上 */public class ObjectTool { public <T> void show(T t) { System.out.println(t); }}
package cn.itcast_05;public class ObjectToolDemo { public static void main(String[] args) { // ObjectTool ot = new ObjectTool(); // ot.show("hello"); // ot.show(100); // ot.show(true); // ObjectTool<String> ot = new ObjectTool<String>(); // ot.show("hello"); // // ObjectTool<Integer> ot2 = new ObjectTool<Integer>(); // ot2.show(100); // // ObjectTool<Boolean> ot3 = new ObjectTool<Boolean>(); // ot3.show(true); // 如果还听得懂,那就说明泛型类是没有问题的 // 但是呢,谁说了我的方法一定要和类的类型的一致呢? // 我要是类上没有泛型的话,方法还能不能接收任意类型的参数了呢? // 定义泛型方法后 ObjectTool ot = new ObjectTool(); ot.show("hello"); ot.show(100); ot.show(true); }}
泛型接口:把泛型定义在接口上
package cn.itcast_06;/* * 泛型接口:把泛型定义在接口上 */public interface Inter<T> { public abstract void show(T t);}
package cn.itcast_06;//实现类在实现接口的时候//第一种情况:已经知道该是什么类型的了//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); }}
package cn.itcast_06;public class InterDemo { public static void main(String[] args) { // 第一种情况的测试 // Inter<String> i = new InterImpl(); // i.show("hello"); // // 第二种情况的测试 Inter<String> i = new InterImpl<String>(); i.show("hello"); Inter<Integer> ii = new InterImpl<Integer>(); ii.show(100); }}
泛型高级(通配符)
package cn.itcast_07;import java.util.ArrayList;import java.util.Collection;/* * 泛型高级(通配符) * ?:任意类型,如果没有明确,那么就是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及其子类 // 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极其父类 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>(); }}class Animal {}class Dog extends Animal {}class Cat extends Animal {}