java SE 基础

java

java特点:

Java的特点和优点_语言 (sohu.com)

最大的优点就是与平台无关,在Windows9x、WindowsNT、Solaris、Linux、MacOS以及其它平台上,都可以使用相同的代码。“一次编写,到处运行”的特点【高可移植性】,使其在互联网上广泛采用。

java和C++对比

即java的新特性

1) 提供了对内存的自动管理,程序员无需在程序中进行分配、释放内存,那些可怕的内存分配错误不会再打扰你了;

2) 去除了C++语言中的令人费解、容易出错的“指针”,用其它方法来进行弥补;

3) 避免了赋值语句(如a=3)与逻辑运算语句(如a==3)的混淆;

4) 取消了多重继承这一复杂的设施。

解释型语言效率低,速度慢;编译型语言效率高,速度快。

java是解释性语言,C++是编译型语言,

go是编译型语言,go静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。

go是09年公开发布,其创始人之一创造了Unix系统和C语言,还有UTF-8编码

Go的编码是Utf-8

服务器编程分布式系统数据库代理器网络编程内存数据库云平台微服务区块链等这些领域或者行业的应用和实施。

java是oracle公司开发的

安卓是谷歌开发的,移动操作系统,是基于linux内核的自由及开放源代码的操作系统,软件语言:C/C++(底层)、Java、Kotlin等(应用层)

面向对象和面向过程

面向对象与面向过程的简单比较_fableking的博客-CSDN博客_面向对象和面向过程哪个简单

面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。

面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。

例如五子棋,面向过程的设计思路就是首先分析问题的步骤:

1、开始游戏,2、黑子先走,3、绘制画面,4、判断输赢,5、轮到白子,6、绘制画面,7、判断输赢,8、返回步骤2,9、输出最后结果。把上面每个步骤用分别的函数来实现,问题就解决了。

面向对象的设计则是从另外的思路来解决问题。整个五子棋可以分为 1、黑白双方,这两方的行为是一模一样的,2、棋盘系统,负责绘制画面,3、规则系统,负责判定诸如犯规、输赢等。第一类对象(玩家对象)负责接受用户输入,并告知第二类对象(棋盘对象)棋子布局的变化,棋盘对象接收到了棋子的i变化就要负责在屏幕上面显示出这种变化,同时利用第三类对象(规则系统)来对棋局进行判定。

可以明显地看出,面向对象是以功能来划分问题,而不是步骤。同样是绘制棋局,这样的行为在面向过程的设计中分散在了总多步骤中,很可能出现不同的绘制版本,因为通常设计人员会考虑到实际情况进行各种各样的简化。而面向对象的设计中,绘图只可能在棋盘对象中出现,从而保证了绘图的统一。

功能上的统一保证了面向对象设计的可扩展性。比如我要加入悔棋的功能,如果要改动面向过程的设计,那么从输入到判断到显示这一连串的步骤都要改动,甚至步骤之间的循序都要进行大规模调整。如果是面向对象的话,只用改动棋盘对象就行了,棋盘系统保存了黑白双方的棋谱,简单回溯就可以了,而显示和规则判断则不用顾及,同时整个对对象功能的调用顺序都没有变化,改动只是局部的。

再比如我要把这个五子棋游戏改为围棋游戏,如果你是面向过程设计,那么五子棋的规则就分布在了你的程序的每一个角落,要改动还不如重写。但是如果你当初就是面向对象的设计,那么你只用改动规则对象就可以了,五子棋和围棋的区别不就是规则吗?(当然棋盘大小好像也不一样,但是你会觉得这是一个难题吗?直接在棋盘对象中进行一番小改动就可以了。)而下棋的大致步骤从面向对象的角度来看没有任何变化。

当然,要达到改动只是局部的需要设计的人有足够的经验,使用对象不能保证你的程序就是面向对象,初学者或者很蹩脚的程序员很可能以面向对象之虚而行面向过程之实,这样设计出来的所谓面向对象的程序很难有良好的可移植性和可扩展性。


网上关于这两个的回答真的很多,但是都有一个共同特点:------------不容易懂。

我今天就简单通俗的说一下(当然,如果你要非常深入的了解,这篇不适合你。如果你只是为了了解什么是面向过程和面向对象,怎么面对考试,面对面试,怎么和别人说两者区别,看我下面几段话够了。)

---------------------------------------------先来两小段通俗解释

面向过程(Procedure Oriented 简称PO :像C语言):

看名字它是注重过程的。当解决一个问题的时候,面向过程会把事情拆分成: 一个个函数和数据(用于方法的参数) 。然后按照一定的顺序,执行完这些方法(每个方法看作一个个过程),等方法执行完了,事情就搞定了。

面向对象(Object Oriented简称OO :像C++,JAVA等语言):

看名字它是注重对象的。当解决一个问题的时候,面向对象会把事物抽象成对象的概念,就是说这个问题里面有哪些对象,然后给对象赋一些属性和方法,然后让每个对象去执行自己的方法,问题得到解决。

------------------------------------------最后来个例子

问题: 冰箱里面放有脏衣服,怎么洗干净?

面向过程:
1 执行加洗衣粉方法;
2 执行加水方法;
3 执行洗衣服方法;
4 执行清洗方法;
5 执行烘干方法;
----------解决问题 拆成一个个方法,是没有对象去调用的。 通过一个个方法的执行解决问题。
面向对象: 我先搞个洗衣机对象和人对象

洗衣机: 加入一些属性和方法 洗衣服方法 清洗方法 烘干方法

人:加洗衣粉方法 加水方法

然后 人.加洗衣粉 人.加水 洗衣机.洗衣服 洗衣机.清洗 洗衣机.烘干

----------同样解决问题 先抽象出对象,然后用对象执行方法的方式解决问题。

然后在来一个我以前知乎看到的例子 : 男女亲密例子 man gril

面向过程: make_love(man,gril) ---------解决问题 拆成一个动作,把数据丢进去

面向对象: man.make_love(gril) 或者 gril.make_love(man) -----解决问题 抽象出对象,对象执行动作 。

当然,你面试的时候,你不要做make_love …你可以说是打牌 。

面向过程就是 打牌 (你,我,他)

面向对象就是 我.打牌(你,他) or 你.打牌(我,他) or 他.打牌(我,你)

https://blog.csdn.net/qiang510939237/article/details/88751224)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zZL9pGts-1663747806831)(java.assets/image-20210831152107683.png)]

IDE就是编译器

对象创建的5种方式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QkjAEHjy-1663747806832)(java.assets\image-20220613191111755.png)]

https://cloud.tencent.com/developer/article/1497720

继承extend

黑马程序员全套Java教程_Java基础入门教程,零基础小白自学Java必备教程_哔哩哔哩_bilibili

1.1 继承概述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NeX4M8Mt-1663747806836)(java.assets/image-20210716133150883.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1NrFHzm2-1663747806836)(java.assets/image-20210716133321039.png)]

继承就是提取出多个类中共有的属性和方法,然后提取,作为父类。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vEv3PidC-1663747806837)(java.assets/image-20210716133402701.png)]

面向对象三大特征:封装、继承、多态。

面向对象的三大基本特征,五大基本原则 - 风之之 - 博客园 (cnblogs.com)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CJvRIUG1-1663747806837)(java.assets/image-20210716133437512.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-25cXnsu4-1663747806837)(java.assets/image-20210716133644804.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XI7KQefT-1663747806838)(java.assets/image-20210716133635231.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g3GMmdqO-1663747806838)(java.assets/image-20210716133728936.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fZWtd3Gw-1663747806838)(java.assets/image-20210804003259641.png)]

重写父类方法,需要加override

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4Jnxuyt4-1663747806839)(java.assets/image-20210804003412604.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1cBo6dMJ-1663747806839)(java.assets/image-20210804003423094.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wDKnTLpS-1663747806839)(java.assets/image-20210716133743670.png)]

1.2 继承的好处和弊端

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h5T46o24-1663747806839)(java.assets/image-20210716133945350.png)]

【继承的好处】:

  • 使子类具有父类的属性和方法,还可以在子类中重新定义,追加方法和属性

  • 子类在访问成员方法和变量的时候,都是一样的顺序,先找子类,再找父类

  • 子类重写父类方法的时候,需要加@Override

  • 子类根本不可能重写父类的私有方法。

  • 子类不可以多继承,但是可以多层继承。

  • 比如儿子继承父亲,父亲继承爷爷,即儿子拥有爷爷属性

1.3 继承中【变量】的访问特点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5UUGUnFT-1663747806840)(java.assets/image-20210716134318759.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ot3WadWU-1663747806840)(java.assets/image-20210716134418973.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Cf1Q9MpF-1663747806840)(java.assets/image-20210716134513863.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N2FwAACn-1663747806841)(java.assets/image-20210716134555464.png)]

换个写法:

package demo;

class FU{
    //年龄
    public int age=40;
}
class ZI extends FU{
    public int height = 175;
    public int age=20;
    public void show(){
        int age=30;
        System.out.println(age);
        System.out.println(height);
    }
}

public class DEMO {
    public static void main(String[] args) {
        ZI Z=new ZI();
        Z.show();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u6xcMUOz-1663747806841)(java.assets/image-20210804103130421.png)]

1.4 super

this代表的本类的成员变量的访问

super可以访问父类中的成员变量

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fbJmoAFL-1663747806841)(java.assets/image-20210716135036570.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JIwEGOCo-1663747806842)(java.assets/image-20210804103900423.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-olaDO4xJ-1663747806842)(java.assets/image-20210804103910976.png)]

this关键字

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F7g8eDjG-1663747806842)(java.assets/image-20210716135302619.png)]

1.5 继承中构造方法的访问特点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PtUqCLU9-1663747806843)(java.assets/image-20210716140125577.png)]

父类:

package com.itheima_04;

public class Fu {

    /*
    public Fu() {
        System.out.println("Fu中无参构造方法被调用");
    }
    */

    public Fu() {}

    public Fu(int age) {
        System.out.println("Fu中带参构造方法被调用");
    }

}

子类:

package com.itheima_04;

public class Zi extends Fu {

    public Zi() {
//        super();  这个是默认会有的
//        super(20);
        System.out.println("Zi中无参构造方法被调用");
    }

    public Zi(int age) {
//        super();
//        super(20);
        System.out.println("Zi中带参构造方法被调用");
    }

}

测试类

package com.itheima_04;
/*
    测试类
*/
public class Demo {
    public static void main(String[] args) {
        //创建对象
        Zi z = new Zi();
        Zi z2 = new Zi(20);
    }
}

1.6 继承中【成员方法】的访问特点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NzECNN4P-1663747806843)(java.assets/image-20210716140536275.png)]

父类:

package com.itheima_05;

public class Fu {

    public void show() {
        System.out.println("Fu中show()方法被调用");
    }

}

子类:

package com.itheima_05;

public class Zi extends Fu {

    public void method() {
        System.out.println("Zi中method()方法被调用");
    }

    public void show() {
        super.show();
        System.out.println("Zi中show()方法被调用");
    }
}

测试类:

package com.itheima_05;

/*
    测试类
 */
public class Demo {
    public static void main(String[] args) {
        //创建对象,调用方法
        Zi z = new Zi();
        z.method();
        z.show();
        //报错
//        z.test();
    }
}

1.7 super内存图

链接:内存过程讲解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G4puhLiO-1663747806843)(java.assets/image-20210716140800699.png)]

1.8 方法重写(添加@Override)

package com.itheima_06;

/*
    手机类
 */

public class Phone {
    public void call(String name) {
        System.out.println("给" + name + "打电话");
    }
}

重写父类方法的时候,很容易把方法写错,为了帮助大家检验这个东西,添加@Override,这个说明,下面的内容是重写的父类,这个注解,可以帮助我们了解方法声明的准确性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3zpqoD1e-1663747806843)(java.assets/image-20210716141916000.png)]

package com.itheima_06;

/*
    新手机
 */
public class NewPhone extends Phone {

    /*
    public void call(String name) {
        System.out.println("开启视频功能");
//        System.out.println("给" + name + "打电话");
        super.call(name);
    }
    */

    @Override
    public void call(String name) {
        System.out.println("开启视频功能");
//        System.out.println("给" + name + "打电话");
        super.call(name);
    }

}

package com.itheima_06;
/*
    测试类
 */
public class PhoneDemo {
    public static void main(String[] args) {
        //创建对象,调用方法
        Phone p = new Phone();
        p.call("林青霞");
        System.out.println("--------");

        NewPhone np = new NewPhone();
        np.call("林青霞");
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AZI7pvcl-1663747806844)(java.assets/image-20210716142019150.png)]

1.9 方法重写的注意事项

子类根本不可能重写父类的私有方法。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZKNAInRa-1663747806844)(java.assets/image-20210716142649184.png)]

也就是说,如果父类是“默认”,那么子类就得用public

package com.itheima_07;

public class Fu {

    private void show() {
        System.out.println("Fu中show()方法被调用");
    }

    /*
    public void method() {
        System.out.println("Fu中method()方法被调用");
    }
    */

    void method() {
        System.out.println("Fu中method()方法被调用");
    }
}
package com.itheima_07;

public class Zi extends Fu {

    /*
    @Override
    private void show() {
        System.out.println("Zi中show()方法被调用");
    }
    */
    /*
    @Override
    public void method() {
        System.out.println("Zi中method()方法被调用");
    }
    */
    @Override
    public void method() {
        System.out.println("Zi中method()方法被调用");
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7rAqJy86-1663747806844)(java.assets/image-20210716142738544.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TEFqnJaI-1663747806845)(java.assets/image-20210716142812340.png)]

1.10 Java中【继承的注意事项】

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dEUDXLPr-1663747806845)(java.assets/image-20210716142925606.png)]

但是可以多层继承。

比如儿子继承父亲,父亲继承爷爷,即儿子拥有爷爷属性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ufCCdd8R-1663747806845)(java.assets/image-20210716143059711.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aBGIBglN-1663747806845)(java.assets/image-20210716143133359.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fFCHOfaX-1663747806846)(java.assets/image-20210716143141981.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l0iO8dMh-1663747806846)(java.assets/image-20210716143156744.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-srJRi7EL-1663747806846)(java.assets/image-20210716143213776.png)]

extend继承,创建一个类的子类

implement是实现,可以实现多个接口

extends与implements的不同

extends是继承父类,只要那个类不是声明为final或者那个类定义为abstract的就能继承,也可以调用父类初始化 this.parent()。而且会覆盖父类定义的变量或者函数。这样的好处是:架构师定义好接口(这里的接口是指父类的成员函数和变量),让工程师实现就可以了。整个项目开发效率和开发成本大大降低。

JAVA中不支持多重继承,但是可以用接口来实现,这样就要用到implements,继承只能继承一个类,但implements可以实现多个接口,用逗号分开就行了。实现父类,子类不可以覆盖父类的方法或者变量。即使子类定义与父类相同的变量或者函数,也会被父类取代掉。

格式:

class A extends B implements C,D,E

一个类通过关键字implements声明自己使用一个或者多个接口。

在类的声明中,通过关键字extends来创建一个类的子类。

class 子类名 extends 父类名 implenments 接口名

{…

}

若同时用到 extends 和 implements 的时候,extends 必须放在 implements 关键字之前。

说的很好:

Java 继承 | 菜鸟教程 (runoob.com)

java只能单继承,不能多继承

1、为什么使用继承

从已有的类派生出新的类,称为继承。

在不同的类中也可能会有共同的特征和动作,可以把这些共同的特征和动作放在一个类中,让其它类共享

因此可以定义一个通用类,然后将其扩展为其它多个特定类,这些特定类继承通用类中的特征和动作。

继承是 Java 中实现软件重用的重要手段,避免重复,易于维护,易于理解

super 关键字

super 表示使用它的类的父类。super 可用于:

  • 调用父类的构造方法;
  • 调用父类的方法(子类覆盖了父类的方法时);
  • 访问父类的数据域(可以这样用但没有必要这样用)。

调用父类的构造方法语法:

super();  

或   

super(参数列表);

注意:super 语句必须是子类构造方法的第一条语句。不能在子类中使用父类构造方法名来调用父类构造方法。 父类的构造方法不被子类继承。调用父类的构造方法的唯一途径是使用 super 关键字,如果子类中没显式调用,则编译器自动将 super(); 作为子类构造方法的第一条语句。这会形成一个构造方法链。

静态方法中不能使用 super 关键字。

调用父类的方法语法:

super.方法名(参数列表);

如果是继承的方法,是没有必要使用 super 来调用,直接即可调用。但如果子类覆盖或重写了父类的方法,则只有使用 super 才能在子类中调用父类中的被重写的方法。

implements关键字

使用 implements 关键字可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)。

this 和super的区别

this 代表本类对应的引用

Super 代表父亲存储空间的标识(可以理解为父亲引用)可以操作父亲 的成员

使用方法:

A:调用成员变量

·this.成员变量 调用本类的成员变量

·super.成员变量 调用父类的成员变量

B:调用构造方法

·this(…) 调用本类的成员变量

·Super(…)调用父类的成员变量

C:调用成员方法

·this.成员方法 调用本类的成员方法

·super.成员方法 调用父类的成员方法

继承:

public class zi extends fu{

//重写父类方法

}

多态

1.1 多态概述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zi5qHjzv-1663747806847)(java.assets/image-20210722130822704.png)]

package com.itheima_01;

public class Animal {

    public void eat() {
        System.out.println("动物吃东西");
    }
}
package com.itheima_01;

public class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
package com.itheima_01;
/*
    多态:
        同一个对象,在不同时刻表现出来的不同形态

    举例:猫
        我们可以说猫是猫:猫 cat = new 猫();
        我们也可以说猫是动物:动物 animal = new 猫();
        这里猫在不同的时刻表现出来了不同的形态,(猫既是猫,也是动物)这就是多态

    多态的前提和体现
        有继承/实现关系
        有方法重写
        有父类引用指向子类对象
 */
public class AnimalDemo {
    public static void main(String[] args) {
        //有父类引用指向子类对象
        Animal a = new Cat();	//这就体现出多态了
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qQy9TeWn-1663747806847)(java.assets/image-20210804111331187.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fdkE9PJf-1663747806847)(java.assets/image-20210804111342875.png)]

1.2 多态中成员访问特点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u4QDfTw1-1663747806847)(java.assets/image-20210722131945402.png)]

package com.itheima_02;

public class Animal {

    public int age = 40;

    public void eat() {
        System.out.println("动物吃东西");
    }

}

package com.itheima_02;

public class Cat extends Animal {

    public int age = 20;
    public int weight = 10;

    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }

    public void playGame() {
        System.out.println("猫捉迷藏");
    }

}

package com.itheima_02;

/*
    测试类
 */
public class AnimalDemo {
    public static void main(String[] args) {
        //有父类引用指向子类对象
        Animal a = new Cat();

        System.out.println(a.age);
//        System.out.println(a.weight);

        a.eat();
//        a.playGame();	这个不能调用,会报错

    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1psy6AtB-1663747806848)(java.assets/image-20210804112209386.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2rUk5uPb-1663747806848)(java.assets/image-20210804112241153.png)]

这就引出了,接下来的多态的好处和弊端了

1.3 多态的好处和弊端

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lKmIh2hu-1663747806848)(java.assets/image-20210722132828917.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9N7aEYZd-1663747806848)(java.assets/image-20210722135404586.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SItFBBMH-1663747806849)(java.assets/image-20210722135515202.png)]

其实也是多继承

package com.itheima_03;

public class Animal {

    public void eat() {
        System.out.println("动物吃东西");
    }

}

package com.itheima_03;

/*
    测试类
 */
public class AnimalDemo {
    public static void main(String[] args) {
        //创建动物操作类的对象,调用方法
        AnimalOperator ao = new AnimalOperator();
        Cat c = new Cat();
        ao.useAnimal(c);


        Dog d = new Dog();
        ao.useAnimal(d);


        Pig p = new Pig();
        ao.useAnimal(p);

    }
}

package com.itheima_03;

/*
    动物操作类
 */
public class AnimalOperator {

    /*
    public void useAnimal(Cat c) { //Cat c = new Cat();
        c.eat();
    }

    public void useAnimal(Dog d) { //Dog d = new Dog();
        d.eat();
    }
    */

    public void useAnimal(Animal a) {
        //Animal a = new Cat();
        //Animal a = new Dog();

        a.eat();
//        a.lookDoor();
    }


}

package com.itheima_03;

public class Cat extends Animal {

    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }

}

package com.itheima_03;

public class Dog extends Animal {

    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }

    public void lookDoor() {
        System.out.println("狗看门");
    }

}

package com.itheima_03;

public class Pig extends Animal {

    @Override
    public void eat() {
        System.out.println("猪吃白菜");
    }
}

1.4 多态中的转型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tbTvnehR-1663747806849)(java.assets/image-20210722141145777.png)]

这个可以帮助我们实现使用子类的特有功能

多态中访问成员方法,编译看左边,访问看右边

package com.itheima_04;

public class Animal {

    public void eat() {
        System.out.println("动物吃东西");
    }
}
package com.itheima_04;

/*
    向上转型
        从子到父
        父类引用指向子类对象

    向下转型
        从父到子
        父类引用转为子类对象
 */
public class AnimalDemo {
    public static void main(String[] args) {
        //多态
        Animal a = new Cat(); //向上转型
        a.eat();
//        a.playGame();

        /*
        //创建Cat类的对象
        Cat c = new Cat();
        c.eat();
        c.playGame();
        */

        //向下转型
        Cat c = (Cat)a;
        c.eat();
        c.playGame();
    }
}

package com.itheima_04;

public class Cat extends Animal {

    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }

    public void playGame() {
        System.out.println("猫捉迷藏");
    }

}

1.5 多态转型内存图解

多态转型内存图解(对于这种堆和栈,建议看视频)

案例:多态版猫和狗

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z1j5eU5J-1663747806849)(java.assets/image-20210722141946509.png)]

package com.itheima_06;

public class Animal {
    private String name;
    private int age;

    public Animal() {
    }

    public Animal(String name, int age) {
        this.name = name;
        this.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;
    }

    public void eat() {
        System.out.println("动物吃东西");
    }
}


package com.itheima_06;

/*
    测试类
 */
public class AnimalDemo {
    public static void main(String[] args) {
        //创建猫类对象进行测试
        Animal a = new Cat();
        a.setName("加菲");
        a.setAge(5);
        System.out.println(a.getName() + "," + a.getAge());
        a.eat();

        a = new Cat("加菲", 5);
        System.out.println(a.getName() + "," + a.getAge());
        a.eat();

    }
}

package com.itheima_06;

public class Cat extends Animal {

    public Cat() {
    }

    public Cat(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

package com.itheima_06;

public class Dog extends Animal {

    public Dog() {
    }

    public Dog(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-li1GOkcO-1663747806849)(java.assets/image-20210724110410955.png)]

抽象类

1.1 抽象类概述

我们不应该在动物类中给出eat方法的实现,而是应该只给出方法体

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NDwZlvGm-1663747806849)(java.assets/image-20210727154032011.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d73uzFJB-1663747806850)(java.assets/image-20210727154707886.png)]

package com.itheima_01;

public abstract class Animal {

    /*
    public void eat() {
        System.out.println("吃东西");
    }
    */

    public abstract void eat();
//没有方法体
}

package com.itheima_01;

/*
    测试类
 */
public class AnimalDemo {

    public static void main(String[] args) {
        /*
        Animal a = new Animal();	//抽象类不能创建对象
        a.eat();
        */
    }
    

}

1.2 抽象类的特点

抽象类参照多态的形式创建对象,既然是多态,那么就要有继承,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VncQjsWT-1663747806850)(java.assets/image-20210727155345431.png)]

package com.itheima_02;
/*
    抽象类
 */
public abstract class Animal {
    //抽象方法
    public abstract void eat();

    public void sleep() {
        System.out.println("睡觉");
    }
}
package com.itheima_02;

public class Cat extends Animal {

    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

package com.itheima_02;

public abstract class Dog extends Animal {

}

package com.itheima_02;

/*
    测试类
 */
public class AnimalDemo {
    public static void main(String[] args) {
//        Animal a = new Animal();
        Animal a = new Cat();
        a.eat();
        a.sleep();
    }
}
	

1.3 抽象类的成员特点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P3nXAY95-1663747806850)(java.assets/image-20210727160853553.png)]

package com.itheima_03;

/*
    抽象类
 */
public abstract class Animal {

    private int age = 20;
    private final String city = "北京";

    public Animal() {}

    public Animal(int age) {
        this.age = age;
    }


    public void show() {
        age = 40;
        System.out.println(age);
//        city = "上海";
        System.out.println(city);
    }

    public abstract void eat();

}

package com.itheima_03;

public class Cat extends Animal {

    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

package com.itheima_03;

/*
    测试类
 */
public class AnimalDemo {
    public static void main(String[] args) {
        Animal a = new Cat();
        a.eat();
        a.show();
    }
}

案例:抽象类版猫和狗

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gWYn0bSS-1663747806850)(java.assets/image-20210727161251567.png)]

package com.itheima_04;

public abstract class Animal {
    private String name;
    private int age;

    public Animal() {
    }

    public Animal(String name, int age) {
        this.name = name;
        this.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;
    }

    public abstract void eat();
}

package com.itheima_04;
/*
    测试类
 */
public class AnimalDemo {
    public static void main(String[] args) {
        //创建对象,按照多态的方式
        Animal a = new Cat();
        a.setName("加菲");
        a.setAge(5);
        System.out.println(a.getName()+","+a.getAge());
        a.eat();
        System.out.println("--------");

        a = new Cat("加菲",5);
        System.out.println(a.getName()+","+a.getAge());
        a.eat();4
    }
}

package com.itheima_04;

public class Cat extends Animal {

    public Cat() {
    }

