版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40646143/article/details/83279388
什么是泛型呢?
泛型是程序设计语言的一种特性。是将类型参数化来达到代码复用以便来提高软件开发工作效率的一种数据类型。一般用<>泛化类型
在JDK1.4以前,我们是这样使用泛型的,比如说有一个班的学生,现在要保存他们的成绩,他们的成绩可能是int类型,也可能是String类型的...
创建一个student实体
package com.hp.student;
/**
* 自定义student泛型类 -->用JDK1.4以前的形势 不安全 省心
*/
public class Student {
private Object grade;
public Student() {
}
public Student(Object grade) {
this.grade = grade;
}
public Object getGrade() {
return grade;
}
public void setGrade(Object grade) {
this.grade = grade;
}
}
处理student这些数据
package com.hp.student;
/**没有泛型方法之前 存储数据的方法
* 向student添加数据
*/
public class StudentMain {
public static void main (String[] args) {
Student student = new Student(80);
Student student1 = new Student("优秀");
Object grade = student.getGrade();
//首先判断这个Object 是否属于 Integer这个类型
if (grade instanceof Integer){
//然后进行强制类型转换
Integer grade1 = (Integer) grade;
System.out.println(grade1);
}
Object grades = student1.getGrade();
//进行类型检查
if (grades instanceof String){
String grades1=(String)grades;
System.out.println(grades1);
}
}
}
有了泛型我们就简单了许多,这时我们更改上面的studentJAVABEAN类
package com.hp.student;
/**使用泛型来存储student数据
* <T> 泛型一般用大写字母来表示 见名知意
* 一般用 K V 表示 key value
* T 表示type
* E 表示Element
*
* 注意泛型不能使用在静态属性上面
*
*/
public class StudentsElement<T> {
// private static T MAX_VALUE=10; 这个会出现编译错误
private T grade;
public StudentsElement(T grade) {
this.grade = grade;
}
public StudentsElement(){
}
public T getGrade() {
return grade;
}
public void setGrade(T grade) {
this.grade = grade;
}
}
操作student的数据类我们也改一下
package com.hp.student;
/**
* 使用泛型来进行处理数据 简单 省心
*/
public class StudentElementMain {
public static void main (String[] args) {
//安全 进行了类型检查
StudentsElement<String> element = new StudentsElement<>("优秀");
//省心 自动做了类型的转换 同时免去了类型检查
String grade = element.getGrade();
System.out.println(grade);
}
}
这样一对比,我们就能发现他们的区别,其中泛型的定义还在下面用到
小知识点 泛型中擦除 例如
/**
* 泛型的擦除 在使用时|实现|继承 没有指定具体的数据类型 按Object来处理 但是并不等同于Object
*/
public class student01 {
public static void main (String[] args) {
StudentsElement element = new StudentsElement();//类似于 StudentsElement<Object> element = new StudentsElement<Object>();
element.setGrade(10); //int 转化为 Integer 再转化为Object 自动装箱
text(element); //如果new StudentsElement(); 编译不会类型检查
StudentsElement<Object> element1 = new StudentsElement<Object>();
//text(element1); //但是你new StudentsElement<Object>(); 编译器一定会进行类型检查
}
public static void text(StudentsElement<Integer> stu){
}
}
定义接口的时候使用泛型
/**
* 定义泛型接口
* 这个T只能用在公共方法上面,不能用于静态属性上面
*/
public interface Computer<T> {
//public final static T MAX_VALUE=1024; 这个是错误的
T findComputer(T type);
}
自定义泛型方法
package com.hp.student;
import java.io.Closeable;
import java.io.IOException;
import java.util.List;
/**
* 自定义泛型方法测试
*/
public class ElementMain {
public static <T> void text(T text) {
System.out.println(text);
}
public static void main(String[] args) {
text("hello 泛型");
text("123");
}
//规定了只能是list 或者是list的子类
public static <T extends List<String>> void text(T text){
text.add("hello word");
}
//IO释放资源
// t... 也可以写成T[] 表示可变参数
public static <T extends Closeable> void text(T... text){
for (T tmp: text) {
if (null!=tmp){
try {
tmp.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
泛型继承
package com.hp.element;
/**泛型父类 ,子类为富二代
*保留父类泛型,-->子类为泛型
*
* 属性及方法类型 -->随位置而定
*1),子类重写方法的类型-->随父类而定
* 子类新增方法类型-->随子类而定
* 2),子类中使用父类的属性 -->随父类而定
* 子类中使用子类的方法属性 -->随自己而定
*
*
* @param <T>
* @param <E>
*/
public abstract class Text<T, E> {
T age;
public abstract void add(E name);
}
//全部保留
class C<T, E, A> extends Text<T, E> {
A teacher; //子类重定义的属性随自己而定
@Override
public void add(E name) {
//this.age 指向父类的实例变量 T类型
}
}
//部分保留
class C1<E, A> extends Text<Integer, E> {
@Override
public void add(E name) {
// this.age 是integer类型
}
};
//擦除 都是object 相当于 Text<Object,Object>
class C3 extends Text {
@Override
public void add(Object name) {
//this.age 是Object类型
}
}
//按需实现
class C2 extends Text<Integer, String> {
@Override
public void add(String name) {
// this.age 是Integer类型
}
};
拓展
extends 泛型上限 即<=类或者自身
package com.hp.frtuits;
import java.util.ArrayList;
import java.util.List;
/**
* 泛型 ?extends 的使用
*
* 一般用于数据的读取 限制 不能用于添加数据上面
*
*/
public class Extends {
public static void main (String[] args) {
//T extends 类 即<=这个类或者只会是你
HelloWord<Frtuits> word = new HelloWord<>();
HelloWord<Apple> appleHelloWord=new HelloWord<>();
HelloWord<Banana> bananaappleHelloWord=new HelloWord<>();
HelloWord<FuShiApple> fuShiAppleHelloWord=new HelloWord<>();
//? extends 类 如果只写一个问号 表示 ? extends Object
List<Frtuits> frtuits=new ArrayList<>();
text(frtuits);
List<Apple> apples=new ArrayList<>();
text(apples);
List<Banana> bananas=new ArrayList<>();
text(bananas);
List<FuShiApple> fuShiApples=new ArrayList<>();
text(fuShiApples);
List<? extends Object> error=new ArrayList<>();
//text(error); 错误的用法
}
public static void text(List<? extends Frtuits> list){
//可以放null 但是不能放 list.add(new Apple());
// 因为我传进方法一个fuShiApples 我们不能再方面里面List.add()添加apple FuShiApple 是apple的子类
list.add(null);
}
static class HelloWord<T extends Frtuits>{
}
}
水果类的java代码
/**
* 水果类
*/
public class Frtuits {
}
/**
* 苹果类
*/
class Apple extends Frtuits{
}
/**
* 香蕉类
*/
class Banana extends Frtuits{
}
/**
* 富士苹果
*/
class FuShiApple extends Apple{
}
super泛型的上限即 >= 类或者自身
package com.hp.frtuits;
import java.util.ArrayList;
import java.util.List;
/**
* <? super apple> >=apple类 表示apple类以上 上限
*/
public class Super {
public static void main(String[] args) {
List<? super Apple> apples = new ArrayList<>();
text(apples);
List<? super FuShiApple> fuShiApples = new ArrayList<>();
//text(fuShiApples); 错误实例 由于FuShiApple是apple的子类 <apple所以编译错误
List<? super Frtuits> frtuits=new ArrayList<>();
text(frtuits);
List<? super Object> objects=new ArrayList<>();
text(objects);
List<? extends Object> objects1=new ArrayList<>();
//text(objects1);
}
public static void text(List<? super Apple> list) {
//不能添加添加父类信息
list.add(new Apple());
list.add(new FuShiApple());
//为什么不能添加父类信息 因为 添加的数据都在apple的范围之上(也包括apple) 所以添加的数据都有apple的子类或者自身
//list.add(new Frtuits());
//list.add(new Banana())
}
}