一,认识泛型
泛型,即“参数化类型”。一提到参数,最熟悉的就 在定义方法时有形参列表,普通方法的形参列表中,每个形参的数据类型是确定的,而变量是一个参数。在调用普通方法时需要传入对应形参数据类型的变量(实参),若传入的实参与形参定义的数据类型不匹配,则会报错。
泛型的本质是为了将类型参数化, 也就是说在泛型使用过程中,数据类型被设置为一个参数,在使用时再从外部传入一个数据类型;而一旦传入了具体的数据类型后,传入变量(实参)的数据类型如果不匹配,编译器就会直接报错。这种参数化类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
那如何可以避免上述异常的出现?即我们希望当我们向集合中添加了不符合类型要求的对象时,编译器能直接给我们报错,而不是在程序运行后才产生异常。这个时候便可以使用
泛型
了。
在下面这段代码中我们在最开始时去在list中加入1111,new Cat()都可以不报错在入参时使得
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("java1");
list.add("java2");
list.add("java3");
list.add(1111);
// list.add(new Cat());
for (int i = 0; i < list.size(); i++) {
String e1 = (String) list.get(i);
System.out.println(e1);
}
System.out.println("------------------------------");
ArrayList<String> list1= new ArrayList<>();//从jdk1.7开始后面的数据类型可以不声明
list1.add("java1");
list1.add("java2");
list1.add("java3");
for (int i = 0; i < list1.size(); i++) {
String e= list1.get(i);
System.out.println(e);
}
}
}
class Cat{}
. 泛型概述小结
- 与使用 Object 对象代替一切引用数据类型对象这样简单粗暴方式相比,泛型使得数据类型的类别可以像参数一样由外部传递进来。它提供了一种扩展能力,更符合面向对象开发的软件编程宗旨。
- 当具体的数据类型确定后,泛型又提供了一种类型安全检测机制,只有数据类型相匹配的变量才能正常的赋值,否则编译器就不通过。所以说,泛型一定程度上提高了软件的安全性,防止出现低级的失误。
- 泛型提高了程序代码的可读性。在定义泛型阶段(类、接口、方法)或者对象实例化阶段,由于 < 类型参数 > 需要在代码中显式地编写,所以程序员能够快速猜测出代码所要操作的数据类型,提高了代码可读性。
二,泛型类
(1)类型参数用于类的定义中,则该类被称为泛型类。通过泛型可以完成对一组类的操作对外开放相同的接口。最典型的就是各种容器类,如:List、Set、Map等。
public class Test {
public static void main(String[] args) {
MyArraylist<String> list =new MyArraylist<>();
list.add("java1");
list.add("java2");
String a= list.get(1);
System.out.println(a);
System.out.println("-----------------------");
Myclass2<Cat ,String> c2 =new Myclass2<>();
// c2.put();
System.out.println("------------------------");
Myclass3<Animal> a1 =new Myclass3<>();//Myclass3限制类型为动物
Myclass3<Cat> a2 =new Myclass3<>();
Myclass3<Dog> a3 = new Myclass3<>();
}
}
import java.util.ArrayList;
//泛型类
public class MyArraylist<E> {
private Object[] arr =new Object[10];
private int size;
public boolean add(E e){
arr[size++] =e;
return true;
}
public E get(int index){
return (E) arr[index];
}
}
public class Myclass2<E,T> {
public void put(E e,T t){}
}
public class Animal {}
public class Cat extends Animal {}
public class Dog extends Animal{}
public class Myclass3<E extends Animal>{
}
三, 泛型接口
场景:系统需要处理学生与老师的数据,需要提供两个功能:保存数据对象,根据名称查找数据。
import java.util.ArrayList;
//掌握泛型接口的定义与使用
//场景:系统需要处理学生与老师的数据,需要提供两个功能:保存数据对象,根据名称查找数据。
public class Test {
public static void main(String[] args) {
StudentData studentData = new StudentData();
TeacherData teacherData = new TeacherData();
// 添加学生
Student student1 = new Student("刘翀羽");
studentData.add(student1);
Student student2 = new Student("李闯豪");
studentData.add(student2);
// 添加教师
Teacher teacher1 = new Teacher("李老师");
teacherData.add(teacher1);
Teacher teacher2 = new Teacher("张老师");
teacherData.add(teacher2);
// 根据名称获取学生
ArrayList<Student> studentsByName = studentData.getByName("刘翀羽");
for (Student student : studentsByName) {
System.out.println("Name: " + student.getName());
}
// 根据名称获取教师
ArrayList<Teacher> teachersByName = teacherData.getByName("李老师");
for (Teacher teacher : teachersByName) {
System.out.println("Name: " + teacher.getName() );
}
}
}
import com.itheima_genericity.class2.Animal;
import java.util.ArrayList;
//既能处理老师,也能处理学生的。
// 注意在此中泛型接口也能通过继承是的只能输入的类型为cat与dog
//public interface Data<T extends Animal>
public interface Data<T> {
void add(T t);
ArrayList<T> getByName(String name);
}
import com.itheima_genericity.class2.Animal;
import com.itheima_genericity.class2.Cat;
import java.util.ArrayList;
public class StudentData implements Data<Student> {
private ArrayList<Student> students =new ArrayList<>();
@Override
public void add(Student student) {
students.add(student);
}
@Override
public ArrayList<Student> getByName(String name) {
ArrayList<Student> result =new ArrayList<>();
for(Student student:students)
{
if(student.getName().equals(name))
{
result.add(student);
}
}
return result;
}
}
import java.util.ArrayList;
public class TeacherData implements Data<Teacher> {
ArrayList<Teacher> teachers =new ArrayList<>();
@Override
public void add(Teacher teacher) {
teachers.add(teacher);
}
@Override
public ArrayList<Teacher> getByName(String name) {
ArrayList<Teacher> result =new ArrayList<>();
for(Teacher teacher:teachers)
{
if(teacher.getName().equals(name))
{
result.add(teacher);
}
}
return result;
}
}
public class Student {
private String name;
public Student() {
}
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Teacher {
private String name;
public Teacher() {
}
public Teacher(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
四,泛型方法,泛型通配符,上下限
1. 泛型方法的定义
当在一个方法签名中的返回值前面声明了一个 < T > 时,该方法就被声明为一个泛型方法
。< T >表明该方法声明了一个类型参数 T,并且这个类型参数 T 只能在该方法中使用。当然,泛型方法中也可以使用泛型类中定义的泛型参数
。
public <类型参数> 返回类型 方法名(类型参数 变量名) {
...
}
(1)只有在方法签名中声明了< T >的方法才是泛型方法,仅使用了泛型类定义的类型参数的方法并不是泛型方法。
public class Test<U> {
// 该方法只是使用了泛型类定义的类型参数,不是泛型方法
public void testMethod(U u){
System.out.println(u);
}
// <T> 真正声明了下面的方法是一个泛型方法
public <T> T testMethod1(T t){
return t;
}
}
(2)泛型方法中可以同时声明多个类型参数。
public class TestMethod<U> {
public <T, S> T testMethod(T t, S s) {
return null;
}
}
(3)泛型方法中也可以使用泛型类中定义的泛型参数。
public class TestMethod<U> {
public <T> U testMethod(T t, U u) {
return u;
}
}
4)特别注意的是:泛型类中定义的类型参数和泛型方法中定义的类型参数是相互独立的,它们一点关系都没有。
public class Test<T> {
public void testMethod(T t) {
System.out.println(t);
}
public <T> T testMethod1(T t) {
return t;
}
}
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
String rs = test("Java");
System.out.println(rs);
//将狗对象传入
Dog d = test(new Dog());
System.out.println(d);
System.out.println("-----------------------");
//所有的车都参加比赛
ArrayList<Car> cars =new ArrayList<>();
cars.add( new BEMZ());
cars.add(new BMW());
go(cars);
ArrayList<BEMZ> bemzs =new ArrayList<>();
bemzs.add(new BEMZ());
bemzs.add(new BEMZ());
go(bemzs);
ArrayList<BMW> bmws = new ArrayList<>();
bmws.add(new BMW());
bmws.add(new BMW());
go(bmws);
//因为为狗类没有继承car类
// ArrayList<Dog> dogs = new ArrayList<>();
// dogs.add(new Dog());
// dogs.add(new Dog());
// go(dogs);
}
// ?通配符,在使用泛型的时候可以代表一切类型
// ? extends Cars(上限) ? super Car (下限)
public static void go(ArrayList<? extends Car> cars)
{
}
//限制T能接的子类必须是car
// public static<T extends Car> void go(ArrayList<T> cars)
// {
//
// }
//泛型方法
public static <T> T test(T t){
return t;
}
}
public class Car {
}
public class BMW extends Car{
}
public class BEMZ extends Car {
}
public class Dog {
}
xjad下载吗
泛型的注意事项
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
//1.泛型擦除:泛型的工作是在编译阶段的,一旦被编译成class文件,class文件中就不存在泛型
ArrayList<String> list =new ArrayList<>();
list.add("java1");
list.add("java2");
list.add("java3");
String rs =list.get(2);
System.out.println(rs);
//2泛型不支持基本数据类型,只支持对象类型(引用数据类型)
// ArrayList<int> list1 =new ArrayList<int>();报错
ArrayList<Integer> list1 =new ArrayList<>();
list1.add(1233);
ArrayList<Double> list2 =new ArrayList<>();
list2.add(12.12333);
}
}