    public Cat(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
package com.itheima_04;

public class Dog extends Animal {

    public Dog() {
    }

    public Dog(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
}

接口

1.1 接口概述

生活中接口是一种公共的规范,只要符合该规范,都可以使用,比如说墙上的插孔。

Java的接口更多的体现在对行为的抽象,接口的实例化,采用多态的形式,抽象类可以不重写

1.2 接口的特点

接口
1.1 接口概述
生活中接口是一种公共的规范,只要符合该规范,都可以使用,比如说墙上的插孔。Java的接口更多的体现在对行为的抽象,
接口的实例化:采用多态的形式,抽象类可以不重写接口。
比如说,运动(接口),打篮球、游泳、跑步,这些是(接口中的方法)
1,接口用关键字interface修饰
2,接口的实现用implements表示
3,接口不能实例化
可以使用多态的形式实现接口的实例化(接口的引用指向实现类的对象),但是不常用
常用的:使用接口的实现类来使用接口方法
4,接口的实现类
要么重写接口中的所有抽象方法
要么是抽象类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4AbLmTTn-1663747806851)(java.assets/image-20210720094131488.png)]

定义一个接口

package com.itheima_01;
/*
    定义了一个接口
 */
public interface Jumpping {
    //定义了一个抽象方法
    public abstract void jump();
}

实现接口

package com.itheima_01;

//类实现接口
public class Cat implements Jumpping {
    @Override
    public void jump() {
        System.out.println("猫可以跳高了");
    }
}

这个是不想重写jupping中的方法,那么就要继续用abstract关键字,然后这个类就变成了抽象类,抽闲类在实现接口的时候,可以不重写方法,但是其子类在继承的时候,还是要重写接口中的方法

package com.itheima_01;

public abstract class Dog implements Jumpping {
//如果实现类不想重写jupping中的方法,那么就使用abstract关键字,那么这个类就变成了抽象类,抽象类在实现接口的时候,可以不重写方法,但是其子类在继承的时候,还是要重写接口中的方法
}

测试类,就是用多态的方式,进行实例化,然后

package com.itheima_01;
/*
    测试类
 */
public class JumppingDemo {
    public static void main(String[] args) {
//      Jumpping j = new Jumpping();  //接口不能这样被实例化
        Jumpping j = new Cat(); //采用多态的方式进行实例化,使用他的实现类对象,进行实例化
       //Cat j = new Cat(); 	//这样也可以
        j.jump();
    }
}

1.3 接口的成员特点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Rj6jWR2L-1663747806851)(java.assets/image-20210727164858726.png)]

接口里面没有成员变量,默认是常量,因为成员变量被final修饰,所以只有常量

接口中的变量是常量

//接口里面不能有构造方法,因为接口主要是对行为进行抽象

所有的类都直接或者间接继承Object类,如果说一个类没有父类,那么object类就是其父类

如果说一个类有父类,那么 这个类就间接的继承Object类

接口继承自object类。

如果一个函数参数是接口类型,那么需要传递一个接口的实现对象,

Java中,接口是否继承自Object?_importGuitar的博客-CSDN博客_接口继承了object类吗

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NoHruuzG-1663747806851)(java.assets/image-20210727164430458.png)]

因为Object就只有这一个构造方法,所以说,所有的构造方法,默认访问父类的都是无参构造,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8MGnT4T8-1663747806851)(java.assets/image-20210727164659177.png)]

案例:接口版猫和狗

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FdxBAjRH-1663747806852)(java.assets/image-20210727165120664.png)]

1.4 类和接口的关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9sjI5Xm3-1663747806852)(java.assets/image-20210728001429795.png)]

1.5 抽象类和接口的区别

黑马程序员全套Java教程_Java基础入门教程,零基础小白自学Java必备教程_哔哩哔哩_bilibili

抽象类和接口的区别_dd_Mr的博客-CSDN博客

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cl8qPh0S-1663747806852)(java.assets/image-20210728221955650.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nQ91KhD1-1663747806852)(java.assets/image-20210728222058063.png)]

当添加报警器后,但不是所有门都有报警器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y8kKXL5q-1663747806853)(java.assets/image-20210728222151212.png)]

所以说,将接口和抽象类结合起来

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3fwqC3gt-1663747806853)(java.assets/image-20210728223539120.png)]

案例:运动员和教练

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rBPtd10T-1663747806853)(java.assets/image-20210728231211680.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TOqCv9Q3-1663747806853)(java.assets/image-20210728231430878.png)]

这个案例用了9个文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GBu3sRdy-1663747806854)(java.assets/image-20210729004138643.png)]

1 形参和返回值【参数传递】

1.1 类名作为形参和返回值

基本数据类型作为形参和返回值就不讨论了,

主要讨论的是引用类型作为形参和返回值,类,抽象类,接口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EeSCqMxm-1663747806854)(java.assets/image-20210729005910150.png)]

1、类名作为方法的形参

方法的形参是类名,其实需要的是该类的对象

实际传递的是该对象的【地址值】

2、类名作为方法的返回值

方法的返回值是类名,其实返回的是该类的对象

实际传递的,也是该对象的【地址值】

package itheima;

class Cat{
    public void eat(){
        System.out.println("猫吃鱼");
    }
}
class CatOperator{
    public void useCat(Cat c){   //Cat c = new Cat();
        c.eat();
    }
    public Cat getCat(){
        Cat c=new Cat();
        return c;
    }
}

public class CatDemo {
    public static void main(String[] args) {
        //创建操作类对象,并调用方法
        CatOperator co=new CatOperator();
        Cat c=new Cat();
        co.useCat(c);
        Cat c2= co.getCat();    //new Cat()
        c2.eat();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-69KnA3vX-1663747806854)(java.assets/image-20210729145729480.png)]

1.2 抽象类名作为形参和返回值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3RiXm4NX-1663747806854)(java.assets/image-20210729010022093.png)]

package itheima2;
//抽象动物类,并创建吃的方法
abstract class Animal{
    public abstract void eat();
}

class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

class AnimalOperator{
    public void useAnimal(Animal a){
        //Animal a = new Cat(); 抽象类名作为参数时,需要的是子类作为实参数
        a.eat();
    }

    public Animal getAnimal(){
        Animal a=new Cat();
        return a;
    }
}

public class AnimalDemo {
    public static void main(String[] args) {
        AnimalOperator ao=new AnimalOperator();
        Animal a=new Cat();     //编译看左边,执行看右边
        ao.useAnimal(a);

        Animal a2 = ao.getAnimal(); //new Cat();    这个返回的是个猫对象,如果想要调用吃,那么就得调用猫
        a2.eat();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R2ISMtim-1663747806854)(java.assets/image-20210729151711939.png)]

1.3 接口名作为形参和返回值(理解)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N41kS2Rg-1663747806855)(java.assets/image-20210729162313148.png)]

package itheima3;

//接口中的成员方法,只能是抽样方法
//public interface Jumpping{
interface Jumpping{
//    public abstract void jump();  //默认修饰符
    void jump();
}

class JumppingOperator{
    public void useJumpping(Jumpping j){
        //形参是个接口,然后这个接口的j可以调用方法jump(),说明这个j是个对象,而接口是不能直接实例化的
        //所以这是按照多态的形式创建的对象,要的是该接口的实现类对象 ,从而有了下面的cat类,用来实现这个接口
        j.jump();
    }
    public Jumpping getJumpping(){
        Jumpping j=new Cat();       //多态的形式创建对象
        return j;   //接口不能实例化,所以,返回的是实现类的 对象
    }
}

class Cat implements Jumpping{
    @Override
    public void jump() {
        System.out.println("猫可以跳高");
    }
}

//接口作为形参和返回值
public class JumppingDemo {
    public static void main(String[] args) {
        //创建操作类对象,并调用方法
        JumppingOperator jo=new JumppingOperator();
        Jumpping j=new Cat();       //多态的形式创建对象
        jo.useJumpping(j);
        Jumpping j2=jo.getJumpping();   //new Cat()
        j2.jump();
    }
}


2 内部类

2.1 内部类的基本使用(理解)

生活中案例:比如笔记本和cpu,笔记本看作是外部类,cpu看作是内部类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7i7Ihdt3-1663747806855)(java.assets/image-20210730111627708.png)]

/*
    内部类访问特点: 内部类可以直接访问外部类的成员,包括私有
    外部类要访问内部类的成员,必须创建对象
*/
public class Outer {
    private int num=10;
    //内部类
    public class Inner{
        public void show(){
            System.out.println(num);    //内部类可以直接访问外部类的成员,包括私有
            System.out.println("内部类的函数");
        }
    }
    public void method(){
        Inner i=new Inner();
        i.show();           // 外部类要访问内部类的成员,必须创建对象
    }
package itheima4;
/*
    内部类访问特点: 内部类可以直接访问外部类的成员,包括私有
    外部类要访问内部类的成员,必须创建对象
*/
public class Outer {
    private int num=10;
    //内部类
    public class Inner{
        public void show(){
            System.out.println(num);    //内部类可以直接访问外部类的成员,包括私有
            System.out.println("内部类的函数");
        }
    }
    public void method(){
        Inner i=new Inner();
        i.show();           // 外部类要访问内部类的成员,必须创建对象
    }
    public static void main(String[] args) {
        Outer o =new Outer();
        o.method(); //通过外部类调用内部类的函数
                     //可不可以直接通过内部类调用内部类的函数呢,可以
        Outer myOuter = new Outer();
        Outer.Inner myInner = myOuter.new Inner();
        System.out.println("-------");
        myInner.show();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NudcxBhl-1663747806855)(java.assets/image-20210730111513881.png)]

2.2 成员内部类(理解)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qGjJwOMq-1663747806855)(java.assets/image-20210730221003757.png)]

成员内部类:是类的成员

局部内部类:就是指在类的方法里面的类

class Outer{
    private int num=10;
    public class Inner{            //成员内部类
        public void show(){
            System.out.println(num);
        }
    }
}

public class InnerDemo {
    public static void main(String[] args) {
        Outer.Inner inner=new Outer().new Inner();
        inner.show();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-71bDPCm0-1663747806856)(java.assets/image-20210730220013800.png)]

上面的例子,一般来说,是不常见的,因为定义内部类的目的就是为了不让外面轻而易举的看到,所以一般用private修饰内部类,而不用public

一般采用,创建一个外部类方法,然后该方法会创建一个内部类对象,然后用这个方法来调用内部类对象

package itheima6;

class Outer{
    int a=10;
    private class Inner{
        public void show(){
            System.out.println(a);
        }
    }
    public void method(){
        Inner inner=new Inner();
        inner.show();
    }
}
public class InnerDemo {
    public static void main(String[] args) {
        Outer outer=new Outer();
        outer.method();
    }
}

2.3 局部内部类(理解)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QDzZx9dS-1663747806856)(java.assets/image-20210730221259810.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WFKWG0ER-1663747806856)(java.assets/image-20210730222115391.png)]

package itheima6;

class Outer{
    private int num = 20;
    public void method(){
        int num2=20;
        class Inner{
            public void show(){
                System.out.println(num);
                System.out.println(num2);
            }
        }
        Inner i=new Inner();
        i.show();
    }
}

public class OuterDemo {
    public static void main(String[] args) {
        Outer outer=new Outer();
        outer.method();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6JaGSzZQ-1663747806856)(java.assets/image-20210730222341956.png)]

2.4 匿名内部类(应用)

我们的类是class开头,但是匿名内部类是new开头的

这个匿名内部类可以是一个类或者是一个接口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jlwbBUyJ-1663747806857)(java.assets/image-20210731094434707.png)]

匿名内部类,本质是匿名的对象,这个类是抽象类居多

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hpOmXbJU-1663747806857)(java.assets/image-20210731090324824.png)]

示例1

package itheima9;

interface Inter{
    void show();
}

class Outer {
    public void method(){
        //这就是一个匿名内部类
        new Inter(){
            @Override
            public void show() {
                System.out.println("匿名内部类");
            }
        };
    }
}
public class OuterDemo{
    public static void main(String[] args) {
        Outer o=new Outer();
        o.method();
    }
}

不会调用show方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TpFrWOWl-1663747806857)(java.assets/image-20210731095734229.png)]

package itheima9;

interface Inter{
    void show();
}

class Outer {
    public void method(){
        //这就是一个匿名内部类
        //这样写仅仅是一个对象
//        new Inter(){
//            @Override
//            public void show() {
//                System.out.println("匿名内部类");
//            }
//        };
//  这样写就是对象调用了方法
      /*  new Inter(){
            @Override
            public void show() {
                System.out.println("匿名内部类");
            }
        }.show();
        //调用两次,就再复制一份
		new Inter(){
            @Override
            public void show() {
                System.out.println("匿名内部类");
            }
        }.show();
      */
    //多次调用的方式    
         Inter i= new Inter(){       //按照多态的形式,这个对象Inter一定是接口的实现类对象或者或者是类的子类对象
            @Override
           public void show() {
                System.out.println("匿名内部类");
            }
        };
        i.show();   //编译看左边,执行看右边
        i.show();   //多次调用
        
    }
}
public class OuterDemo{
    public static void main(String[] args) {
        Outer o=new Outer();
        o.method();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VH3Jnacw-1663747806857)(java.assets/image-20210731100137352.png)]

2.5 匿名内部类在开发中的使用(应用)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P5dHjOBS-1663747806857)(java.assets/image-20210731101139957.png)]

如果一个方法的参数是接口名,那么他实际要的是接口的实现类对象,

可以省去一些不需要的对象

package itheima8;
/**
 * 跳高接口
 */
interface Jumpping{
    void jump();
}

/**
 * 实现接口
 */
class Cat implements Jumpping{
    @Override
    public void jump() {
        System.out.println("猫可以跳高");
    }
}

class Dog implements Jumpping{
    @Override
    public void jump() {
        System.out.println("狗可以跳高");
    }
}

/**
 * 接口操作类,里面有一个方法,方法的参数是接口名
 */
class JumppingOperator{
    public void method(Jumpping j){
        j.jump();
    }
}

public class JumppingDemo {
    public static void main(String[] args) {
        //需求:创建接口操作类对象,调用method方法
        JumppingOperator jo=new JumppingOperator();
        Jumpping j=new Cat();
        jo.method(j);

        Jumpping j2=new Dog();
        jo.method(j2);
        //。。。
        //如果有很多动物,那么就很冗余,匿名内部类可以很好的解决
        
        System.out.println("---------");

        //匿名内部类,可以简化操作
        jo.method(  //这个方法要的是一个接口,其实是接口的实现类对象,
                    //而匿名内部类的格式他的本质就是实现类对象,并且是实现了该接口的对象,

          new Jumpping() {      //这个就和猫完全没有关系,把猫删了也可,
              //所以,采用后面这两种形式,不需要多写两个类出来,

            @Override
            public void jump() {
                System.out.println("猫可以跳高");
            }
        }
        );
        jo.method(new Jumpping() {
            @Override
            public void jump() {
                System.out.println("狗可以跳高");
            }
        });
    }
}
package InnerClassDemo;

/**
 * 匿名内部类的本质,就是对接口或者类的实现或者继承
 * 1,定义一个接口,【对于接口来说,如果要实现接口,那么就要实现接口中的所有方法,这样对吗?】
 * 2,实现接口,创建小狗,小猫,实现接口中的方法
 * 3,接口操作类,创建,里面的参数是接口名
 */
interface Jumpping{
    public void jump();
}
class Dog implements Jumpping{
    @Override
    public void jump(){
        System.out.println("小狗跳");
    }
}
class Cat implements Jumpping{
    @Override
    public void jump() {
        System.out.println("小猫跳");
    }
}
class JumppingOperator{
    public void Operator(Jumpping j){
            j.jump();
    }
}
public class AnonymousInnerClass {
    public static void main(String[] args) {
        JumppingOperator jo = new JumppingOperator();
        //如果想要调用接口操作类的方法,就需要一个接口Jumpping的实现类,所以需要传递一个对象
        //但是这个对象可以用匿名内部类来实现,这样就不用频繁创建,狗,猫等对象
        Jumpping j=new Cat();
        Jumpping j1=new Dog();

        jo.Operator(j);
        jo.Operator(j1);

        /**
         * 匿名内部类本质上是对接口或者类的实现或者继承
         */

        jo.Operator(new Jumpping() {
            @Override
            public void jump() {
                System.out.println("匿名内部类之实现狗蹦");
            }
        });

        jo.Operator(new Jumpping() {
            @Override
            public void jump() {
                System.out.println("匿名内部类之实现猫跳");
            }
        });
    }
}

/**
 * 匿名内部类的好处:不用频繁创建类和对象,对于一些需要传值的东西,直接写即可。
 */

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5jEYqOvo-1663747806858)(java.assets/image-20210917180205982.png)]

String

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4YKE733Z-1663747806858)(java.assets/image-20210626222755435.png)]

package com.itheima_02;
/*
    String构造方法:
        public String():创建一个空白字符串对象,不含有任何内容
        public String(char[] chs):根据字符数组的内容,来创建字符串对象
        public String(byte[] bys):根据字节数组的内容,来创建字符串对象
        String s = “abc”;	直接赋值的方式创建字符串对象,内容就是abc
        推荐使用直接赋值的方式得到字符串对象
 */

public class StringDemo01 {
    public static void main(String[] args) {
        //public String():创建一个空白字符串对象,不含有任何内容
        String s1 = new String();
        System.out.println("s1:" + s1);
//输出:null
        //public String(char[] chs):根据字符数组的内容,来创建字符串对象
        char[] chs = {'a', 'b', 'c'};
        String s2 = new String(chs);
        System.out.println("s2:" + s2);
//输出abc
        //public String(byte[] bys):根据字节数组的内容,来创建字符串对象
        byte[] bys = {97, 98, 99};
        String s3 = new String(bys);
        System.out.println("s3:" + s3);
//输出:979899,猜错了,,,
        //String s = “abc”;	直接赋值的方式创建字符串对象,内容就是abc
        String s4 = "abc";
        System.out.println("s4:" + s4);
//输出:abc
    }
}

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MGjsTJr0-1663747806858)(java.assets/image-20210617160433634.png)]

2.1 String概述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DdBS2sKv-1663747806858)(java.assets/image-20210830170252454.png)]

2.3 string对象的特点:

1, [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lq0wKDkp-1663747806859)(java.assets/image-20210617160654718.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G5GSezRR-1663747806859)(java.assets/image-20210617160812795.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3OLhdWcE-1663747806859)(java.assets/image-20210617161129210.png)]

当执行结束,main方法就从栈内存消失

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kCg9VVMX-1663747806859)(java.assets/image-20210617161211649.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dpPJ2Zq1-1663747806860)(java.assets/image-20210617161346126.png)]

package com.itheima_02;

/*
    使用 == 做比较:
        基本类型:比较的是数据值是否相同
        引用类型:比较的是地址值是否相同

     public boolean equals​(Object anObject):
        将此字符串与指定对象进行比较。由于我们比较的是字符串对象,所以参数直接传递一个字符串
 */
public class StringDemo02 {
    public static void main(String[] args) {
        //构造方法的方式得到对象
        char[] chs = {'a', 'b', 'c'};
        String s1 = new String(chs);
        String s2 = new String(chs);

        //直接赋值的方式得到对象
        String s3 = "abc";
        String s4 = "abc";

        //比较字符串对象地址是否相同
        System.out.println(s1 == s2);
        System.out.println(s1 == s3);
        System.out.println(s3 == s4);
        System.out.println("--------");

        //比较字符串内容是否相同
        System.out.println(s1.equals(s2));
        System.out.println(s1.equals(s3));
        System.out.println(s3.equals(s4));
    }
}

3 StringBuilder

3.1 StringBuilder概述

可变的字符串容器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NPv53Bez-1663747806860)(java.assets/image-20210617163810431.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WOJO0X3l-1663747806860)(java.assets/image-20210617163835070.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eSc8lTjH-1663747806860)(java.assets/image-20210617163906138.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bCCcMAfG-1663747806861)(java.assets/image-20210617164023538.png)]

String和StringBuilder的区别:

  • String:内容是不可变的
  • StringBuilder:内容是可变的

3.2 StringBuilder构造方法:

/*
    StringBuilder构造方法:
        public StringBuilder():创建一个空白可变字符串对象,不含有任何内容
        public StringBuilder(String str):根据字符串的内容,来创建可变字符串对象
 */
public class StringBuilderDemo01 {
    public static void main(String[] args) {
        //public StringBuilder():创建一个空白可变字符串对象,不含有任何内容
        StringBuilder sb = new StringBuilder();
        System.out.println("sb:" + sb);		//空
        System.out.println("sb.length():" + sb.length());	//0

        //public StringBuilder(String str):根据字符串的内容,来创建可变字符串对象
        StringBuilder sb2 = new StringBuilder("hello");
        System.out.println("sb2:" + sb2);	//hello
        System.out.println("sb2.length():" + sb2.length());	//5
    }
}

3.3 StringBuilder 的添加和反转方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pqArvu14-1663747806861)(java.assets/image-20210618221006345.png)]

/*
    StringBuilder 的添加和反转方法
        public StringBuilder append(任意类型):添加数据,并返回对象本身
        public StringBuilder reverse():返回相反的字符序列
 */
public class StringBuilderDemo02 {
    public static void main(String[] args) {
        StringBuilder sb=new StringBuilder();
        StringBuilder sb2 = sb.append("hello");
        
        System.out.println("sb:"+sb);
        System.out.println("sb2:"+sb2);
        System.out.println(sb==sb2);
        
        //【因为append是添加对象,并返回对象本身,所以就不需要用另一个StringBuilder来接收了,所以下面那个是进阶
        
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bZzOp9iu-1663747806861)(java.assets/image-20210618222017857.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lA2JCQgp-1663747806861)(java.assets/image-20210618222359338.png)]

package com.itheima;

/*
    StringBuilder 的添加和反转方法
        public StringBuilder append(任意类型):添加数据,并返回对象本身
        public StringBuilder reverse():返回相反的字符序列
 */
public class StringBuilderDemo02 {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();
//        StringBuilder sb2 = sb.append("hello");
//        System.out.println("sb:"+sb);
//        System.out.println("sb2:"+sb2);
//        System.out.println(sb==sb2);
        sb.append("hello");
        sb.append("world");
        sb.append("100");
        System.out.println("sb:"+sb);   //sb:helloworld100

    }
}
public class StringBuilderDemo01 {
    public static void main(String[] args) {
        //创建对象
        StringBuilder sb = new StringBuilder();
//因为append方法返回的是对象本身,对象就可以调方法,所以,可以一直调用方法,即链式编程
        //链式编程
        sb.append("hello").append("world").append("java").append(100);
        System.out.println("sb:" + sb);

        //public StringBuilder reverse():返回相反的字符序列,直接把内容反转
        sb.reverse();
        System.out.println("sb:" + sb);
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EC7Bju6u-1663747806861)(java.assets/image-20210618223224200.png)]

3.4 StringBuilder和String相互转换

String不能直接使用append或者reserve,所以要把string转换成stringbuilder,然后再把stringbuilder转换成string

package com.itheima;

public class StringBuilderDemo03 {
    public static void main(String[] args) {
        //string转换成stringbuilder,通过构造方法实现。
        String s="hello";
        System.out.println(s);
        StringBuilder sb=new StringBuilder(s);
        sb.append("可以添加内容");
        //stringbuilder转换成string,通过tostring方法实现
        sb.toString();
        System.out.println(sb);
    }
}

3.5 案例:拼接字符串

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HTQRXbOm-1663747806862)(java.assets/image-20210619181320281.png)]

/*
    需求:
        定义一个方法,把 int 数组中的数据按照指定的格式拼接成一个字符串返回,调用该方法,并在控制台输出结果。
        例如,数组为int[] arr = {1,2,3}; ,执行方法后的输出结果为:[1, 2, 3]
    思路:
        1:定义一个 int 类型的数组,用静态初始化完成数组元素的初始化
        2:定义一个方法,用于把 int 数组中的数据按照指定格式拼接成一个字符串返回。
          返回值类型 String,参数列表 int[] arr
        3:在方法中用 StringBuilder 按照要求进行拼接,并把结果转成 String 返回
        4:调用方法,用一个变量接收结果
        5:输出结果
 */
public class StringBuilderDemo04 {
    public static void main(String[] args) {
        int[] arr={1,2,3};
        String a=arrayToString(arr);
        System.out.println(a);          //[1,2,3]
    }

    //定义一个方法,实现字符串反转。返回值类型 String,参数 String s
    /*
        两个明确:
            返回值类型:String
            参数:String s
     */
    public static String arrayToString(int[] arr){
        //在方法中用 StringBuilder 按照要求进行拼接,并把结果转成 String 返回
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for (int i=0;i<arr.length;i++){
            if (i==arr.length-1){
                sb.append(arr[i]);
            }else{
                sb.append(arr[i]).append(",");
            }
        }
        sb.append("]");
        String s=sb.toString();
        return s;
    }
}

3.6 字符串反转

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NGrllasD-1663747806862)(java.assets/image-20210619184605620.png)]

package com.itheima_03;

import java.util.Scanner;

/*
    需求:
        定义一个方法,实现字符串反转。键盘录入一个字符串,调用该方法后,在控制台输出结果
        例如,键盘录入abc,输出结果 cba

    思路:
        1:键盘录入一个字符串,用 Scanner 实现
        2:定义一个方法,实现字符串反转。返回值类型 String,参数 String s
        3:在方法中用StringBuilder实现字符串的反转,并把结果转成String返回
        4:调用方法,用一个变量接收结果
        5:输出结果
 */
public class StringBuilderTest02 {
    public static void main(String[] args) {
        //键盘录入一个字符串,用 Scanner 实现
        Scanner sc = new Scanner(System.in);

        System.out.println("请输入一个字符串:");
        String line = sc.nextLine();

        //调用方法,用一个变量接收结果
        String s = myReverse(line);

        //输出结果
        System.out.println("s:" + s);
    }

    //定义一个方法,实现字符串反转。返回值类型 String,参数 String s
    /*
        两个明确:
            返回值类型:String
            参数:String s
     */
    public static String myReverse(String s) {
        //在方法中用StringBuilder实现字符串的反转,并把结果转成String返回
        //String --- StringBuilder --- reverse() --- String
//        StringBuilder sb = new StringBuilder(s);
//        sb.reverse();
//        String ss = sb.toString();
//        return ss;

       return new StringBuilder(s).reverse().toString();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5GLyaJys-1663747806862)(java.assets/image-20210619210803741.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ETmBcope-1663747806862)(java.assets/image-20210619211109275.png)]

