1.泛型的概述
2.使用泛型的好坏
package com.itheima.demo04generic;
import java.util.ArrayList;
import java.util.Iterator;
/*
创建集合对象使用泛型的好处
反射:java中的泛型是一个伪泛型,在.java文件中有,在编译生成的.class文件没有泛型概念的
*/
public class Demo01Generic {
public static void main(String[] args) {
show02();
}
/*
创建ArrayList集合对象,使用泛型
弊端:
集合的泛型使用什么类型,就只能存储什么类型的数据
好处:
集合的泛型是什么类型,取出的数据就是什么类型
不需要向下转型就可以使用元素特有的方法
*/
private static void show02() {
ArrayList<String> list = new ArrayList();
list.add("aaa");
//list.add(1);//'add(java.lang.String)' in 'java.util.ArrayList' cannot be applied to '(int)'
//list.add(8.8);
//list.add(true);
Iterator<String> it = list.iterator();
while (it.hasNext()){
String s = it.next();
System.out.println(s+"==>"+s.length());
}
}
/*
创建ArrayList集合对象,不使用泛型
好处:
集合的数据类型默认就是Object类型,可以存储任意数据类型的元素
弊端:
所有元素默认都会提示为Object类型,想要使用元素特有的功能,使用不了(多态)
向下转型,在转型之前增加判断,防止类型转换异常==>麻烦
*/
private static void show01() {
ArrayList list = new ArrayList();
list.add("aaa");
list.add(1);
list.add(8.8);
list.add(true);
//使用迭代器遍历集合
Iterator it = list.iterator();
while (it.hasNext()){
Object obj = it.next();
System.out.println(obj);
//需求:使用String类特有的方法length(),获取字符串元素的长度
//多态: Object obj = "aaa";
//System.out.println(obj.length());
if(obj instanceof String){
String s = (String)obj;
System.out.println(s.length());
}
}
}
}
3.定义和使用含有泛型的类
package com.itheima.demo05GenericClass;
/*
定义和使用含有泛型的类
泛型:是一种未知的数据类型,当我们不知道使用什么类型的时候,就可以使用泛型
格式:模拟ArrayList集合
public class 类名<泛型>{
类中所有使用数据类型的地方,都可以使用类上的泛型
}
什么时候确定泛型的类型:创建对象时候,使用什么类型,类中的泛型就是什么类型
*/
public class Person<C> {
private C name;
public C getName() {
return name;
}
public void setName(C name) {
this.name = name;
}
}
package com.itheima.demo05GenericClass;
public class Demo01 {
public static void main(String[] args) {
Person p = new Person();
//默认就是Object
p.setName("aa");
p.setName(true);
p.setName(1);
Person<String> p1 = new Person<>();
p1.setName("jack");
String n = p1.getName();
System.out.println(n);
Person<Integer> p2 = new Person<>();
p2.setName(10);
Integer a = p2.getName();
System.out.println(a);
}
}
4.定义和使用含有泛型的方法
package com.itheima.demo06GenericMethod;
/*
定义和使用含有泛型的方法(重点)
定义格式:把泛型定义在方法的修饰符和返回值类型之间
修饰符 <泛型> 返回值类型 方法名(参数列表){
方法体;
}
方法的参数的数据类型和返回值数据类型可以使用定义的泛型
什么时候确定泛型的数据类型
调用方法的时候,传递什么类型的参数,方法上的泛型就是什么类型
传递的参数是基本数据类型==>泛型使用包装类
*/
public class Person {
//定义一个含有泛型的方法
public <M> void show01(M m){
System.out.println(m);
}
//定义一个含有泛型的静态方法
public static <S> void show02(S s){
System.out.println(s);
}
//定义一个参数和返回值类型,都使用泛型的方法
public static <V> V show03(V name){
return name;
}
}
package com.itheima.demo06GenericMethod;
public class Demo01 {
public static void main(String[] args) {
//创建Person对象
Person p = new Person();
p.show01(10);
p.show01(true);
p.show01("aaa");
p.show01(1.1);
p.show01('#');
p.show01(new Student("张三",18));
//静态方法,通过类名可以直接使用
Person.show02(10);
Person.show02(true);
Person.show02("aaa");
Person.show02(1.1);
Person.show02('#');
Person.show02(new Student("张三",18));
Integer in = Person.show03(10);
System.out.println(in);
String name = Person.show03("张安");
System.out.println(name);
}
}
5.定义和使用含有泛型的接口
package com.itheima.demo07GenericInterface;
/*
定义和使用含有泛型的接口
定义格式:
public interface 接口名<泛型>{
接口中使用数据类型的地方,都可以使用泛型
}
*/
public interface MyInter<I> {
//定义一个抽象方法
public abstract void show(I i);
}
package com.itheima.demo07GenericInterface;
/*
含有泛型的接口:第一种使用方式
在实现类实现接口的同时,指定接口泛型的数据类型
指定什么类型,那么泛型就是什么类型
格式:
public class MyInterImpl1 implements MyInter<String>{
@Override
public void show(String s) {}
}
public class MyInterImpl1 implements MyInter<Double>{
@Override
public void show(Double s) {}
}
*/
public class MyInterImpl1 implements MyInter<Double>{
@Override
public void show(Double s) {
System.out.println(s);
}
}
package com.itheima.demo07GenericInterface;
/*
含有泛型的接口:第二种使用方式
实现类在实现含有泛型接口的时候,接口使用什么泛型,实现类也使用什么泛型
就相当于定义了一个含有泛型的类,创建实现类对象的时候确定泛型的数据类型
*/
public class MyInterImpl2<I> implements MyInter<I>{
@Override
public void show(I i) {
System.out.println(i);
}
}
package com.itheima.demo07GenericInterface;
public class Demo01 {
public static void main(String[] args) {
//创建接口的实现类对象
MyInterImpl1 my01 = new MyInterImpl1();
my01.show(1.1);
MyInterImpl2<Character> my02 = new MyInterImpl2<>();
my02.show('a');
MyInterImpl2<Boolean> my03 = new MyInterImpl2<>();
my03.show(true);
}
}
6.泛型的通配符:?
可以作为方法参数的数据类型使用:可以接收任意数据类型的数据
package com.itheima.demo08Generic;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/*
泛型的通配符: ?
可以作为方法参数的数据类型使用:可以接收任意数据类型的数据
*/
public class Demo01 {
public static void main(String[] args) {
ArrayList<Integer> list01 = new ArrayList<>();
list01.add(1);
list01.add(2);
ArrayList<String> list02 = new ArrayList<>();
list02.add("jack");
list02.add("rose");
print(list01);
print(list02);
}
/*
需求:定义一个方法,方法的参数可以接收任意数据类型的集合
*/
public static void print(Collection<?> coll){
//使用迭代器遍历集合:迭代器的泛型跟着集合走,集合是什么泛型,迭代器就是什么泛型
Iterator<?> it = coll.iterator();
while (it.hasNext()){
//it.next();取出的元素是什么类型? Object类型
Object obj = it.next();
System.out.println(obj);
}
}
}
package com.itheima.demo08Generic;
import java.util.ArrayList;
import java.util.Collection;
/*
?:作为方法的参数使用,代表可以接收任意的数据类型
? extends E: 泛型的上限限定 ==> 代表?只能接收E或者E的子类
? super E: 泛型的下限限定 ==> 代表?只能接收E或者E的父类
*/
public class Demo02Generic {
public static void main(String[] args) {
Collection<Integer> list1 = new ArrayList<Integer>();
Collection<String> list2 = new ArrayList<String>();
Collection<Number> list3 = new ArrayList<Number>();
Collection<Object> list4 = new ArrayList<Object>();
/*
Integer|Double... extends Number extends Object
String extends Object
*/
getElement1(list1);
//getElement1(list2);//报错 String和Number没有关系
getElement1(list3);
//getElement1(list4);//报错 Object类型是Number的父类,需要Number的子类
//getElement2(list1);//报错 Integer是Number的子类,需要Number的父类
//getElement2(list2);//报错 String和Number没有关系
getElement2(list3);
getElement2(list4);
}
// 泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类
public static void getElement1(Collection<? extends Number> coll){}
// 泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类
public static void getElement2(Collection<? super Number> coll){}
}