Java基础——jdk1.5新特性及集合与数组的转换

2023-11-17

jdk1.5的新特性

泛型是一种泛泛的类型,泛指某一种类型,是在创建对象或者调用方法或者实现接口才明确的类型。

泛型好处提高安全性(将运行期的类型转换错误提前到编译期),省去强转的麻烦。

泛型使用注意事项

  1. <>中放的必须是引用数据类型;
  2. 前后的泛型必须一致,或者后面的泛型可以省略不写(1.7的新特性菱形泛型) (建议后面的也写全);
  3. 在创建对象或者调用方法或者实现接口明确泛型的时候,尽量不要明确成Object,因为这样做没有意义(泛型的由来就是由Object的转型的问题得到的);
  4. 泛型是JDK1.5出现的。

代码演示:

public static void demo1() {
    ArrayList list = new ArrayList();
    list.add(110);//添加一个Integer类型的 110,在没有使用泛型的时候 list可以添加任意的引用类型  
    list.add(true);	//添加一个Boolean类型的 true
    list.add(new Person("张三", 23));	//添加一个Person
    Iterator it = list.iterator();
    while(it.hasNext()) {
        System.out.println(it.next());	//将集合里面的元素打印出来
    }
}

public static void demo2() {
    ArrayList list = new ArrayList();
    list.add(110);			
    list.add(true);				
    list.add(new Person("张三", 23));	
    Iterator it = list.iterator();
    while(it.hasNext()) {
    	//如果我想使用Person的特有功能 需要强制转换成Person类型
        Person p = (Person)it.next();//编译不报错, 运行的时候立刻报错,因为存储的 110 和 true 并不是Person类型 单却强制转换成Person类型 会报出类型转换错误			
        System.out.println(p.getName() + "..." + p.getAge());
    }
}

//ArrayList存储字符串并遍历泛型版
public static void demo3() {
    ArrayList<Person> list = new ArrayList<>();		//<Person>规定 list对象里面必须存储Person类型的元素,存储其他类型的编译就会报错
    list.add(new Person("张三", 23));
    list.add(new Person("李四", 24));
    list.add(new Person("王五", 25));
    list.add(new Person("赵六", 26));

    Iterator<Person> it = list.iterator();			//获取的迭代器也是Person类型的泛型
    while(it.hasNext()) {
        Person p = it.next();				//it.next()获取到的元素 就不再是Object了,泛型里面规定的类型 it.next()就获取什么样类型的元素,所以就不用强制类型转换了
        System.out.println(p.getName() + "..." + p.getAge());
    }
}


public static void main(String[] args) {
    //ArrayList<int> list = new ArrayList<int>();		//编译报错 <>中放的必须是引用数据类型 
    //ArrayList<Object> list = new ArrayList<Person>();	//编译报错 集合的泛型要保证前后的数据类型一致
    ArrayList<Object> list = new ArrayList<>();//泛型最好不要定义成Object,没有意义,1.7版本的新特性,菱形泛型,后面的<>可以不用填写
    list.add("aaa");
    list.add(true);
}
泛型类: public class 类名<泛型类型1,泛型类型2,…>{}
public class Worker<QQ> {
    public void show(QQ qq){
    	System.out.println(qq);
    }
}
public class Worker<QQ,MM,DD,RR> {	//可以写一个泛型 也可以写多个
    public void show(QQ qq){
    	System.out.println(qq);
    }
}
泛型非静态方法: public <泛型类型> 返回类型 方法名(泛型类型 变量名){}

代码演示:

public class Demo1_Generic {
	public static void main(String[] args) {
		/*Tool t = new Tool();
		t.show("abc");		//调用show(String s)方法 传入一个"abc"
		t.show(100);*/		//调用show(Integer i)方法 传入一个100
        //如果想继续接着调用一个show(Student s)方法, 就需要继续修改Tool类,再继续编写一个show(Student s)方法 才能调用
        //如果想继续接着调用一个show(Animal a)方法, 就需要继续修改Tool类,再继续编写一个show(Animal a)方法 才能调用
        //如果想继续接着调用一个show(Worker w)方法, 就需要继续修改Tool类,再继续编写一个show(Worker w)方法 才能调用
        //这样修改  将无穷无尽,所以用下面的泛型类改进代码

        /*Tool1<String> t = new Tool1<>();	//想调用show方法 传入一个"abc" 那么就创建一个泛型为String的对象
		t.show("abc");
		
		Tool1<Integer> t1 = new Tool1<>();	//想调用show方法 传入一个100 那么就创建一个泛型为Integer的对象
		t1.show(100);

		Tool1<Student> t2 = new Tool1<>();	//想调用show方法 传入一个Student 那么就创建一个泛型为Student的对象
		t2.show(new Student());*/		
        //如果想接着调用show方法 传入一个Animal 就又要创建一个泛型为Animal的对象 ,每次都要创建一个新的对象 浪费空间 所以用下面的泛型方法改进

        Tool2 t = new Tool2();	
        t.show("abc");	//调用show方法的时候就明确了QQ是String类型
        t.show(100);//调用show方法的时候就明确了QQ是Integer类型
        t.show(new Student());//调用show方法的时候就明确了QQ是Student类型
        //想传什么样的类型都可以 而且代码非常的简单
    }
}
public class Tool {
    public void show(String s) {
        System.out.println(s);
    }
    public void show(Integer i) {
        System.out.println(i);
    }
}

public class Tool1<QQ> {
    public void show(QQ qq){
        System.out.println(qq);
    }
}
public class Tool2 {
    public <QQ>void show(QQ s){
        System.out.println(s);
    }
}
泛型静态方法: public static <泛型类型> 返回类型 方法名(泛型类型 变量名){}
public class Tools<Q> {	
    /*public static void show(Q q) {		//编译报错,因为静态的 优先于对象而存在
			System.out.println(q);
	}*/
    public static<W> void print(W w) {		//静态方法必须声明自己的泛型
        System.out.println(w);
    }
}
泛型接口:public interface 接口名<泛型类型>

子类在实现父接口的时候可以明确泛型,也可以直接沿用父类的泛型

代码演示:

interface Inter<T> {
    public void show(T t);
}

class Demo implements Inter<String> {		//子类在实现父接口的时候 可以明确泛型 明确成了String类型
    @Override
    public void show(String t) {
        System.out.println(t);
    }
}

class Demo<T> implements Inter<T> {		//也可以直接沿用父类的泛型 T
    @Override
    public void show(T t) {
        System.out.println(t);
    }
}
泛型-通配符:

A:泛型通配符<?>任意类型

List<?> list = new ArrayList(); //当右边的泛型是不确定时,左边可以指定为?
B:<? extends E >明确泛型的时候明确成E或者E的儿子
代码演示:

public static void main(String[] args) {
    ArrayList<Person> list1 = new ArrayList<>();
    list1.add(new Person("张三", 23));
    list1.add(new Person("李四", 24));
    list1.add(new Person("王五", 25));

    ArrayList<Student> list2 = new ArrayList<>();
    list2.add(new Student("赵六", 26));
    list2.add(new Student("周七", 27));

    //boolean addAll(Collection<? extends E> c)
    list1.addAll(list2);		//Student 是Person的儿子 所以 可以添加成功
    System.out.println(list1);
}

C:<? super E >明确泛型的时候明确成 E或者E的父类

增强for循环

为了简化数组或者集合的遍历而出现的(JDK1.5出现的)

for(集合或者数组里面元素的数据类型 变量名 : 数组或者集合){
	直接使用变量名就ok;
}

代码演示:

public static void demo1() {
    int[] arr = {11,22,33,44,55};
    for (int i : arr) {		//增强for循环可以遍历数组
        //增强for循环在遍历数组或者集合的时候,优点:代码的书写确实简单了,但缺点是遍历时候没有索引,如果想用索引的时候,就请用普通for循环
        System.out.println(i);
    }

    ArrayList<String> list = new ArrayList<>();
    list.add("a");
    list.add("b");
    list.add("c");
    list.add("d");

    for (String string : list) {	//增强for循环可以遍历集合
        System.out.println(string);
    }
}

遍历过程中能否删除元素总结:
1)普通for循环在遍历的时候(只能遍历List体系的集合),可以删除,但是在删除过程中索引会改变, size也会发生改变,所以容易出现漏删的情况。

解决:索引–,代码片段如下:

ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("b");
list.add("c");
list.add("d");
for(int i = 0; i < list.size(); i++) {
    if("b".equals(list.get(i))) {
        list.remove(i--);	//通过索引删除元素
    }
}

2)迭代器在遍历集合的时候 Iterator(可以遍历任何单列集合),不可以通过集合操作元素,否则会报并发修改异常。只能通过迭代器自身来对元素进行操作,如果是删除:可以用Iterator 也可以用ListIterator 因为他们里面都有remove();如果是添加:只能使用ListIterator,因为只有ListIterator里面有add()
代码片段如下:

ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("b");
list.add("c");
list.add("d");
Iterator<String> it = list.iterator();
while(it.hasNext()) {
    if("b".equals(it.next())) {
        //list.remove("b");	//不能用集合的删除方法,因为迭代过程中如果集合修改会出现并发修改异常
        it.remove();		//让迭代器自己来删除元素
    }
}

3)增强for循环遍历集合的时候(可以遍历任何单列集合),由于底层就是调用的迭代器,所以不能删除,只能遍历。代码片段如下:

ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("b");
list.add("c");
list.add("d");
for (String string : list) {
    if("b".equals(string)) {
        list.remove("b");	//运行报错,并发修改异常,增强for循环底层用的是迭代器 所以不能在迭代器过程中让集合来删除元素,如果用迭代器自己来删除 ,哪有迭代器来让你使用呢?,在底层呢 你又看不到
    }
}
System.out.println(list);

可变参数
格式:修饰符 返回值类型 方法名(数据类型 … 变量名){}
注意:

  1. 可变参数是JDK1.5后出现的新特性
  2. 可变参数其实是一个数组,所以调用带有可变参数的方法的时候,可以传入一个相同类型的数组
  3. 有多个参数的时候,可变参数放到最后

代码演示:

public class Demo3_ChangeableArgs {
	public static void main(String[] args) {
		int[] arr = {11,22,33,44,55};
		print();			//调用的时候 可以不传入参数
		print(arr);			//调用的时候 可以传入一个数组,因为可变参数的底层就是使用的数组
		print(11,22,55);		//调用的时候 可以传入多个参数		
	}

    public static void print(int ... arr) {	//可变参数其实是一个数组
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
    public static void show(String s , int ... arr) {	//有多个参数的时候,可变参数放到最后

    }
    /*
		public static void method(int ... arr , String s) {	//编译报错 有多个参数的时候,可变参数放到最后

		}*/
}

//可变参数的应用
public class Demo4_ChangeableArgs {
    public static void main(String[] args) {	
        //求两个数的最大值,我需要定义一个,含两个参数的方法max(int a , int b)
        int big = max(5,6);
        //假如现在需求变了,我想求三个数的最大值,那么我需要定义一个含三个参数的方法 max(int a , int b , int c)
        int big1 = max(5,6,10);

        //假如现在需求又变了,我想求四个数的最大值,难道我就再继续定义一个含有四个参数的方法 max(int a , int b , int c , int d)吗? 这样太麻烦了, 解决方案就是 用可变参数
        int big2 = max(11,432,7,87,23);
    }

    //求两个数的最大值
    public static int max(int a , int b) {
        return a>b?a:b;
    }

    //求三个数的最大值
    public static int max(int a , int b , int c) {
        return a>b ? (a>c?a:c) : (b>c?b:c);
    }