如果其他方法被使用到,要求会用帮助文档知道该方法如何使用

数组

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nCUD1eKv-1663747806863)(java.assets/image-20210906004542350.png)]

1 数组定义格式

1.1 数组概述

【精简:一次性声明大量用于存储数据的变量

要存储的数据通常是同类型数据,例如考试成绩】

1.2 什么是数组

数组(array)是一种用于存储多个相同类型数据的存储模型

1.3 数组的定义格式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8UPfDQjh-1663747806863)(java.assets/image-20210906005151015.png)]

2 数组初始化之动态初始化

2.1 数组初始化概述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-42sLRF7U-1663747806863)(java.assets/image-20210906005347342.png)]

分配【内存空间】和【赋值】

2.2 数组初始化方式

  • 动态初始化
  • 静态初始化

2.3 动态初始化

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EYglpSkb-1663747806863)(java.assets/image-20210906005511279.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ceVEOTwo-1663747806864)(C:\Users\菠萝啤\AppData\Roaming\Typora\typora-user-images\image-20220105175308020.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6OoyVI1y-1663747806864)(C:\Users\菠萝啤\AppData\Roaming\Typora\typora-user-images\image-20220105175350364.png)]

二维数组【动力节点】

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tq75odJz-1663747806864)(C:\Users\菠萝啤\AppData\Roaming\Typora\typora-user-images\image-20220105153735328.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YOMUECvD-1663747806864)(C:\Users\菠萝啤\AppData\Roaming\Typora\typora-user-images\image-20220105153746638.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pnnvkwxj-1663747806865)(C:\Users\菠萝啤\AppData\Roaming\Typora\typora-user-images\image-20220105153753643.png)]

二维数组的读和写没有看

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HoyxVfyy-1663747806865)(C:\Users\菠萝啤\AppData\Roaming\Typora\typora-user-images\image-20220105153816702.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AOWGCb9a-1663747806865)(C:\Users\菠萝啤\AppData\Roaming\Typora\typora-user-images\image-20220105153830015.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ATHfnWah-1663747806865)(java.assets/image-20220106012306863.png)]

array.length   	输出的结果是=3

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wMYAHk4w-1663747806865)(C:\Users\菠萝啤\AppData\Roaming\Typora\typora-user-images\image-20220105153840640.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tUyeAcD9-1663747806866)(C:\Users\菠萝啤\AppData\Roaming\Typora\typora-user-images\image-20220105153855670.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FiRXIH84-1663747806866)(C:\Users\菠萝啤\AppData\Roaming\Typora\typora-user-images\image-20220105153902910.png)]

用数组完成这道题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JTAR16FZ-1663747806866)(C:\Users\菠萝啤\AppData\Roaming\Typora\typora-user-images\image-20220105154801943.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NEosE5T3-1663747806866)(C:\Users\菠萝啤\AppData\Roaming\Typora\typora-user-images\image-20220105154814511.png)]

406,回顾数组

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2P1clvmv-1663747806867)(C:\Users\菠萝啤\AppData\Roaming\Typora\typora-user-images\image-20220105154912762.png)]

Java零基础教程视频(适合Java 0基础,Java初学入门)_哔哩哔哩_bilibili

p410 数组模拟栈数据结构

3 修饰符

3.4 final

状态修饰符

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-StfoORmW-1663747806867)(java.assets/image-20210617165210957.png)]

3.5 final修饰局部变量

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pqodgjk4-1663747806867)(java.assets/image-20210617165852204.png)]

static(静态)

static是一个修饰符,用于修饰类成员变量,方法,以及编写static代码块

static修饰成员方法,一般叫静态方法,不依赖于任何对象,可以直接访问,但是,对于静态方法,不能访问类的非静态成员变量和非静态成员方法,

因为非静态成员方法或者变量都必须依赖具体对象才能被调用。

但是要注意的是,虽然在

静态方法中不能访问非静态成员方法和非静态成员变量,

但是在非静态成员方法中是可以访问静态成员方法/变量的。

java 中 public,default,protected,private,final、static的区别_dd_Mr的博客-CSDN博客

正则表达式

1,判断功能

案例1

判断录入的手机号是否为13或者18开头

import java.util.Scanner;

public class RegexDm {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入手机好:");
        String s = sc.nextLine();
        String regex = "1[38]\\d{9}";//定义手机好规则
        boolean flag = s.matches(regex);//判断功能
        System.out.println("flag:"+flag);
    }
}

手机号是11位的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zBWDQzae-1663747806867)(java.assets/image-20220310210343285.png)]

表达式含义:

\d表示[0—9]
中括号[]:只有方括号里面指定的字符才参与匹配,也只能匹配单个字符。
{n}表示恰好n次

2,分割功能

import java.util.Scanner;

/**
 * @Author: 从南到北
 * @Date: 2022/03/10/21:00
 */

public class RegexDm1 {
    public static void main(String[] args){
        String age = "18-24";//定义年龄范围
        String regex = "-";
        String[] strArr = age.split(regex);//分割成字符串数组

        int startAge = Integer.parseInt(strArr[0]);
        int endAge = Integer.parseInt(strArr[1]);

        Scanner sc = new Scanner(System.in);
        System.out.println("请输入您的年龄:");
        int a = sc.nextInt();
        if (a >= startAge && a <= endAge){
            System.out.println("你就是我想找的");
        }else{
            System.out.println("滚");
        }
    }
}

3,替换功能

public class RegexDm {
    public static void main(String[] args){
        String s = "12342jasfkgnas234";
        //把字符串里面的数字替换成*
        String regex = "\\d";
        String ss = "*";
        String result = s.replaceAll(regex,ss);
        System.out.println(result);
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iHGztV9V-1663747806868)(java.assets/image-20220310211156882.png)]

校验qq号

import java.util.Scanner;

/**
 * @Author: 从南到北
 * @Date: 2022/03/10/21:15
 * 效验QQ号(要求:5-15位数字,0不能开头)
 */
public class RegexDm {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入您的QQ号码:");
        String qq = sc.nextLine();
        System.out.println("checkQQ:"+checkQQ(qq));
    }

    private static boolean checkQQ(String qq) {
        return qq.matches("[1-9]{1}\\d{4,14}");
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xp7BFlgU-1663747806868)(java.assets/image-20220310211820189.png)]

参考链接:

https://blog.csdn.net/weixin_43860260/article/details/91417485

MessageFormat类{占位符}

java中自定义使用{0}占位符功能之MessageFormat类

用于组装消息

​ java中自定义使用{0}占位符功能之MessageFormat类 - JavaShuo

java中{0}占位符的使用 - JavaShuo

MessageFormat类_sinat_41233888的博客-CSDN博客

MessageFormat类的用法 - 知乎 (zhihu.com)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CeliPpFZ-1663747806868)(java.assets/image-20220310223557625.png)]

集合

1 集合概述

因为数组的长度是固定的,不能随便改变,所以就出现了集合的概念

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S0EcNnTH-1663747806868)(java.assets/image-20210619211352889.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TFNNyybz-1663747806868)(java.assets/image-20210619211453470.png)]

package com.itheima;

import java.util.ArrayList;

public class ArrayListDemo01 {
    public static void main(String[] args) {
        ArrayList<String> array = new ArrayList<>();
        //public boolean add(E e):将指定的元素追加到此集合的末尾
        System.out.println(array.add("hello")); 	//添加成功,返回true
        //因为array.add()一定是成功的,所以就没有必要打印输出这句话
        System.out.println("打印输出结果:"+array);	//输出结果
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v1LL4HRZ-1663747806869)(java.assets/image-20220402124837857.png)]

package com.itheima;
import java.util.ArrayList;

/*
    ArrayList构造方法:
        public ArrayList():创建一个空的集合对象

    ArrayList添加方法:
        public boolean add(E e):将指定的元素追加到此集合的末尾
        public void add(int index,E element):在此集合中的指定位置插入指定的元素
 */
public class ArrayListDemo01 {
    public static void main(String[] args) {
        
         //public ArrayList():创建一个空的集合对象
		//ArrayList array = new ArrayList<>();
		//在使用泛型的时候要注意:
		//前后的泛型必须一致,或者后面的泛型可以省略不写(1.7的新特性菱形泛型)  
        
        ArrayList<String> array = new ArrayList<String>();

         //public boolean add(E e):将指定的元素追加到此集合的末尾
		//System.out.println(array.add("hello"));

        array.add("hello");
        array.add("world");
        array.add("java");

        //public void add(int index,E element):在此集合中的指定位置插入指定的元素
        array.add(1,"javase");  //原来的元素会往后以
//      array.add(3,"javaee");    //直接在后面添加

        //IndexOutOfBoundsException 集合索引越界
//        array.add(4,"javaee");    //报错
        //输出集合
         System.out.println("array集合结果:"+array);
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nG4sJk50-1663747806869)(java.assets/image-20220402125202823.png)]

ArrayList集合常用方法

ArrayList 插入和删除的效率真的不如 LinkedList?_流浪马龙的博客-CSDN博客

散列表就是hashset啊

散列表就是哈希表

ArrayList集合的扩容机制

https://blog.csdn.net/qq_45689630/article/details/106525874

ArrayList类是一个特殊的数组–动态数组。

​ 普通的数组是静态的,只有先确定了他的大小才能给它初始化赋值或者参与运算,而且这个大小一但初始化后是不能被修改的,所以当你刚开始不确定你要输入数据的多少时,普通的数组不容易实现(万一你输入的数据多于数组大小时,就会数组溢出,导致报错),为此java有了" 数组列表"(ArrayList)。

(小声bb:其实我感觉ArrayList,甚至是Java的整个集合类,都有与C++里的STL类似,所以有C++一些基础的同学们学这一部分应该会很轻松)

优点:

1、支持自动改变大小
2、可以灵活的插入删除元素

缺点:

比普通的数组的速度慢一些

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fj0xRAS3-1663747806869)(java.assets/image-20210619213122114-16488732794561.png)]

方法名 说明
add 增【在上一节】
remove
set 修改
get 查找
size() 返回大小
package com.itheima_01;

import java.util.ArrayList;

/*
    ArrayList常用方法:
        public boolean remove(Object o):删除指定的元素,返回删除是否成功
        public E remove(int index):删除指定索引处的元素,返回被删除的元素
        public E set(int index,E element):修改指定索引处的元素,返回被修改的元素
        public E get(int index):返回指定索引处的元素
        public int size():返回集合中的元素的个数
 */
public class ArrayListDemo02 {
    public static void main(String[] args) {
        //创建集合
        ArrayList<String> array = new ArrayList<String>();

        //添加元素
        array.add("hello");
        array.add("world");
        array.add("java");

        //public boolean remove(Object o):删除指定的元素,返回删除是否成功
//        System.out.println(array.remove("world"));
//        System.out.println(array.remove("javaee"));

        //public E remove(int index):删除指定索引处的元素,返回被删除的元素
//        System.out.println(array.remove(1));

        //IndexOutOfBoundsException
//        System.out.println(array.remove(3));

        //public E set(int index,E element):修改指定索引处的元素,返回被修改的元素
//        System.out.println(array.set(1,"javaee"));

        //IndexOutOfBoundsException
//        System.out.println(array.set(3,"javaee"));

        //public E get(int index):返回指定索引处的元素
//        System.out.println(array.get(0));
//        System.out.println(array.get(1));
//        System.out.println(array.get(2));
        //System.out.println(array.get(3)); //?????? 自己测试

        //public int size():返回集合中的元素的个数
        System.out.println(array.size());

        //输出集合
        System.out.println("array:" + array);
    }
}

2 集合进阶

  • Collection
  • List
  • Set
  • 泛型
  • Map
  • Collections

主要集合概述:

此图来自哪里

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I0LOueQb-1663747806869)(java.assets/image-20220112200914191.png)]

集合继承结构图_Collection 部分

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rQS3KPOb-1663747806870)(java.assets/image-20220111233422458.png)]

2.1 List集合概述和特点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iO27NdtC-1663747806870)(java.assets/image-20210708163132461.png)]

有序,是指的是有下标索引,从0开始

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

/**
 * @Author: 从南到北
 * @Date: 2022/01/11/15:40
 *    List集合特点
 *    有序:存储和取出的元素顺序一致
 *    可重复:存储的元素可以重复
 */

public class ListDemo01 {
    public static void main(String[] args) {
        //创建集合对象,List是一个接口,而ArrayList是List接口的一个实现类。 
        List<String> list = new ArrayList<String>();
        //添加元素
        list.add("hello");
        list.add("world");
        list.add("java");
        list.add("world");
        System.out.println("输出集合对象:");
        System.out.println(list);
        System.out.println("迭代器的方式遍历:");
        Iterator<String> it = list.iterator();
        while (it.hasNext()) {
            String s = it.next();
            System.out.print(s+",");
        }
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k5STFhQ1-1663747806870)(java.assets/image-20220111154448700.png)]

list是一个接口继承自Collection接口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tpwH6jlw-1663747806870)(java.assets/image-20210708164509151.png)]

List是一个接口,而ArrayList是List接口的一个实现类。

Java中List和ArrayList的区别 - 小赵小楠 - 博客园 (cnblogs.com)

2.2 List集合特有方法

视频链接:黑马 ---- List集合特有方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DtZq5G7A-1663747806871)(java.assets/image-20210708165010780.png)]

方法名 说明
void add() 直接在末尾插入元素
void add(int index,E element) 在此集合中的指定位置插入指定的元素
E remove(int index) 删除指定索引处的元素,返回被删除的元素
E set(int index,E element) 修改指定索引处的元素,返回被修改的元素
E get(int index) 返回指定索引处的元素

E是返回的结果类型

//测试set方法,
public class ListDemo1 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("world");
        list.add("java");
        list.add("world");
        System.out.println( list.set(3,"niu"));
        System.out.println("输出集合对象:"+list);
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-96KHwHcC-1663747806871)(java.assets/image-20220402132052781.png)]

注意:带索引操作的时候,常见的一个错误,索引越界!这个比较常见

案例:List集合存储学生对象并遍历

视频链接:

黑马程序员全套Java教程_Java基础入门视频教程,零基础小白自学Java必备教程_哔哩哔哩_bilibili

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Rz6PzT12-1663747806871)(java.assets/image-20220402132900151.png)]

学生类

package com.itheima_02;

public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {


        this.name = name;
        this.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;
    }
}

package com.itheima_02;

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

/*
    需求:
        创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合

    思路:
        1:定义学生类
        2:创建List集合对象
        3:创建学生对象
        4:把学生添加到集合
        5:遍历集合(迭代器方式,for循环方式)
 */
public class ListDemo {
    public static void main(String[] args) {
        //创建List集合对象
        List<Student> list = new ArrayList<Student>();

        //创建学生对象
        Student s1 = new Student("林青霞", 30);
        Student s2 = new Student("张曼玉", 35);
        Student s3 = new Student("王祖贤", 33);

        //把学生添加到集合
        list.add(s1);
        list.add(s2);
        list.add(s3);

        //迭代器方式
        Iterator<Student> it = list.iterator();
        while (it.hasNext()) {
            Student s = it.next();
            System.out.println(s.getName() + "," + s.getAge());
        }
        System.out.println("--------");

        //for循环方式
        for(int i=0; i<list.size(); i++) {
            Student s = list.get(i);
            System.out.println(s.getName() + "," + s.getAge());
        }

    }
}

2.3 并发修改异常

这个异常居然也可以在jdk文档中找到

因为这个异常继承runtimeException,所以,这个是运行时异常

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6H5Thjik-1663747806871)(java.assets/image-20220402134752402.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hcYBbAt9-1663747806871)(java.assets/image-20220402142122594.png)]

2.4 迭代器

ListIterator 列表迭代器

视频链接:ListIterator 列表迭代器

iterator、hasnext、next

[迭代器原理视频]https://www.bilibili.com/video/BV1pA411u7HD

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fg0tCerG-1663747806872)(java.assets/image-20220409144718205.png)]

小结:

Iterator iterator():创建迭代器对象,默认指向当前集合的0索引。

boolean hasNext():判断当前位置是否有元素可以被取出

E next(): 获取当前位置的元素

将迭代器对象移向下一个索引位置

控制台输入内容

这个是输入的源码,有空看一下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LImLhYS8-1663747806872)(java.assets/image-20220409145615833.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KEMhMiqX-1663747806872)(java.assets/image-20220409145541083.png)]

test111,练习,

  1. list的三种遍历方式、
  2. 迭代器、
  3. 控制的获取持续获取输入、

迭代器的3步骤和获取输入的3步骤,完全一样,

就是Hasnext、next:功能完全一样

package chat;

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

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: 从南到北
 * @Date: 04/12/2022/15:34
 * @Description:
 */
public class iteratorTet {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(4);
        list.add(1);
        list.add(43);
        list.add(42);
        list.add(34);
        //遍历集合,因为集合有下标,所以可以采用for,foreach,iterator
//        System.out.println("---------");
//        for (int i=0;i
//            System.out.println(list.get(i));
//        }
        System.out.println("-----------");
//        //2
        for(Integer a:list){
//        for(int a:list){    //foreach可以用包装类和基本数据类型
//            System.out.println(a);
//        }

        /**
         * 1,集合的迭代器,此时指向第一个元素,下标为0
         * 2,hasNext,用来判断是否有元素
         * 3,next,获取该元素,并指向下一个元素
         */
        //通过控制台输入内容来给集合赋值
        Scanner sc = new Scanner(System.in);    //获取输入的内容
//        boolean b = sc.hasNext();//判断是否有元素

//        list.add(i);
        //
        while(sc.hasNext()){

            int i = sc.nextInt();//获取到当前内容
            if (i==100){    //只要输入的不是100,那么就一直获取输入的内容
                break;
            }
            list.add(i);
        }

        //迭代器遍历3
        Iterator<Integer> it = list.iterator();
        while(it.hasNext()){
            Integer a = it.next();
            System.out.println(a);
        }

    }
}

2.5 增强for

集合的遍历,迭代器

增强for循环就是继承了iterator这个接口

其底层就是包装的迭代器

所以,collection体系的集合,都可以成为增强for的目标

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-szEfspbj-1663747806872)(java.assets/image-20220402153922919.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YnWs7ksA-1663747806873)(java.assets/image-20220402154114638.png)]

格式:for(ElementType element: arrayName){};

案例:

List<Integer> intList = new ArrayList<Integer>();
for (Integer i: intList) {
    System.out.print(i);
}

简化了数组和collection集合的遍历

以下代码抛出了并发修改异常,说明,其内部是迭代器原理

并发修改异常,看前两节课程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FKeA0GqT-1663747806873)(java.assets/image-20220402154632558.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7JjYtFWl-1663747806873)(java.assets/image-20220402154659664.png)]

总结:

相对于for(;;)而言 增强for循环有两个好处:

1.写起来简单

2.遍历集合、容器简单

Java Iterator(迭代器)_dd_Mr的博客-CSDN博客

Java增强for循环_dd_Mr的博客-CSDN博客

3种方式遍历集合list

参考链接:三种方式遍历集合对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SFrK4TLq-1663747806873)(java.assets/image-20220402155119156.png)]

学生类

package jihe;

/**
 * @Author: 从南到北
 * @Date: 2022/04/02/13:30
 */
public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {


        this.name = name;
        this.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;
    }
}

三种遍历方式:

package jihe;

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

/**
 * @Author: 从南到北
 * @Date: 2022/04/02/21:42
 * 三种遍历方式,遍历学生
 */
public class ListDemo2 {
    public static void main(String[] args) {
        //创建集合对象
        List<Student> list = new ArrayList<>();

        //创建学生对象
        Student s1 = new Student("大公",10);
        Student s2 = new Student("大诚",20);
        Student s3 = new Student("大勇",30);
        Student s4 = new Student("大毅",30);

        //把学生添加到集合
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s4);

        //迭代器,集合特有的遍历方式
        Iterator<Student> it = list.iterator();
        while(it.hasNext()){//当前元素是否有值
            Student s = it.next();
            System.out.println(s.getName()+","+s.getAge());
        }
        
        System.out.println("------------------");
        //普通for:带有索引的遍历方式
        for(int i=0;i<list.size();i++){
            Student s = list.get(i);
            System.out.println(s.getName()+","+s.getAge());
        }
        System.out.println("------------------");

        //增强for的方式:最方便的遍历方式,增强ford
        for (Student s:list){
            System.out.println(s.getName()+","+s.getAge());
        }
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ywQ0JKrA-1663747806874)(java.assets/image-20220402220246551.png)]

2.6 数据结构

​ 数据结构是计算机存储、组织数据的方式。是指相互之间存在一种或者多种特定关系的数据元素的集合,通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cCLAPBa2-1663747806874)(java.assets/image-20220402220726734.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KeFWE7bO-1663747806874)(java.assets/image-20220402220849336.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GjhNhpUl-1663747806875)(java.assets/image-20220402220917381.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kEYoSCBS-1663747806875)(java.assets/image-20220402221030565.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RB0JyaMm-1663747806875)(java.assets/image-20220402221047669.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nSUlumiT-1663747806875)(java.assets/image-20220402221221337.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FNtQE8iF-1663747806875)(java.assets/image-20220402221435833.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FobktdlN-1663747806876)(java.assets/image-20220402221536573.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4StaJ4yv-1663747806876)(java.assets/image-20220402221627799.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vdzgMyF2-1663747806876)(java.assets/image-20220402221724957.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UfbZ3T6a-1663747806876)(java.assets/image-20220402221737132.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f0RhMdKw-1663747806877)(java.assets/image-20220402221840417.png)]

3 Set

3.1 Set集合概述和特点

黑马程序员全套Java教程_Java基础入门视频教程,零基础小白自学Java必备教程_哔哩哔哩_bilibili

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0pcP3hUs-1663747806877)(java.assets/image-20210823153517500.png)]

所以,set集合最重要的应用,就是去重

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NK6C6YmQ-1663747806877)(java.assets/image-20210823150502207.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0lT556Sr-1663747806877)(java.assets/image-20210823150423951.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-di25169R-1663747806878)(java.assets/image-20210823153422553.png)]

3.2 哈希值

散列集-集合-CSDNJava技能树

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zMRM8x1w-1663747806878)(java.assets/image-20210823160139917.png)]

Object类有hashCode()这个方法,说明,所有的类都有hashCode()这个方法

字符串string重写了hashcode()方法

package com.itheima_02;

/*
    哈希值:
        是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值

    Object类中有一个方法可以获取对象的哈希值
        public int hashCode():返回对象的哈希码值
 */
public class HashDemo {
    public static void main(String[] args) {
        //创建学生对象
        Student s1 = new Student("林青霞",30);

        //同一个对象多次调用hashCode()方法返回的哈希值是相同的
        System.out.println(s1.hashCode()); //1060830840
        System.out.println(s1.hashCode()); //1060830840
        System.out.println("--------");

        Student s2 = new Student("林青霞",30);

        //默认情况下,不同对象的哈希值是不相同的
        //通过方法重写,可以实现不同对象的哈希值是相同的
        System.out.println(s2.hashCode()); //2137211482
        System.out.println("--------");

        System.out.println("hello".hashCode()); //99162322
        System.out.println("world".hashCode()); //113318802
        System.out.println("java".hashCode()); //3254818

        System.out.println("world".hashCode()); //113318802
        System.out.println("--------");

        //因为hashcode重写了hashCode()这个方法,所以,他们的值是相同的
        System.out.println("重地".hashCode()); //1179395
        System.out.println("通话".hashCode()); //1179395
    }
}
package itheima11;


public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.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 int hashCode() {
        return 0;
    }
     */
    
}

3.3 HashSet集合概述和特点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-do9tPCu4-1663747806878)(java.assets/image-20210823183158498.png)]

package com.itheima_03;

import java.util.HashSet;

/*
    HashSet集合特点
        1:底层数据结构是哈希表
        2:对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
        3:没有带索引的方法,所以不能使用普通for循环遍历
        4:由于是Set集合,所以是不包含重复元素的集合
 */

public class HashSetDemo01 {
    public static void main(String[] args) {
        //创建集合对象
        HashSet<String> hs = new HashSet<String>();

        //添加元素
        hs.add("hello");
        hs.add("world");
        hs.add("java");

        hs.add("world");

        //遍历
        for(String s : hs) {
            System.out.println(s);
        }
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eTQkDc94-1663747806878)(java.assets/image-20210823183247299.png)]

3.4 HashSet集合保证元素唯一性源码分析

HashSet集合保证元素唯一性源码分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xfLGLycc-1663747806879)(java.assets/image-20210823184220498.png)]

HashSet集合存储元素:

要保证元素唯一性,需要重写hashCode()和equals()方法

这两个方法是分别用来比较哈希值和内容是否相同的

源码中的resize()函数:这个是哈希表的扩容机制

参考链接:【转】Java8 resize() 机制_AllenBolg的博客-CSDN博客_java resize

3.5 常见数据结构之哈希表

hash值是由元素的hashcode()方法计算得到的

视频链接:

[经典242哈希表存储数据流程](https://www.bilibili.com/video/BV18J411W7cE?p=242)

哈希表

  • jdk8之前,底层采用 实现,可以说是一个元素为链表的数组

  • jdk8之后,在长度比较长的时候,底层实现了优化,是数组、链表、红黑树

哈希表结构存储元素的时候保证元素唯一性的整个流程:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n8HYvjym-1663747806879)(java.assets/image-20220405144859894.png)]

由此可知,当哈希值和内容都相同的时候,就不会存储了,所以这就是为啥hashset不能存储相同元素的原因

先比较哈希值再比较内容

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sLjziIYf-1663747806879)(java.assets/image-20220405154338857.png)]

hashSet()集合方法,默认初始容量是16,

所以上图除以16.【取余】

