Java泛型简介、定义和使用含有泛型的类、定义和使用含有泛型的方法、定义和使用含有泛型的接口、泛型通配符?、受限泛型_java泛型类的定义和使用-程序员宅基地

技术标签: Java  java  开发语言  

泛型简介:

集合中存储数据的类型称之为泛型,泛型是一种未知的数据类型,当不知道使用什么数据类型的时候可以使用泛型;

当创建对象时在指明数据类型并赋值给泛型即可;泛型也可以看做是一个变量,用来存储数据。

常见泛型中:字母E表示元素,字母T表示Type,当然如果泛型的数据类型已知的话可以传入确定的数据类型,如String,底层实际是将String传递给了E

import java.util.ArrayList;//导包
import java.util.Iterator;
public class Generic{
    
    public static void main(String[] args){
    
        // 1.集合中为了安全,一般是需要指定数据类型的,<类型>,类型值除int(Integer)、char(Character),其它类型将数据类型的首字母大写即可
        ArrayList<String> arraylist = new ArrayList<String>();
        arraylist.add("星期一");
        System.out.println(arraylist); // [星期一]
        arraylist.add("星期二");
        System.out.println(arraylist); // [星期一, 星期二]

        // 2.使用泛型的好处:避免数据类型转换,存什么类型取什么类型;将运行期异常提升到了编译器;泛型的弊端:指明数据类型后只能存储指定类型的数据。
        ArrayList<Integer> arrayInt = new ArrayList<Integer>();
        arrayInt.add(10);
        System.out.println(arrayInt);
        // arrayInt.add("20"); // 泛型是什么类型,在新增数据的时候就是什么数据类型的数据,否则编译不通过
        arrayInt.add(20);
        System.out.println(arrayInt);

        // 3.集合不使用泛型时,默认数据类型是Object,可以存储任意类型的数据,此时不安全会发生异常。
        ArrayList list = new ArrayList();
        list.add('1');
        list.add("abc");
        list.add(12);
        System.out.println(list); // 编译时提示: Generic.java使用了未经检查或不安全的操作; 打印结果:[1, 1, abc]

        // 4.使用迭代器遍历list:
        // 获取集合的迭代器:
        Iterator iter = list.iterator();
        //遍历并打印数据:
        //hasNext判断是否有元素
        while (iter.hasNext()) {
    
            // next获取元素
            Object item = iter.next();
            System.out.println(item);

            // 向下转型时会抛出异常:Exception in thread "main" java.lang.ClassCastException: java.base/java.lang.Integer cannot be cast to java.base/java.lang.String at Generic.main(Generic.java:37),使用泛型约束后在编译时就会提示
            String str = (String) item;
            System.out.println(str.length());
            System.out.println(str);
        }
    };
};

定义和使用含有泛型的类:

定义泛型类时只需要在类名称后面加<类型>,类里面的数据类型用尖括号中的类型代替,使用泛型类时和普通类一样创建,区别就是可以使用泛型创建对象,也可以不使用泛型创建对象,但是不使用泛型创建对象时,它默认是Object类型,而且也是不推荐的,如下面E的使用:

泛型类:

// 定义含有泛型的类时,在类名称后面写<类型>即可,E表示任意元素的泛型
public class GenericClass<E> {
    
//public class GenericClass{
    
    // 1.定义一个含有泛型的类(模拟ArrayList集合),泛型是一个未知的数据类型,当不确定数据类型的时候可以使用泛型,泛型可以接收任意数据类型,在创建对象时在指明数据类型:
    private E name;
//    private String name;

    public E getName() {
    
//    public String getName() {
    
        return name;
    }

    public void setName(E name) {
    
//    public void setName(String name) {
    
        this.name = name;
    }
};

使用泛型类:

public class UserGenerIcClass {
    