    //求任意个数的最大值
    public static void max(int ... arr) {	//可变参数其实是一个数组
        int a = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if(arr[i]> a){
                a = arr[i]
            }
        }
        return a;
    }
}
集合和数组之间的转换

Arrays工具类的asList(T … t):将数组转成集合(该方法用的可变参数)
注意:

1)返回一个长度固定的集合,可以改和查,不能增和删,也就是改变其长度的操作都不可以做。

2)将数组转换成集合,数组必须是引用数据类型。

Collection中toArray(T[] a)泛型版的集合转数组:

T[] 明确成什么样的数组 toArray(T[] a)方法就返回什么类型的数组

注意:当集合转换数组时,数组长度如果是小于等于集合的size时,转换后的数组长度等于集合的size;如果数组的长度大于了size,分配的数组长度就和你指定的长度一样。

好了今天就先说到这了,想了解更多学习知识,请关注微信公众号“阿Q说”,获取更多学习资料吧!你也可以后台留言说出你的疑惑,阿Q将会在后期的文章中为你解答。每天学习一点点,每天进步一点点。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java基础——jdk1.5新特性及集合与数组的转换 的相关文章

  • 如何用xp系统做服务器,xp系统如何做远程服务器呢

    xp系统如何做远程服务器呢 内容精选 换一换 网站的访问与云服务器的网络配置 端口通信 防火墙配置 安全组配置等多个环节相关联 任意一个环节出现问题 都会导致网站无法访问 本节操作介绍网站无法访问时的排查思路 网站无法访问怎么办 如果打开网