所以上图数组默认长度是16,即0-15

所以,如果要把上图的数字存放到其中,那么就让其除以16,取余,看该放到哪个里面

就是将上面的数据转换为对应的0-15的数字

很简单,就是对他们进行16取余

这些取余的动作,大家可以自己算一下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UnOht35e-1663747806879)(java.assets/image-20210823184823486.png)]

动力字节:

哈希表、哈希函数,了解即可

哈希表:数组和单向链表的结合体

06 案例:HashSet集合存储学生对象并遍历

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nnFxASut-1663747806880)(java.assets/image-20210823190233431.png)]

package itheima11;
import java.util.Objects;

public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.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;
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}
package itheima11;

import java.util.HashSet;

public class HashSetDemo02 {
    public static void main(String[] args) {
        //创建HashSet集合对象
        HashSet<Student> hs = new HashSet<Student>();
        //创建学生对象
        Student s1 = new Student("林青霞", 30);
        Student s2 = new Student("张曼玉", 35);
        Student s3 = new Student("王祖贤", 33);
        Student s4 = new Student("王祖贤", 33);

        //把学生添加到集合
        hs.add(s1);
        hs.add(s2);
        hs.add(s3);
        hs.add(s4);

        //遍历集合(增强for)
        for (Student s : hs) {
            System.out.println(s.getName()+","+s.getAge());
        }
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LCjyc3j5-1663747806880)(java.assets/image-20210823190113166.png)]

alt+insert一直点即可

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QFHP7ydz-1663747806880)(java.assets/image-20210823190325466.png)]

07 LinkedHashSet集合概述和特点

3.7 TreeSet集合概述和特点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ej0SH9HO-1663747806880)(java.assets/image-20220408152207476.png)]

参考链接:黑马程序员全套Java教程_Java基础入门视频教程,零基础小白自学Java必备教程_哔哩哔哩_bilibili

代码实例:

package com.itheima_05;

import java.util.TreeSet;

/*
    TreeSet集合特点
        1:元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法
            TreeSet():根据其元素的自然排序进行排序
            TreeSet(Comparator comparator) :根据指定的比较器进行排序
        2:没有带索引的方法,所以不能使用普通for循环遍历
        3:由于是Set集合,所以不包含重复元素的集合
 */
public class TreeSetDemo01 {
   public static void main(String[] args) {
        //创建集合,添加元素,遍历集合
        TreeSet<Integer> tset = new TreeSet<>();
        tset.add(7);
        tset.add(1);
        tset.add(4);
        tset.add(3);
        //没有索引 ,只能用增强for循环
        for(Integer s: tset){
            System.out.println(s);
        }
    }
}

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3UbajxGs-1663747806881)(java.assets/image-20220408153352371.png)]

就是会自动进行排序

09 自然排序Comparable的使用

优先级队列:

每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根.

  1. 由于优先队列底层是堆而堆的底层又是数组,所以入队需要判断数组是否满,如果满则需要扩容
  2. 根据堆的特性,无论是入堆还是出堆,都要保持大根堆或者小根堆.

对于一个类,如果我们想要对这个类进行排序,我们就得重写自定义比较器

就是如果我们没有重写student中的comparable方法,在遍历treeset中的元素时就会出现

类转换异常

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L8c98YJW-1663747806881)(java.assets/image-20220406201157395.png)]

原因:如果我们要做自然排序,就要去实现这个自然排序的接口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PTJa4H9M-1663747806881)(java.assets/image-20220406205054022.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xRqUjF6V-1663747806881)(java.assets/image-20220406204549930.png)]

返回1就是放后面,-1就是放前面,0就是说明是和上一个元素相同,重复元素

【或者理解为,正数就是正序该放后面,负数就是该放前面】

主要条件和次要条件

比如主要条件是比较年龄,次要条件比较的是姓名

3.9 比较器排序Comparator的使用

参考链接:黑马程序员全套Java教程_Java基础入门视频教程,零基础小白自学Java必备教程_哔哩哔哩_bilibili

package com.itheima_06;
import java.util.Comparator;
import java.util.TreeSet;
/*
    存储学生对象并遍历,创建TreeSet集合使用带参构造方法
    要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
 */

public class TreeSetDemo {
    public static void main(String[] args) {
        //创建集合对象
        TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
	   //匿名内部类,同时对这个类的方法进行重写
            @Override
            public int compare(Student s1, Student s2) {
                //this.age - s.age
                //s1,s2
                int num = s1.getAge() - s2.getAge();
                int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
                return num2;
            }
        });
        //创建学生对象
        Student s1 = new Student("xishi", 29);
        Student s2 = new Student("wangzhaojun", 28);
        Student s3 = new Student("diaochan", 30);
        Student s4 = new Student("yangyuhuan", 33);
        Student s5 = new Student("linqingxia",33);
        Student s6 = new Student("linqingxia",33);
        //把学生添加到集合
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);
        ts.add(s6);
        //遍历集合
        for (Student s : ts) {
            System.out.println(s.getName() + "," + s.getAge());
        }
        
    }
}

对比较器的理解:

应用题目:347. 前 K 个高频元素 - 力扣(LeetCode) (leetcode-cn.com)

我应该进行hashmap的题,进行整理

  • 升序还是降序

int compare(Object o1, Object o2) 返回一个基本类型的整型
如果要按照升序排序,
则o1 小于o2,返回-1(负数),相等返回0,01大于02返回1(正数)
如果要按照降序排序
则o1 小于o2,返回1(正数),相等返回0,01大于02返回-1(负数)

这个意思就是,不要看局部,整体来看,就是如果你想要按照升序,那么就规定,o1o2,返回1(正数)

如果你想要按照降序排序,那么就规定o1o2返回-1(负数)

数字升序就是123456

字母升序就是abcdefj,应该按照ascii码吧【未经测试】

参考链接:https://blog.csdn.net/zzq900503/article/details/51119714

升降序的一种全新,我觉得可行的理解

下面还是匿名比较器 的一种标准写法,注意学着点

优先级队列,内部是怎么排序的???

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6YOqAB7d-1663747806882)(java.assets/image-20220412171545467.png)]

  • Comparator和Comparable基本介绍和在哪里用

    Comparator是外部比较器,用于比较对象和对象之间的,两个对象进行比较,多用于集合排序,

    Comparable可以认为是一个内部比较器,根据对象某一属性进行排序的

    参考链接:https://blog.csdn.net/kuishao1314aa/article/details/100527985

    文章代码如下

     
    import java.util.*;
     
    class Node{
        int x;
        int y;
        Node(int x,int y){
            this.x=x;
            this.y=y;
        }
        @Override
        public String toString() {
            return "Node{" +
                    "x=" + x +
                    ", y=" + y +
                    '}';
        }
    }
    public class Main {
     
        public static void way(int num[],int n){
     
        }
        public static void main(String[] args) {
            Node node4=new Node(2,2);
            Node node3=new Node(2,1);
            Node node1=new Node(1,2);
            Node node2=new Node(1,1);
            Node node5=new Node(3,1);
            Node node6=new Node(3,2);
            ArrayList<Node> list=new ArrayList<>();
            list.add(node1);
            list.add(node2);
            list.add(node3);
            list.add(node4);
            list.add(node5);
            list.add(node6);
            Collections.sort(list, new Comparator<Node>() {
                /**o1-o2为升序序排列,o2-o1为降序排列,若具体到某一字段,则根据该字段进行排列*/
                @Override
                public int compare(Node o1, Node o2) {
                    if (o1.x==o2.x) //若x属性相等,根据y来升序
                        return o1.y-o2.y;
                    return o1.x-o2.x;//x属性不相等,根据x来升序排列
                }
            });
            for (Node node:list
                 ) {
                System.out.println(node.toString());
            }
        }
    }
    
  • comparator的父类是谁

我傻了,之前我思考这个问题,后来我一想,java中所有类的父类,都是object类啊!

这个是18万阅读量的大佬文章:https://blog.csdn.net/u012250875/article/details/55126531

  • comparator和 comparable 区别

这篇文章阐明了二者的用法和区别:https://blog.csdn.net/tayanxunhua/article/details/11100011

文章代码:

(一)、使用Comporable接口
    //需要在要比较的类中实现接口并覆盖重写compareto方法
public class Student implements Comporable 
{
     private String name;
     private int age;
     public Student(String name, int age) 
     {
          this.name = name;
          this.age = age;
     }
     //覆写toString()方法
     //如果实现Comparable接口必须覆写compareTo方法
     public int compareTo(Object o)
     {
          if(!(o instanceof Student)) 
          {
               throw new RuntimeException("不是学生对象!");
          }
          Student stu = (Student) o;
          int i = 0;
          i = this.name.compareTo(stu.name);
          if(i == 0)//如果两个对象的name相同,则比较age 
          {
               return this.age - stu.age;
          }
          else 
          {
               return i;//否则返回比较name的结果i
          }
          
     } 
}      

//测试类
public class Test
{
     public static void main(String [] args) 
     {
          List stuList = new ArrayList();
          stuList.add(new Student("zhangsan", 21));
          stuList.add(new Student("lisi", 22));
          stuList.add(new Student("wangwu", 23));
          Collections.sort(stuList);
          System.out.println(stuList);
     }
}
     (二)、使用Comporator接口
         /**
         使用这个,则可以自己定义一个比较器然后实现@override这个方法,然后
         用Collections.sort(stuList, new MyCompare());这个集合的sort方法,
         或者还可以使用匿名内部类
         */
public class Student
{
     private String name;
     private int age;
     public Student(String name, int age)
     {
          this.name = name;
          this.age = age;
     }
     //覆写toString()方法
     //set和get方法
}
//自己的比较器类
public class MyCompare implements Comporator
{
     //覆写compare()方法
     public int compare(Object o1, Object o2)
     {
          Student stu1 = (Student) o1;
          Student stu2 = (Student) o2;
          int num = stu1.getName().compareTo(stu2.getName);
          if(num == 0)
          {
               return o1.getAge() - o2.getAge();
          }
          else 
          {
               return num;
          }
     }
}
//测试类
public class Test
{
     public static void main(String [] args) 
     {
          List stuList = new ArrayList();
          stuList.add(new Student("zhangsan", 21));
          stuList.add(new Student("lisi", 22));
          stuList.add(new Student("wangwu", 23));
          Collections.sort(stuList, new MyCompare());
          System.out.println(stuList);
     }
}

  • Collections.sort()源码分析

https://wangye7303.blog.csdn.net/article/details/108574808

11 成绩排序

package com.itheima_07;

import java.util.Comparator;
import java.util.TreeSet;

/*
    需求:
        用TreeSet集合存储多个学生信息(姓名,语文成绩,数学成绩),并遍历该集合
        要求:按照总分从高到低出现

    思路:
        1:定义学生类
        2:创建TreeSet集合对象,通过比较器排序进行排序
        3:创建学生对象
        4:把学生对象添加到集合
        5:遍历集合
 */
public class TreeSetDemo {
    public static void main(String[] args) {
        //创建TreeSet集合对象,通过比较器排序进行排序
        TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
//                int num = (s2.getChinese()+s2.getMath())-(s1.getChinese()+s1.getMath());
                //主要条件
                int num = s2.getSum() - s1.getSum();
                //次要条件
                int num2 = num == 0 ? s1.getChinese() - s2.getChinese() : num;
                int num3 = num2 == 0 ? s1.getName().compareTo(s2.getName()) : num2;
                return num3;
            }
        });

        //创建学生对象
        Student s1 = new Student("林青霞", 98, 100);
        Student s2 = new Student("张曼玉", 95, 95);
        Student s3 = new Student("王祖贤", 100, 93);
        Student s4 = new Student("柳岩", 100, 97);
        Student s5 = new Student("风清扬", 98, 98);

        Student s6 = new Student("左冷禅", 97, 99);
//        Student s7 = new Student("左冷禅", 97, 99);
        Student s7 = new Student("赵云", 97, 99);

        //把学生对象添加到集合
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);
        ts.add(s6);
        ts.add(s7);

        //遍历集合
        for (Student s : ts) {
            System.out.println(s.getName() + "," + s.getChinese() + "," + s.getMath() + "," + s.getSum());
        }
    }
}

12 不重复的随机数

4 泛型

4.1 泛型概述【类型参数化】

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rNmTpGBf-1663747806882)(java.assets/image-20210815154147905.png)]

类比先前学过的。

定义方法时候,有形参,然后调用此方法时传递实参

泛型:参数化类型

就是将类型由原来的具体的类型参数化,然后在使用/调用时传入具体的类型

集合被规定泛型后,就只能使用所规定的类型了

例子:使用泛型List之后,表示List集合中只允许存储Animal类型的数据。如果存储String类型,那么就报错了

List<Animal> myList = new ArrayList<Animal>();

使用泛型后,集合中元素的数据类型更加统一了。

【泛型就是将变量类型参数化,你i想是什么类型,就<在这里面传什么类型>】

其好处,两个:

package itheima1;

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

public class GenericDemo {
    public static void main(String[] args) {

        //创建集合对象
//        Collection c=new ArrayList();
        Collection<String> c=new ArrayList<String>();

        //添加元素,当我们没有指定添加类型的时候,添加的是默认object类型,因为泛型默认是引用类型,object可以代表所有的引用类型

        c.add("hello");
        c.add("world");
        c.add("java");      //我们把字符串赋值给object是向上转型
       // c.add(100);       这里会报错,因为前面已经用了String泛型,所以,100是一个int类型,会报错,就将运行期间的错误提前到编译阶段

        //使用迭代器来进行遍历

        Iterator<String> it = c.iterator();
        while(it.hasNext()){
            /**
             *    Object obj=it.next();   //添加的时候,指针是object类型,所以获取的时候,也是object类型
             *             System.out.println(obj);
             */
            //因为存储的是object类型, 所以我们向下转型,想将其变成string类型,
//            String s=(String) it.next();
            String s=it.next();     //有了泛型,就不用加强制类型转换了

            System.out.println(s);

        }
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uf0n9TGr-1663747806882)(java.assets/image-20210815160406095.png)]

在使用泛型的时候要注意:

*前后的泛型必须一致*,或者后面的泛型可以省略不写(1.7的新特性菱形泛型)

4.2 泛型类 < T >

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zGaUaEdR-1663747806882)(java.assets/image-20210815164444034.png)]

泛型方法

泛型接口

泛型类

package itheima;

public class Teacher {
    private Integer age;

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

package itheima;

public class Student {
    private String name;

    public String getName() {
        return name;
    }

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

package itheima;

public class Generic<T> {		//T可以是String、Integer、Boolean
    private T t;
    public T getT(){
        return t;
    }
    public void setT(T t){
        this.t = t;
    }
}
package itheima;
//测试类
public class GenericDemo {
    public static void main(String[] args) {
     Student s=new Student();
     s.setName("林青霞");
        System.out.println(s.getName());

        Teacher t=new Teacher();
        t.setAge(30);
        System.out.println(t.getAge());
        
  		System.out.println("______________________");
        
        Generic<String> g1=new Generic<String>();
        g1.setT("林青霞");
        System.out.println(g1.getT());

        Generic<Integer> g2= new Generic<Integer>();
        g2.setT(30);
        System.out.println(g2.getT());

        Generic<Boolean> g3 = new Generic<Boolean>();
        g3.setT(true);
        System.out.println(g3.getT());
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o4ezj1Wk-1663747806883)(java.assets/image-20220107134900876.png)]

CSDN总结:

java泛型T_dd_Mr的博客-CSDN博客

基本数据类型无法泛型化

动力节点泛型

动力节点,泛型讲解,很好

4.3

4.5 类型通配符

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mF66QdVB-1663747806883)(java.assets/image-20210817141707054.png)]

4.6 可变参数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-avp4L4XQ-1663747806883)(java.assets/image-20210817150718928.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JKIxDdw3-1663747806883)(java.assets/image-20210817143455241.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sFfojjJ9-1663747806884)(java.assets/image-20210817144342841.png)]

package itheima01;

public class ArhsDemo01 {
    public static void main(String[] args) {
        System.out.println(sum(10,20));
        System.out.println(sum(10,20,30));
        System.out.println(sum(10,20,30,40));
        System.out.println(sum(10,20,30,40,50));
    }

    public static int sum(int... a){
//        System.out.println(a);
        int sum=0;
        for(int i:a){
            sum+=i;
        }
        return sum;
    }


}


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gDb5P4WH-1663747806884)(java.assets/image-20210817150401974.png)]

package itheima01;

public class ArhsDemo01 {
    public static void main(String[] args) {
        System.out.println(sum(10,20));
        System.out.println(sum(10,20,30));
        System.out.println(sum(10,20,30,40));
        System.out.println(sum(10,20,30,40,50));
    }
    /*
    public static int sum(int... a){
//        System.out.println(a);
        int sum=0;
        for(int i:a){
            sum+=i;
        }
        return sum;
    }
*/
    public static int sum(int b,int... a) {
        return 0;//这样会首先给b,然后剩余的给a
    }
}

4.7 可变参数的使用

5 Map【字典】

map是无序的!

集合继承结构图_Map 部分

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3DelKpga-1663747806884)(java.assets/image-20220111233351234.png)]

java中一般用map与hashmap来创建一个key-value对象
使用前提是要导入方法包:
  import java.util.HashMap;
  import java.util.Map;
格式:
  Map 数据名称 =  new HashMap();

key()-value()类似python里面的字典
key-value是【一对一】对应关系(简单的打比方例如生活中的丈夫与妻子的关系)
就例如看到key就会想到说这是value的老公,你看到value就会说这是key的老婆
一般格式是{ key : value }

5.1 Map集合概述和使用

黑马程序员全套Java教程_Java基础入门视频教程,零基础小白自学Java必备教程_哔哩哔哩_bilibili

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xyip7B8z-1663747806884)(java.assets/image-20220408160037199.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2O9zvuqO-1663747806885)(java.assets/image-20210823191336362.png)]

package itheima11;

import java.util.HashMap;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: 从南到北
 * @Date: 11/08/2021/14:40
 * @Description:
 *
 */
public class MapDemo01 {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<String,String>();
        map.put("资源1","无人机");
        map.put("资源2","火炮");
        map.put("资源3","飞机");	// 被替代
        map.put("资源3","电脑");    // 每个键只能映射一个值 

        //输出集合对象
        System.out.println(map);
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xj3lyKNd-1663747806885)(java.assets/image-20211108144800602.png)]

5.2 Map集合的基本功能

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SYTLsTw6-1663747806885)(java.assets/image-20210823192305735.png)]

package com.itheima_01;

import java.util.HashMap;
import java.util.Map;

/*
    Map集合的基本功能:
        V put(K key,V value):添加元素
        V remove(Object key):根据键删除键值对元素
        void clear():移除所有的键值对元素
        boolean containsKey(Object key):判断集合是否包含指定的键
        boolean containsValue(Object value):判断集合是否包含指定的值(自学)
        boolean isEmpty():判断集合是否为空
        int size():集合的长度,也就是集合中键值对的个数
 */
public class MapDemo02 {
    public static void main(String[] args) {
        //创建集合对象
        Map<String,String> map = new HashMap<String,String>();

        //V put(K key,V value):添加元素
        map.put("张无忌","赵敏");
        map.put("郭靖","黄蓉");
        map.put("杨过","小龙女");

        //V remove(Object key):根据键删除键值对元素
//        System.out.println(map.remove("郭靖"));
//        System.out.println(map.remove("郭襄"));

        //void clear():移除所有的键值对元素
//        map.clear();

        //boolean containsKey(Object key):判断集合是否包含指定的键
//        System.out.println(map.containsKey("郭靖"));
//        System.out.println(map.containsKey("郭襄"));

        //boolean isEmpty():判断集合是否为空
//        System.out.println(map.isEmpty());

        //int size():集合的长度,也就是集合中键值对的个数
        System.out.println(map.size());
        //输出集合对象
        System.out.println(map);
    }
}

package itheima11;

import java.util.HashMap;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: 从南到北
 * @Date: 11/08/2021/14:51
 * @Description:
 */
public class MapDemo02 {
    public static void main(String[] args) {

        //创建集合对象
        Map<String,String> map = new HashMap<String,String>();

        //V put(K key,V value):添加元素
        map.put("张无忌","赵敏");
        map.put("郭靖","黄蓉");
        map.put("杨过","小龙女");

        System.out.println(map.remove("郭靖"));
        System.out.println(map);    //删除郭靖后,只剩“两个键值对”还有一个“黄蓉”

    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zC7IaK63-1663747806885)(java.assets/image-20211108145444287.png)]

5.3 Map集合的获取功能

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2lOqNnGB-1663747806886)(java.assets/image-20211108151526784.png)]

[map的增删改查]https://blog.csdn.net/i_belive_my_love/article/details/78220415

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: 从南到北
 * @Date: 11/08/2021/15:02
 * @Description:
 */
public class MapDemo03 {
    public static void main(String[] args) {
        //创建集合对象
        Map<String, String> map = new HashMap<String,String>();
        //添加元素
        map.put("张无忌","赵敏");
        map.put("郭靖","黄蓉");
        map.put("杨过","小龙女");

        //V get(Object Key):根据键获取值
        System.out.println(map.get("张无忌")); //输出赵敏

        //获取所有键的集合
        Set<String> keySet = map.keySet();
        for(String key:keySet){
            System.out.println(key);
        }

        // Collection values() 获取所有值的集合
        Collection<String> values = map.values();
        for (String value : values) {
            System.out.println(value);
        }
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YPSX7eEb-1663747806886)(java.assets/image-20211108151624239.png)]

5.4 Map集合的遍历(方式1)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KX7vAHYV-1663747806886)(java.assets/image-20211108152712212.png)]

package itheima11;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: 从南到北
 * @Date: 11/08/2021/15:20
 * @Description:
 *
 * map集合遍历的方式1
 */
public class MapDemo04 {
    public static void main(String[] args) {
        //创建集合对象
        Map<String, String> map = new HashMap<String,String>();
        //添加元素
        map.put("张无忌","赵敏");
        map.put("郭靖","黄蓉");
        map.put("杨过","小龙女");

        //获取所有键的集合,用keySet()方法实现
        Set<String> keySet = map.keySet();
        for (String key : keySet) {
            //根据键去找值,用get(Object key) 方法实现
            String value = map.get(key);
            System.out.println(key+","+value);
        }
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4PuRSonI-1663747806886)(java.assets/image-20211108152749266.png)]

5.5 Map集合的遍历(方式2)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uqEb0a2n-1663747806887)(java.assets/image-20211108153341167.png)]

Map.Entry是Map声明的一个内部接口,此接口为泛型,定义为Entry。它表示Map中的一个实体(一个key-value对)。接口中有getKey(),getValue方法

接口就是只有方法名,没有实现

package itheima11;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: 从南到北
 * @Date: 11/08/2021/15:34
 * @Description:
 *      5.5 Map集合的遍历(方式2)
 */
public class MapDemo05 {
    public static void main(String[] args) {
        //创建集合对象
        Map<String, String> map = new HashMap<String,String>();
        //添加元素
        map.put("张无忌","赵敏");
        map.put("郭靖","黄蓉");
        map.put("杨过","小龙女");
        //获得所有键值对,对象的集合
        Set<Map.Entry<String, String>> entrySet = map.entrySet();
        //遍历键值对,对象集合,得到每一个键值对对象
        for (Map.Entry<String, String> me : entrySet) {
            //根据键值对 对象获取键和值
            String key = me.getKey();
            String value = me.getValue();
            System.out.println(key+","+value);
        }
    }
}

案例:HashMap集合存储学生对象并遍历

package com.itheima_03;

public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.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;
    }
}

package com.itheima_03;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/*
    需求:
        创建一个HashMap集合,键是学号(String),值是学生对象(Student)。存储三个键值对元素,并遍历

    思路:
        1:定义学生类
        2:创建HashMap集合对象
        3:创建学生对象
        4:把学生添加到集合
        5:遍历集合
            方式1:键找值
            方式2:键值对对象找键和值
 */
public class HashMapDemo {
    public static void main(String[] args) {
        //创建HashMap集合对象
        HashMap<String, Student> hm = new HashMap<String, Student>();

        //创建学生对象
        Student s1 = new Student("林青霞", 30);
        Student s2 = new Student("张曼玉", 35);
        Student s3 = new Student("王祖贤", 33);

        //把学生添加到集合
        hm.put("itheima001", s1);
        hm.put("itheima002", s2);
        hm.put("itheima003", s3);

        //方式1:键找值
        Set<String> keySet = hm.keySet();
        for (String key : keySet) {
            Student value = hm.get(key);
            System.out.println(key + "," + value.getName() + "," + value.getAge());
        }
        System.out.println("--------");

        //方式2:键值对对象找键和值
        Set<Map.Entry<String, Student>> entrySet = hm.entrySet();
        for (Map.Entry<String, Student> me : entrySet) {
            String key = me.getKey();
            Student value = me.getValue();
            System.out.println(key + "," + value.getName() + "," + value.getAge());
        }
    }
}
package maptest;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: 从南到北
 * @Date: 04/08/2022/16:11
 * @Description:
 */
public class HashMapDemo {
    public static void main(String[] args) {
        //创建集合对象,键值对,键为学号,值学生
        //将学生添加进去
        //遍历
        Map<String,Student> st = new HashMap<>();
        Student s1 = new Student("xiaoming",12);
        Student s2 = new Student("xiaohong",13);
        Student s3 = new Student("xiaobai",10);
        st.put("1",s1);
        st.put("2",s2);
        st.put("3",s3);
//        for (String s:st){
//            System.out.println(s);
//        }
        //map的遍历方式有两种
        //键找值
        //得到所有键
        Set<String> ks = st.keySet();
        //set是无序
        for (String s:ks){
            //通过key得到值
            Student value = st.get(s);
            //输出学号,姓名,年龄
            System.out.println(s+","+value.getName()+","+value.getAge());
        }

        //方式2
        Set<Map.Entry<String, Student>> entries = st.entrySet();
        for (Map.Entry<String, Student> me:entries){
            String key =me.getKey();
            Student value = me.getValue();
            System.out.println(key+","+value.getName()+","+value.getAge());
        }

    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p1oQIVR8-1663747806887)(java.assets/image-20220408164811562.png)]

