泛型
泛型的定义及优点
import java.util.ArrayList;
import java.util.Iterator;
/*
ClassCastException:类型转换异常
我们按照正常的写法,在集合中添加一些不是同类型的数据,在遍历的时候向下转型
报错了。
为什么呢?
因为我们在存储数据的时候,存储了一些String和Integer类型的数据
但是呢,我们遍历的时候,默认集合中只存放String类型的数据,但是呢,又没有在
存储数据的时候告诉我只能存String类型的数据,突然觉得这样的设计很不好
如果能在存储的时候告诉我能存储哪些数据类型就好了。
就像数组这样:
String[] arr = new String[3];
arr[0] = "hello";
//arr[1] = 20;--不能存储
java中集合就模仿着数组,也有了这样的做法,在创建集合的时候,就明确了
元素的数据类型,创建后,再往集合中加入的元素的时候,只能是定义好的数据类型相关的
数据了,然后再向下转型就没有问题了。
这样的技术,java中叫做:泛型
泛型:
把明确数据类型的工作,提前到了编译时期,在创建集合的时候明确数据类型。
这样的做法有点像把数据类型当作参数一样进行传递。所以泛型还有一个名字
叫做:参数化类型。
定义格式:
<引用数据类型>
注意:尖括号中的数据类型只能是引用数据类型
泛型的好处:
1、将我们之前运行时候出现的问题,提前到了编译时期
2、不需要强制类型转换了
3、优化了代码,消除不必要的黄色警告线
通过观察API发现,泛型可以出现了类,接口,方法上,看到一些类似与<E>,一般来说泛型
出现在大多使用集合中。
*/
public class GenericDemo1 {
public static void main(String[] args) {
//创建List集合对象
//报错之后,在创建集合的时候加入泛型,明确集合的数据类型
//赋值号右边的尖括号里可以不写,因为JDK1.7之后会自动进行类型推断
ArrayList<String> list = new ArrayList<String>();
list.add("hello");
//添加泛型之后就不能存放Integer类型了
//list.add(10); //向上转型 10 --> int --> Integer
list.add("world");
list.add("java");
list.add("bigdata");
//获取迭代器对象--也要加泛型
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
//加入泛型之后就不需要进行强转了,因为类型已经明确下来了
String next = iterator.next();
System.out.println(next + "--" + next.length());
//加入泛型之前:
// Object next = iterator.next();
//ClassCastException:类型转换异常
// String s = (String)next;
// System.out.println(s);
}
}
}
泛型应用
/*
泛型类: 把泛型定义在类上
格式:public class 类名<泛型类型1,…>
注意:泛型类型必须是引用类型
这里的<>里面的内容仅仅表示的是一种参数数据类型,参数类型是一种变量,
既然是一种变量,就符合变量的命名规则,可以是任意符合标识符起名规则的名字。
*/
public class GenericTool1<T> {
private T obj;
public T getObj() {
return obj;
}
public void setObj(T obj) {
this.obj = obj;
}
}
import com.shujia.wyh.day22.Student;
/*
泛型类的测试
*/
public class GenericTest1 {
public static void main(String[] args) {
//不加泛型不会报错,默认是Object类型
// GenericTool1 gt1 = new GenericTool1();
//默认是Object类型的时候,我传入什么类型的值都可以
// gt1.setObj("hello");
// gt1.setObj(20);
// gt1.setObj(12.34);
// gt1.setObj(new Student());
//加了泛型之后:
GenericTool1<String> gt2 = new GenericTool1<>();
gt2.setObj("hello");
//加了泛型并明确了类型为String类型的时候
//传入String类型之外的类型就会报错
// gt2.setObj(20);
//明确了String类型之后,返回值就是String类型
String obj = gt2.getObj();
}
}
/*
泛型方法
把泛型定义在方法上
格式:public <泛型类型> 返回类型 方法名(泛型类型 .)
*/
public class GenericTool2 <T>{//-第一种方式:在类中指定泛型
//没有加入泛型的时候
// public void show(String s){
// System.out.println(s);
// }
//
// public void show(int i){
// System.out.println(i);
// }
//
// public void show(double d){
// System.out.println(d);
// }
//第一种方式:在类中指定泛型,在参数列表里面使用泛型
// public void show(T t){
// System.out.println(t);
// }
//第二种方式:不在类中指定泛型
//而是在方法中指定泛型
public <T> void show(T t){
System.out.println(t);
}
}
import com.shujia.wyh.day22.Student;
/*
泛型方法的使用
*/
public class GenericTest2 {
public static void main(String[] args) {
//没有加入泛型的时候每次想要传入一个新的数据类型
//都要重载一遍show()方法
// GenericTool2 gt1 = new GenericTool2();
// gt1.show(10);
// gt1.show("hello");
// gt1.show(12.34);
//----------用泛型方法第一种方式改进之后--------
// gt1.show(new Student());
//创建泛型类对象--此时show()方法中只能传入在初始化泛型类时被声明的数据类型
// GenericTool2<String> gt2 = new GenericTool2<>();
// gt2.show("hello");
//不能传入int类型
// //gt2.show(20);
//那想要传入Integer类型怎么办呢?只能再创建一个泛型类的对象
// GenericTool2<Integer> gt3 = new GenericTool2<>();
// gt3.show(20);
//
//到目前为止,如果你能看懂,说明泛型类你是可以掌握的
//但是有个问题,谁规定了方法的参数类型一定要和类的类型一致呢?
//如果类上面没有泛型的话,方法还能不能随便传参呢?--可以
//--------用泛型方法第二种方式改进之后--------
//创建对象
GenericTool2 gt = new GenericTool2();
//可以放入任何一种数据类型
gt.show("hello");
gt.show(20);
gt.show(true);
}
}
/*
泛型接口
*/
public interface GenericTool3<T> {
public abstract void show(T t);
}
//将来开发中实现接口的类名字后面加上Impl,易于区分
//实现泛型接口的类的类名后面也要加上<T>
public class GenericTool3Impl<T> implements GenericTool3<T>{
@Override
public void show(T t) {
System.out.println(t);
}
}
/*
泛型接口的测试
*/
public class GenericTest3 {
public static void main(String[] args) {
//创建实现接口的类的对象
GenericTool3Impl<String> sgt1 = new GenericTool3Impl<>();
sgt1.show("hello");
}
}
泛型高级(通配符)
public class Animal {
}
public class Dog extends Animal {
}
public class Cat extends Animal {
}
import java.util.ArrayList;
/*
泛型通配符<?>
任意类型,如果没有明确,那么就是Object以及任意的Java类了
? extends E
向下限定,E及其子类
? super E
向上限定,E及其父类
*/
public class GenericDemo2 {
public static void main(String[] args) {
//如果泛型里面的类型只用一个,并且明确数据类型的时候,前后必须要写一致
ArrayList<Animal> list1 = new ArrayList<Animal>();
ArrayList<Dog> list2 = new ArrayList<Dog>();
ArrayList<Object> list3 = new ArrayList<Object>();
//泛型通配符<?>
//任意类型,如果没有明确,那么就是Object以及任意的Java类了
ArrayList<?> objects1 = new ArrayList<Animal>();
ArrayList<?> objects2 = new ArrayList<Dog>();
ArrayList<?> objects3 = new ArrayList<Object>();
// ? extends E 向下限定,E及其子类
ArrayList<? extends Animal> list4 = new ArrayList<Animal>();
ArrayList<? extends Animal> list5 = new ArrayList<Dog>();
ArrayList<? extends Animal> list6 = new ArrayList<Cat>();
//向下限定,只能传入E及其子类,不能是E的父类
//ArrayList<? extends Animal> list7 = new ArrayList<Object>();
// ? super E 向上限定,E及其父类
ArrayList<? super Animal> list7 = new ArrayList<Animal>();
ArrayList<? super Animal> list8 = new ArrayList<Object>();
//向上限定,只能传入E及其父类,不能是E的子类
//ArrayList<? super Animal> list9 = new ArrayList<Dog>();
}
}