    public static void main(String[] args) {
    
        // 1.使用GenericClass类,不传泛型时默认是Object类型
        GenericClass gc = new GenericClass();
        // 当创建类的时候,如果数据类型是写死的,那么在这里设置和读取的时候也只能是指定写死的类型,如:
        gc.setName("苦海");
        System.out.println(gc.getName());// 苦海

        // 2.使用泛型创建对象:
        GenericClass<Integer> gcInt = new GenericClass<Integer>();
        // gcInt.setName('1'); 使用了泛型,如果数据类型不符合就会编译不通过
        gcInt.setName(18);
        System.out.println(gcInt.getName());// 18

        GenericClass<Character> gcChar = new GenericClass<Character>();
        gcChar.setName('f');
        System.out.println(gcChar.getName());// f
    }
}

定义和使用含有泛型的方法:

定义含有泛型的方法:

// 含有泛型的方法:泛型定义在方法修饰符和返回值之间,如: public <泛型> 返回值类型(参数(使用泛型)){}
public class DefGenericMethodsClass {
    
    // 前面定义了泛型,后面括号中才可以使用:这里S是随便写的,这里可以写任意字符串
    public <S> void defGenericMethods(S s) {
    
        System.out.println(s);
    }

    // 定义一个含有泛型的静态方法:
    public static <S> void staGenericMethods(S s) {
    
        System.out.println(s);
    }

    // 定义一个普通的方法:
    public static void commonMethods (String s) {
    
        System.out.println(s);
    }
}


使用含有泛型的方法:

public class UseGenericMethodsClass {
    
    public static void main(String[] args) {
    
        // 创建含有泛型方法的对象:
        DefGenericMethodsClass gm = new DefGenericMethodsClass();
        // 调用含有泛型的方法,传递什么类型,泛型就是什么类型
        gm.defGenericMethods(10); // 10
        gm.defGenericMethods('a'); // a
        gm.defGenericMethods("121"); // 121

        // 调用静态方法:
        DefGenericMethodsClass.staGenericMethods("静态方法");
        // 调用普通方法:接收参数时必须指定类型,且传参数时也要求一直
        gm.commonMethods("hello");
        // gm.commonMethods(true); // 定义什么类型,传递什么类型,否则报错
        // gm.commonMethods(123);
    }
}

定义和使用含有泛型的接口:

定义含有泛型的接口:

// 定义含有泛型的接口:在接口名称后面加<类型>
public interface DefGenericInterface<S> {
    
    // 定义一个抽象方法:
    public abstract void methods(S s);
}

使用含有泛型的接口,有两种方式:

方式一接口实现类:

// 使用含有泛型的接口第一种方式:定义接口实现类,实现接口,指定接口泛型:
public class UseGenericInterface implements DefGenericInterface<String> {
    
    @Override
    public void methods(String s) {
    
        System.out.println(s);
    };
}

方式一使用接口实现类:、

// 定义一个普通的类使用接口实现类:
public class UseGenericInterfaceClass {
    
    public static void main(String[] args) {
    
        UseGenericInterface gi = new UseGenericInterface();
        gi.methods("hello"); // hello
    }
}

方式二接口实现类:

// 使用含有泛型的接口第二种方式:接口使用什么泛型,实现类就用什么泛型,类跟着接口走,相当于定义了一个含有泛型的类,创建对象时指定泛型的类型
public class UseGenericInterfaceTwo<S> implements DefGenericInterface<S> {
    
    @Override
    public void methods(S s) {
    
        System.out.println(s);
    };
}

方式二使用接口实现类:

public class UseGenericInterfaceClassTwo {
    
    public static void main(String[] args) {
    
        UseGenericInterfaceTwo<Integer> gi = new UseGenericInterfaceTwo<Integer>();
        gi.methods(255); // 255
    }
}

泛型通配符?:

当使用泛型类或者接口时,传逆的数据中,泛型类型不确定,可以通过通配符<?>表示。但是一旦使用泛型的通配符后,只能使用Objet类中的共性方法,集合中元素自身方法无法使用,只能接收数据,不能往集合中存储数据:

import java.util.ArrayList;
import java.util.Iterator;

// 泛型通配符:只能作为方法的参数使用,不能创建对象使用,如下面定一个万能遍历结合的方法
public class GenericWildcard {
    