进阶

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SXDXfW12-1663747806887)(java.assets/image-20220408165247866.png)]

这个是键是学生,值是居住地

所以需要重写学生类

package maptest;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: 从南到北
 * @Date: 04/08/2022/17:02
 * @Description:
 * 创建map集合
 * 创建学生<学生,地址>
 * 添加学生
 * 遍历学生
 */
public class HashMapDemo1 {
    public static void main(String[] args) {
        Map<Student,String> s = new HashMap<>();
        Student a1 = new Student("A",12);
        Student a2 = new Student("B",13);
        Student a3 = new Student("C",16);
        Student a4 = new Student("C",16);
        s.put(a1,"北京");//键是学生对象,值是地址
        s.put(a2,"上海");
        s.put(a3,"天津");//如果添加相同的,会被覆盖
        s.put(a4,"重庆");

        //两种方式遍历
        //1,获取键,keySet存储所有键
        //然后这个键是存储的学生
        //获取所有的键值
        Set<Student> skey = s.keySet();
        //然后遍历键值,键值是学生类型
        for (Student t:skey){
            String name = t.getName();
            int age = t.getAge();
            //怎么获取值呢?
            //有个通过键获取值的函数
            String values = s.get(t);
            System.out.println(name+","+age+","+values);
        }

        System.out.println("---------------");
        //两种,还有一种是获取键值
        Set<Map.Entry<Student, String>> entries = s.entrySet();
        //遍历
        for (Map.Entry<Student, String> e:entries){
            //获取键值
            Student key = e.getKey();
            String value = e.getValue();
            System.out.println(key.getName()+","+key.getAge()+","+value);
        }


    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jn4GDrTZ-1663747806887)(java.assets/image-20220408193901270.png)]

集合嵌套:HashMap集合存储ArrayList元素并遍历

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WxitaeIY-1663747806887)(java.assets/image-20220408194241557.png)]

package chat;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;

/*
    需求:
        创建一个ArrayList集合,存储三个元素,每一个元素都是HashMap,每一个HashMap的键和值都是String,并遍历

    思路:
        1:创建ArrayList集合
        2:创建HashMap集合,并添加键值对元素
        3:把HashMap作为元素添加到ArrayList集合
        4:遍历ArrayList集合2

    给出如下的数据:
        第一个HashMap集合的元素:
  		    孙策		大乔
  		    周瑜		小乔
        第二个HashMap集合的元素:
  		    郭靖		黄蓉
  		    杨过		小龙女
        第三个HashMap集合的元素:
  		    令狐冲	任盈盈
  		    林平之	岳灵珊
 */
public class ArrayListIncludeHashMapDemo1 {
    public static void main(String[] args) {
        //创建ArrayList集合
        ArrayList<HashMap<String, String>> array = new ArrayList<HashMap<String, String>>();

        //创建HashMap集合,并添加键值对元素
        HashMap<String, String> hm1 = new HashMap<String, String>();
        hm1.put("孙策", "大乔");
        hm1.put("周瑜", "小乔");
        //把HashMap作为元素添加到ArrayList集合
        array.add(hm1);

        HashMap<String, String> hm2 = new HashMap<String, String>();
        hm2.put("郭靖", "黄蓉");
        hm2.put("杨过", "小龙女");
        //把HashMap作为元素添加到ArrayList集合
        array.add(hm2);

        HashMap<String, String> hm3 = new HashMap<String, String>();
        hm3.put("令狐冲", "任盈盈");
        hm3.put("林平之", "岳灵珊");
        //把HashMap作为元素添加到ArrayList集合
        array.add(hm3);

        //遍历ArrayList集合
        for (HashMap<String, String> hm : array) {
            Set<String> keySet = hm.keySet();
            for (String key : keySet) {
                String value = hm.get(key);
                System.out.println(key + "," + value);
            }
        }
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0uczmPnP-1663747806888)(java.assets/image-20220408200559909.png)]

下面是有问题的代码,有空记得修改

package chat;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: 从南到北
 * @Date: 04/08/2022/19:46
 * @Description: arraylist中包含hashmap,hashmap里面是string类型的值
 */
public class ArrayListIncludeHashMapDemo {
    public static void main(String[] args) {
        ArrayList<Map<String,String>> array = new ArrayList<>();
        Map<String, String> hashmap1 = new HashMap<>();
        Map<String, String> hashmap2= new HashMap<>();
        Map<String, String> hashmap3 = new HashMap<>();

        hashmap1.put("河南","周口");
        hashmap1.put("河南","郑州");
        hashmap2.put("陕西","西安");
        hashmap2.put("陕西","咸阳");
        hashmap3.put("北京","海淀");
        hashmap3.put("北京","曹阳");
        array.add(hashmap1);
        array.add(hashmap2);
        array.add(hashmap3);

        //arraylist集合遍历
        //类型是Map 要遍历定义的内容  :要遍历array

        for (Map<String,String> m:array){
            //array集合里面是hashmap集合
//            首先对set集合进行遍历,获取所有键值
            Set<String> strings = m.keySet();
            for (String s:strings){
                String value =m.get(s);
                System.out.println(s + "," + value);
            }
        }


    }
}

没有显示完全

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r7d7LtSq-1663747806888)(java.assets/image-20220408200642990.png)]

集合嵌套:hashmap和arraylist

案例:统计字符串中每个字符出现的次数

黑马程序员全套Java教程_Java基础入门视频教程,零基础小白自学Java必备教程_哔哩哔哩_bilibili

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aXJ94A3W-1663747806888)(java.assets/image-20220408202236372.png)]

4.13

package com.itheima_06;

import java.util.HashMap;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeMap;

/*
    需求:
        键盘录入一个字符串,要求统计字符串中每个字符串出现的次数。
        举例:键盘录入“aababcabcdabcde”	在控制台输出:“a(5)b(4)c(3)d(2)e(1)”

    思路:
        1:键盘录入一个字符串
        2:创建HashMap集合,键是Character,值是Integer
        3:遍历字符串,得到每一个字符
        4:拿得到的每一个字符作为键到HashMap集合中去找对应的值,看其返回值
            如果返回值是null:说明该字符在HashMap集合中不存在,就把该字符作为键,1作为值存储
            如果返回值不是null:说明该字符在HashMap集合中存在,把该值加1,然后重新存储该字符和对应的值
        5:遍历HashMap集合,得到键和值,按照要求进行拼接
        6:输出结果
 */
public class HashMapDemo {
    public static void main(String[] args) {
        //键盘录入一个字符串
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个字符串:");
        String line = sc.nextLine();

        //创建HashMap集合,键是Character,值是Integer
//        HashMap hm = new HashMap();
        TreeMap<Character, Integer> hm = new TreeMap<Character, Integer>();

        //遍历字符串,得到每一个字符
        for (int i = 0; i < line.length(); i++) {
            char 		 = line.charAt(i);

            //拿得到的每一个字符作为键到HashMap集合中去找对应的值,看其返回值
            Integer value = hm.get(key);

            if (value == null) {
                //如果返回值是null:说明该字符在HashMap集合中不存在,就把该字符作为键,1作为值存储
                hm.put(key,1);
            } else {
                //如果返回值不是null:说明该字符在HashMap集合中存在,把该值加1,然后重新存储该字符和对应的值
                value++;
                hm.put(key,value);
            }
        }

        //遍历HashMap集合,得到键和值,按照要求进行拼接
        StringBuilder sb = new StringBuilder();

        Set<Character> keySet = hm.keySet();
        for(Character key : keySet) {
            Integer value = hm.get(key);
            sb.append(key).append("(").append(value).append(")");
        }

        String result = sb.toString();

        //输出结果
        System.out.println(result);
    }
}

4.13


自动装箱操作:将基本数据类型,装成对应的包装类型

存的时候,有个自动装箱的操作

treemap就是对键进行排序而已,其他的一样

File文件操作

1 File

1.1 File类概述和构造方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WkLqiz9T-1663747806888)(java.assets/image-20210619214223001.png)]

package com.itheima;

import java.io.File;

/*
    File:文件和目录路径名的抽象表示
          1:文件和目录是可以通过File封装成对象的
          2:对于File而言,其封装的并不是一个真正存在的文件,仅仅是一个路径名而已。它可以是存在的,也可以是不存在的。
            将来是要通过具体的操作把这个路径的内容转换为具体存在的

    构造方法:
        File(String pathname):通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
        File(String parent, String child):从父路径名字符串和子路径名字符串创建新的 File实例。
        File(File parent, String child):从父抽象路径名和子路径名字符串创建新的 File实例。
 */
public class FileDemo01 {
    public static void main(String[] args) {
        //File(String pathname):通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
        File f1 = new File("D:\\itcast\\java.txt");
        System.out.println(f1);

        //File(String parent, String child):从父路径名字符串和子路径名字符串创建新的 File实例。
        File f2 = new File("D:\\itcast","java.txt");
        System.out.println(f2);

        //File(File parent, String child):从父抽象路径名和子路径名字符串创建新的 File实例。
        File f3 = new File("D:\\itcast");
        File f4 = new File(f3,"java.txt");
        System.out.println(f4);
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H4tH0ykb-1663747806889)(java.assets/image-20210619220503030.png)]

并且不会创建该文件!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RSr2Mla1-1663747806889)(java.assets/image-20210624091541639.png)]

  • 这个parent我知道啥意思了,就是他的上一级目录,然后child就是这个文件本身

  • 这个是将文件路径封装成一个可以操作的对象

     File f1 = new File("D:\\itcast\\java.txt");
    

1.2 File类创建功能

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8mep3y00-1663747806889)(java.assets/image-20210619220619360.png)]

package com.itheima;

import java.io.File;
import java.io.IOException;

/*
    File类创建功能:
        public boolean createNewFile():当具有该名称的文件不存在时,创建一个由该抽象路径名命名的新空文件
            如果文件不存在,就创建文件,并返回true
            如果文件存在,就不创建文件,并返回false

        public boolean mkdir():创建由此抽象路径名命名的目录
            如果目录不存在,就创建目录,并返回true
            如果目录存在,就不创建目录,并返回false

        public boolean mkdirs():创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录
            自己补齐
 */
public class FileDemo02 {
    public static void main(String[] args) throws IOException {
        //需求1:我要在E:\\itcast目录下创建一个文件java.txt
        File f1 = new File("E:\\itcast\\java.txt");
        System.out.println(f1.createNewFile());
        System.out.println("--------");

        //需求2:我要在E:\\itcast目录下创建一个目录JavaSE
        File f2 = new File("E:\\itcast\\JavaSE");
        System.out.println(f2.mkdir());
        System.out.println("--------");

        //需求3:我要在E:\\itcast目录下创建一个多级目录JavaWEB\\HTML
        File f3 = new File("E:\\itcast\\JavaWEB\\HTML");
//        System.out.println(f3.mkdir());
        System.out.println(f3.mkdirs());
        System.out.println("--------");

        //需求4:我要在E:\\itcast目录下创建一个文件javase.txt
        File f4 = new File("E:\\itcast\\javase.txt");
//      System.out.println(f4.mkdir());   //创建文件就用创建文件的函数,不然这个会生成一个javase.txt的文件夹的
        System.out.println(f4.createNewFile());
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VItmylBz-1663747806890)(java.assets/image-20210619221744319.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fCBSOVSx-1663747806890)(java.assets/image-20210619221802361.png)]

1.3 File类删除功能

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EYMWTnzd-1663747806890)(java.assets/image-20210625103825493.png)]

1.4 File类判断和获取功能

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DxAnmOFz-1663747806890)(java.assets/image-20210619221910427.png)]

黑马程序员全套Java教程_Java基础入门教程,零基础小白自学Java必备教程_哔哩哔哩_bilibili

package com.itheima;

import java.io.File;

/*
    File类的判断和获取功能:
        public boolean isDirectory():测试此抽象路径名表示的File是否为目录
        public boolean isFile():测试此抽象路径名表示的File是否为文件
        public boolean exists():测试此抽象路径名表示的File是否存在

        public String getAbsolutePath():返回此抽象路径名的绝对路径名字符串
        public String getPath():将此抽象路径名转换为路径名字符串
        public String getName():返回由此抽象路径名表示的文件或目录的名称

        public String[] list():返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
        public File[] listFiles():返回此抽象路径名表示的目录中的文件和目录的File对象数组
 */
public class FileDemo04 {
    public static void main(String[] args) {
        //创建一个File对象
        File f = new File("myFile\\java.txt");

//        public boolean isDirectory():测试此抽象路径名表示的File是否为目录
//        public boolean isFile():测试此抽象路径名表示的File是否为文件
//        public boolean exists():测试此抽象路径名表示的File是否存在
        System.out.println(f.isDirectory());
        System.out.println(f.isFile());
        System.out.println(f.exists());

//        public String getAbsolutePath():返回此抽象路径名的绝对路径名字符串
//        public String getPath():将此抽象路径名转换为路径名字符串
//        public String getName():返回由此抽象路径名表示的文件或目录的名称
        System.out.println(f.getAbsolutePath());
        System.out.println(f.getPath());    //这个是我们封装好的路径
        System.out.println(f.getName());    //文件的名称
        System.out.println("--------");

//        public String[] list():返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
//        public File[] listFiles():返回此抽象路径名表示的目录中的文件和目录的File对象数组
        File f2 = new File("E:\\itcast");

        String[] strArray = f2.list();
        for(String str : strArray) {
            System.out.println(str);
        }
        System.out.println("--------");

        File[] fileArray = f2.listFiles();
        for(File file : fileArray) {
//            System.out.println(file);
//            System.out.println(file.getName());
            if(file.isFile()) {
                System.out.println(file.getName());
            }
        }
    }
}

2 字节流

2.1 IO流概述和分类(inputstream,outputstream)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XFTPC6g0-1663747806890)(java.assets/image-20210620205244239.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-su8xougw-1663747806891)(java.assets/image-20210620205404707.png)]

输入:就是从硬盘读数据到程序

输出:就是从程序把内容写到硬盘

出入以内存为参考

IO流分类:

  • 按照数据的流向
    ​ 输入流:读数据

    ​ 输出流:写数据

  • 按照数据类型来分

    字节流

    ​ 字节输入流;字节输出流

    字符流

    ​ 字符输入流;字符输出流

一般来说,我们说的IO流是按照数据类型来分的

输入流inputstream,读数据

输出流outputstream,写数据

这是两个抽象基类

2.2 字节流写数据(FileOutputStream,write)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f1x4kWli-1663747806891)(java.assets/image-20210620212119447.png)]

package com.itheima_01;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/*
    FileOutputStream:文件输出流用于将数据写入File
        FileOutputStream(String name):创建文件输出流以指定的名称写入文件
 */
public class FileOutputStreamDemo01 {
    public static void main(String[] args) throws IOException {
        //创建字节输出流对象
        //FileOutputStream (String name):创建文件输出流以指定的名称写入文件
        FileOutputStream fos = new FileOutputStream("myByteStream\\fos.txt");
        /*
            做了三件事情:
                A:调用系统功能创建了文件
                B:创建了字节输出流对象
                C:让字节输出流对象指向创建好的文件
         */

        //void write (int b):将指定的字节写入此文件输出流
        fos.write(97);	//b
//        fos.write(57);	//9
//        fos.write(55);	//7

        //最后都要释放资源
        //void close ():关闭此文件输出流并释放与此流相关联的任何系统资源。
        fos.close();
    }
}

2.3 字节流写数据的3种方式(一次-1个字节,1个字节数组,1个字节的部分字节数组)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jA9JmDtF-1663747806891)(java.assets/image-20210620212321692.png)]

package com.itheima_01;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/*
    构造方法:
        FileOutputStream(String name):创建文件输出流以指定的名称写入文件
        FileOutputStream(File file):创建文件输出流以写入由指定的 File对象表示的文件

    写数据的三种方式:
        void write(int b):将指定的字节写入此文件输出流
        一次写一个字节数据

        void write(byte[] b):将 b.length字节从指定的字节数组写入此文件输出流
        一次写一个字节数组数据

        void write(byte[] b, int off, int len):将 len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流
        一次写一个字节数组的部分数据
*/
public class FileOutputStreamDemo02 {
    public static void main(String[] args) throws IOException {
        //FileOutputStream(String name):创建文件输出流以指定的名称写入文件
        FileOutputStream fos = new FileOutputStream("myByteStream\\fos.txt");
       //代码一执行,整个文件都是重新建立的
        //new File(name)
//        FileOutputStream fos = new FileOutputStream(new File("myByteStream\\fos.txt"));

        //FileOutputStream(File file):创建文件输出流以写入由指定的 File对象表示的文件
//        File file = new File("myByteStream\\fos.txt");
//        FileOutputStream fos2 = new FileOutputStream(file);
//        FileOutputStream fos2 = new FileOutputStream(new File("myByteStream\\fos.txt"));

        //void write(int b):将指定的字节写入此文件输出流
//        fos.write(97);
//        fos.write(98);
//        fos.write(99);
//        fos.write(100);
//        fos.write(101);

//        void write(byte[] b):将 b.length字节从指定的字节数组写入此文件输出流
//        byte[] bys = {97, 98, 99, 100, 101};
        //byte[] getBytes():返回字符串对应的字节数组
        byte[] bys = "abcde".getBytes();
//        fos.write(bys);

        //void write(byte[] b, int off, int len):将 len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流	
//        fos.write(bys,0,bys.length);
        fos.write(bys,1,3); //bcd//这个意思是,从索引为1开始,写3个

        //释放资源
        fos.close();
    }
}

2.4 字节流写数据的两个小问题?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PyYZwpyp-1663747806891)(java.assets/image-20210621144536397.png)]

package com.itheima_01;

import java.io.FileOutputStream;
import java.io.IOException;

/*
    字节流写数据的两个小问题:
        1:字节流写数据如何实现换行呢?

        (不同的系统识别换行是不一样的)
            window:\r\n
            linux:\n
            mac:\r

        2:字节流写数据如何实现追加写入呢?
            public FileOutputStream​(String name,boolean append)
                创建文件输出流以指定的名称写入文件。
                如果第二个参数为true ,则字节将写入文件的末尾而不是开头
 */
public class FileOutputStreamDemo03 {
    public static void main(String[] args) throws IOException {
        //创建字节输出流对象
//        FileOutputStream fos = new FileOutputStream("myByteStream\\fos.txt");
        FileOutputStream fos = new FileOutputStream("myByteStream\\fos.txt",true);

        //写数据
        for (int i = 0; i < 10; i++) {
            fos.write("hello".getBytes());
            fos.write("\r\n".getBytes());
        }

        //释放资源
        fos.close();
    }
}

2.5 字节流写数据加异常处理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qkKlIq0d-1663747806892)(java.assets/image-20210621144806656.png)]

因为throw抛出异常后,后面的close()就不会执行了,所以就用finally函数

try。。。catch。。。finally处理异常可以在编译时找到 发生问题的原因,并明确原因

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hnzKJXuh-1663747806892)(java.assets/image-20210621145435409.png)]

package com.itheima;

import java.io.FileOutputStream;
import java.io.IOException;

/*
    字节流写数据加入异常处理
 */
public class FileOutputStreamDemo04 {
    public static void main(String[] args) {
//        try {
//            FileOutputStream fos = new FileOutputStream("myByteStream\\fos.txt");
//            fos.write("hello".getBytes());
//            fos.close();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }

        //加入finally来实现释放资源
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream("myByteStream\\fos.txt");
//            fos = new FileOutputStream("Z:\\myByteStream\\fos.txt");
            fos.write("hello".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

黑马程序员全套Java教程_Java基础入门教程,零基础小白自学Java必备教程_哔哩哔哩_bilibili

2.6 字节流读数据(FileInputStream,read)

2.6.1 一次读一个字节数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z2o5Awk9-1663747806892)(java.assets/image-20210621145900172.png)]

 FileInputStream fis = new FileInputStream("idea_test\\fos.txt");

【fos、fis,老师的这个命名也是非常讲究的】

package com.itheima;

import java.io.FileInputStream;
import java.io.IOException;

/*
    需求:
        把文件fos.txt中的内容读取出来在控制台输出

        FileInputStream:从文件系统中的文件获取输入字节
        FileInputStream(String name):通过打开与实际文件的连接来创建一个FileInputStream,该文件由文件系统中的路径名name命名

    使用字节输入流读数据的步骤:
        1:创建字节输入流对象
        2:调用字节输入流对象的读数据方法
        3:释放资源
 */

public class FileInputStreamDemo01 {
    public static void main(String[] args) throws IOException {
        //创建字节输入流对象
        //FileInputStream(String name)
        FileInputStream fis = new FileInputStream("myByteStream\\fos.txt");

        //调用字节输入流对象的读数据方法
        //int read():从该输入流读取一个字节的数据

        /*
        //第一次读取数据
        int by = fis.read();
        System.out.println(by);
        System.out.println((char)by);

        //第二次读取数据
        by = fis.read();
        System.out.println(by);
        System.out.println((char)by);

        //再多读取两次
        by = fis.read();
        System.out.println(by);
        by = fis.read();
        System.out.println(by);

        //如果达到文件的末尾, -1
        */

        /*
        int by = fis.read();
        while (by != -1) {
            System.out.print((char)by);
            by = fis.read();
        }
        */

        //优化上面的程序
        int by;
        /*
            fis.read():读数据
            by=fis.read():把读取到的数据赋值给by
            by != -1:判断读取到的数据是否是-1
         */
        while ((by=fis.read())!=-1) {
            System.out.print((char)by);
        }

        //释放资源
        fis.close();
    }
}

每次读取一个字节也有3种方式,当读到文件末尾时,返回结果-1

fis.read(),读数据是fis流

案例:复制文本文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4kKTdu7L-1663747806892)(java.assets/image-20210621154904558.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vvJTUPNk-1663747806893)(java.assets/image-20210621154926595.png)]

OutputStream和InputStream是抽象类

package com.itheima_02;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/*
    需求:
        把“E:\\itcast\\窗里窗外.txt”复制到模块目录下的“窗里窗外.txt”

        数据源:
            E:\\itcast\\窗里窗外.txt --- 读数据 --- InputStream --- FileInputStream
        目的地:
            myByteStream\\窗里窗外.txt --- 写数据 --- OutputStream --- FileOutputStream

    思路:
        1:根据数据源创建字节输入流对象
        2:根据目的地创建字节输出流对象
        3:读写数据,复制文本文件(一次读取一个字节,一次写入一个字节)
        4:释放资源
 */
public class CopyTxtDemo {
    public static void main(String[] args) throws IOException {
        //根据数据源创建字节输入流对象
        FileInputStream fis = new FileInputStream("E:\\itcast\\窗里窗外.txt");
        //根据目的地创建字节输出流对象
        FileOutputStream fos = new FileOutputStream("myByteStream\\窗里窗外.txt");

        //读写数据,复制文本文件(一次读取一个字节,一次写入一个字节)
        int by;
        while ((by=fis.read())!=-1) {
            fos.write(by);
        }

        //释放资源
        fos.close();
        fis.close();
    }
}

2.6.2 一次读一个字节数组数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nGCLpz0d-1663747806893)(java.assets/image-20210621161445821.png)]

package com.itheima;

import java.io.FileInputStream;
import java.io.IOException;

/*
    需求:把文件fos.txt中的内容读取出来在控制台输出

    使用字节输入流读数据的步骤:
        1:创建字节输入流对象
        2:调用字节输入流对象的读数据方法
        3:释放资源
 */
public class FileInputStreamDemo02 {
    public static void main(String[] args) throws IOException {
        //创建字节输入流对象
        FileInputStream fis = new FileInputStream("myByteStream\\fos.txt");

        //调用字节输入流对象的读数据方法
        //int read(byte[] b):从该输入流读取最多 b.length个字节的数据到一个字节数组
        /*
        byte[] bys = new byte[5];

        //第一次读取数据
        int len = fis.read(bys);        //这个length不是字节数组的长度,而是实际读取的数据的个数
        System.out.println(len);
        //String(byte[] bytes)      将字节数组的数据转到字符串里面,然后输出
//          string的一个构造方法,直接把字节数组变成字符串

//      System.out.println(new String(bys));
        System.out.println(new String(bys,0,len));

        //第二次读取数据
        len = fis.read(bys);
        System.out.println(len);
//        System.out.println(new String(bys));
        System.out.println(new String(bys,0,len));

        //第三次读取数据
        len = fis.read(bys);
        System.out.println(len);
        //   System.out.println(new String(bys));     //这次只读了四个,所以还有一个上次读的没有替换掉
        //String(byte[] bytes, int offset, int length) 这个方法是只显示数组长度的内容
        System.out.println(new String(bys,0,len));

        //再多读取两次
        len = fis.read(bys);
        System.out.println(len);
        len = fis.read(bys);
        System.out.println(len);
        */

        /*
            hello\r\n
            world\r\n

            第一次:hello
            第二次:\r\nwor
            第三次:ld\r\nr

         */

        byte[] bys = new byte[1024]; //1024及其整数倍
        int len;	 //这个len是实际每次读取的数据的个数
        
        while ((len=fis.read(bys))!=-1) {
            System.out.print(new String(bys,0,len));
        }
		  System.out.println(len);    //此时输出的是-1
        //释放资源
        fis.close();
    }
}

注意:

  • String(byte[] bytes, int offset, int length, Charset charset)

    构建了一种新的 String通过解码指定的字节数组使用指定的 charset。

  • byte[] bys = new byte[1024]; //1024及其整数倍,这个[]里面通常是1024的整倍数

  • int len; //这个len是实际每次读取的数据的个数

2.7 字节缓冲流( BufferOutputStream,BufferedInputStream)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dB5hxYn9-1663747806893)(java.assets/image-20210621170757957.png)]

package com.itheima_03;
import java.io.*;

