第十章 泛型
10、java泛型 | |
10.1 为什么要有泛型 | 1课时 |
10.2 使用泛型 | 1课时 |
10.3 泛型的几个重要应用(在集合中使用泛型,自定义泛型类,自定义泛型接口,自定义泛型方法) | 1课时 |
10.4 泛型在继承上的体现 | 1课时 |
10.5 通配符的使用 | 1课时 |
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.junit.Test;
/**
* 泛型的使用
* 1.jdk 5.0 新增的特性
*
* 2.主要内容:
* 2.1 在集合中使用泛型 (掌握)
* 2.2 如何自定义泛型类、泛型接口;泛型方法 (理解)
* 2.3 泛型在继承上的体现 (掌握)
* 2.4 通配符的使用 (掌握)
*
*/
public class GenericTest {
//*************关于自定义泛型类、泛型接口、泛型方法的使用********************
/*
* 自定义泛型类的使用:
* 1.在实例化泛型类时,可以指明泛型的参数类型
* 2.提供泛型类的子类时,可以指明泛型的参数类型。比如:SubOrder1类
*/
@Test
public void test4(){
Order<String> order = new Order<>();
order.setT("足球");
String interest = order.getT();
System.out.println(interest);
//************
//SubOrder是泛型类
SubOrder<Integer> order1 = new SubOrder();
order1.setT(123);
//************
//SubOrder1:不是泛型类
// SubOrder1<Integer> order2 = new SubOrder1<Integer>();//错误的
SubOrder1 order2 = new SubOrder1();
String s = order2.getT();
//测试泛型方法
Integer[] arr = new Integer[]{1,2,3,4};
List<Integer> list = new ArrayList<>();
List<Integer> myList = Order.fromArrayToList(arr, list);
System.out.println(myList);
}
//*************关于集合中使用泛型的情况********************
//在集合中使用泛型
//1.在java集合中,声明的接口或类已经声明泛型
//2.在实例化接口时,可以指明泛型的类型。
//3.不能使用基本数据类型,需要使用对应的包装类替换。
//4.一旦创建对象时,使用了泛型,则通过对象调用方法、属性时,如果方法或属性中使用了类的泛型,则此时泛型类型就是
//对象实例化时的类型。
//5.如果在实例化不指明泛型参数的类型,则默认为Object类型。
//体现二:
@Test
public void test3(){
Map<String,Integer> map = new HashMap<String,Integer>();
map.put("Tom1",34);
map.put("Tom2",44);
map.put("Tom3",33);
map.put("Tom4",32);
// map.put(33, "Tom");
Set<Entry<String,Integer>> entrySet = map.entrySet();
Iterator<Entry<String,Integer>> iterator = entrySet.iterator();
while(iterator.hasNext()){
Entry<String,Integer> entry = iterator.next();
System.out.println(entry.getKey() + "--->" + entry.getValue());
}
}
//体现一:
@Test
public void test2(){
ArrayList<Integer> list = new ArrayList<>();//类型推断
// ArrayList<int> list1 = new ArrayList<>();
list.add(78);
list.add(88);
list.add(77);
list.add(66);
//不能向List中添加非Integer类型的数据
// list.add("AA");
//遍历方式一:
// for(Integer i : list){
// //不需要强转
// System.out.println(i);
// }
//遍历方式二:
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
//在集合中使用泛型前
@Test
public void test1(){
List list = new ArrayList();
list.add(78);
list.add(77);
list.add(88);
list.add(66);
//1.问题一:类型不安全。
list.add("Tom");
for(Object o : list){
//2.问题二:要想使用成绩,必须要强转:繁琐。同时,可能出现ClassCastException的异常。
int score = (Integer)o;
System.out.println(score);
}
}
}
import java.util.List;
/**
* 自定义泛型类。
* 仿照着List去创建。
* 1.在类的声明后面,指明泛型参数。参数通常使用:T E K V
* 2.在类的属性、方法、构造器中,可以使用类的泛型参数。
*/
public class Order<T> {
String orderName;
int orderId;
T orderT;
public Order(){}
public Order(T orderT){
this.orderT = orderT;
}
//如下的三个方法不是泛型方法!
public T getT(){
return orderT;
}
public void setT(T t){
this.orderT = t;
}
public String toString(){
return "name = " + orderName + "id = " + orderId + ",t = " + orderT;
}
//注意点1:使用了类的泛型参数的方法,不能声明为static
// public static T info(){
// return orderT;
// }
//注意点2:不能在try-catch中使用泛型参数表示异常类型
public void show(){
// try{
// System.out.println(10/0);
// }catch(T t){
//
// }
}
//定义泛型方法
//泛型方法所属的类,可以不是泛型类。
public static <E> List<E> fromArrayToList(E[] arr,List<E> list){
for(E e : arr){
list.add(e);
}
return list;
}
}
public class SubOrder
public SubOrder(){
// arr = new T[10];//错误的
arr = (T[]) new Object[10];
}
}
import java.util.List;
public class SubOrder1 extends Order<String>{
public static <E> List<E> fromArrayToList(E[] arr,List<E> list){
return null;
}
}
- 解决元素存储的安全性问题
- 解决获取数据元素时,需要类型强转的问题
泛型,JDK1.5新加入的,解决数据类型的安全性问题,其主要原理是在类声明时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这样在类声明或实例化时只要指定好需要的具体的类型即可。
Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生ClassCastException异常。同时,代码更加简洁、健壮。
Comparable c = new Date();
System.out.println(c.compareTo("red"));
JDK 1.5 之前
Comparable<Date> c = new Date();
System.out.println(c.compareTo("red"));
JDK 1.5
体会:使用泛型的主要优点是能够在编译时而不是在运行时检测错误。
10-2 使用泛型
1.泛型的声明
interface List
其中,T,K,V不代表值,而是表示类型。这里使
用任意字母都可以。常用T表示,是Type的缩写。
2.泛型的实例化:
一定要在类名后面指定类型参数的值(类型)。如:
List<String> strList = new ArrayList<String>();
Iterator<Customer> iterator = customers.iterator();
T只能是类,不能用基本数据类型填充。但可以使用包装类填充
把一个集合中的内容限制为一个特定的数据类型,这就是generics背后的核心思想
10-3 泛型的几个重要应用
10.3.1 在集合中使用泛型
10.3.2 自定义泛型类
10.3.3 自定义泛型接口
10.3.4 自定义泛型方法
10.3.1 对于泛型类(含集合类)
-
对象实例化时不指定泛型的话,默认为:Object。
-
泛型类可能有多个参数,此时应将多个参数一起放在尖括号内。比如<E1,E2,E3>
-
泛型类的构造器如下:
public GenericClass(){}。而如下是错误的: public GenericClass<E>(){}
4.从泛型类派生子类,泛型类型需具体化。
5.如果泛型类是一个接口或抽象类,则不可创建泛型类的对象。
6.静态方法中不能使用类的泛型
7.异常类不能是泛型的
8.加入集合中的对象类型必须与指定的泛型类型一致。
9.泛型不同的引用不能相互赋值。
>尽管在编译时ArrayList<String>和ArrayList<Integer>是两种类型,但
是,在运行时只有一个ArrayList被加载到JVM中。
10 . 泛型的指定中不能使用基本数据类型,可以使用包装类替换。
11 . 不能使用new E[]。但是可以:
E[] elements = (E[])new Object[capacity];
10.3.2 自定义泛型类
class Person<T>{
//使用T类型定义变量
private T info;
//使用T类型定义一般方法
public T getInfo(){
return info;
}
public void setInfo(T info){
this.info = info;
}
//使用T类型定义构造器
public Person(){}
public Person(T info){
this.info = info;
}
//static的方法中不能声明泛型
//public static void show(T t){
//}
//不能在try-catch中使用泛型定义
//try{}
//catch(MyException<T> ex){}
}
10.3.3 对于泛型方法
方法,也可以被泛型化,不管此时定义在其中的类是不是泛型类。在泛型方法中可以定义泛型参数,此时,参数的类型就是传入数据的类型。
泛型方法的格式:[访问权限] <泛型> 返回类型 方法名([泛型标识 参数名称]) 抛出的异常
public class DAO {
public <E> E get(int id, E e){
E result = null;
return result;
}}
static <T> void fromArrayToCollection(T[] a, Collection<T> c) {
for (T o : a) {
c.add(o);
} }
public static void main(String[] args) {
Object[] ao = new Object[100];
Collection<Object> co = new ArrayList<Object>();
fromArrayToCollection(ao, co);
String[] sa = new String[20];
Collection<String> cs = new ArrayList<>();
fromArrayToCollection(sa, cs);
Collection<Double> cd = new ArrayList<>();
// 下面代码中T是Double类,但sa是String类型,编译错误。
// fromArrayToCollection(sa, cd);
// 下面代码中T是Object类型,sa是String类型,可以赋值成功。
fromArrayToCollection(sa, co); }
10-4 泛型在继承上的体现
请输出如下来两段代码有何不同
void printCollection(Collection c) {
Iterator i = c.iterator();
for (int k = 0; k < c.size(); k++) {
System.out.println(i.next());
} }
void printCollection(Collection<Object> c) {
for (Object e : c) {
System.out.println(e);
} }
如果B是A的一个子类型(子类或者子接口),而G是具有泛型声明的类或接口,G <B>并不是G<A>的子类型!
比如:String是Object的子类,但是List
您的资助是我最大的动力!
金额随意,欢迎来赏!