随机推荐

  • 14-5_Qt 5.9 C++开发指南_基于HTTP 协议的网络应用程序

    文章目录 1 实现高层网络操作的类 2 基于HTTP协议的网络文件下载 3 源码 3 1 可是化UI设计 3 2 mainwindow h 3 3 mainwindow cpp 1 实现高层网络操作的类 Qt 网络模块提供一些类实现 OSI
  • Synchronized的锁升级过程

    Synchronized的锁升级过程 synchronized锁升级过程 在synchronized中引入了偏向锁 轻量级锁 重量级锁之后 当前具体使用的是synchronzed中的那种类型锁 是根据线程竞争激烈程度来决定的 偏向锁 在锁对
  • vue使用luckysheet,引入图表chartmix,实现打印按钮功能

    1 下载Luckysheet源码 下载地址 https github com dream num Luckysheet 按照下载地址提示 npm run build 打包源码 生成dist文件夹 2 引入luckysheet的js文件和cs
  • TinyWebServer

    遇到的问题 1 Reactor和Proactor 当下开源软件能做到网络高性能的原因就是 I O 多路复用吗 是的 基本是基于 I O 多路复用 用过 I O 多路复用接口写网络程序的同学 肯定知道是面向过程的方式写代码的 这样的开发的效率
  • 数据可视化pyecharts绘制饼状图和环形图

    艰难做了新的作业练习 记录一下 from pyecharts import options as opts from pyecharts charts import Pie Page from pyecharts faker import
  • FC基本定义

    FC基本定义 虚拟化的软件有很多 华为开发的服务器虚拟化软件Fusioncompute CAN compute node agent 提供虚拟化功能 版本6 3之前是基于开源的xen开发的 6 3之后是基于开源的Kvm开发的 1 CAN V
  • 10月08日星期二 恒指/美原油/美黄金 走势分析

    财经早餐 2019年10月08日星期二 重点关注的财经数据与事件 07 50 日本8月贸易帐 09 45 中国9月财新服务业PMI 13 45 瑞士9月季调后失业率 14 00 德国8月季调后工业产出月率 14 45 法国8月贸易帐 18
  • Linux下创建所线程

    一 线程 线程是轻量级的进程 LWP light weight process 在 Linux 环境下线程的本质仍是进程 在计算机上运行的程序是一组指令及指令参数的组合 指令按照既定的逻辑控制计算机运行 操作系统会以进程为单位 分配系统资源
  • 百万前端之vue2.x最快上手

    1 创建项目 vue create 项目名 2 认识vue初始文件夹 3 安装插件 移动端安装vant ui pc端安装element ui Vue 2 项目 安装 Vant 2 npm i vant latest v2 S 安装axios
  • R_Studio(学生成绩)绘制频率分布直方图、分布饼图、折线比较图

    对 Gary csv 中的成绩数据进行分布分析 1 按0 59 60 69 70 79 80 89 90 100分组绘制高级语言程序设计成绩的频率分布直方图 2 按0 59 60 69 70 79 80 89 90 100分组绘制计算机导论
  • Sping为什么使用依赖注入而不使用实例化对象的方式?

    首先说明一下概念 依赖注入 Dependency of Injection 和控制反转 Inversion of Control 简称 ioc 是一个概念 具体含义 当某个角色 Java实例class A 调用者 需要另一个角色 另一个Ja
  • 专业心理咨询师助你轻装上阵,向内耗说不!

    引言 身为技术人 你是否经常感觉自己被掏空了精力 行动力不佳 又或者觉得自己的工作没有成就和意义 工作状态持续不佳 你是否总有一种无法消除的疲惫 即使没有学习 工作 而是选择看剧 刷短视频 甚至外出度假 也不能得到纾解 反而感到越来越累 实
  • 【MySQL安装问题】mysqld --initialize初始化报错

    在显示安装成功MySQL后 初始化mysqld initialize报错 错误显示如下 2023 04 03T709 05 28 842980Z O Warning TMESTAMP with implicit DEFAULT walue
  • pyltp 安装过程总结

    在安装pyltp的过程中踩了不少坑 这里对坑过程进行总结下 避免大家踩坑 第一步 安装pyltp 这里看别的blog给了两个方法 一个是直接pip 另一个是通过git clone pyltp的github 再通过python setup p
  • AD/DA模块使用说明及原理分析

    一 硬件资源 AD芯片 TLC549 DA芯片 TLC5615 LCD1602 LCD12864接口 6个独立按键 液晶背光可通过电位器 U6 调节 自带模拟测试信号 可通过 U20 调节测试信号幅值大小 二 模数转换 AD转换 1 知识背
  • 二叉堆的介绍

    一 介绍 习惯上 我们将二叉堆简称为 堆 二叉堆是以数组存储的完全二叉树 父节点值大于或等于其孩子节点值的 叫最大堆 父节点值小于或等于孩子节点值的 叫最小堆 最大堆的根节点的值最大 最小堆的根节点的值最小 下图为树形结构表示的堆 二 二叉
  • 云、边、端三协同下的边缘计算:未来数据处理的新范式

    随着移动互联网的快速发展 人们对于数据的需求越来越大 而传统的云计算已经无法满足人们对于数据处理的需求 为了更好地满足人们的需求 边缘计算应运而生 边缘计算是指将计算和数据处理等任务从中心服务器移到离用户更近的边缘节点上 以提高数据处理速度
  • mybatis基础教程之二:接口的方式编程

    前面一节 已经搭建好了myeclipse mybatis mysql的环境 并且实现了一个简单的查询 请注意 这种方式是用SqlSession实例来直接执行已映射的SQL语句 session selectOne com yihaomen m
  • 使用 pandas.pivot 构造透视表时,报错:ValueError: Index contains duplicate entries, cannot reshape

    1 pivot 语法 DataFrame pivot index None columns None values None 当 index column 构成的组合中存在重复数据时 会报下图中的错误 2 案例 df pd DataFram
  • Java基础——jdk1.5新特性及集合与数组的转换

    jdk1 5的新特性 泛型是一种泛泛的类型 泛指某一种类型 是在创建对象或者调用方法或者实现接口才明确的类型 泛型好处提高安全性 将运行期的类型转换错误提前到编译期 省去强转的麻烦 泛型使用注意事项 lt gt 中放的必须是引用数据类型 前