/*
    字节缓冲流:
        BufferOutputStream
        BufferedInputStream
    构造方法:
        字节缓冲输出流:BufferedOutputStream(OutputStream out)
        字节缓冲输入流:BufferedInputStream(InputStream in)
 */

public class BufferStreamDemo {
    public static void main(String[] args) throws IOException {
        //字节缓冲输出流:BufferedOutputStream(OutputStream out)
//        FileOutputStream fos = new FileOutputStream("myByteStream\\bos.txt");
//        BufferedOutputStream bos = new BufferedOutputStream(fos);
        
        /*
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("myByteStream\\bos.txt"));
        //写数据
        bos.write("hello\r\n".getBytes());
        bos.write("world\r\n".getBytes());
        //释放资源
        bos.close();
        */
        
        //字节缓冲输入流:BufferedInputStream​(InputStream in)
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("myByteStream\\bos.txt"));

        //一次读取一个字节数据
//        int by;
//        while ((by=bis.read())!=-1) {
//            System.out.print((char)by);
//        }
        
        //一次读取一个字节数组数据
        byte[] bys = new byte[1024];
        int len;
        while ((len=bis.read(bys))!=-1) {
            System.out.print(new String(bys,0,len));
        }
        
        //释放资源
        bis.close();
    }
}

注意:字节缓冲流里面存放字节流

package com.itheima_03;
import java.io.*;
public class BufferStreamDemo {
    public static void main(String[] args) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("myByteStream\\bos.txt"));
        byte[] bys = new byte[1024];
        int len;
        while ((len=bis.read(bys))!=-1) {
            System.out.print(new String(bys,0,len));
        }
        bis.close();
    }
}

案例:复制视频

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jFOlwVsL-1663747806893)(java.assets/image-20210623140201975.png)]

package com.itheima_03;

import java.io.*;

/*
    需求:
        把E:\\itcast\\字节流复制图片.avi 复制到模块目录下的 字节流复制图片.avi

    思路:
        1:根据数据源创建字节输入流对象
        2:根据目的地创建字节输出流对象
        3:读写数据,复制图片(一次读取一个字节数组,一次写入一个字节数组)
        4:释放资源

    四种方式实现复制视频,并记录每种方式复制视频的时间
        1:基本字节流一次读写一个字节             共耗时:64565毫秒
        2:基本字节流一次读写一个字节数组          共耗时:107毫秒
        3:字节缓冲流一次读写一个字节             共耗时:405毫秒
        4:字节缓冲流一次读写一个字节数组          共耗时:60毫秒
 */
public class CopyAviDemo {
    public static void main(String[] args) throws IOException {
        //记录开始时间
        long startTime = System.currentTimeMillis();

        //复制视频
//        method1();
//        method2();
//        method3();
        method4();

        //记录结束时间
        long endTime = System.currentTimeMillis();
        System.out.println("共耗时:" + (endTime - startTime) + "毫秒");
    }

    //字节缓冲流一次读写一个字节数组
    public static void method4() throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\itcast\\字节流复制图片.avi"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("myByteStream\\字节流复制图片.avi"));

        byte[] bys = new byte[1024];
        int len;
        while ((len=bis.read(bys))!=-1) {
            bos.write(bys,0,len);
        }
        bos.close();
        bis.close();
    }

    //字节缓冲流一次读写一个字节
    public static void method3() throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\itcast\\字节流复制图片.avi"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("myByteStream\\字节流复制图片.avi"));

        int by;
        while ((by=bis.read())!=-1) {
            bos.write(by);
        }

        bos.close();
        bis.close();
    }


    //基本字节流一次读写一个字节数组
    public static void method2() throws IOException {
        //E:\\itcast\\字节流复制图片.avi
        //模块目录下的 字节流复制图片.avi
        FileInputStream fis = new FileInputStream("E:\\itcast\\字节流复制图片.avi");
        FileOutputStream fos = new FileOutputStream("myByteStream\\字节流复制图片.avi");

        byte[] bys = new byte[1024];
        int len;
        while ((len=fis.read(bys))!=-1) {
            fos.write(bys,0,len);
        }

        fos.close();
        fis.close();
    }

    //基本字节流一次读写一个字节
    public static void method1() throws IOException {
        //E:\\itcast\\字节流复制图片.avi
        //模块目录下的 字节流复制图片.avi
        FileInputStream fis = new FileInputStream("E:\\itcast\\字节流复制图片.avi");
        FileOutputStream fos = new FileOutputStream("myByteStream\\字节流复制图片.avi");

        int by;
        while ((by=fis.read())!=-1) {
            fos.write(by);
        }

        fos.close();
        fis.close();
    }
}

3 字符流

3.1 为什么会出现字符流

注意:字符>字节

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MnDjghzF-1663747806894)(java.assets/image-20210623151238462.png)]

package com.itheima_01;

/*
    需求:字节流读文本文件数据

    一个汉字存储:
        如果是GBK编码,占用2个字节
        如果是UTF-8编码,占用3个字节
 */

import java.io.FileInputStream;
import java.io.IOException;

public class FileInputStreamDemo {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("idea_test\\a.txt");
        int by;
        while((by=fis.read())!=-1){
            System.out.print((char)by);
        }
        fis.close();
    }
}

文本文件:abc

输出结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4sb9rbF9-1663747806894)(java.assets/image-20210623145741162.png)]

文本文件:abc汉字

输出结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AvOTfo6S-1663747806894)(java.assets/image-20210623145813322.png)]

原因:

一个汉字存储:
    如果是GBK编码,占用2个字节
    如果是UTF-8编码,占用3个字节
   因为你是一个字节一个的读的

故,提供了字符流

还有一点疑惑:

用字节流读写文件的时候,为什么没有问题:因为此时,汉字的字节为负数

实例如下:

import java.io.IOException;
import java.util.Arrays;

public class FileInputStreamDemo {
    public static void main(String[] args) throws IOException {
            String s="abc"; //[97, 98, 99]
            String s1="中国";
            byte[] bys=s.getBytes();
            byte[] bys1=s1.getBytes("UTF-8");   //[-28, -72, -83, -27, -101, -67]       此时编译器会将3个字符组成一个汉字
            byte[] bys2=s1.getBytes("GBK");     //[-42, -48, -71, -6]               此时编译器会将2个字符组成一个汉字
            System.out.println(Arrays.toString(bys2));
    }
}

3.2

3.5 字符流写数据的5种方式(OutputStreamWriter,write,flush刷新流)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fEKKxRDk-1663747806894)(java.assets/image-20210623151801863.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZvK7263M-1663747806894)(java.assets/image-20210623155706645.png)]

构造方法:

OutputStreamWriter(OutputStream out):创建一个使用默认字符编码的OutputStreamWriter

void write(int c):写一个字符

package com.itheima_02;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

/*
    构造方法:
        OutputStreamWriter(OutputStream out):创建一个使用默认字符编码的OutputStreamWriter

    写数据的5种方式:
        void write(int c):写一个字符
        void write(char[] cbuf):写入一个字符数组
        void write(char[] cbuf, int off, int len):写入字符数组的一部分
        void write(String str):写一个字符串
        void write(String str, int off, int len):写一个字符串的一部分
 */

public class OutputStreamWriterDemo {
    public static void main(String[] args) throws IOException {
        //字符流写数据不能直接写进文件中,会先放到缓存区中,最终需要通过字节流写,需要用flush()刷新流
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("idea_test\\osw.txt"));
        osw.write(97);  //写一个字符
        osw.flush();    //刷新流
        osw.write(98);
        osw.flush();
        osw.write(99);
        //close()这个方法,关闭流,先刷新
        osw.close();
        //Exception in thread "main" java.io.IOException: Stream closed
      //  osw.write(100);
    }
}

void write(char[] cbuf):写入一个字符数组

字符流write写数据()

OutputStreamWriter:

package com.itheima_02;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

public class OutputStreamWriterDemo {
    public static void main(String[] args) throws IOException {
        //字符流写数据不能直接写进文件中,会先放到缓存区中,最终需要通过字节流写,需要用flush()刷新流
        //OutputStreamWriter(OutputStream out):创建一个使用默认字符编码的OutputStreamWriter
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("myCharStream\\osw.txt"));

        //方法二:void write(char[] cbuf):写入一个字符数组
        char[] chs = {'a', 'b', 'c', 'd', 'e'};
//        osw.write(chs);

        //方法三:void write(char[] cbuf, int off, int len):写入字符数组的一部分
//        osw.write(chs, 0, chs.length);
//        osw.write(chs, 1, 3);

        //方法四:void write(String str):写一个字符串
//        osw.write("abcde");

        //方法五:void write(String str, int off, int len):写一个字符串的一部分
//        osw.write("abcde", 0, "abcde".length());
        osw.write("abcde", 1, 3);

        //释放资源
        osw.close();
        //Exception in thread "main" java.io.IOException: Stream closed
//        osw.write(100);
    }
}

注意:字符流写数据不能直接到文件,需要刷新flush()一下.

实际上字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区再操作文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1Pm6OYbd-1663747806895)(java.assets/162655699.jpg)]

/**
        * flush() 方法是清空,即清空缓冲区数据,就是说
        * 你用读写流的时候,其实数据是先被读到了内存中,
        * 然后用数据写到文件中,当你数据读完的时候不代表你的数据已经写完了,
        * 因为还有一部分有可能留在内存这个缓冲区中.这时候如果你调用了
        * close方法关闭了读写流,那么这部分数据就会丢失,【注意:现在close()在关闭的时候,会先刷新一次】
        * 所以应该再关闭读写流之前先flush(),显得清空数据.
        */
       //刷新就是将内存(缓冲区)中的数据(是一个字节数组)强制写到磁盘/浏览器/控制台/文件

参考链接: 使用字符流 必须刷新缓冲区 flush_Hurricane_m的博客-CSDN博客

3.6 字符流读数据的两种方式(InputStreamReader,read)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KpGBtNS0-1663747806895)(java.assets/image-20210623155752234.png)]

字节流和字符流读数据读的内容是一样的,只是方式不一样

package com.itheima_02;
/*	
    构造方法:
        InputStreamReader(InputStream in):创建一个使用默认字符集的InputStreamReader

    读数据的2种方式:
        int read():一次读一个字符数据
        int read(char[] cbuf):一次读一个字符数组数据
 */

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;

public class InputStreamReaderDemo {
    public static void main(String[] args) throws IOException {
        InputStreamReader isr = new InputStreamReader(new FileInputStream("idea_test\\osw.txt"));
//      第一种方式:
//      int read():一次读一个字符数据
//        int ch;
//        while((ch=isr.read())!=-1){
//            System.out.print((char)ch);
//        }
//        isr.close();
        //第二种方式:
        // int read(char[] cbuf):一次读一个字符数组数据
        char[] chs=new char[1024];
        int len;
        while((len =isr.read(chs))!=-1){
            System.out.println(new String(chs,0,len));
        }
        isr.close();
    }
}

案例:复制java文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oRilW7FT-1663747806895)(java.assets/image-20210623183524821.png)]

package com.itheima_03;

import java.io.*;

/*
    需求:
        把模块目录下的ConversionStreamDemo.java 复制到模块目录下的 Copy.java

    思路:
        1:根据数据源创建字符输入流对象
        2:根据目的地创建字符输出流对象
        3:读写数据,复制文件
        4:释放资源
 */
public class CopyJavaDemo01 {
    public static void main(String[] args) throws IOException {
        //根据数据源创建字符输入流对象
        InputStreamReader isr = new InputStreamReader(new FileInputStream("myCharStream\\ConversionStreamDemo.java"));
        //根据目的地创建字符输出流对象
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("myCharStream\\Copy.java"));

        //读写数据,复制文件
        //一次读写一个字符数据
//        int ch;
//        while ((ch=isr.read())!=-1) {
//            osw.write(ch);
//        }
//一次读写一个字符数组数据
        char[] chs = new char[1024];
        int len;
        while ((len=isr.read(chs))!=-1) {
            osw.write(chs,0,len);
        }
        //释放资源
        osw.close();
        isr.close();
    }
}

案例:复制java文件(改进版使用FileReader,FileWriter)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2NpfxePf-1663747806895)(java.assets/image-20210623185251736.png)]

注意:如果在字符流中涉及到编码和解码问题,还得使用转换流inputstreamreader和outputstreamreader

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s2kjlr40-1663747806896)(java.assets/image-20210623205724958.png)]

package com.itheima_03;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/*
    需求:
        把模块目录下的ConversionStreamDemo.java 复制到模块目录下的 Copy.java

    数据源和目的地的分析
        数据源:myCharStream\\ConversionStreamDemo.java --- 读数据 --- Reader --- InputStreamReader --- FileReader
        目的地: myCharStream\\ Copy.java --- 写数据 --- Writer --- OutputStreamWriter --- FileWriter

    思路:
        1:根据数据源创建字符输入流对象
        2:根据目的地创建字符输出流对象
        3:读写数据,复制文件
        4:释放资源
 */
public class CopyJavaDemo02 {
    public static void main(String[] args) throws IOException {
        //根据数据源创建字符输入流对象
        FileReader fr = new FileReader("myCharStream\\ConversionStreamDemo.java");
        //根据目的地创建字符输出流对象
        FileWriter fw = new FileWriter("myCharStream\\Copy.java");

//读写数据,复制文件
//        int ch;
//        while ((ch=fr.read())!=-1) {
//            fw.write(ch);
//        }        
        char[] chs = new char[1024];
        int len;
        while ((len=fr.read(chs))!=-1) {
            fw.write(chs,0,len);
        }
        //释放资源
        fw.close();
        fr.close();
    }
}

3.7 字符缓存流(BufferedWriter,BufferedReader)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9pnneUYt-1663747806896)(java.assets/image-20210622112448656.png)]

BufferedWriter

BufferedReader

缓冲流:用来提高读写效率

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ykeORUI1-1663747806896)(java.assets/image-20210624103607089.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FHpbmjmV-1663747806896)(java.assets/image-20210624103650824.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ls7lIKfY-1663747806897)(java.assets/image-20210624103703345.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S7D4qiWh-1663747806897)(java.assets/image-20210623210827841.png)]

通过源码知道:这两个缓冲流封装的是长度为8192个字符的字符数组

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kQWkkOQk-1663747806897)(java.assets/image-20210624104855129.png)]

package com.itheima_04;

import java.io.*;

/*
    字符缓冲流:
        BufferedWriter:将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可以指定缓冲区大小,或者可以接受默认大小。默认值足够大,可用于大多数用途
        BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取,可以指定缓冲区大小,或者可以使用默认大小。 默认值足够大,可用于大多数用途

    构造方法:
        BufferedWriter(Writer out)
        BufferedReader(Reader in)
 */
public class BufferedStreamDemo01 {
    public static void main(String[] args) throws IOException {
        //BufferedWriter(Writer out)
//        FileWriter fw = new FileWriter("idea_test\\bw.txt");
//        BufferedWriter bw = new BufferedWriter(fw);
        BufferedWriter bw = new BufferedWriter(new FileWriter("idea_test\\bw.txt"));

        bw.write("hello\r\n");
        bw.write("world\r\n");

        bw.close();

        //BufferedReader(Reader in)
       // BufferedReader br = new BufferedReader(new FileReader("myCharStream\\bw.txt"));

        //一次读取一个字符数据
//        int ch;
//        while ((ch=br.read())!=-1) {
//            System.out.print((char)ch);
//        }

//        //一次读取一个字符数组数据
//        char[] chs = new char[1024];
//        int len;
//        while ((len=br.read(chs))!=-1) {
//            System.out.print(new String(chs,0,len));
//        }
//
//        br.close();

    }
}

package com.itheima_04;
import java.io.*;
public class BufferedStreamDemo01 {
    public static void main(String[] args) throws IOException {
        BufferedWriter bw = new BufferedWriter(new FileWriter("idea_test\\bw.txt"));
        bw.write("hello\r\n");
        bw.write("world\r\n");
        bw.close();
    }
}

案例:复制java文件(字符缓冲流改进版)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WPIaQI26-1663747806897)(java.assets/image-20210623234211872.png)]

package com.itheima_03;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/*
    需求:
        把模块目录下的ConversionStreamDemo.java 复制到模块目录下的 Copy.java

    数据源和目的地的分析
        数据源:myCharStream\\ConversionStreamDemo.java --- 读数据 --- Reader --- InputStreamReader --- FileReader
        目的地: myCharStream\\ Copy.java --- 写数据 --- Writer --- OutputStreamWriter --- FileWriter

    思路:
        1:根据数据源创建字符输入流对象
        2:根据目的地创建字符输出流对象
        3:读写数据,复制文件
        4:释放资源
 */

     
        
public class CopyJavaDemo02 {
    public static void main(String[] args) throws IOException {
        //根据数据源创建字符输入流对象
        FileReader fr = new FileReader("myCharStream\\ConversionStreamDemo.java");
        //根据目的地创建字符输出流对象
        FileWriter fw = new FileWriter("myCharStream\\Copy.java");

        //读写数据,复制文件
//        int ch;
//        while ((ch=fr.read())!=-1) {
//            fw.write(ch);
//        }

        char[] chs = new char[1024];
        int len;
        while ((len=fr.read(chs))!=-1) {
            fw.write(chs,0,len);
        }

        //释放资源
        fw.close();
        fr.close();
    }
}

3.8 字符缓冲流特有功能

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G3TmQvno-1663747806898)(java.assets/image-20210624103121041.png)]

package com.itheima_04;
import java.io.*;
/*
    字符缓冲流的特有功能
        BufferedWriter:
            void newLine():写一行行分隔符,行分隔符字符串由系统属性定义

        BufferedReader:
            public String readLine():读一行文字。
                结果包含行的内容的字符串,不包括任何行终止字符,如果流的结尾已经到达,则为null
 */

public class BufferedStreamDemo02 {
    public static void main(String[] args) throws IOException {
     /*
        //创建字符缓冲输出流
        BufferedWriter bw = new BufferedWriter(new FileWriter("idea_test\\bw.txt"));
        //写数据
        for (int i=0;i<10;i++){
            bw.write("hello"+i);
//            bw.write("\r\n");
            bw.newLine();
            bw.flush();
        }
        //释放资源
        bw.close();
        */

        //创建字符缓冲输入流读数据
        BufferedReader br = new BufferedReader(new FileReader("idea_test\\bw.txt"));
//        public String readLine():读一行文字。不包括换行,所以要自己添加换行
//        //第一次读取数据
//        String line=br.readLine();
//        System.out.println(line);
//          //第二次读取数据
//       line=br.readLine();
//        System.out.println(line);
//          //在多读两次
//       line=br.readLine();
//        System.out.println(line);
//        line=br.readLine();
        System.out.println(line);
        String line;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
        br.close();
    }
}

案例:复制java文件(字符缓冲流特有功能改进版)字符流复制文件最常用方式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ekzxEXY7-1663747806898)(java.assets/image-20210624111026373.png)]

package com.itheima_04;

import java.io.*;

/*
    需求:
        把模块目录下的ConversionStreamDemo.java 复制到模块目录下的 Copy.java

    思路:
        1:根据数据源创建字符缓冲输入流对象
        2:根据目的地创建字符缓冲输出流对象
        3:读写数据,复制文件
            使用字符缓冲流特有功能实现
        4:释放资源
 */
public class CopyJavaDemo02 {
    public static void main(String[] args) throws IOException {
        //根据数据源创建字符缓冲输入流对象
        BufferedReader br = new BufferedReader(new FileReader("myCharStream\\ConversionStreamDemo.java"));
        //根据目的地创建字符缓冲输出流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("myCharStream\\Copy.java"));

        //读写数据,复制文件
        //使用字符缓冲流特有功能实现
        String line;
        while ((line=br.readLine())!=null) {
            bw.write(line);//该方法不会换行,所以需要换行的方法
            bw.newLine();//行分隔符
            bw.flush();	//刷新一下,事实证明,没有这句,仍然可以
        }

        //释放资源
        bw.close();
        br.close();
    }
}

3.9 IO流小结

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J8v03Aqm-1663747806898)(java.assets/image-20210624170059328.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M71GJVWX-1663747806898)(java.assets/image-20210624170207878.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vNcudyzO-1663747806899)(java.assets/image-20210624170335872.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZDmuBrat-1663747806899)(java.assets/image-20210624195527382.png)]

案例:集合到文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vSnVb85H-1663747806899)(java.assets/image-20210624195652190.png)]

package com.itheima_05;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

/*
    需求:
        把ArrayList集合中的字符串数据写入到文本文件。要求:每一个字符串元素作为文件中的一行数据

    思路:
        1:创建ArrayList集合
        2:往集合中存储字符串元素
        3:创建字符缓冲输出流对象
        4:遍历集合,得到每一个字符串数据
        5:调用字符缓冲输出流对象的方法写数据
        6:释放资源
 */
 
public class ArrayListToTxtDemo {
    public static void main(String[] args) throws IOException {
        //创建ArrayList集合
        ArrayList<String> array = new ArrayList<String>();

        //往集合中存储字符串元素
        array.add("hello");
        array.add("world");
        array.add("java");

        //创建字符缓冲输出流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("myCharStream\\array.txt"));

        //遍历集合,得到每一个字符串数据
        for(String s : array) {
            //调用字符缓冲输出流对象的方法写数据
            bw.write(s);
            bw.newLine();
            bw.flush();
        }

        //释放资源
        bw.close();
    }
}

注意:说明文件的内容可能来自于集合

案例:文件到集合

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3BH7bBl6-1663747806899)(java.assets/image-20210624204611610.png)]

package com.itheima_05;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

/*
    需求:
        把文本文件中的数据读取到集合中,并遍历集合。要求:文件中每一行数据是一个集合元素

    思路:
        1:创建字符缓冲输入流对象
        2:创建ArrayList集合对象
        3:调用字符缓冲输入流对象的方法读数据
        4:把读取到的字符串数据存储到集合中
        5:释放资源
        6:遍历集合
 */
public class TxtToArrayListDemo {
    public static void main(String[] args) throws IOException {
        //创建字符缓冲输入流对象
        BufferedReader br = new BufferedReader(new FileReader("myCharStream\\array.txt"));

        //创建ArrayList集合对象
        ArrayList<String> array = new ArrayList<String>();

        //调用字符缓冲输入流对象的方法读数据
        String line;
        while ((line=br.readLine())!=null) {
            //把读取到的字符串数据存储到集合中
            array.add(line);
        }

        //释放资源
        br.close();

        //遍历集合
        for(String s : array) {
            System.out.println(s);
        }
    }
}

案例:点名器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M0PdtqxW-1663747806900)(java.assets/image-20210624210526135.png)]

package com.itheima_05;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;

/*
    需求:
        我有一个文件里面存储了班级同学的姓名,每一个姓名占一行,要求通过程序实现随点名器

    思路:
        1:创建字符缓冲输入流对象
        2:创建ArrayList集合对象
        3:调用字符缓冲输入流对象的方法读数据
        4:把读取到的字符串数据存储到集合中
        5:释放资源
        6:使用Random产生一个随机数,随机数的范围在:[0,集合的长度)
        7:把第6步产生的随机数作为索引到ArrayList集合中获取值
        8:把第7步得到的数据输出在控制台
 */
public class CallNameDemo {
    public static void main(String[] args) throws IOException {
        //创建字符缓冲输入流对象
        BufferedReader br = new BufferedReader(new FileReader("idea_test\\array.txt"));

        //创建ArrayList集合对象
        ArrayList<String> array = new ArrayList<String>();

        //调用字符缓冲输入流对象的方法读数据
        String line;
        while ((line=br.readLine())!=null) {
            //把读取到的字符串数据存储到集合中
            array.add(line);
        }
        //释放资源
        br.close();

        //使用Random产生一个随机数,随机数的范围在:[0,集合的长度)
        Random r = new Random();
        int index = r.nextInt(array.size());    
        //size()数组的长度
        //nextInt下一个伪随机、均匀分布的 int价值从这个随机数生成器的序列


        //把第6步产生的随机数作为索引到ArrayList集合中获取值
        String name = array.get(index);

        //把第7步得到的数据输出在控制台
        System.out.println("幸运者是:" + name);
    }
}

4 特殊操作流

4.1 标准输入输出流

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZiSJJQZv-1663747806900)(java.assets/image-20210624215117675.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4IIHHA7Z-1663747806900)(java.assets/image-20210624211801925.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LBOsFyzT-1663747806900)(java.assets/image-20210624211841446.png)]

标准输入流

package com.itheima_05;


import java.io.IOException;
import java.io.InputStream;

/*
    public static final InputStream in:标准输入流。通常该流对应于键盘输入或由主机环境或用户指定的另一个输入源
 */
public class SystemInDemo {
    public static void main(String[] args) throws IOException {
        InputStream is=System.in;
        int by;
        while ((by= is.read())!=-1){
            System.out.print((char)by); //因为汉字是三个字节,这个是按照一个一个读的
        }
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pt4shwSB-1663747806900)(java.assets/image-20210624213048269.png)]

package com.itheima_05;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

/*
    public static final InputStream in:标准输入流。通常该流对应于键盘输入或由主机环境或用户指定的另一个输入源
 */
public class SystemInDemo {
    public static void main(String[] args) throws IOException {
        // InputStream is=System.in;    //1
//        int by;
//        while ((by= is.read())!=-1){
//            System.out.print((char)by);
//        }

        //如何把字节流转换成字符流?用转换流
        //InputStreamReader isr=new InputStreamReader(is); //2
        //字符流能不能实现一次读取一行数据呢?可以
        //一次读取一行数据是字符缓冲流特有的方法
       // BufferedReader br=new BufferedReader(isr);//3
        //不过上面的三句话可以用一句来实现
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        //我们把System.in这个字节流通过转换流转换成字符流,再通过bufferreader包装成字符缓冲输入流,
        // 真正底层读数据的还是用到的是底层的字节流
        System.out.println("请输入一个字符串:");
        String line= br.readLine(); //用一个字符串来接收
        System.out.println("你输入的字符串是:"+line);
        System.out.println("请输入一个整数:");
        int i = Integer.parseInt(br.readLine());        //因为我们得到的是字符串,如果我们想要得到int类型的,就要用这个来转换
        System.out.println("你输入的整数是:" + i);

    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qPU4r2GK-1663747806901)(java.assets/image-20210624214909963.png)]

