泛型快速入门
问题
泛型前代码
没学泛型前的代码
package com.hansp;
import java.util.ArrayList;
@SuppressWarnings({"all"})
public class genericParadigm {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add(new Dog("sw",10));
arrayList.add(new Dog("s",11));
arrayList.add(new Dog("e",12));
arrayList.add(new Dog("qe",13));
arrayList.add(new Dog("we",14));
System.out.println(arrayList);
}
}
class Dog{
public String name;
public int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
这样写的话
假如我们的程序员不小心添加了一只猫(与想添加的对象类型不同)
如果你有遍历,并且向下转型成Dog想用Dog独特的方法
此时就会发生类型转换异常
而且
你需要进行foreach遍历的时候
for(Object o:arraylist){
//操作
//如果调用Dog类方法
Dog a=(Dog)o;//需要向下转型,每个都向下转型效率会低
}
这里的Object还不能直接换成Dog尽管你存的可能都是Dog
此时我们就可以用泛型解决前面的问题
泛型后代码
经历泛型后的改编版
package com.hansp;
import java.util.ArrayList;
@SuppressWarnings({"all"})
public class genericParadigm {
public static void main(String[] args) {
//当这样带上<Dog>时,这个集合只能存放Dog类型
ArrayList<Dog> arrayList = new ArrayList<Dog>();
arrayList.add(new Dog("sw",10));
arrayList.add(new Dog("s",11));
for (Dog a:arrayList//这里可以直接取Dog效率比之前高
) {
System.out.println(a);
}
}
}
class Dog{
public String name;
public int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
运行效果
试图在arrayList加入处理Dog外的其他对象
细节在后面说
改进处
改进了两点
1.可以直接取Dog
2.不可以存放处理你指定外的其他元素
泛型基本介绍
可以把泛型理解为可以表示数据类型的一种数据类型
4的解释
package com.hansp.generic;
public class generic01 {
public static void main(String[] args) {
Person<Object> objectPerson = new Person<>();
//如果你不写的话,默认为Object
objectPerson.s=new String("c");
Person<String> Person = new Person<String>();
//现在Person里面的s只能是String了
Person.s="小袁";//传入其他类型的会报错
}
}
class Person<T>{
String name;//代表我们的name是String类型
T s;//s则是T类型,这个T类型是你在创建的时候定义的类型
}
就是相当于把你<>里面传入的类型(实参)
代替为那个类里面的T(形参)
如图
图中相当于把 E全换为Integer
我们的是相当于把T全换为String
所以说可以把泛型理解为可以表示数据类型的一种数据类型
泛型的语法(应用实例)
题目
代码
package com.hansp.generic;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
public class generic01 {
public static void main(String[] args) {
HashMap<String, Student> Map = new HashMap<String,Student>();
Student a = new Student("A");
Student b = new Student("B");
Student c = new Student("C");
Map.put(a.name,a);
Map.put(b.name,b);
Map.put(c.name,c);
Collection<Student> values = Map.values();
for (Student d:values
) {
System.out.println(d);
}
Iterator<Student> iterator = values.iterator();
while (iterator.hasNext()) {
Student next = iterator.next();
System.out.println(next);
}
}
}
class Student{
String name;
public Student(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
'}';
}
}
泛型使用细节
1.泛型只能是引用数据类型
2.
class A extends B{}
new ArrayList<B>();
这个集合不仅可以存放B类型的对象还可以A类型(B的子类)的对象
3.接口<> 名字=new 接口继承类()<>;就是多态
然后实际开发中用的较多的是
List<String> a=new ArrayList<>();//没错就是把右边的那个<>里面的东西去掉
自动生成的也是省略的
而且省略和不省略是一样的
new ArrayList<Integer>().var
ArrayList<Integer> a=new ArrayList<>();//上面代码生成的结果
ArrayList<Integer> a=new ArrayList<>();等同于ArrayList<Integer> a=new ArrayList<Integer>();
没有指定具体类型默认为Object
自定义型泛型
自定义泛型类
下面就是自定义泛型类的例子
1.R和M和T都是数据类型
r和m和t都是属性
可以在成员中使用
比如说构造器
还可以在get和set方法里用
这个比较难想
要了解对应大写字母的数据类型
用set方法才能放入对应数据类型
因为类型没有确定,就不知道要开辟多大空间,所以不能初始化
3.
静态方法是和类相关的,不是和对象相关,在类加载时,对象还没有创建
静态方法或者属性使用泛型,JVM不能完成初始化(不知道具体类型,不知道怎么开辟空间)
4和5在前面说过
自定义泛型接口
1.注意接口中的属性都是静态性质的
接口的属性的修饰符只能是public static final。比如int a = 1; 实际上是public static final int a = 1(必须初始化)
左边是泛型接口的定义
右边是继承泛型接口
如果是第一种Class C implements IUsb{
}
等同于Class C implements IUsb<Object,Object>{
}
而且
用快捷生成会自动把原来的大写字母替换成你写的数据类型
继承接口
Iusb<U,R>{
}
实现接口
都是这样
3.
自定义泛型方法
1.
2.
3.注意3
方法使用泛型和泛型方法是不一样的
泛型方法
public <T,R> void x(T t,R r){
}
使用泛型的方法
public void e(M m){
}
这里是使用了类中声明的泛型
泛型方法可以使用自己的泛型也可以使用类中声明的泛型
比如
public <T,R> void x(T t,R r,M m){
}
M是类中的泛型
T和R是泛型方法里的泛型
泛型的继承和通配
1.不对
不能这样写,前后必须对应,或者后面什么也不写
234比较好理解
属于是不仅约束
你传入实现了List类型的类的对象
还要规定你这个对象的泛型的范围
是都可以
还是要必须是哪个类型的子类或者父类