本来想不放在集合中说,但是看了一下,集合中用泛型的地方太多,所以就加入进来
为什么需要使用泛型
起因:JDK1.4 以前类型不明确:装入集合的类型都被当作 Object 对待,从而失去自己的实际 类型。从集合中取出时往往需要转型,效率低,容易产生错误。
解决办法:
泛型,在定义集合的时候同时定义集合中对象的类型
好处:
增强程序的可读性和安全性
实际开发中,我们多用泛型指定集合元素的类型,下面的内容可以作为了解
泛型的分类
(1)泛型类
(2)泛型接口
(3)泛型方法
泛型类
/**
* 泛型类 在使用类创建对象的时候对创建的对象类型做约束,如果用英文字母代替,则创建的时候需要指定数据类型
*/
public class TestGeneric {
public static void main(String[] args) {
MyGeneric<String> generic1 = new MyGeneric<>();//1.8后后面的泛型可以省略,这里是String类型
MyGeneric<Integer> generic2 = new MyGeneric<Integer>();//这里是Integer类型
}
}
class MyGeneric<T>{//T只是一个英文字母,代表一种数据类型,具体的数据类型只有创建类的对象的时候才能指定
}
泛型接口
/**
* 泛型接口
* 对实现类的数据类型做约束
* 一般使用英文字母时,在实现类实现接口时定义
* @param <T>
*/
public interface TestGenericInterface<T> { //泛型接口的类型是在实现类的时候定义的
}
/*
如果知道实现类是代表什么类型,可以直接指定
*/
class MyImplement implements TestGenericInterface<String>{
}
/*
如果不知道实现类是什么类型,那么实现类也需要定义字母代替类型的泛型
这个泛型类型由实现类创建对象时决定
*/
class MyImplement2<T> implements TestGenericInterface<T>{
}
class TestGenericInterface1{
public static void main(String[] args) {
MyImplement m1 = new MyImplement();//由于指定了类型,所以不需要再用泛型
MyImplement2<Integer> m2 = new MyImplement2<>();//因为没有指定泛型,所以需要定义泛型
}
}
泛型方法
package com.lin.test;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
public class TestMethodGeneric<T> {//泛型类
public void show(T t){ //创建MethodGeneric对象的时候决定
System.out.println(t);
}
public <Q> void method(Q q){//在调用method这个方法的时候明确
System.out.println(q);
}
public <K> void fun(K...K){//可变参数的泛型方法 K...k在这是被当作数组
for (int i = 0; i < K.length; i++) {
System.out.println(K[i]); //根据索引来获取
}
}
}
test类
package com.lin.test;
public class TestMethGeneric {
public static void main(String[] args) {
TestMethodGeneric<String> mg = new TestMethodGeneric<>();
mg.show("123");//因为创建对象的泛型是String类型,这里就只能是String类型
//在有了泛型方法后,解决了参数个数相同情况下的方法重载
mg.method("hello");
mg.method(123);
mg.method('a');
//可变参数的泛型方法,解决参数的个数不同,类型不同的方法重载
mg.fun("hello");
mg.fun("hello","world","java");
mg.fun(123,456);
}
}
泛型在集合中的使用
泛型的上下限
上限:
泛型的上限 谁继承了这个类谁就能用
下限:
这个类及这个类的父类都能用
person类
重写了hashCode 和 equals方法
实现了Comparable接口 重写了其中方法
package com.lin.generic;
import java.util.Objects;
public class Person implements Comparable<Person> {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public int compareTo(Person o) {
//重写方法,按照英文字母的升序去排序
return this.getName().compareTo(o.getName());
}
}
Student类
继承了Person类
package com.lin.generic;
import java.util.Objects;
public class Student extends Person {
private String stuNO;
public Student() {
}
public Student(String stuNO) {
this.stuNO = stuNO;
}
public Student(String name, int age, String stuNO) {
super(name, age);
this.stuNO = stuNO;
}
public String getStuNO() {
return stuNO;
}
public void setStuNO(String stuNO) {
this.stuNO = stuNO;
}
@Override
public String toString() {
return super.toString()+"Student{" +
"stuNO='" + stuNO + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
Student student = (Student) o;
return Objects.equals(stuNO, student.stuNO);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), stuNO);
}
}
1.泛型的上下限
上限:
泛型的上限 谁继承了这个类谁就能用
下限:
这个类及这个类的父类都能用
package com.lin.generic;
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
//创建集合对象,同时明确了集合中所有存储的对象的类型只能是Person类型
ArrayList<Person> a1 = new ArrayList<>();
//创建Person类型的对象添加到集合中
Person lin = new Person("lin", 18);
Person liang = new Person("liang", 20);
Person chaoChaoGeGe = new Person("ChaoChaoGeGe", 20);
//添加对象到集合中 ,
a1.add(lin);
a1.add(liang);
a1.add(chaoChaoGeGe);
//遍历
print(a1);
//创建一个集合对象,由于存储Student类型的对象
ArrayList<Student> a2 = new ArrayList<>();
//创建学生对象
Student kankan = new Student("康康", 12, "1");
Student maliya = new Student("玛利亚", 13, "2");
Student jian = new Student("简", 13, "3");
//添加到集合中
a2.add(kankan);
a2.add(maliya);
a2.add(jian);
// print(a2); 使用37-41代码报错
// 报错,因为 相当于ArrayList<Person> a1 = new ArrayList<Student>() 泛型限定于Person 所以错误
print(a2);//适用泛型上限方法
//调用show方法
show(a1);
show(a2);
}
/*public static void print(ArrayList<Person> a1) { //这里只能遍历Person 所以没有意义需要修改
for (Person person : a1) {
System.out.println(person);
}
}*/
//泛型的上限: Person及子类就都能用
public static void print(ArrayList<? extends Person> a1){//泛型的上限 谁继承了person谁就能用
for (Person person : a1) {
System.out.println(person);
}
}
//泛型的下限: 确定子类 本类及父类可使用
public static void show(ArrayList<? super Student> a1){
for (Object obj : a1) {
System.out.println(obj);
}
}
}
泛型在集合中的使用,泛型只在编译中生效
package com.lin.generic;
import java.util.*;
/**
* 泛型在集合中的使用
*/
public class Test2 {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("hello");
LinkedList<Integer> linkedList = new LinkedList<>();
linkedList.add(123);//这里做了自动装箱的处理
//存储自定对象的时候要求重写对象的hashCode()和equals()
HashSet<Person> hashSet = new HashSet<>();
hashSet.add(new Person("lin",18));
//Person 对象需要具备内部或者外部比较器 就是实现
TreeSet<Person> treeSet = new TreeSet<>();
HashMap<String, Integer> hashMap = new HashMap<>();
hashMap.put("hello",123);//123做了自动装箱
//HashMap 存储自定义对象
HashMap<Person, String> hashMap1 = new HashMap<>();
Person p1 = new Person("lin",18);
hashMap1.put(p1,p1.getName());
//TreeMap 存储自定义对象
TreeMap<Person, Integer> treeMap = new TreeMap<>();
treeMap.put(p1,p1.getAge());
//泛型只在编译中起作用
}
}