package com.itheima_05;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Scanner;

/*
    public static final InputStream in:标准输入流。通常该流对应于键盘输入或由主机环境或用户指定的另一个输入源
 */
public class SystemInDemo {
    public static void main(String[] args) throws IOException {
        //自己实现键盘录入数据太麻烦了,所以Java就提供了一个类供我们使用
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个字符串:");
        String name=sc.nextLine();
        System.out.println("你输入的字符串是:"+name);
        System.out.println("请输入一个整数:");
        int i = sc.nextInt();
        System.out.println("你输入的整数是:" + i);   
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HflBaPZr-1663747806901)(java.assets/image-20210624215646620.png)]

标准输出流

还有没看的:黑马程序员全套Java教程_Java基础入门教程,零基础小白自学Java必备教程_哔哩哔哩_bilibili

讲的是标准输出流

package com.itheima_01;

import java.io.PrintStream;

/*
    public static final PrintStream out:标准输出流。通常该流对应于显示输出或由主机环境或用户指定的另一个输出目标
 */
public class SystemOutDemo {
    public static void main(String[] args) {
        //public static final PrintStream out:标准输出流
        PrintStream ps = System.out;

        //能够方便地打印各种数据值
//        ps.print("hello");
//        ps.print(100);

//        ps.println("hello");
//        ps.println(100);

        //System.out的本质是一个字节输出流
        System.out.println("hello");
        System.out.println(100);

        System.out.println();
//        System.out.print();
    }
}

4.2 打印流

字节打印流

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Txf36tuI-1663747806901)(java.assets/image-20210628153202005.png)]

字节输出流,说明是用来写数据的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UvqEhHjc-1663747806901)(java.assets/image-20210628155049006.png)]

package com.itheima_02;

import java.io.IOException;
import java.io.PrintStream;

/*
    打印流的特点:
        只负责输出数据,不负责读取数据
        有自己的特有方法

    字节打印流
        PrintStream(String fileName):使用指定的文件名创建新的打印流
 */
public class PrintStreamDemo {
    public static void main(String[] args) throws IOException {
        //PrintStream(String fileName):使用指定的文件名创建新的打印流
        PrintStream ps = new PrintStream("myOtherStream\\ps.txt");

        //写数据
        //字节输出流有的方法
//        ps.write(97);

        //使用特有方法写数据
//        ps.print(97);
//        ps.println();
//        ps.print(98);
        ps.println(97);
        ps.println(98);


        //释放资源
        ps.close();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V5HmpKr2-1663747806902)(java.assets/image-20210628155329296.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wTAUXixZ-1663747806902)(java.assets/image-20210628155524023.png)]

看其继承体系,继承writer,所以是字符输出流,所以我们应该看其写数据的方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jGyrtxv6-1663747806902)(java.assets/image-20210628155545175.png)]

字符打印流

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-InqXtFZd-1663747806902)(java.assets/image-20210628155736086.png)]

package com.itheima_02;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

/*
    字符打印流的构造方法:
        PrintWriter(String fileName) :使用指定的文件名创建一个新的PrintWriter,而不需要自动执行行刷新

        PrintWriter(Writer out, boolean autoFlush):创建一个新的PrintWriter
            out:字符输出流
            autoFlush: 一个布尔值,如果为真,则println , printf ,或format方法将刷新输出缓冲区
 */
public class PrintWriterDemo {
    public static void main(String[] args) throws IOException {
        //PrintWriter(String fileName) :使用指定的文件名创建一个新的PrintWriter,而不需要自动执行行刷新
//        PrintWriter pw = new PrintWriter("myOtherStream\\pw.txt");

//        pw.write("hello");
//        pw.write("\r\n");
//        pw.flush();
//        pw.write("world");
//        pw.write("\r\n");
//        pw.flush();

//        pw.println("hello");
        /*
            pw.write("hello");
            pw.write("\r\n");
         */
//        pw.flush();
//        pw.println("world");
//        pw.flush();

        //PrintWriter(Writer out, boolean autoFlush):创建一个新的PrintWriter
        PrintWriter pw = new PrintWriter(new FileWriter("myOtherStream\\pw.txt"),true);
//        PrintWriter pw = new PrintWriter(new FileWriter("myOtherStream\\pw.txt"),false);

        pw.println("hello");
        /*
            pw.write("hello");
            pw.write("\r\n");
            pw.flush();
         */
        pw.println("world");

        pw.close();
    }
}

案例:复制java文件(打印流改进版)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zgnysw8r-1663747806903)(java.assets/image-20210628161338704.png)]

package com.itheima_02;

import java.io.*;

    /*
        需求:
            把模块目录下的PrintStreamDemo.java 复制到模块目录下的 Copy.java

        思路:
            1:根据数据源创建字符输入流对象
            2:根据目的地创建字符输出流对象
            3:读写数据,复制文件
            4:释放资源
    */
public class CopyJavaDemo {
    public static void main(String[] args) throws IOException {
        /*
        //根据数据源创建字符输入流对象
        BufferedReader br = new BufferedReader(new FileReader("myOtherStream\\PrintStreamDemo.java"));
        //根据目的地创建字符输出流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("myOtherStream\\Copy.java"));

        //读写数据,复制文件
        String line;
        while ((line=br.readLine())!=null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }

        //释放资源
        bw.close();
        br.close();
        */

        //根据数据源创建字符输入流对象
        BufferedReader br = new BufferedReader(new FileReader("myOtherStream\\PrintStreamDemo.java"));
        //根据目的地创建字符输出流对象
        PrintWriter pw = new PrintWriter(new FileWriter("myOtherStream\\Copy.java"),true);

        //读写数据,复制文件
        String line;
        while ((line=br.readLine())!=null) {
            pw.println(line);
        }

        //释放资源//这个关闭资源好像也有顺序,就是先开的后关,后开的先关
        pw.close();
        br.close();
    }
}

4.3 对象序列化流

对象序列化流

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wIlcafMv-1663747806903)(java.assets\image-20220613184813774.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w9oRtOu9-1663747806903)(java.assets/image-20210628165306177.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EjSxMKRB-1663747806903)(java.assets/image-20210629102042626.png)]

package com.itheima_03;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

/*
    对象序列化流
        构造方法:
            ObjectOutputStream(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream

        序列化对象的方法:
            void writeObject(Object obj):将指定的对象写入ObjectOutputStream

    NotSerializableException:抛出一个实例需要一个Serializable接口。 序列化运行时或实例的类可能会抛出此异常

    类的序列化由实现java.io.Serializable接口的类启用。 不实现此接口的类将不会使任何状态序列化或反序列化
 */
public class ObjectOutputStreamDemo {
    public static void main(String[] args) throws IOException {
        //ObjectOutputStream(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("myOtherStream\\oos.txt"));

        //创建对象
        Student s = new Student("林青霞",30);

        //void writeObject(Object obj):将指定的对象写入ObjectOutputStream
        oos.writeObject(s);

        //释放资源
        oos.close();
    }
}

package com.itheima_03;

import java.io.Serializable;
//类要想实现序列化,必须要实现这个接口,这只是一个标识,里面没有方法要重写
public class Student implements Serializable {
    private static final long serialVersionUID = 42L;
    private String name;
//    private int age;
    private transient int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.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 String toString() {
//        return "Student{" +
//                "name='" + name + '\'' +
//                ", age=" + age +
//                '}';
//    }
}

运行结果截图:

对象反序列化流

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jBPuiFZN-1663747806904)(java.assets/image-20210629103722095.png)]

package com.itheima_03;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

/*
    构造方法:
        ObjectInputStream​(InputStream in):创建从指定的InputStream读取的ObjectInputStream

    反序列化对象的方法:
        Object readObject​():从ObjectInputStream读取一个对象
 */
public class ObjectInputStreamDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //ObjectInputStream​(InputStream in):创建从指定的InputStream读取的ObjectInputStream
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("myOtherStream\\oos.txt"));

        //Object readObject​():从ObjectInputStream读取一个对象
        Object obj = ois.readObject();

        Student s = (Student) obj;
        System.out.println(s.getName() + "," + s.getAge());

        ois.close();
    }
}

还有一集

黑马程序员全套Java教程_Java基础入门教程,零基础小白自学Java必备教程_哔哩哔哩_bilibili

参考链接:序列化和反序列化的详解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5vhHQsrO-1663747806904)(java.assets/image-20210626191118764.png)]

多线程

1 多线程

1.1 进程

进程:是正在运行的程序

  • 是系统进行资源分配和调用的独立单位
  • 每个进程都有它自己的内存空间和系统资源

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bm0fXMjL-1663747806904)(java.assets/image-20210626160630047.png)]

1.2 线程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yeEr4jwL-1663747806904)(java.assets/image-20210626161252498.png)]

单线程:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nZSiJ00C-1663747806905)(java.assets/image-20210626161458160.png)]

多线程:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PhyAVupp-1663747806905)(java.assets/image-20210626161716883.png)]

1.3 多线程的实现方式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sMZdgypF-1663747806905)(java.assets/image-20210626161935005.png)]

这个thread类继承object类,已经实现了runnable接口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QcQeW23a-1663747806905)(java.assets/image-20211127180131709.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-duMaAplZ-1663747806905)(java.assets/image-20211127180237973.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hBav34kf-1663747806906)(java.assets/image-20210626163339724.png)]

jvm:java虚拟机

为什么要重写run方法

因为在mythread里面有很多要执行的程序,重写run,里面只放你要运行的内容

代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KrI7fLKq-1663747806906)(java.assets/image-20210626163404347.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vyORTXfa-1663747806906)(java.assets/image-20210626163424788.png)]

直接调用run方法,并不会启动线程,而是单纯的输出run方法中的内容罢了,要通过start方法才行

执行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-06GJT0ex-1663747806906)(java.assets/image-20210626163247402.png)]

1.4 设置和获取线程名称*(讲源码)

黑马程序员全套Java教程_Java基础入门教程,零基础小白自学Java必备教程_哔哩哔哩_bilibili

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VzGjXnr0-1663747806907)(java.assets/image-20210626172816242.png)]

package com.itheima_02;

public class MyThread extends Thread {

    public MyThread() {}

    public MyThread(String name) {
        super(name);    //调用的父类的带参构造方法
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName()+":"+i);
        }
    }
}

/*
private String name;

public Thread() {
    this(null, null, "Thread-" + nextThreadNum(), 0);
}

public Thread(String name) {
    this(null, null, name, 0);
}

public Thread(ThreadGroup group, Runnable target, String name,
                  long stackSize) {
    this(group, target, name, stackSize, null, true);
}

private Thread(ThreadGroup g, Runnable target, String name,
                   long stackSize, AccessControlContext acc,
                   boolean inheritThreadLocals) {
    this.name = name;
}

public final synchronized void setName(String name) {
    this.name = name;
}

public final String getName() {
    return name;
}

private static int threadInitNumber; //0,1,2
private static synchronized int nextThreadNum() {
    return threadInitNumber++;//0,1,...
}

 */
package com.itheima_02;

/*
    Thread类中获取和设置线程名称的方法
        void setName(String name):将此线程的名称更改为等于参数 name
        String getName():返回此线程的名称
 */
public class MyThreadDemo {
    public static void main(String[] args) {
//        MyThread my1 = new MyThread();
//        MyThread my2 = new MyThread();
//
//        //void setName(String name):将此线程的名称更改为等于参数 name
//        my1.setName("高铁");
//        my2.setName("飞机");

        //Thread(String name)
//        MyThread my1 = new MyThread("高铁");
//        MyThread my2 = new MyThread("飞机");
//
//        my1.start();
//        my2.start();

        //static Thread currentThread() 返回对当前正在执行的线程对象的引用
        System.out.println(Thread.currentThread().getName());
    }
}

1.5线程调度

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yw9z883L-1663747806907)(java.assets/image-20210626181341491.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-adOUyjb6-1663747806907)(java.assets/image-20211129113217834.png)]

package com.itheima_03;

/*
    Thread类中设置和获取线程优先级的方法
        public final void setPriority(int newPriority):更改此线程的优先级
        public final int getPriority():返回此线程的优先级
 */
public class ThreadPriorityDemo {
    public static void main(String[] args) {
        ThreadPriority tp1 = new ThreadPriority();
        ThreadPriority tp2 = new ThreadPriority();
        ThreadPriority tp3 = new ThreadPriority();

        tp1.setName("高铁");
        tp2.setName("飞机");
        tp3.setName("汽车");

        //public final int getPriority():返回此线程的优先级
//        System.out.println(tp1.getPriority()); //5
//        System.out.println(tp2.getPriority()); //5
//        System.out.println(tp3.getPriority()); //5

        //public final void setPriority(int newPriority):更改此线程的优先级
//        tp1.setPriority(10000); //IllegalArgumentException
//        System.out.println(Thread.MAX_PRIORITY); //10
//        System.out.println(Thread.MIN_PRIORITY); //1
//        System.out.println(Thread.NORM_PRIORITY); //5

        //设置正确的优先级,线程优先级高,只能表示获取cpu时间片的几率的高,并不是每一次都会跑在最前面
        tp1.setPriority(5);
        tp2.setPriority(10);
        tp3.setPriority(1);


        tp1.start();
        tp2.start();
        tp3.start();
    }
}

1.6 线程控制

线程守护

线程休眠

线程死亡

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-om2m4ZdM-1663747806907)(java.assets/image-20210626181551313.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Nbh03frF-1663747806908)(java.assets/image-20210626182600690.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zEjrlT2x-1663747806908)(java.assets/image-20210626182708942.png)]

每输出一次,就要线程休眠1秒

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AUHmW0Ls-1663747806908)(java.assets/image-20210626182718282.png)]


void join():等待这个线程死亡

package com.itheima_04;

public class ThreadJoin extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName() + ":" + i);
        }
    }
}
package com.itheima_04;
/*
    void join():等待这个线程死亡
 */
public class ThreadJoinDemo {
    public static void main(String[] args) {
        ThreadJoin tj1 = new ThreadJoin();
        ThreadJoin tj2 = new ThreadJoin();
        ThreadJoin tj3 = new ThreadJoin();

        tj1.setName("康熙");
        tj2.setName("四阿哥");
        tj3.setName("八阿哥");

        tj1.start();
        try {
            tj1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        tj2.start();
        tj3.start();
    }
}

守护线程

package dch.thread04;

public class ThreadDaemon extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName() + ":" + i);
        }
    }
}

package dch.thread04;

public class ThreadDaemonDemo {
    public static void main(String[] args) {
        ThreadDaemon td1=new ThreadDaemon();
        ThreadDaemon td2=new ThreadDaemon();

        td1.setName("关羽");
        td2.setName("张飞");

        //设置主线程(main)为刘备,刘备挂了,张飞关羽也能长在
        Thread.currentThread().setName("刘备");
        //设置守护线程
        td1.setDaemon(true);
        td2.setDaemon(true);

        td1.start();
        td2.start();

        for(int i=0; i<10; i++) {
            System.out.println(Thread.currentThread().getName()+":"+i);
        }

    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ii2CYy4S-1663747806908)(java.assets/image-20210626184507885.png)]

runnable,是实现的接口,所以不能用thread类中的getname方法

首先拿到当前线程,然后再使用getname方法

​ 不能直接使用getname方法,因为这个类没有继承thread,只是实现了runnable方法

1.7 线程的生命周期

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zSzcb6Im-1663747806909)(java.assets/image-20210626184947619.png)]

1.8 多线程的实现方式

看jdk文档

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MZQXMBa7-1663747806909)(java.assets/image-20210626191027283.png)]

package dch.thread05;
//通过实现接口的方式来实现多线程,不影响他再继承其他的类
public class MyRunnable implements Runnable {
//实现runnable接口,并没有继承thread类,好处:将来可以有自己的父类,
    @Override
    public void run() {
        for (int i=0;i<100;i++){
            //这个方法会报错,因为这个类只是实现了Runnable接口,和Thread类没有关系,
            //不能直接调用Thread类中的方法
//            System.out.println(getName()+":"+i);
            //我们先拿到当前线程,然后再去拿这个名字,就可以了
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}
package dch.thread05;
/*
    方式2:实现Runnable接口
        1:定义一个类MyRunnable实现Runnable接口
        2:在MyRunnable类中重写run()方法
        3:创建MyRunnable类的对象
        4:创建Thread类的对象,把MyRunnable对象作为构造方法的参数
        5:启动线程
 */

public class MyRunnableDemo {
    public static void main(String[] args) {
        //创建myrunable类对象
        MyRunnable my=new MyRunnable();
        //创建thread类对象,把myrunnable对象作为构造方法的参数
        //Thread(Runnable target)
//        Thread t1=new Thread(my);
//        Thread t2=new Thread(my);
        //   Thread(Runnable target, String name)
        //将myRunnable实现类的对象作为参数传递,可以将myRunnable看作同一个资源,由多个线程去使用
        Thread t1=new Thread(my,"高铁"); 
        Thread t2=new Thread(my,"飞机");
    }
}

2 线程同步

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ABwzynqy-1663747806909)(java.assets/image-20210626191336746.png)]

2.1 卖票案例的思考

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-970gF5Hl-1663747806909)(java.assets/image-20211129172519450.png)]

2.2 卖票案例数据安全问题的解决

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BUWXhjrC-1663747806910)(java.assets/image-20211129173649918.png)]

2.3 同步代码块

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gH9ywbWz-1663747806910)(java.assets/image-20211129174623201.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bx5S5PSW-1663747806910)(java.assets/image-20211129173938034.png)]

正确上锁方式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xLS03csS-1663747806910)(java.assets/image-20211129174539755.png)]

2.4 同步方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KmmSHXQl-1663747806910)(java.assets/image-20211129180337238.png)]

2.5 线程安全的类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8AYQ3viV-1663747806911)(java.assets/image-20211129200930557.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g1KbaBPE-1663747806911)(java.assets/image-20211129200943626.png)]

hashtable的源码中有同步代码块,所以是线程安全的类

hashmap里面的方法,没有加同步代码块,所以是线程不安全类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s3ZDItEi-1663747806911)(java.assets/image-20211129201604085.png)]

这三个类都是加了

synchronized关键字的,所以是线程安全类

2.6 Lock锁

3 生产者消费者

3.1 生产者消费者模式概述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GJNNrYFa-1663747806911)(java.assets/image-20210627093316330.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2KIXsCyM-1663747806912)(java.assets/image-20210627093416861.png)]

3.2 生产者消费者案例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YRfcUoXP-1663747806912)(java.assets/image-20210627093646976.png)]

黑马程序员全套Java教程_Java基础入门视频教程,零基础小白自学Java必备教程_哔哩哔哩_bilibili

4 动力节点多线程

视频链接:

Java多线程实战精讲-带你一次搞明白Java多线程高并发_哔哩哔哩_bilibili

getid获取线程编号

package com.wkcto.threadmethod.p5yield;

/**
 * @Author: 从南到北
 * @Date: 2022/01/06/12:38
 *
 *  输出线程id和名字
 */
public class SubThread5 extends Thread{

    @Override
    public void run() {
        System.out.println("currentName:"+Thread.currentThread().getName()+","+"cuttentgetID:"+this.getId());
    }

}

package com.wkcto.threadmethod.p5yield;

/**
 * @Author: 从南到北
 * @Date: 2022/01/06/13:11
 */
public class Test {
    public static void main(String[] args) {

        System.out.println(Thread.currentThread().getName()+",id="+Thread.currentThread().getId());
        //子线程

        for (int i =1;i<100;i++){
            new SubThread5().start();

            try {
                Thread.sleep(100);  //就是说可能会取相同的id
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }

    }
}

yield()使当前线程抛弃获取的CPU资源,并重新cpu分配执行权

package Donglizijie.com.wkcto.threadmehtod.p5yield;

/**
 * @Author: 从南到北
 * @Date: 2022/01/05/18:43
 */
public class SubThread6 extends Thread{

    @Override
    public void run() {

        long begin = System.currentTimeMillis();
        long sum = 0;
        for (int i=1;i<=10000000;i++){
            sum+=i;
            Thread.yield(); //线程让步,放弃cpu执行权,然后线程调度器再给他分配资源
        }

        long end = System.currentTimeMillis();
        System.out.println(Thread.currentThread().getName()+"用时:"+(end-begin));

    }
}

package Donglizijie.com.wkcto.threadmehtod.p5yield;

/**
 * @Author: 从南到北
 * @Date: 2022/01/05/18:46
 */
public class Test {
    public static void main(String[] args) {
        //开启子线程,计算累加和
        SubThread6 t6 = new SubThread6();

        t6.start();
        //在main函数中计算累加和
        long begin = System.currentTimeMillis();
        long sum=0;
        for (int i=1;i<=100000000;i++){
            sum+=i;
        }
        long end = System.currentTimeMillis();
        System.out.println("main方法,用时:"+(end-begin));
    }
}

执行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HTDMOINv-1663747806912)(java.assets/image-20220106140529244.png)]

setPriority()

重点:线程间的通信

4.1 等待通知机制

在单线程编程中,要执行的操作需要满足一定的条件才能执行,可 以把这个操作放在 if 语句块中. 蛙课网【动力节点旗下品牌】 http://www.wkcto.com 在多线程编程中,可能 A 线程的条件没有满足只是暂时的, 稍后其 他的线程 B 可能会更新条件使得 A 线程的条件得到满足. 可以将 A 线 程暂停,直到它的条件得到满足后再将 A 线程唤醒.

它的伪代码:

atomics{
 //原子操作
 while(条件不成立){
	 等待 
  }
 	当前线程被唤醒条件满足后,继续执行下面的操作
 }

4.2 join()

套接字通讯

参考链接:OSI 和 TCP/IP 网络分层模型详解(基础) | JavaGuide

进行网络传输的一套API,本质上是可以在网络使用的流

​ ## 网络基本概念:

7层,就是说,只要你在网上传数据,都是要经过这7 层的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s59JJDCi-1663747806912)(java.assets\image-20220607164451299.png)]

物理层

数据链路层:转换信号

网络层

传输层-udp、tcp

会话层,表示层,应用层

这些都是后三层的协议

http,ftp,pop3,SMTP,这两个是在用在邮件

重点是传输层(要学的)

IP地址:在网络中标记主机,ipv4,

已经有ipv6地址了。

当万物互联的时候,ipv6也不够用了,所以推出了ipv9了,

平时上网,使用的ip地址都是动态分配的,就是说,这次上网是这个网址,下次可以就变了。提高IP地址的利用率,一般来说都是用动态ip,都是公用的

静态ip费用太贵

ip地址标记主机,端口号标记程序,

端口:计算机与外界交互的媒介,

端口号:0-65535

一部分被计算机内部占用,

80端口号,是被浏览器占用,

一般来说0-1024被计算机内部占用,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oXwjhemr-1663747806913)(java.assets\image-20210617182402040.png)]

记忆IP地址比较麻烦,所以出现了域名

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RXRbXb1T-1663747806913)(java.assets\image-20210617182431490.png)]

域名倒着看,一级:com

二级baidu

有时候会加。cn(也是一级域名)

去掉cn,然后一级域名表示分类

com表示商业网站,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FKR09EXs-1663747806913)(java.assets\image-20210617182710996.png)]

二级是公司具体的名字,三级就是表示其分类了,百度新闻

dns解析服务器:j将域名和ip地址对应,当你输入域名的时候,会先到dns服务器中先解析成对应的ip,然后顺着ip找这个地址,每个网络中都会有一个dns解析服务器,默认存在每一个电脑中都会有一个微型的dns,全球的互联网中会有一个公告的dns

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sUJnIGTN-1663747806913)(java.assets\image-20210617183311028.png)]

当你输入一个域名,然后你的电脑dns会对其进行解析,然后如果没有找到,那么就会向上请求,到你电脑所链接的局域网中寻找,如果还是没有找到,继续向上请求寻找,一直没找到,。最后可能是该网址你写错了

,当找到后,就会告诉你下级的dns,然后没有该地址的dns就会刷新一下保存该dns,每一个dns都会存一下,刷新一下,下次寻找,就不用往上找了,因为本机存的有了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-17VG8xhU-1663747806914)(java.assets\image-20210617183730544.png)]

反射

在web中会用得到

udp

基于流的,不建立连接,不可靠,

依靠网络进行传输,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bUkLQoP9-1663747806914)(java.assets\image-20210617192258230.png)]

视频聊天

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E3woLx6G-1663747806914)(java.assets\image-20210617193902208.png)]

idea添加异常,用alt+enter

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YktNUBBX-1663747806914)(java.assets\image-20210617193929782.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-710TYxta-1663747806914)(java.assets\image-20210617193951549.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WoEcOVF2-1663747806915)(java.assets\image-20210617195936177.png)]

接收端

package com.itheima;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UDPReceiverDemo {
    public static void main(String[] args) throws IOException {
        //创建套接字对象,绑定端口号
        DatagramSocket ds = new DatagramSocket(8090);
        //准备数据包,
        DatagramPacket dp =new DatagramPacket(new byte[1024],1024);
        //接收数据
        ds.receive(dp);
        //关流,这个是非常耗费流量的,所以用完一定要关
        ds.close();
        //将数据从数据包中解析出来,我们不需要全都,所以需要获取一下长度
        //获取数据包的底层数组
        byte[] bs = dp.getData();
        //获取数据的实际大小
        int len=dp.getLength();

        System.out.println(new String(bs,0,len));
		//获取发送过来的主机的地址
        System.out.println(dp.getAddress());
         //获取发送过来的主机的端口号
        System.out.println(dp.getPort());
    }

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BFJP00Gc-1663747806915)(java.assets\image-20210617200623005.png)]

发送端

package com.itheima;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;