    public static void main(String[] args) {
    
        ArrayList<Integer> list1 = new ArrayList<Integer>();
        list1.add(1);
        list1.add(2);
        forEachArrayList(list1);

        ArrayList<Character> list2 = new ArrayList<Character>();
        list2.add('z');
        list2.add('a');
        forEachArrayList(list2);
    }
    public static void forEachArrayList(ArrayList<?> list) {
    
        // 获取遍历器:
        Iterator<?> item = list.iterator();
        while(item.hasNext()){
    
            Object it = item.next();
            System.out.println(it);
        }
    }
}

受限泛型:

前面设置泛型的时候是没有做限制的,只要是类都可以设置,但是在Java的泛型中可以指定一个泛型的上限和下限:

泛型上限:只能接收该类型及其子类

格式:类型名称 <? extends 类> 对象名称

泛型下限: 只能接收该类及其父类

格式:类型名称 <? super 类> 对象名称

import java.util.ArrayList;
import java.util.Collection;

public class GenericLimit {
    
    public static void main(String[] args) {
    
        // 定义多个类型的集合并测试受限泛型:
        Collection<Integer> list1 = new ArrayList<Integer>();
        getElementExtends(list1);
        // getElementSuper(list1); // 报错:只能传入当前类型或父类

        Collection<String> list2 = new ArrayList<String>();
        // getElementExtends(list2); // 报错:String和Number没有上下级关系
        // getElementSuper(list2); // 报错:String和Number没有上下级关系

        Collection<Number> list3 = new ArrayList<Number>();
        getElementExtends(list3);
        getElementSuper(list3);

        Collection<Object> list4 = new ArrayList<Object>();
        getElementExtends(list3);
        getElementSuper(list3);
    }
    // 类之间的继承关系:
    // Integer 继承-> Number 继承-> Object
    // String 继承-> Object

    // 定义一个泛型下限:传入的类型只能是Number或子类
    public static void getElementExtends(Collection<? extends Number> param){
    };
    // 定义一个泛型上限:传入的类只能是Number或父类
    public static void getElementSuper(Collection<? super Number> param){
    };
}

提示:本文图片等素材来源于网络,若有侵权,请发邮件至邮箱:[email protected]联系笔者删除。
笔者:苦海

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_46758988/article/details/128088586

智能推荐

tomcat启动占了12g_tomcat服务为何报内存相关错误??-程序员宅基地

文章浏览阅读86次。本帖最后由 linux_love 于 2014-9-19 11:46 编辑多谢各位英雄支持,这个问题困扰我N久了,昨天终于让我给拿下了,在Linux下有个CommitLimit 用于限制系统应用使用的内存资源,#grep -i commit /proc/meminfoCommitLimit: 20389524 kBCommitted_AS: 18541832 kB其中:CommitLim..._commited_as 被谁占了

计算机基础知识判断题答案,计算机基础知识试题及答案判断题模板.docx-程序员宅基地