public class UDPSenderDmo
{
    public static void main(String[] args) throws IOException {
        //创建一个udp套接字对象
        DatagramSocket ds = new DatagramSocket();
        //准备数据包,并将数据放入数据包中


        DatagramPacket dp = new DatagramPacket("hello~~~".getBytes(),"hello~~~".getBytes().length,
                new InetSocketAddress("localhost",8090));
        //发送数据包
        ds.send(dp);
        //关流
        ds.close();
    }

}

先运行接收端

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5DJE4r46-1663747806915)(java.assets\image-20210617200722845.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0HEbm23g-1663747806915)(java.assets/image-20210618131833609.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ne1043o1-1663747806916)(java.assets/image-20210618132352898.png)]

udp分发送端和接收端

tcp分客户端和服务器端

tcp三次握手

客户端发起连接,

服务器端接收连接

客户端再次发起连接

tcp不进行封包,没有数据包的概念,所以只能用流来传输数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tqzA2r7b-1663747806916)(java.assets/image-20210618191008704.png)]

3 TCP通信程序

3.1 TCP通信原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mmaG2XL4-1663747806916)(java.assets/image-20210625145210983.png)]

3.2 TCP发送数据(getOutputStream)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zXNqZQQf-1663747806916)(java.assets/image-20210625150606451.png)]

3.3 TCP接收数据(getInputStream)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mDb5IGMz-1663747806917)(java.assets/image-20210625155105747.png)]

接收数据的步骤

  1. 创建服务器端套接字对象(ServerSocket)

    ServerSocket(int port)

  2. 监听客户端连接,返回一个Socket对象

    Socket accept()

  3. 获取输入流,读数据,并把数据显示在控制台

    InputStream getInputStream()

  4. 释放资源

    void close()

只要有getinputstream和getoutputstream,就可以通过这两个来进行

Class Socket

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nfVcbOS0-1663747806917)(java.assets/image-20210626135128812.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yOLs8uVg-1663747806917)(java.assets/image-20210626135232507.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zg4MkoHw-1663747806917)(java.assets/image-20210625151959332.png)]

3.4 TCP通信程序练习

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-08eFt7kP-1663747806918)(java.assets/image-20210626143219687.png)]

练习1

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I2reUw2j-1663747806918)(java.assets/image-20210707142924879.png)]

客户端:

package com.itheima_05;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

/*
    客户端:发送数据,接收服务器反馈
 */

public class ClientDemo {
    public static void main(String[] args) throws IOException {
        //创建客户端的Socket对象(Socket)
        Socket s = new Socket("192.168.1.66", 10000);

        //获取输出流,写数据
        OutputStream os = s.getOutputStream();
        os.write("hello,tcp,我来了".getBytes());

        //接收服务器反馈
        InputStream is = s.getInputStream();
        byte[] bys = new byte[1024];
        int len = is.read(bys);
        String data = new String(bys, 0, len);
        System.out.println("客户端:" + data);

        //释放资源
//        is.close();
//        os.close();
        s.close();
    }
}

服务器端:

package com.itheima_05;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/*
    服务器:接收数据,给出反馈
 */
public class ServerDemo {
    public static void main(String[] args) throws IOException {
        //创建服务器端的Socket对象(ServerSocket)
        ServerSocket ss = new ServerSocket(10000);

        //监听客户端连接,返回一个Socket对象
        Socket s = ss.accept();

        //获取输入流,读数据,并把数据显示在控制台
        InputStream is = s.getInputStream();
        byte[] bys = new byte[1024];
        int len = is.read(bys);
        String data = new String(bys, 0, len);
        System.out.println("服务器:" + data);

        //给出反馈
        OutputStream os = s.getOutputStream();
        os.write("数据已经收到".getBytes());

        //释放资源

        ss.close();
    }
}

练习2

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cZxjkogw-1663747806918)(java.assets/image-20210707133917720.png)]

黑马程序员全套Java教程_Java基础入门视频教程,零基础小白自学Java必备教程_哔哩哔哩_bilibili****

客户端:

package com.itheima_06;

import java.io.*;
import java.net.Socket;

/*
    客户端:数据来自于键盘录入,直到输入的数据是886,发送数据结束
 */

public class ClientDemo {
    public static void main(String[] args) throws IOException {
        //创建客户端Socket对象
        Socket s = new Socket("192.168.1.66",10000);

        //数据来自于键盘录入,直到输入的数据是886,发送数据结束 ,不用scanner,用自己包装的键盘录入
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        //封装输出流对象
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        String line;
        while ((line=br.readLine())!=null) {
            if("886".equals(line)) {
                break;
            }

            //获取输出流对象,
//            OutputStream os = s.getOutputStream();    //这是一个字节流,要转换成字符流
//            os.write(line.getBytes());
//一次写一个字符串,而不是写一个字节
            bw.write(line); //写一行
            bw.newLine();   //换行
            bw.flush(); //刷新
        }

        //释放资源
        s.close();
    }
}

服务器端:

package com.itheima_06;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

/*
    服务器:接收到的数据在控制台输出
 */
public class ServerDemo {
    public static void main(String[] args) throws IOException {
        //创建服务器Socket对象
        ServerSocket ss = new ServerSocket(10000);

        //监听客户端的连接,返回一个对应的Socket对象
        Socket s = ss.accept();

        //获取输入流
//        InputStream is = s.getInputStream();
//        InputStreamReader isr = new InputStreamReader(is);
//        BufferedReader br = new BufferedReader(isr);
        BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        String line;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }

        //释放资源
        ss.close();
    }
}

练习3

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mzdR71l5-1663747806918)(java.assets/image-20211220173941847.png)]

客户端和2一样不变

package com.itheima_07;

import java.io.*;
import java.net.Socket;

/*
    客户端:数据来自于键盘录入,直到输入的数据是886,发送数据结束
 */
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        //创建客户端Socket对象
        Socket s = new Socket("192.168.1.66",10000);

        //数据来自于键盘录入,直到输入的数据是886,发送数据结束
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        //封装输出流对象
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        String line;
        while ((line=br.readLine())!=null) {
            if("886".equals(line)) {
                break;
            }
            bw.write(line);
            bw.newLine();
            bw.flush();
        }

        //释放资源
        s.close();
    }
}

服务器端:

package com.itheima_07;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/*
    服务器:接收到的数据写入文本文件
 */
public class ServerDemo {
    public static void main(String[] args) throws IOException {
        //创建服务器Socket对象
        ServerSocket ss = new ServerSocket(10000);

        //监听客户端连接,返回一个对应的Socket对象
        Socket s = ss.accept();

        //接收数据
        BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        //把数据写入文本文件
        BufferedWriter bw = new BufferedWriter(new FileWriter("myNet\\s.txt"));

        String line;
        while ((line=br.readLine())!=null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }

        //释放资源
        bw.close();
        ss.close();
    }
}

练习4

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aKeKRDuR-1663747806919)(java.assets/image-20210626160041275.png)]

就是上传文件到服务器

客户端:

package com.itheima_08;

import java.io.*;
import java.net.Socket;

/*
    客户端:数据来自于文本文件
 */
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        //创建客户端Socket对象
        Socket s = new Socket("192.168.1.66",10000);

        //封装文本文件的数据
        BufferedReader br = new BufferedReader(new FileReader("myNet\\InetAddressDemo.java"));
        //封装输出流写数据
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

        String line;
        while ((line=br.readLine())!=null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }

        //释放资源
        br.close();
        s.close();
    }
}

服务器不变3

package com.itheima_08;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/*
    服务器:接收到的数据写入文本文件
 */
public class ServerDemo {
    public static void main(String[] args) throws IOException {
        //创建服务器Socket对象
        ServerSocket ss = new ServerSocket(10000);

        //监听客户端连接,返回一个对应的Socket对象
        Socket s = ss.accept();

        //接收数据
        BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        //把数据写入文本文件
        BufferedWriter bw = new BufferedWriter(new FileWriter("myNet\\Copy.java"));

        String line;
        while ((line=br.readLine())!=null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }

        //释放资源
        bw.close();//bw 把数据写入文本
        ss.close();//ss服务器套接字
    }
}

练习5

黑马程序员全套Java教程_Java基础入门教程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vcp6RdAy-1663747806919)(java.assets/image-20210626155841154.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kb9IJL4W-1663747806919)(java.assets/image-20210626155929955.png)]

服务器端:

package com.itheima_09;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/*
    服务器:接收到的数据写入文本文件,给出反馈
 */

public class ServerDemo {
    public static void main(String[] args) throws IOException {
        //创建服务器Socket对象
        ServerSocket ss = new ServerSocket(10000);

        //监听客户端连接,返回一个对应的Socket对象
        Socket s = ss.accept();

        //接收数据
        BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        //把数据写入文本文件
        BufferedWriter bw = new BufferedWriter(new FileWriter("myNet\\Copy.java"));

        String line;
        while ((line=br.readLine())!=null) { //等待读取数据
//            if("886".equals(line)) {
//                break;
//            }
            bw.write(line);
            bw.newLine();
            bw.flush();
        }

//        System.out.println(11111);

        //给出反馈
        BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        bwServer.write("文件上传成功");
        bwServer.newLine();
        bwServer.flush();

        //释放资源
        bw.close();
        ss.close();
    }
}

客户端:

package com.itheima_09;

import java.io.*;
import java.net.Socket;

/*
    客户端:数据来自于文本文件,接收服务器反馈
 */
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        //创建客户端Socket对象
        Socket s = new Socket("192.168.1.66",10000);

        //封装文本文件的数据
        BufferedReader br = new BufferedReader(new FileReader("myNet\\InetAddressDemo.java"));
        //封装输出流写数据
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

        String line;
        while ((line=br.readLine())!=null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }

//        System.out.println(22222);
//		 自定义结束标记
//        bw.write("886");
//        bw.newLine();
//        bw.flush();

        //public void shutdownOutput()
        s.shutdownOutput(); //输出结束的标记

        //接收反馈
        BufferedReader brClient = new BufferedReader(new InputStreamReader(s.getInputStream()));
        String data = brClient.readLine(); //等待读取数据
        System.out.println("服务器的反馈:" + data);

        //释放资源
        br.close();
        s.close();
    }
}

这个就是,客户端发完数据,然后开始等待服务器发数据

但是,同时服务器也在一直读数据,并不知道客户端已经写完数据,依旧在那里等待,

所以要给客户端一个标记,就是告诉服务器我已经数据读完了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f6oBeZ40-1663747806919)(java.assets/image-20220324225453774.png)]

然后服务器这样写:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SZqk2x3N-1663747806919)(java.assets/image-20220324225832468.png)]

服务器有了结束的标志,那么就可以继续往下面走了,就可以给客户端反馈了

但是这样写,不行,因为如果数据中有886,那么,就直接结束接收 数据,这样就芭比q了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0qKGLYot-1663747806920)(java.assets/image-20220324230102503.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zxFSrvuf-1663747806920)(java.assets/image-20220324230200624.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h09DOUT6-1663747806920)(java.assets/image-20220324230352460.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V4wm1wMk-1663747806920)(java.assets/image-20220324230417924.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QkVwiGwm-1663747806921)(java.assets/image-20220324230442845.png)]

shutdownoutput,关闭输出流

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fq1NBN5h-1663747806921)(java.assets/image-20220324230611692.png)]

因为要返回的是一个客户端的对象,但是这个是只是监听,要返回监听的套接字

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UYmsiZ6g-1663747806921)(java.assets/image-20220324231000722.png)]

关键:是readline是阻塞式的,需要看前面的学习

练习6

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VLN7YKeg-1663747806921)(java.assets/image-20211220215613005.png)]

客户端:

package com.itheima_10;

import java.io.*;
import java.net.Socket;

/*
    客户端:数据来自于文本文件,接收服务器反馈
 */

public class ClientDemo {
    public static void main(String[] args) throws IOException {
        //创建客户端Socket对象
        Socket s = new Socket("192.168.1.66",10000);

        //封装文本文件的数据
        BufferedReader br = new BufferedReader(new FileReader("myNet\\InetAddressDemo.java"));
        //封装输出流写数据
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

        String line;
        while ((line=br.readLine())!=null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }

        s.shutdownOutput();		//如果没有这一句,那么,就代表

        //接收反馈
        BufferedReader brClient = new BufferedReader(new InputStreamReader(s.getInputStream()));
        String data = brClient.readLine(); //等待读取数据
        System.out.println("服务器的反馈:" + data);

        //释放资源
        br.close();
        s.close();
    }
}

服务器端:

package com.itheima_10;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/*
    服务器:接收到的数据写入文本文件,给出反馈,代码用线程进行封装,为每一个客户端开启一个线程
 */
public class ServerDemo {
    public static void main(String[] args) throws IOException {
        //创建服务器Socket对象
        ServerSocket ss = new ServerSocket(10000);	//服务器套接字

        while (true) {
            //监听客户端连接,返回一个对应的Socket对象
            Socket s = ss.accept();	//监听客户端,
            //为每一个客户端开启一个线程
            new Thread(new ServerThread(s)).start();		//把客户端放到套接字中
        }

//        ss.close();	//一般,服务器是不会关的
    }
}

多线程

package com.itheima_10;

import java.io.*;
import java.net.Socket;

public class ServerThread implements Runnable {
    private Socket s;	//服务器套接字
    
    public ServerThread(Socket s) {		
        this.s = s;
    }
    
    @Override
    public void run() {
        try {
            //接收数据写到文本文件
            BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
//            BufferedWriter bw = new BufferedWriter(new FileWriter("myNet\\Copy.java"));
            //解决名称冲突问题
            int count = 0;
            File file = new File("myNet\\Copy["+count+"].java");
            while (file.exists()) {	//如果文件不存在,就不会触发这个循环
                count++;
                file = new File("myNet\\Copy["+count+"].java");
            }
            BufferedWriter bw = new BufferedWriter(new FileWriter(file));

            String line;
            while ((line=br.readLine())!=null) {
                bw.write(line);
                bw.newLine();
                bw.flush();
            }
            //给出反馈
            BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
            bwServer.write("文件上传成功");
            bwServer.newLine();
            bwServer.flush();
            //释放资源
            s.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Lambda表达式

黑马程序员全套Java教程_Java基础入门视频教程,零基础小白自学Java必备教程_哔哩哔哩_bilibili

1 类加载器

1.1 类加载

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N4UXoH0Q-1663747806922)(java.assets/image-20210815143429416.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UXyvhJte-1663747806922)(java.assets/image-20210815143752376.png)]

1.2 类加载器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iQhAgmCV-1663747806922)(java.assets/image-20210815143925316.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0bL4H3xZ-1663747806922)(java.assets/image-20210815144224616.png)]

package com.itheima_01;

/*
    ClassLoader 中的两个方法
        static ClassLoader getSystemClassLoader​():返回用于委派的系统类加载器
        ClassLoader getParent​():返回父类加载器进行委派
 */
public class ClassLoaderDemo {
    public static void main(String[] args) {
        //static ClassLoader getSystemClassLoader​():返回用于委派的系统类加载器
        ClassLoader c = ClassLoader.getSystemClassLoader();
        System.out.println(c); //AppClassLoader

        //ClassLoader getParent​():返回父类加载器进行委派
        ClassLoader c2 = c.getParent();
        System.out.println(c2); //PlatformClassLoader

        ClassLoader c3 = c2.getParent();
        System.out.println(c3); //null
    }
}

2 反射

2.1 反射概述

视频链接:

黑马程序员全套Java教程_Java基础入门视频教程,零基础小白自学Java必备教程_哔哩哔哩_bilibili

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GYdDJXdn-1663747806923)(java.assets/image-20210815141718689.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c5n2Z7ZM-1663747806923)(java.assets/image-20210815141818178.png)]

2.2 获取Class类的对象

什么是字节码?采用字节码的好处是什么?

在 Java 中,JVM 可以理解的代码就叫做字节码(即扩展名为 .class 的文件),它不面向任何特定的处理器,只面向虚拟机。Java 语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以, Java 程序运行时相对来说还是高效的(不过,和 C++,Rust,Go 等语言还是有一定差距的),而且,由于字节码并不针对一种特定的机器,因此,Java 程序无须重新编译便可在多种不同操作系统的计算机上运行。

我们需要格**外注意的是 .class->机器码 这一步。**在这一步 JVM 类加载器首先加载字节码文件,然后通过解释器逐行解释执行,这种方式的执行速度会相对比较慢。而且,有些方法和代码块是经常需要被调用的(也就是所谓的热点代码),所以后面引进了 JIT(just-in-time compilation) 编译器,而 JIT 属于运行时编译。当 JIT 编译器完成第一次编译后,其会将字节码对应的机器码保存下来,下次可以直接使用。而我们知道,机器码的运行效率肯定是高于 Java 解释器的。这也解释了我们为什么经常会说 Java 是编译与解释共存的语言

java文件(.java)先变成字节码文件(.class),在变成机器可以理解的机器码文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PtMGhgSH-1663747806923)(java.assets\image-20220705163615239.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-953pZotM-1663747806923)(java.assets/image-20210815141932109.png)]

2.3 反射获取构造方法并使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ApPqH5ke-1663747806924)(java.assets/image-20210823115021793.png)]

package com.itheima_03;
import com.itheima_02.Student;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/*
    反射获取构造方法并使用
 */
public class ReflectDemo01 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class<?> c = Class.forName("com.itheima_02.Student");

        //Constructor[] getConstructors​() 返回一个包含 Constructor对象的数组, Constructor对象反映了由该 Class对象表示的类的所有公共构造函数
//        Constructor[] cons = c.getConstructors();
        //Constructor[] getDeclaredConstructors​() 返回反映由该 Class对象表示的类声明的所有构造函数的 Constructor对象的数组
        Constructor<?>[] cons = c.getDeclaredConstructors();
        for(Constructor con : cons) {
            System.out.println(con);
        }
        System.out.println("--------");

        //Constructor getConstructor​(Class... parameterTypes) 返回一个 Constructor对象,该对象反映由该 Class对象表示的类的指定公共构造函数
        //Constructor getDeclaredConstructor​(Class... parameterTypes) 返回一个 Constructor对象,该对象反映由此 Class对象表示的类或接口的指定构造函数
        //参数:你要获取的构造方法的参数的个数和数据类型对应的字节码文件对象

        Constructor<?> con = c.getConstructor();

        //Constructor提供了一个类的单个构造函数的信息和访问权限
        //T newInstance(Object... initargs) 使用由此 Constructor对象表示的构造函数,使用指定的初始化参数来创建和初始化构造函数的声明类的新实例
        Object obj = con.newInstance();
        System.out.println(obj);

//        Student s = new Student();
//        System.out.println(s);
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BLM6v3Vj-1663747806924)(java.assets/image-20210823133915928.png)]

2.4 反射获取构造方法并使用练习

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VG8YeU7H-1663747806924)(java.assets/image-20210818163838756.png)]

正常来说,不能通过私有方法创建对象,但是在反射里面可以,通过暴力反射

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s6Qb4jMh-1663747806924)(java.assets/image-20210818163821196.png)]

成员变量也叫字段,file,下面这个方法,很明显是拿的所有的成员变量

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DFMlJG2K-1663747806925)(java.assets/image-20210818164115874.png)]

练习1代码

package itheima3;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/*
    通过反射实现如下的操作:
        Student s = new Student("林青霞",30,"西安");
        System.out.println(s);
 */
public class ReflectDemo02 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //获取Class对象
        Class<?> c = Class.forName("itheima2.Student");
        Constructor<?> con = c.getConstructor(String.class, int.class, String.class);
        Object obj = con.newInstance("林青霞", 30, "西安");
        System.out.println(obj);
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gX6bmzic-1663747806925)(java.assets/image-20210823134322584.png)]

练习2代码

package com.itheima_03;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/*
    通过反射实现如下的操作:
        Student s = new Student("林青霞");
        System.out.println(s);
 */

public class ReflectDemo03 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class<?> c = Class.forName("com.itheima_02.Student");

        //private Student(String name)
        //Constructor getDeclaredConstructor(Class... parameterTypes)
        Constructor<?> con = c.getDeclaredConstructor(String.class);

        //暴力反射
        //public void setAccessible​(boolean flag):值为true,取消访问检查
        con.setAccessible(true);

        Object obj = con.newInstance("林青霞");
        System.out.println(obj);

    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qFC4Bfnq-1663747806925)(java.assets/image-20210823134937287.png)]

2.5 反射获取成员变量并使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C8PsWsT3-1663747806925)(java.assets/image-20210819140701413.png)]

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
/*
    反射获取成员变量并使用
 */
public class ReflectDemo02 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class<?> c = Class.forName("com.itheima_02.Student"); //拿到这个类

        //Field[] getFields() 返回一个包含 Field对象的数组, Field对象反映由该 Class对象表示的类或接口的所有可访问的公共字段
        //Field[] getDeclaredFields() 返回一个 Field对象的数组,反映了由该 Class对象表示的类或接口声明的所有字段


//        Field[] fields = c.getFields();     //返回所有公共成员变量
//        Field[] fields = c.getDeclaredFields();
//        for(Field field : fields) {
//            System.out.println(field);
//        }
//        System.out.println("--------");

        //Field getField(String name) 返回一个 Field对象,该对象反映由该 Class对象表示的类或接口的指定公共成员字段
        //Field getDeclaredField(String name) 返回一个 Field对象,该对象反映由该 Class对象表示的类或接口的指定声明字段
        Field addressField = c.getField("name");
//      System.out.println(addressField);
//        //获取无参构造方法创建对象
        Constructor<?> con = c.getConstructor();  //这两步等同于这一步Student s = new Student();,获取对象的构造方法
        Object obj = con.newInstance();
        
        //Field提供有关类或接口的单个字段的信息和动态访问
        //void set(Object obj, Object value) 将指定的对象参数中由此 Field对象表示的字段设置为指定的新值
        addressField.set(obj,"西安"); //给obj的成员变量addressField赋值为西安    //等同于这一步obj.setaddressField = "西安";
        System.out.println(obj);

//        Student s = new Student();
//        s.address = "西安";
//        System.out.println(s);
    }
}

2.6 反射获取成员变量并使用练习

package com.itheima_04;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

/*
    练习:通过反射实现如下操作
        Student s = new Student();
        s.name = "林青霞";
        s.age = 30;
        s.address = "西安";
        System.out.println(s);
 */
public class ReflectDemo02 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
       
        Class<?> c = Class.forName("com.itheima_02.Student"); 	//获取Class对象

    
        Constructor<?> con = c.getConstructor();    //这两步等同于这一步Student s = new Student();
        Object obj = con.newInstance();  
        
        System.out.println(obj);

         //s.name = "林青霞";
	    //Field nameField = c.getField("name"); //NoSuchFieldException: name
        Field nameField = c.getDeclaredField("name");
        //以后,当你不知道该用上面的两个哪一个时,就用下面那个,因为下面那个,无论公共私有,都可以拿到
        //而且在调方法之前,都先取消公共访问检查,就下面那个语句,这样就可以使用了    
        nameField.setAccessible(true);
        nameField.set(obj, "林青霞");
        System.out.println(obj);

        //s.age = 30;
        Field ageField = c.getDeclaredField("age");
        ageField.setAccessible(true);
        ageField.set(obj,30);
        System.out.println(obj);

        //s.address = "西安";
        Field addressField = c.getDeclaredField("address");
        addressField.setAccessible(true);
        addressField.set(obj,"西安");
        System.out.println(obj);
    }
}

2.7 反射获取成员方法并使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aK3y1OuI-1663747806925)(java.assets/image-20210819220731409.png)]

    //Object invoke(Object obj, Object... args) 在具有指定参数的指定对象上调用此 方法对象表示的基础方法
    //Object:返回值类型   //obj:调用方法的对象   //args:方法需要的参数
    Method m3 = c.getMethod("method3", String.class, int.class);
    Object o = m3.invoke(obj, "林青霞", 30);    //调用有参且带有返回值的方法
        System.out.println(o);
package com.itheima_05;

import com.itheima_02.Student;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/*
    反射获取成员方法并使用
 */
public class ReflectDemo01 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class<?> c = Class.forName("com.itheima_02.Student");

        //Method[] getMethods​() 返回一个包含 方法对象的数组, 方法对象反映由该 Class对象表示的类或接口的所有公共方法,包括由类或接口声明的对象以及从超类和超级接口继承的类
        //Method[] getDeclaredMethods​() 返回一个包含 方法对象的数组, 方法对象反映由 Class对象表示的类或接口的所有声明方法,
        //包括public,protected,default(package)访问和私有方法,但不包括继承方法
//        Method[] methods = c.getMethods();
        Method[] methods = c.getDeclaredMethods();
        for(Method method : methods) {
            System.out.println(method);
        }
        System.out.println("--------");

        //Method getMethod​(String name, Class... parameterTypes) 返回一个 方法对象,该对象反映由该 Class对象表示的类或接口的指定公共成员方法
        //Method getDeclaredMethod​(String name, Class... parameterTypes) 返回一个 方法对象,它反映此表示的类或接口的指定声明的方法 Class对象
  
        //public void method1()
        Method m = c.getMethod("method1");

        //获取无参构造方法创建对象
        Constructor<?> con = c.getConstructor();
        Object obj = con.newInstance();

//        obj.m();

        //在类或接口上提供有关单一方法的信息和访问权限
        //Object invoke​(Object obj, Object... args) 在具有指定参数的指定对象上调用此 方法对象表示的基础方法
        //Object:返回值类型
        //obj:调用方法的对象
        //args:方法需要的参数
        m.invoke(obj);

//        Student s = new Student();
//        s.method1();
    }
}

2.8 反射获取成员方法并使用练习

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MXR0vYsU-1663747806926)(java.assets/image-20210820015713345.png)]

package com.itheima_05;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/*
     练习:通过反射实现如下操作
        Student s = new Student();
        s.method1();
        s.method2("林青霞");
        String ss = s.method3("林青霞",30);
        System.out.println(ss);
        s.function();
 */
public class ReflectDemo02 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class<?> c = Class.forName("com.itheima_02.Student");

        //Student s = new Student();    通过无参构造方法,构造一个对象
        Constructor<?> con = c.getConstructor();        
        Ob

你可能感兴趣的:(java,java)