文章浏览阅读1.5k次。优质文档PAGE 页码页码/NUMPAGES 总页数总页数计算机基础知识试题及答案判断题(一)1、 冯?诺依曼原理是计算机的唯一工作原理。.( × )2、 计算机能直接识别汇编语言程序。.( × )3、 计算机能直接执行高级语言源程序。.( × )4、 计算机掉电后,ROM中的信息会丢失。( × )5、 计算机掉电后,外存中的信息会丢失。( √ )6、 应用软件的作用是扩大计算机的存储容量。( ×..._计算机判断题及答案

最新全流程GMS地下水数值模拟及溶质(包含反应性溶质)运移模拟技术深度应用-程序员宅基地

文章浏览阅读704次,点赞30次,收藏18次。最新全流程GMS地下水数值模拟及溶质(包含反应性溶质)运移模拟技术深度应用_gms地下水数值模拟

Android 自定义横向进度条_android自定义横向进度条-程序员宅基地

文章浏览阅读2.4k次。private int max; private double progress; private int bgColor; private int progressColor; private int padding; private boolean openGradient; private int gradientFrom; private int gradientTo; private boolean showSecondProgres_android自定义横向进度条

宝塔打开后,内容渲染失败(405)【了解一下】_宝塔部署后405 not allowed-程序员宅基地

文章浏览阅读111次。如果你是以上这种情况,打开以后发现,数据渲染不上,很可能是因为你的配置反向代理的顺序搞错了,造成的结果就是反向代理没有替换成功!还是那些内容,只是改变了操作步骤;数据就能加载出来了!_宝塔部署后405 not allowed

联想计算机管理员权限设置,Windows XP系统如何新建administrator管理员权限账户-程序员宅基地

文章浏览阅读1.6k次。知识点分析:对于Windows XP系统,有很多种创建用户账户的操作方法。其中包括:使用CMD命令行的net命令进行,也可以使用控制面板的图形界面进行,还可以使用计算机管理控制台中的“本地用户和组”进行。其中后者自定义功能多,本文以此为例进行操作示范。操作步骤:1. 在系统桌面找到并使用鼠标右键点击“我的电脑”图标,然后在弹出菜单中选择“管理(G)”,如下图所示:2. 在弹出的计算机管理窗口,展开..._xp 开启管理员账户

随便推点

WebGL快速入门_webgl入门-程序员宅基地

文章浏览阅读2.3k次,点赞2次,收藏11次。WebGL是一种用于在Web浏览器中实现高性能3D图形的技术。本文将帮助读者快速入门WebGL,了解其基本概念和使用方法。我们将介绍WebGL的基本架构和API,包括如何创建WebGL上下文、渲染对象和着色器编程等。此外,我们还会深入探讨WebGL的基本原理和渲染管线,以及如何通过优化渲染流程来提升性能。通过学习本文,读者将能够理解WebGL的核心概念和使用方法,并能够开始开发高性能的3D应用程序。_webgl入门

C++中的String的常用函数用法总结_string函数-程序员宅基地

文章浏览阅读10w+次,点赞1.3k次,收藏6.1k次。一. string的构造函数的形式: string str:生成空字符串string s(str):生成字符串为str的复制品string s(str, strbegin,strlen):将字符串str中从下标strbegin开始、长度为strlen的部分作为字符串初值string s(cstr, char_len):以C_string类型cstr的前char_len个字..._string函数

金融风控训练营金融风控基础知识学习笔记_风控师学习笔记-程序员宅基地

文章浏览阅读162次。一、赛题理解和学习目标:本次挑战赛以个人信贷为背景,要求选手对金融风控之贷款是否违约进行预测,以此判断是否通过此项贷款的一项问题型比赛。通过学习Task1了解第一个学习内容,要求对金融风控的问题建立数学模型最后给定金融风险程度。在此过程中要了解混淆矩阵、AUC评价指标,KS统计量等二、学习内容:混淆矩阵就是一个2×2的矩阵分为真正类TP、真分类TN、假正类FT、假反类FNFP FN TP TN AUC被定义在ROC曲线下与坐标轴围成的面积(ROC曲线:以真阳性率._风控师学习笔记

哈希表 添加 增添 删除 获取方法 Js封装_js hash追加-程序员宅基地

文章浏览阅读237次。<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>D._js hash追加

JS数据结构-Set集合,创建Set,常用Set方法_js set-程序员宅基地

文章浏览阅读7.6k次,点赞7次,收藏12次。Set  ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。  很多时候我们把Set叫做 集合,但是,Set可以是集合,集合不一定是Set。  特性:唯一性=>不重复=>能够对数据进行去重操作。  注:集合去重,是全等匹配,===。创建Set  Set 本身是一个构造函数,调用构造函数用来生成 Set 数据结构。  关键词 标识符 = new Set();  例 let i = new Set();    Set 函数可以接受一个数组_js set

C#版的抓包软件_c# winpcap-程序员宅基地

文章浏览阅读5.4k次,点赞3次,收藏27次。NetAnalyzer实现结构在上一篇中介绍一点VC++开发环境的配置,与基本的运行方式。因为NetAnalyzer使用的C#作为开发语言,所以在此主要介绍一些在C#环境下的开发环境的配置,与一些基本开发情况,力求在完成本篇后后,读者可以制作一个简单的抓包程序。在开始编程前先要介绍连个.Net类库SharpPcap.dll与PacketDotNet.dll。在2004年Tamir _c# winpcap

推荐文章

热门文章

相关标签