JAVASE

javaSE

进制&字节&DOS命令&Jvm

进制

计算机中的数据不同于人们生活中的数据,人们生活采用十进制数,而计算机中全部采用二进制数表示,它只包含 0、1两个数,逢二进一,1+1=10。每一个0或者每一个1,叫做一个bit(比特)。


字节

字节是我们常见的计算机中最小存储单元。计算机存储任何的数据,都是以字节的形式存储,右键点击文件属性, 我们可以查看文件的字节大小。 8个bit(二进制位) 0000-0000表示为1个字节,写成1 byte或者1 B。

  • 位(bit):一个数字0或者一个数字1,代表一位。
  • 字节(Byte):每逢8位是一个字节,这是数据存储的最小单位。
1 Byte = 8 bit
1 KB = 1024 Byte
1 MB = 1024 KB
1 GB = 1024 MB
1 TB = 1024 GB
1 PB = 1024 TB
1 EB = 1024 PB
1 ZB = 1024 EB

DOS命令

MS-DOS(Microsoft Disk Operating System)

命令提示符(cmd)

启动:		Win+R,输入cmd回车
切换盘符	盘符名称:
进入文件夹	cd 文件夹名称
进入多级文件夹	cd 文件夹1\文件夹2\文件夹3
返回上一级	cd ..
直接回根路径	cd \
查看当前内容	dir
清屏		cls
退出		exit

JVM

  • JVM(Java Virtual Machine ):Java虚拟机,简称JVM,是运行所有Java程序的假想计算机,是Java程序的 运行环境,是Java 最具吸引力的特性之一。我们编写的Java代码,都运行在 JVM 之上。
  • 跨平台:任何软件的运行,都必须要运行在操作系统之上,而我们用Java编写的软件可以运行在任何的操作系 统上,这个特性称为Java语言的跨平台特性。该特性是由JVM实现的,我们编写的程序运行在JVM上,而JVM 运行在操作系统上。
JRE 和 JDK

JRE (Java Runtime Environment) :是Java程序的运行时环境,包含 JVM运行时所需要的 核心类库

JDK (Java Development Kit):是Java程序开发工具包,包含 JRE 和开发人员使用的工具。 我们想要运行一个已有的Java程序,那么只需安装 JRE 即可。 我们想要开发一个全新的Java程序,那么必须安装 JDK 。

三者关系: JDK > JRE > JVM


数据类型

基本数据类型:

包括 整数 、 浮点数 、 字符 、 布尔 。

整数型	byte short int long
	浮点型	float double
	字符型	char
	布尔型	boolean
  • 字符串不是基本类型,而是引用类型。
  • 浮点型可能只是一个近似值,并非精确的值。
  • 数据范围与字节数不一定相关,例如float数据范围比long更加广泛,但是float是4字节,long是8字节。
  • 浮点数当中默认类型是double。如果一定要使用float类型,需要加上一个后缀F。
    如果是整数,默认为int类型,如果一定要使用long类型,需要加上一个后缀L。推荐使用大写字母后缀。

引用数据类型:

包括 类 、 数组 、 接口 。

字符串、数组、类、接口、Lambda

变量

变量定义的格式包括三个要素: 数据类型 、 变量名 、 数据值 。

格式 :

数据类型 变量名 = 数据值;
  • long类型:建议数据后加L表示。

  • float类型:建议数据后加F表示。

  • 变量名称:在同一个大括号范围内,变量的名字不可以相同。

  • 变量赋值:定义的变量,不赋值不能使用。

数据类型转换

    1. 自动转换

      范围小的类型向范围大的类型提升, byteshortchar 运算时直接提升为 intbyteshortchar‐‐>int‐‐>long‐‐>float‐‐>double
      
  1. 强制转换

强制类型转换:将 取值范围大的类型 强制转换成 取值范围小的类型 。

转换格式:

数据类型 变量名 = (数据类型)被转数据值;

浮点转成整数,直接取消小数点,可能造成数据损失精度。

**int 强制转成 short 砍掉2个字节,可能造成数据丢失。**
ASCII编码表

编码表 :就是将人类的文字和一个十进制数进行对应起来组成一张表格。

ASCII码表:American Standard Code for Information Interchange,美国信息交换标准代码。
Unicode码表:万国码。也是数字和符号的对照关系,开头0-127部分和ASCII完全一样,但是从128开始包含有更多字符。

字符数值
048
957
A65
Z90
a97
z122
  • 将所有的英文字母,数字,符号都和十进制进行了对应,因此产生了世界上第一张编码表ASCII( American Standard Code for Information Interchange 美国标准信息交换码)。
  • 在char类型和int类型计算的过程中,char类型的字符先查询编码表,得到97,再和1求和,结果为98。char类型提升 为了int类型。char类型内存2个字节,int类型内存4个字节。

运算符

1.算数运算符

加:+
减:-
乘:*
除:/
取模(取余数):%

一旦运算当中有不同类型的数据,那么结果将会是数据类型范围大的那种


  1. 对于数值来说,那就是加法。
  2. 对于字符char类型来说,在计算之前,char会被提升成为int,然后再计算。
    char类型字符,和int类型数字,之间的对照关系表:ASCII、Unicode
  3. 对于字符串String(首字母大写,并不是关键字)来说,加号代表字符串连接操作。
    任何数据类型和字符串进行连接的时候,结果都会变成字符串

自增运算符:++ 自减运算符:–

  • A. 如果是【前++】,那么变量【立刻马上+1】,然后拿着结果进行使用。 【先加后用】
  • B. 如果是【后++】,那么首先使用变量本来的数值,【然后再让变量+1】。 【先用后加】

2.赋值运算符

    +=		a += 3		相当于		a = a + 3
	-=		b -= 4		相当于		b = b - 4
	*=		c *= 5		相当于		c = c * 5
	/=		d /= 6		相当于		d = d / 6
	%=		e %= 7		相当于		e = e % 7

3.比较运算符

大于:		>
小于:		<
大于等于:	>=
小于等于:	<=
相等:		==	【两个等号连写才是相等,一个等号代表的是赋值】
不相等:	!=

4.逻辑运算符

与(并且)	&&	全都是true,才是true;否则就是false
或(或者)	||	至少一个是true,就是true;全都是false,才是false
非(取反)	!	本来是true,变成false;本来是false,变成true

5.三元运算符

  • 一元运算符:只需要一个数据就可以进行操作的运算符。例如:取反!、自增++、自减–
  • 二元运算符:需要两个数据才可以进行操作的运算符。例如:加法+、赋值=
  • 三元运算符:需要三个数据才可以进行操作的运算符。

格式:

数据类型 变量名称 = 条件判断 ? 表达式A : 表达式B;

流程:
首先判断条件是否成立:
如果成立为true,那么将表达式A的值赋值给左侧的变量;
如果不成立为false,那么将表达式B的值赋值给左侧的变量;
二者选其一。

注意事项:

  1. 必须同时保证表达式A和表达式B都符合左侧数据类型的要求。
  2. 三元运算符的结果必须被使用。

流程控制语句

数组

初始化方式:

  1. 动态初始化(指定长度)
  2. 静态初始化(指定内容)

1。动态初始化数组

格式:

数据类型[] 数组名称 = new 数据类型[数组长度];

含义

  1. 左侧数据类型:也就是数组当中保存的数据,全都是统一的什么类型
  2. 左侧的中括号:代表我是一个数组
  3. 左侧数组名称:给数组取一个名字
  4. 右侧的new:代表创建数组的动作
  5. 右侧数据类型:必须和左边的数据类型保持一致
  6. 右侧中括号的长度:也就是数组当中,到底可以保存多少个数据,是一个int数字

动态初始化(指定长度):在创建数组的时候,直接指定数组当中的数据元素个数。
静态初始化(指定内容):在创建数组的时候,不直接指定数据个数多少,而是直接将具体的数据内容进行指定。

2。静态初始化基本格式:

数据类型[] 数组名称 = new 数据类型[] { 元素1, 元素2, … };


如果是整数类型,那么默认为0;
如果是浮点类型,那么默认为0.0;
如果是字符类型,那么默认为'\u0000';
如果是布尔类型,那么默认为false;
如果是引用类型,那么默认为null。
  • 任何数据类型都能作为方法的参数类型,或者返回值类型。
  • 数组作为方法的参数,传递进去的其实是数组的地址值。
  • 数组作为方法的返回值,返回的其实也是数组的地址值。

OOP

​ Java语言是一种面向对象的程序设计语言,而面向对象思想是一种程序设计思想,我们在面向对象思想的指引下, 使用Java语言去设计、开发计算机程序。 这里的对象泛指现实中一切事物,每种事物都具备自己的属性和行为。面 向对象思想就是在计算机程序设计过程中,参照现实中事物,将事物的属性特征、行为特征抽象出来,描述成计算 机事件的设计思想。 它区别于面向过程思想,强调的是通过调用对象的行为来实现功能,而不是自己一步一步的去 操作实现。

区别:

  1. 面向过程:强调步骤。
  2. 面向对象:强调对象。

类&对象

  1. 类:是一组相关属性和行为的集合。可以看成是一类事物的模板,使用事物的属性特征和行为特征来描述该 类事物。
  2. 现实中,描述一类事物:
  3. 属性:就是该事物的状态信息。
  4. 行为:就是该事物能够做什么
  5. 对象:是一类事物的具体体现。对象是类的一个实例(对象并不是找个女朋友),必然具备该类事物的属性 和行为。
  • 类是对一类事物的描述,是抽象的。
  • 对象是一类事物的实例,是具体的
  • 类是对象的模板,对象是类的实体。

成员变量和局部变量区别

  • 在类中的位置不同

    成员变量:类中,方法外 
    局部变量:方法中或者方法声明上(形式参数) 
    
  • 作用范围不一样

 成员变量:类中 
 局部变量:方法中 
  • 初始化值的不同
 成员变量:有默认值 
 局部变量:没有默认值。必须先定义,赋值,最后使用 

在内存中的位置不同

 成员变量:堆内存 
 局部变量:栈内存 

生命周期不同

 成员变量:随着对象的创建而存在,随着对象的消失而消失 
 局部变量:随着方法的调用而存在,随着方法的调用完毕而消失

封装

概述

​ 面向对象编程语言是对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界无法直接操作和修改。 封装可以被认为是一个保护屏障,防止该类的代码和数据被其他类随意访问。要访问该类的数据,必须通过指定的 方式。适当的封装可以让代码更容易理解与维护,也加强了代码的安全性。

封装性在Java当中的体现:
1. 方法就是一种封装
2. 关键字private也是一种封装
原则
  • 将属性隐藏起来,若需要访问某个属性,提供公共方法对其访问。
  • 封装的步骤
    1. 使用 private 关键字来修饰成员变量。
    2. 对需要访问的成员变量,提供对应的一对 getXxx 方法 、 setXxx 方法。
    3. 封装的操作——private关键字
1. private是一个权限修饰符,代表最小权限。 
2.  可以修饰成员变量和成员方法。 
3.private修饰后的成员变量和成员方法,只在本类中才能访问。
  • private的使用格式:
private 数据类型 变量名 ;

this关键字

this代表所在类的当前对象的引用(地址值),即对象自己的引用。

  • 方法被哪个对象调用,方法中的this就代表那个对象。即谁在调用,this就代表谁

  • this使用格式:

    this.成员变量名;
    
构造方法
  • 当一个对象被创建时候,构造方法用来初始化该对象,给对象的成员变量赋初始值。

  • 无论你与否自定义构造方法,所有的类都有构造方法,因为Java自动提供了一个无参数构造方法, 一旦自己定义了构造方法,Java自动提供的默认无参数构造方法就会失效。

  • 构造方法的定义格式:

    修饰符 构造方法名(参数列表){
    // 方法体
    }
    
    
  1. 如果你不提供构造方法,系统会给出无参数构造方法。
  2. 如果你提供了构造方法,系统将不再提供无参数构造方法。
  3. 构造方法是可以重载的,既可以定义参数,也可以不定义参数。
JavaBean
  • JavaBean 是 Java语言编写类的一种标准规范。符合 JavaBean 的类,要求类必须是具体的和公共的,并且具有无 参数的构造方法,提供用来操作成员变量的 set 和 get 方法

  • public class ClassName{
    //成员变量
    //构造方法
    //无参构造方法【必须】
    //有参构造方法【建议】
    //成员方法
    //getXxx()
    //setXxx()
    }
    
    

继承

概述
  • 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要 继承那一个类即可

  • 其中,多个类可以称为子类,单独那一个类称为父类、超类(superclass)或者基类。

  • 继承:就是子类继承父类的属性行为,使得子类对象具有与父类相同的属性、相同的行为。子类可以直接 访问父类中的非私有的属性和行为。

  • 好处

    1. 提高代码的复用性。
    2. 类与类之间产生了关系,是多态的前提。
    
  • 格式
    class 父类 {
    ...
    }
    class 子类 extends 父类 {
    ...
    }
    
    
  • 成员变量

    直接通过子类对象访问成员变量:
        等号左边是谁,就优先用谁,没有则向上找。
    间接通过成员方法访问成员变量:
        该方法属于谁,就优先用谁,没有则向上找。
    
    成员变量不重名:
       如果子类父类中出现不重名的成员变量,这时的访问是没有影响的
    成员变量重名:
    	如果子类父类中出现重名的成员变量,这时的访问是有影响的。
    	子父类中出现了同名的成员变量时,在子类中需要访问父类中非私有成员变量时,需要使用 super 关键字,修饰
    父类成员变量,类似于之前学过的 this 。
    格式 : super.父类成员变量名
    
  • 成员方法

    创建的对象是谁,就优先用谁,如果没有则向上找。

    成员方法不重名
    	如果子类父类中出现不重名的成员方法,这时的调用是没有影响的。
    成员方法重名——重写(Override)
    	如果子类父类中出现重名的成员方法,这时的访问是一种特殊情况,叫做方法重写 (Override)
    	方法重写 :子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效
    果,也称为重写或者复写。声明不变,重新实现。
    

    1.子类方法覆盖父类方法,必须要保证权限大于等于父类权限。

    2.子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一模一样。

  • 构造方法

    1. 构造方法的名字是与类名一致的。所以子类是无法继承父类构造方法的。
    2. 构造方法的作用是初始化成员变量的。所以子类的初始化过程中,必须先执行父类的初始化动作。
        子类的构造方法中默认有一个 super() ,表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。
    
  • super和this

    父类空间优先于子类对象产生
    	在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。目的在于子类对象中包含了其对应的父类空
    间,便可以包含其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。代码体现在子类的构
    造方法调用时,一定先调用父类的构造方法
    

    super和this的含义

    子类必须调用父类构造方法,不写则赠送super();写了则用写的指定的super调用,super只能有一个,还必须是第一个。

    super :代表父类的存储空间标识(可以理解为父亲的引用)this :代表当前对象的引用(谁调用就代表谁)
    this.成员变量 ‐‐ 本类的
    super.成员变量 ‐‐ 父类的
    this.成员方法名() ‐‐ 本类的
    super.成员方法名() ‐‐ 父类的
    this(...) ‐‐ 本类的构造方法
    super(...) ‐‐ 父类的构造方法
    
  • 特点

    1. Java只支持单继承,不支持多继承。
    2. Java支持多层继承(继承体系)。
    顶层父类是Object类。所有的类默认继承Object,作为父类。
    3. 子类和父类是一种相对的概念。
    

多态

概述
  • ​ 多态: 是指同一行为,具有多个不同表现形式。

  • 格式:
    	父类类型 变量名 = new 子类对象;
        变量名.方法名();
    父类类型:指子类对象继承的父类类型,或者实现的父接口类型
    

    当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,执行的是子类重写 后方法。

向上转型:
  • 向上转型:多态本身是子类类型向父类类型向上转换的过程,这个过程是默认的。 当父类引用指向一个子类对象时,便是向上转型。

    使用格式 变量名 = new 子类类型();
    
  • 对象一旦向上转型为父类,那么就无法调用子类原本特有的内容。

  • 用对象的向下转型【还原】

向下转型:
  • 向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的。

  • 一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型。

    使用格式:子类类型 变量名 = (子类类型) 父类变量名;
    

    当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误。也就是说,不能调用子类拥 有,而父类没有的方法。编译都错误,更别说运行了。这也是多态给我们带来的一点"小麻烦"。所以,想要调用子 类特有的方法,必须做向下转型。

    变量名 instanceof 数据类型
    如果变量属于该数据类型,返回true。
    如果变量不属于该数据类型,返回false

重载(Overload)&重写(Override)

  • 重载:

         **方法的名称一样,参数列表【不一样】。**
    
  • 重写:

    方法的名称一样,参数列表【也一样】。覆盖、覆写。

    ​ 如果子类父类中出现重名的成员方法,这时的访问是一种特殊情况,叫做方法重写 (Override)
    ​ 方法重写 :子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效
    果,也称为重写或者复写。声明不变,重新实现。

    1. 必须保证父子类之间方法的名称相同,参数列表也相同。
    @Override:写在方法前面,用来检测是不是有效的正确覆盖重写。
    这个注解就算不写,只要满足要求,也是正确的方法覆盖重写。
    
    2. 子类方法的返回值必须【小于等于】父类方法的返回值范围。
    小扩展提示:java.lang.Object类是所有类的公共最高父类(祖宗类),java.lang.String就是Object的子类。
    
    3. 子类方法的权限必须【大于等于】父类方法的权限修饰符。
    小扩展提示:public > protected > (default) > private
    备注:(default)不是关键字default,而是什么都不写,留空。
    

抽象类&接口&final

抽象类

概述

父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。那么父类的方法声明和方法主体,只有声明还有 意义,而方法主体则没有存在的意义了。我们把没有方法主体的方法称为抽象方法。Java语法规定,包含抽象方法 的类就是抽象类。

定义
  • 抽象方法 : 没有方法体的方法。

抽象方法:就是加上abstract关键字,然后去掉大括号,直接分号结束

  • 抽象类:包含抽象方法的类。

    抽象类:抽象方法所在的类,必须是抽象类才行。在class之前写上abstract即可。

定义格式:

如果一个类包含抽象方法,那么该类必须是抽象类。

修饰符 abstract 返回值类型 方法名 (参数列表)abstract class 类名字 {
}
如何使用抽象类和抽象方法:
1. 不能直接创建new抽象类对象。
2. 必须用一个子类来继承抽象父类。
3. 子类必须覆盖重写抽象父类当中所有的抽象方法。
覆盖重写(实现):子类去掉抽象方法的abstract关键字,然后补上方法体大括号。
4. 创建子类对象进行使用。

继承抽象类的子类必须重写父类所有的抽象方法。否则,该子类也必须声明为抽象类。最终,必须有子类实现该父 类的抽象方法,否则,从最初的父类到最终的子类都不能创建对象,失去意义

1. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。
2. 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。
3. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类
理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设
计。
4. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象
类。
理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有
意义。

接口

  • ​ 接口,是Java语言中一种引用类型,是方法的集合,如果说类的内部封装了成员变量、构造方法和成员方法,那么 接口的内部主要就是封装了方法,包含抽象方法(JDK 7及以前),默认方法和静态方法(JDK 8),私有方法 (JDK 9)。

  • ​ 接口的定义,它与定义类方式相似,但是使用 interface 关键字。它也会被编译成.class文件,但一定要明确它并 不是类,而是另外一种引用数据类型。

  • 引用数据类型:数组,类,接口。

  • 接口的使用,它不能创建对象,但是可以被实现( implements ,类似于被继承)。一个实现接口的类(可以看做 是接口的子类),需要实现接口中所有的抽象方法,创建该类对象,就可以调用方法了,否则它必须是一个抽象 类。

  • 格式

    public interface 接口名称 {   
     // 抽象方法
     // 默认方法   
     // 静态方法  
     // 私有方法 
     }
    
  • 1. 成员变量其实是常量,格式:
    [public] [static] [final] 数据类型 常量名称 = 数据值;
    注意:
    	常量必须进行赋值,而且一旦赋值不能改变。
    	常量名称完全大写,用下划线进行分隔。
    
    2. 接口中最重要的就是抽象方法,格式:
    [public] [abstract] 返回值类型 方法名称(参数列表);
    注意:实现类必须覆盖重写接口所有的抽象方法,除非实现类是抽象类。
    
    3. 从Java 8开始,接口里允许定义默认方法,格式:
    [public] default 返回值类型 方法名称(参数列表) { 方法体 }
    注意:默认方法也可以被覆盖重写
    
    4. 从Java 8开始,接口里允许定义静态方法,格式:
    [public] static 返回值类型 方法名称(参数列表) { 方法体 }
    注意:应该通过接口名称进行调用,不能通过实现类对象调用接口静态方法
    
    5. 从Java 9开始,接口里允许定义私有很乏,格式:
    普通私有方法:private 返回值类型 方法名称(参数列表) { 方法体 }
    静态私有方法:private static 返回值类型 方法名称(参数列表) { 方法体 }
    注意:private的方法只有接口自己才能调用,不能被实现类或别人使用。
    
  • 访问成员变量的两种方式:
    1. 直接通过对象名称访问成员变量:看等号左边是谁,优先用谁,没有则向上找。
    2. 间接通过成员方法访问成员变量:看该方法属于谁,优先用谁,没有则向上找。
    
    
  • 抽象方法:使用 abstract 关键字修饰,可以省略,没有方法体。该方法供子类实现使用。

  • 非抽象子类实现接口:

    1.必须重写接口中所有抽象方法。
    2. 继承了接口的默认方法,即可以直接调用,也可以重写
    实现格式:
      class 类名 implements 接口名 {
    	// 重写接口中抽象方法【必须】
    	// 重写接口中默认方法【可选】
    	}
    	class 类名 [extends 父类名] implements 接口名1,接口名2,接口名3... {
    	// 重写接口中抽象方法【必须】
    	// 重写接口中默认方法【不重名时可选】
    	}
    
  • 默认方法的使用:可以继承,可以重写,二选一,但是只能通过实现类的对象来调用。

  • 静态方法的使用 静态与.class 文件相关,只能使用接口名调用,不可以通过实现类的类名或者实现类的对象调用

  • 私有方法的使用

    私有方法:只有默认方法可以调用。
    私有静态方法:默认方法和静态方法可以调用。 如果一个接口中有多个默认方法,并且方法中有重复的内容,那么可以抽取出来,封装到私有方法中,供默认方法 去调用。从设计的角度讲,私有的方法是对默认方法和静态方法的辅助。
    
  • 抽象方法:接口中,有多个抽象方法时,实现类必须重写所有抽象方法。如果抽象方法有重名的,只需要重写一次

  • 默认方法 接口中,有多个默认方法时,实现类都可继承使用。如果默认方法有重名的,必须重写一次

  • 静态方法 接口中,存在同名的静态方法并不会冲突,原因是只能通过各自接口名访问静态方法

  • 优先级的问题 当一个类,既继承一个父类,又实现若干个接口时,父类中的成员方法与接口中的默认方法重名,子类就近选择执 行父类的成员方法。

  • 接口中,无法定义成员变量,但是可以定义常量,其值不可以改变,默认使用public static final修饰。
    接口中,没有构造方法,不能创建对象。
    接口中,没有静态代码块。
    

final

  • final: 不可改变。可以用于修饰类、方法和变量。

     类:被修饰的类,不能被继承。
    
     方法:被修饰的方法,不能被重写。
    
     变量:被修饰的变量,不能被重新赋值。
    
    
  • 格式:

     修饰类 :
         final class 类名 { 
         }
     修饰方法: 
         修饰符 final 返回值类型 方法名(参数列表){
         //方法体 
     }
    	含义:当前这个类不能有任何的子类。(太监类)
    	注意:一个类如果是final的,那么其中所有的成员方法都无法进行覆盖重写(因为没儿子。)
        
        
    修饰变量:
        局部变量-基本变量:
        		基本类型的局部变量,被final修饰后,只能赋值一次,不能再更改
        局部变量——引用类型:
        		引用类型的局部变量,被final修饰后,只能指向一个对象,地址不能再更改。但是不影响对象内部的成员变量值的 修改
        成员变量
                成员变量涉及到初始化的问题,初始化方式有两种,只能二选一:
                显示初始化;
        				     public class User {
       							 final String USERNAME = "张三";     
    							private int age; 
    						}
    			构造方法初始化:
                   			   public class User {
    									final String USERNAME ;
    									private int age;
    							public User(String username, int age) {
    										this.USERNAME = username;
    										this.age = age;
    								}
    							}
    
    
  • 对于类、方法来说,abstract关键字和final关键字不能同时使用,因为矛盾。

权限修饰符

  • public:公共的。

  • protected:受保护的

  • default:默认的

  • private:私有的

  • Java中有四种权限修饰符:
                        public  >   protected   >   (default)   >   private
    同一个类(我自己)        YES         YES             YES             YES
    同一个包(我邻居)        YES         YES             YES             NO
    不同包子类(我儿子)       YES         YES             NO              NO
    不同包非子类(陌生人)      YES         NO              NO              NO
        
    注意事项:(default)并不是关键字“default”,而是根本不写。
    

Scanner&Random&Object&String&StringBuilder类&Arrays类&Math类&static关键字&System类&包装类

Scanner(java.util.Scanner)

  • 一个可以解析基本类型和字符串的简单文本扫描器。

  • 可以实现键盘输入数据,到程序当中。

  • 创建对象 使用该类的构造方法,创建一个该类的对象。

  • 格式:

    数据类型 变量名 = new 数据类型(参数列表);
    Scanner sc = new Scanner(System.in);
    System.in 系统输入指的是通过键盘录入数据
    

方法:

  • 格式:

    变量名.方法名();
    int i = sc.nextInt(); // 接收一个键盘录入的整数
    

Random(java.util.Random)

创建一个 Random 对象,每次调用 nextInt() 方法,都会生成一个随机数。

public Random() :创建一个新的随机数生成器。
public int nextInt(int n) :返回一个伪随机数,范围在 0 (包括)和 指定值 n (不包括)之间的
int 值。

Object(java.lang.Object

概述

java.lang.Object类是Java语言中的根类,即所有类的父类。它中描述的所有方法子类都可以使用。在对象实例化的时候,最终找的父类就是Object。

如果一个类没有特别指定父类, 那么默认则继承自Object类。例如:

public class MyClass /*extends Object*/ {
  	// ...
}
  • public String toString():返回该对象的字符串表示。

    toString方法返回该对象的字符串表示,其实该字符串内容就是对象的类型+@+内存地址值。

    由于toString方法返回的结果是内存地址,而在开发中,经常需要按照对象的属性得到相应的字符串表现形式,因此也需要重写它。

  • public boolean equals(Object obj):指示其他某个对象是否与此对象“相等”。

    调用成员方法equals并指定参数为另一个对象,则可以判断这两个对象是否是相同的。这里的“相同”有默认和自定义两种方式。

    默认地址比较

    如果没有覆盖重写equals方法,那么Object类中默认进行==运算符的对象地址比较,只要不是同一个对象,结果必然为false。

    对象内容比较

    如果希望进行对象的内容比较,即所有或指定的部分成员变量相同就判定两个对象相同,则可以覆盖重写equals方法

    Person类默认继承了Object类,所以可以使用Object类的equals方法
                boolean equals(Object obj) 指示其他某个对象是否与此对象“相等”。
                equals方法源码:
                    public boolean equals(Object obj) {
                        return (this == obj);
                    }
                    参数:
                        Object obj:可以传递任意的对象
                        == 比较运算符,返回的是一个布尔值 true false
                        基本数据类型:比较的是值
                        引用数据类型:比价的是两个对象的地址值
                   this是谁?那个对象调用的方法,方法中的this就是那个对象;p1调用的equals方法所以this就是p1
                   obj是谁?传递过来的参数p2
                   this==obj -->p1==p2
    
    import java.util.Objects;
    
    public class Person {	
    	private String name;
    	private int age;
    	
        @Override
        public boolean equals(Object o) {
            // 如果对象地址一样,则认为相同
            if (this == o)
                return true;
            // 如果参数为空,或者类型信息不一样,则认为不同
            if (o == null || getClass() != o.getClass())
                return false;
            // 转换为当前类型
            Person person = (Person) o;
            // 要求基本类型相等,并且将引用类型交给java.util.Objects类的equals静态方法取用结果
            return age == person.age && Objects.equals(name, person.name);
        }
    }
    
    package com.itheima.demo01.Object;
    
    import java.util.Objects;
    
    public class Person {
        private String name;
        private int age;
    
        public Person() {
        }
    
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        /*
            直接打印对象的地址值没有意义,需要重写Object类中的toString方法
            打印对象的属性(name,age)
         */
        /*@Override
        public String toString() {
           //return "abc";
           return "Person{name="+name+" ,age="+age+"}";
        }*/
        /*@Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }*/
    
        /*
            Object类的equals方法,默认比较的是两个对象的地址值,没有意义
            所以我们要重写equals方法,比较两个对象的属性(name,age)
            问题:
                隐含着一个多态
                多态的弊端:无法使用子类特有的内容(属性和方法)
                Object obj = p2 = new Person("古力娜扎",19);
                解决:可以使用向下转型(强转)把obj类型转换为Person
         */
        /*@Override
        public boolean equals(Object obj) {
            //增加一个判断,传递的参数obj如果是this本身,直接返回true,提高程序的效率
            if(obj==this){
                return true;
            }
    
            //增加一个判断,传递的参数obj如果是null,直接返回false,提高程序的效率
            if(obj==null){
                return false;
            }
    
            //增加一个判断,防止类型转换一次ClassCastException
            if(obj instanceof Person){
                //使用向下转型,把obj转换为Person类型
                Person p = (Person)obj;
                //比较两个对象的属性,一个对象是this(p1),一个对象是p(obj->p2)
                boolean b = this.name.equals(p.name) && this.age==p.age;
                return b;
            }
            //不是Person类型直接返回false
            return false;
        }*/
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            //getClass() != o.getClass() 使用反射技术,判断o是否是Person类型  等效于 obj instanceof Person
            if (o == null || getClass() != o.getClass()) return false;
            Person person = (Person) o;
            return age == person.age &&
                    Objects.equals(name, person.name);
        }
    
        @Override
        public int hashCode() {
    
            return Objects.hash(name, age);
        }
    
        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 static boolean equals(Object a, Object b):判断两个对象是否相等。

    源码:

    public static boolean equals(Object a, Object b) {  
        return (a == b) || (a != null && a.equals(b));  
    }
    
  • 哈希值:是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,是模拟出来得到地址,不是数据实际存储的物理地址)
    在Object类有一个方法,可以获取对象的哈希值

   		int hashCode() 返回该对象的哈希码值。
   	 hashCode方法的源码:
        public native int hashCode();
        native:代表该方法调用的是本地操作系统的方法

String(java.lang.String)

概述

  • ​ java.lang.String 类代表字符串。
  • ​ Java程序中所有的字符串文字(例如 “abc” )都可以被看作是实现此类的实 例。
  • ​ 类 String 中包括用于检查各个字符串的方法,比如用于比较字符串,搜索字符串,提取子字符串以及创建具有翻 译为大写或小写的所有字符的字符串的副本。
特点
  • 字符串不变:字符串的值在创建后不能被更改。

  • 因为String对象是不可变的,所以它们可以被共享

  • 字符串效果上相当于是char[]字符数组,但是底层原理是byte[]字节数组。

    "abc" 等效于 char[] data={ 'a' , 'b' , 'c' }
三种构造方法:
public String():创建一个空白字符串,不含有任何内容。
public String(char[] array):根据字符数组的内容,来创建对应的字符串。
public String(byte[] array):根据字节数组的内容,来创建对应的字符串。

StringBuilder类(java.lang.StringBuilder)

查阅java.lang.StringBuilder的API,StringBuilder又称为可变字符序列,它是一个类似于 String 的字符串缓冲区,通过某些方法调用可以改变该序列的长度和内容。

原来StringBuilder是个字符串的缓冲区,即它是一个容器,容器中可以装很多字符串。并且能够对其中的字符串进行各种操作。

它的内部拥有一个数组用来存放字符串内容,进行字符串拼接时,直接在数组中加入新内容。StringBuilder会自动维护数组的扩容。

  • StringBuilder() 构造一个不带任何字符的字符串生成器,其初始容量为 16 个字符。

  • StringBuilder(String str) 构造一个字符串生成器,并初始化为指定的字符串内容。

StringBuilder和String可以相互转换:
String->StringBuilder:可以使用StringBuilder的构造方法
StringBuilder(String str) 构造一个字符串生成器,并初始化为指定的字符串内容。
StringBuilder->String:可以使用StringBuilder中的toString方法
public String toString():将当前StringBuilder对象转换为String对象。

Arrays类(java.util.Arrays)

  • public static String toString(int[] a) :返回指定数组内容的字符串表示形式。

  • public static void sort(int[] a) :对指定的 int 型数组按数字升序进行排序

    1. 如果是数值,sort默认按照升序从小到大
    2. 如果是字符串,sort默认按照字母升序
    3. 如果是自定义的类型,那么这个自定义的类需要有Comparable或者Comparator接口的支持。
    

Math类(java.lang.Math)

  • public static double abs(double a) :返回 double 值的绝对值。

  • public static double ceil(double a) :返回大于等于参数的最小的整数。

  • public static double floor(double a) :返回小于等于参数最大的整数。

  • public static long round(double a) :返回最接近参数的 long。(相当于四舍五入方法)


static关键字

概述
  • 关于 static 关键字的使用,它可以用来修饰的成员变量和成员方法,被修饰的成员是属于类的,而不是单单是属 于某个对象的。也就是说,既然属于类,就可以不靠创建对象来调用了。

  • 类变量 当 static 修饰成员变量时,该变量称为类变量。该类的每个对象都共享同一个类变量的值。任何对象都可以更改 该类变量的值,但也可以在不创建该类的对象的情况下对类变量进行操作。 类变量:使用 static关键字修饰的成员变量。

    定义格式:static 数据类型 变量名;
    
  • 静态方法

    当 static 修饰成员方法时,该方法称为类方法 。

    静态方法在声明中有 static ,建议使用类名来调用,而不需要 创建类的对象。调用方式非常简单。

    类方法:使用 static关键字修饰的成员方法,习惯称为静态方法。

    格式:修饰符 static 返回值类型 方法名 (参数列表){
    // 执行语句
    }
    
  • 静态方法调用的注意事项:

    静态方法可以直接访问类变量和静态方法。

    静态方法不能直接访问普通成员变量或成员方法。反之,成员方法可以直接访问类变量或静态方法。

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

    静态方法只能访问静态成员。

  • static 修饰的内容:

    是随着类的加载而加载的,且只加载一次。

    存储于一块固定的内存区域(静态区),所以,可以直接被类名调用。

    它优先于对象存在,所以,可以被所有对象共享。

  • 静态代码块

    静态代码块:定义在成员位置,使用static修饰的代码块{ }。

    位置:类中方法外。

    执行:随着类的加载而执行且执行一次,优先于main方法和构造方法的执行。

    public class ClassName{
       static {
      // 执行语句
     }
    }
    

System类(java.lang.System

java.lang.System类中提供了大量的静态方法,可以获取与系统相关的信息或系统级操作,在System类的API文档中,常用的方法有:

  • public static long currentTimeMillis():返回以毫秒为单位的当前时间。

    实际上,currentTimeMillis方法就是 获取当前系统时间与1970年01月01日00:00点之间的毫秒差值

  • public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length):将数组中指定的数据拷贝到另一个数组中。

    数组的拷贝动作是系统级的,性能很高。System.arraycopy方法具有5个参数,含义分别为:

    参数序号参数名称参数类型参数含义
    1srcObject源数组
    2srcPosint源数组索引起始位置
    3destObject目标数组
    4destPosint目标数组索引起始位置
    5lengthint复制元素个数

包装类

基本类型对应的包装类(位于java.lang包中)
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean
  • 装箱与拆箱

     装箱:把基本类型的数据,包装到包装类中(基本类型的数据->包装类)
            构造方法:
                Integer(int value) 构造一个新分配的 Integer 对象,它表示指定的 int 值。
                Integer(String s) 构造一个新分配的 Integer 对象,它表示 String 参数所指示的 int 值。
                    传递的字符串,必须是基本类型的字符串,否则会抛出异常 "100" 正确  "a" 抛异常
            静态方法:
                static Integer valueOf(int i) 返回一个表示指定的 int 值的 Integer 实例。
                static Integer valueOf(String s) 返回保存指定的 String 的值的 Integer 对象。
        拆箱:在包装类中取出基本类型的数据(包装类->基本类型的数据)
            成员方法:
                int intValue()int 类型返回该 Integer 的值。
    

    基本类型与对应的包装类对象之间,来回转换的过程称为”装箱“与”拆箱“:

    • 装箱:从基本类型转换为对应的包装类对象。

    • 拆箱:从包装类对象转换为对应的基本类型。

    用Integer与 int为例:(看懂代码即可)

    基本数值---->包装对象

    Integer i = new Integer(4);//使用构造函数函数
    Integer iii = Integer.valueOf(4);//使用包装类中的valueOf方法
    

    包装对象---->基本数值

    int num = i.intValue();
    
  • 自动装箱与自动拆箱

    由于我们经常要做基本类型与包装类之间的转换,从Java 5(JDK 1.5)开始,基本类型与包装类的装箱、拆箱动作可以自动完成。例如:

    Integer i = 4;//自动装箱。相当于Integer i = Integer.valueOf(4);
    i = i + 5;//等号右边:将i对象转成基本数值(自动拆箱) i.intValue() + 5;
    //加法运算完成后,再次装箱,把基本数值转成对象。
    
  • 基本类型与字符串之间的转换

    String转换成对应的基本类型

    除了Character类之外,其他所有包装类都具有parseXxx静态方法可以将字符串参数转换为对应的基本类型:

    • public static byte parseByte(String s):将字符串参数转换为对应的byte基本类型。
    • public static short parseShort(String s):将字符串参数转换为对应的short基本类型。
    • public static int parseInt(String s):将字符串参数转换为对应的int基本类型。
    • public static long parseLong(String s):将字符串参数转换为对应的long基本类型。
    • public static float parseFloat(String s):将字符串参数转换为对应的float基本类型。
    • public static double parseDouble(String s):将字符串参数转换为对应的double基本类型。
    • public static boolean parseBoolean(String s):将字符串参数转换为对应的boolean基本类型。

    如果字符串参数的内容无法正确转换为对应的基本类型,则会抛出java.lang.NumberFormatException异常。

日期时间类(java.util.Date)

Date类

  • DateFormat类(java.text.DateFormat)

    java.text.DateFormat 是日期/时间格式化子类的抽象类,我们通过这个类可以帮我们完成日期和文本之间的转换,也就是可以在Date对象与String对象之间进行来回转换。

    • 格式化:按照指定的格式,从Date对象转换为String对象。
    • 解析:按照指定的格式,从String对象转换为Date对象。

    DateFormat类的常用方法有:

    • public String format(Date date):将Date对象格式化为字符串。

    • public Date parse(String source):将字符串解析为Date对象。

  • public SimpleDateFormat(String pattern):用给定的模式和默认语言环境的日期格式符号构造SimpleDateFormat。

    参数pattern是一个字符串,代表日期时间的自定义格式。

格式规则为:

标识字母(区分大小写)含义
y
M
d
H
m
s

Calendar类(java.util.Calendar)

在Date后出现,替换掉了许多Date的方法。该类将所有可能用到的时间信息封装为静态成员变量,方便获取。日历类就是方便获取各个时间属性的。

获取方式

Calendar为抽象类,由于语言敏感性,Calendar类在创建对象时并非直接创建,而是通过静态方法创建,返回子类对象,如下:

Calendar静态方法

  • public static Calendar getInstance():使用默认时区和语言环境获得一个日历

常用方法

根据Calendar类的API文档,常用方法有:

  • public int get(int field):返回给定日历字段的值。
  • public void set(int field, int value):将给定的日历字段设置为给定值。
  • public abstract void add(int field, int amount):根据日历的规则,为给定的日历字段添加或减去指定的时间量。
  • public Date getTime():返回一个表示此Calendar时间值(从历元到现在的毫秒偏移量)的Date对象。

Calendar类中提供很多成员常量,代表给定的日历字段:

字段值含义
YEAR
MONTH月(从0开始,可以+1使用)
DAY_OF_MONTH月中的天(几号)
HOUR时(12小时制)
HOUR_OF_DAY时(24小时制)
MINUTE
SECOND
DAY_OF_WEEK周中的天(周几,周日为1,可以-1使用)

集合

Iterator迭代器(java.util.Iterator

Iterator接口也是Java集合中的一员,但它与CollectionMap接口有所不同,Collection接口与Map接口主要用于存储元素,而Iterator主要用于迭代访问(即遍历)Collection中的元素,因此Iterator对象也被称为迭代器。

  • public Iterator iterator(): 获取集合对应的迭代器,用来遍历集合中的元素的。

下面介绍一下迭代的概念:

  • 迭代:即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。

Iterator接口的常用方法如下:

  • public E next():返回迭代的下一个元素。

  • public boolean hasNext():如果仍有元素可以迭代,则返回 true。

    在进行集合元素取出时,如果集合中已经没有元素了,还继续使用迭代器的next方法,将会发生java.util.NoSuchElementException没有集合元素的错误。

  • 原理

    在调用Iterator的next方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next方法后,迭代器的索引会向后移动一位,指向第一个元素并将该元素返回,当再次调用next方法时,迭代器的索引会指向第二个元素并将该元素返回,依此类推,直到hasNext方法返回false,表示到达了集合的末尾,终止对元素的遍历。
    
  • 增强for

    增强for循环(也称for each循环)是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。

    格式:for(元素的数据类型  变量 : Collection集合or数组){ 
      	//写操作代码
    }
    

    它用于遍历Collection和数组。通常只进行遍历元素,不要在遍历的过程中对集合元素进行增删操作。

Collection(java.util.Collection)

  • 数组的长度是固定的。集合的长度是可变的。

  • Collection:单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是java.util.Listjava.util.Set。其中,List的特点是元素有序、元素可重复。Set的特点是元素无序,而且不可重复。List接口的主要实现类有java.util.ArrayListjava.util.LinkedListSet接口的主要实现类有java.util.HashSetjava.util.TreeSet

public boolean add(E e):  把给定的对象添加到当前集合中 。
public void clear() :清空集合中所有的元素。
public boolean remove(E e): 把给定的对象在当前集合中删除。
public boolean contains(E e): 判断当前集合中是否包含给定的对象。
public boolean isEmpty(): 判断当前集合是否为空。
public int size(): 返回集合中元素的个数。
public Object[] toArray(): 把集合中的元素,存储到数组中。
List接口(java.util.List )
List接口

在List集合中允许出现重复的元素,所有的元素是以一种线性方式进行存储的,在程序中可以通过 索引来访问集合中的指定元素。另外,List集合还有一个特点就是元素有序,即元素的存入顺序和取出顺序一致

  • 它是一个元素存取有序的集合。例如,存元素的顺序是11、22、33。那么集合中,元素的存储就是按照11、 22、33的顺序完成的)。
  • 它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)。
  • 集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素

List作为Collection集合的子接口,不但继承了Collection接口中的全部方法,而且还增加了一些根据元素索引来操 作集合的特有方法,如下:

public void add(int index, E element) : 将指定的元素,添加到该集合中的指定位置上。
public E get(int index) :返回集合中指定位置的元素。
public E remove(int index) : 移除列表中指定位置的元素, 返回的是被移除的元素。 
public E set(int index, E element) :用指定元素替换集合中指定位置的元素,返回值的更新前的元素
ArrayList(java.util.ArrayList )
  • java.util.ArrayList 集合数据存储的结构是数组结构元素增删慢,查找快

  • java.util.ArrayList 是大小可变的数组的实现,存储在内的数据称为元素。此类提供一些方法来操作内部存储 的元素。 ArrayList 中可不断添加元素,其大小也自动增长

  • java.util.ArrayList :该类需要 import导入使后使用。 表示一种指定的数据类型,叫做泛型。 E ,取自Element(元素)的首字母。在出现 E 的地方,我们使 用一种引用数据类型将其替换即可,表示我们将存储哪种引用类型的元素。代码如下:

    ArrayList<String>,ArrayList<Student>
    
  • 基本格式:

    ArrayList<String> list = new ArrayList<String>();
    
  • 在JDK 7后,右侧泛型的尖括号之内可以留空,但是<>仍然要写。简化格式:

    ArrayList<String> list = new ArrayList<>();
    
  • 存储基本数据类型

    如果希望向集合ArrayList当中存储基本类型数据,必须使用基本类型对应的“包装类”。
    
    基本类型    包装类(引用类型,包装类都位于java.lang包下)
    byte        Byte
    short       Short
    int         Integer     【特殊】
    long        Long
    float       Float
    double      Double
    char        Character   【特殊】
    boolean     Boolean
    

    从**JDK 1.5+**开始,支持自动装箱、自动拆箱。

    自动装箱:基本类型 --> 包装类型
    自动拆箱:包装类型 --> 基本类型

  • 对于ArrayList集合来说,直接打印得到的不是地址值,而是内容。
    如果内容是空,得到的是空的中括号:[]

LinkedList集合 (java.util.LinkedList )
  • java.util.LinkedList 集合数据存储的结构是链表结构方便元素添加、删除的集合。

  • LinkedList是一个双向链表

  • 添加与删除经常涉及到首尾操作,而LinkedList提供了大量首尾操作的方法。

    public void addFirst(E e) :将指定元素插入此列表的开头。
    public void addLast(E e) :将指定元素添加到此列表的结尾。
    public E getFirst() :返回此列表的第一个元素。
    public E getLast() :返回此列表的后一个元素。
    public E removeFirst() :移除并返回此列表的第一个元素。
    public E removeLast() :移除并返回此列表的后一个元素。
    public E pop() :从此列表所表示的堆栈处弹出一个元素。
    public void push(E e) :将元素推入此列表所表示的堆栈。
    public boolean isEmpty() :如果列表不包含元素,则返回true
    
  • ,LinkedList集合也可以作为堆栈,队列的结构使用

Set接口 (java.util.Set)
Set接口
  • java.util.Set 接口和 java.util.List 接口一样,同样继承自 Collection 接口,它与 Collection 接口中的方 法基本一致,并没有对 Collection 接口进行功能上的扩充,只是比 Collection 接口更加严格了。与 List 接口不 同的是, Set 接口中元素无序,并且都会以某种规则保证存入的元素不出现重复
  • 特点:
    1.不允许存储重复的元素
    2.没有索引,没有带索引的方法,也不能使用普通的for循环遍历
HashSet集合(java.util.HashSet)
  • java.util.HashSet 是 Set 接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的(即存取顺序 不一致)。

  • java.util.HashSet 底层的实现其实是一个 java.util.HashMap 支持

  • HashSet 是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。保证元素唯一性 的方式依赖于: hashCode 与 equals 方法

  • 特点:

             1.不允许存储重复的元素
             2.没有索引,没有带索引的方法,也不能使用普通的for循环遍历
             3.是一个无序的集合,存储元素和取出元素的顺序有可能不一致
             4.底层是一个哈希表结构(查询的速度非常的快)
    
  • HashSet集合存储数据的结构(哈希表)

    在JDK1.8之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。 但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。而JDK1.8中,哈 希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找 时间
    
LinkedHashSet 集合(java.util.LinkedHashSet )
  • 在HashSet下面有一个子类 java.util.LinkedHashSet ,它是链表和哈希表组合的一个数据存储结构
  • 底层是一个哈希表(数组+链表/红黑树)+链表:多了一条链表(记录元素的存储顺序),保证元素有序

Map(java.util.Map)

Map
  • Collection中的集合,元素是孤立存在的(理解为单身),向集合中存储元素采用一个个元素的方式存储。

  • Map中的集合,元素是成对存在的(理解为夫妻)。每个元素由键与值两部分组成,通过键可以找对所对应的值。

  • Collection中的集合称为单列集合,Map中的集合称为双列集合。

  • 需要注意的是,Map中的集合不能包含重复的键,值可以重复;每个键只能对应一个值。

  • 特点:

            1.Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)
            2.Map集合中的元素,key和value的数据类型可以相同,也可以不同
            3.Map集合中的元素,key是不允许重复的,value是可以重复的
            4.Map集合中的元素,key和value是一一对应
    
  • HashMap<K,V>:存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。

  • LinkedHashMap<K,V>:HashMap下有个子类LinkedHashMap,存储数据采用的哈希表结构+链表结构。通过链表结构可以保证元素的存取顺序一致;通过哈希表结构可以保证的键的唯一、不重复,需要重写键的hashCode()方法、equals()方法

tips:Map接口中的集合都有两个泛型变量<K,V>,在使用时,要为两个泛型变量赋予数据类型。两个泛型变量<K,V>的数据类型可以相同,也可以不同。

* `public V put(K key, V value)`:  把指定的键与指定的值添加到Map集合中。
* `public V remove(Object key)`: 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。
* `public V get(Object key)` 根据指定的键,在Map集合中获取对应的值。
* `boolean containsKey(Object key)  ` 判断集合中是否包含指定的键。
* `public Set<K> keySet()`: 获取Map集合中所有的键,存储到Set集合中。
* `public Set<Map.Entry<K,V>> entrySet()`: 获取到Map集合中所有的键值对对象的集合(Set集合)

使用put方法时,若指定的键(key)在集合中没有,则没有这个键对应的值,返回null,并把指定的键值添加到集合中;

若指定的键(key)在集合中存在,则返回值为集合中键对应的值(该值为替换前的值),并把指定键所对应的值,替换成指定的新值。

map的遍历
方式一(通过键找值的方式)

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

/*
    Map集合的第一种遍历方式:通过键找值的方式
    Map集合中的方法:
         Set<K> keySet() 返回此映射中包含的键的 Set 视图。
    实现步骤:
        1.使用Map集合中的方法keySet(),把Map集合所有的key取出来,存储到一个Set集合中
        2.遍历set集合,获取Map集合中的每一个key
        3.通过Map集合中的方法get(key),通过key找到value
 */
public class Demo02KeySet {
    public static void main(String[] args) {
        //创建Map集合对象
        Map<String,Integer> map = new HashMap<>();
        map.put("赵丽颖",168);
        map.put("杨颖",165);
        map.put("林志玲",178);

        //1.使用Map集合中的方法keySet(),把Map集合所有的key取出来,存储到一个Set集合中
        Set<String> set = map.keySet();

        //2.遍历set集合,获取Map集合中的每一个key
        //使用迭代器遍历Set集合
        Iterator<String> it = set.iterator();
        while (it.hasNext()){
            String key = it.next();
            //3.通过Map集合中的方法get(key),通过key找到value
            Integer value = map.get(key);
            System.out.println(key+"="+value);
        }
        System.out.println("-------------------");
        //使用增强for遍历Set集合
        for(String key : set){
            //3.通过Map集合中的方法get(key),通过key找到value
            Integer value = map.get(key);
            System.out.println(key+"="+value);
        }
        System.out.println("-------------------");
        //使用增强for遍历Set集合
        for(String key : map.keySet()){
            //3.通过Map集合中的方法get(key),通过key找到value
            Integer value = map.get(key);
            System.out.println(key+"="+value);
        }
    }
}

方式二(使用Entry对象遍历)

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

/*
    Map集合遍历的第二种方式:使用Entry对象遍历

    Map集合中的方法:
        Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射关系的 Set 视图。

    实现步骤:
        1.使用Map集合中的方法entrySet(),把Map集合中多个Entry对象取出来,存储到一个Set集合中
        2.遍历Set集合,获取每一个Entry对象
        3.使用Entry对象中的方法getKey()和getValue()获取键与值
 */
public class Demo03EntrySet {
    public static void main(String[] args) {
        //创建Map集合对象
        Map<String,Integer> map = new HashMap<>();
        map.put("赵丽颖",168);
        map.put("杨颖",165);
        map.put("林志玲",178);

        //1.使用Map集合中的方法entrySet(),把Map集合中多个Entry对象取出来,存储到一个Set集合中
        Set<Map.Entry<String, Integer>> set = map.entrySet();

        //2.遍历Set集合,获取每一个Entry对象
        //使用迭代器遍历Set集合
        Iterator<Map.Entry<String, Integer>> it = set.iterator();
        while(it.hasNext()){
            Map.Entry<String, Integer> entry = it.next();
            //3.使用Entry对象中的方法getKey()和getValue()获取键与值
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key+"="+value);
        }
        System.out.println("-----------------------");
        for(Map.Entry<String,Integer> entry:set){
            //3.使用Entry对象中的方法getKey()和getValue()获取键与值
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key+"="+value);
        }
    }
}

HashMap<K,V>
  • 特点:

        1.HashMap集合底层是哈希表:查询的速度特别的快
                JDK1.8之前:数组+单向链表
                JDK1.8之后:数组+单向链表|红黑树(链表的长度超过8):提高查询的速度
        2.hashMap集合是一个无序的集合,存储元素和取出元素的顺序有可能不一致
    
LinkedHashMap<K,V>
  • 特点:

    		 1.LinkedHashMap集合底层是哈希表+链表(保证迭代的顺序)
            2.LinkedHashMap集合是一个有序的集合,存储元素和取出元素的顺序是一致的
    
Hashtable<K,V>集合
  • java.util.Hashtable<K,V>集合

  • Hashtable:底层也是一个哈希表,是一个线程安全的集合,是单线程集合,速度慢
    HashMap:底层是一个哈希表,是一个线程不安全的集合,是多线程的集合,速度快
    
    HashMap集合(之前学的所有的集合):可以存储null值,null键
    Hashtable集合,不能存储null值,null键
    
    Hashtable和Vector集合一样,在jdk1.2版本之后被更先进的集合(HashMap,ArrayList)取代了
    Hashtable的子类Properties依然活跃在历史舞台
    Properties集合是一个唯一和IO流相结合的集合
    

可变参数

可变参数:是JDK1.5之后出现的新特性

  • ​ 使用前提:
    ​ 当方法的参数列表数据类型已经确定,但是参数的个数不确定,就可以使用可变参数.
    ​ 使用格式:定义方法时使用
修饰符 返回值类型 方法名(数据类型...变量名){}
  • ​ 可变参数的原理:

​ 可变参数底层就是一个数组,根据传递参数个数不同,会创建不同长度的数组,来存储这些参数
​ 传递的参数个数,可以是0个(不传递),1,2…多个

  • 可变参数的注意事项
    1.一个方法的参数列表,只能有一个可变参数
    2.如果方法的参数有多个,那么可变参数必须写在参数列表的末尾
public static void method(int...a,String...b){

 }
public static void method(String b,double c,int d,int...a){
    }

//可变参数的特殊(终极)写法
public static void method(Object...obj){

    }

Collections 集合工具类

  • java.utils.Collections 是集合工具类

  • public static <T> boolean addAll(Collection<T> c, T... elements) :往集合中添加一些元素。 public static void shuffle(List<?> list) 打乱顺序 :打乱集合顺序。
    public static <T> void sort(List<T> list) :将集合中元素按照默认规则排序。 public static <T> void sort(List<T> list,Comparator<? super T> ) :将集合中元素按照指定规则排 序
    
  • java.utils.Collections是集合工具类,用来对集合进行操作。部分方法如下:
    public static void sort(List list):将集合中元素按照默认规则排序。

注意:
     sort(List<T> list)使用前提
     被排序的集合里边存储的元素,必须实现Comparable,重写接口中的方法compareTo定义排序的规则

Comparable接口的排序规则:
    自己(this)-参数:升序
  • Comparator比较器

    public int compare(String o1, String o2) :比较其两个参数的顺序。
    两个对象比较的结果有三种:大于,等于,小于。 如果要按照升序排序, 则o1 小于o2,返回(负数),相等返回001大于02返回(正数) 如果要按照 降序排序 则o1 小于o2,返回(正数),相等返回001大于02返回(负数)
    
    
  • Comparable和Comparator两个接口的区别。

       Comparable:强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo方法 被称为它的自然比较方法。只能在类中实现compareTo()一次,不能经常修改类的代码实现自己想要的排序。实现 此接口的对象列表(和数组)可以通过Collections.sort(和Arrays.sort)进行自动排序,对象可以用作有序映射中 的键或有序集合中的元素,无需指定比较器。
           
        Comparator强行对某个对象进行整体排序。可以将Comparator 传递给sort方法(如Collections.sort或 Arrays.sort),从而允许在排序顺序上实现精确控制。还可以使用Comparator来控制某些数据结构(如有序set或 有序映射)的顺序,或者为那些没有自然顺序的对象collection提供排序。
    
     public static <T> void sort(List<T> list,Comparator<? super T> ):将集合中元素按照指定规则排序。 
    Comparable:自己(this)和别人(参数)比较,自己需要实现Comparable接口,重写比较的规则compareTo方法
            Comparator:相当于找一个第三方的裁判,比较两个
    
        Comparator的排序规则:
            o1-o2:升序
    

匿名对象&内部类& 匿名内部类&局部内部类&Lamda表达式

匿名对象概念

创建对象时,只有创建对象的语句,却没有把对象地址值赋值给某个变量。虽然是创建对象的简化写法,但是应用 场景非常有限。

匿名对象 :没有变量名的对象。

格式:

new 类名(参数列表);
  • 创建匿名对象直接调用方法,没有变量名。
  • 一个匿名对象,只能使用一次
  • 匿名对象可以作为方法的参数和返回值

内部类

概念:

什么是内部类

​ 将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。

  • 成员内部类

​ 成员内部类 :定义在类中方法外的类。

格式:class 外部类 {
		class 内部类{ 
	} 
}
  • 访问特点

    内部类可以直接访问外部类的成员,包括私有成员。

    外部类要访问内部类的成员,必须要建立内部类的对象。

    使用成员内部类:

    1. 间接方式:在外部类的方法当中,使用内部类;然后main只是调用外部类的方法。
    2. 直接方式,公式:
    类名称 对象名 = new 类名称();
    【外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();

    内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的.class文件,但是前面冠以外部类的类名 和$符号 。

匿名内部类

  • 匿名内部类 :是内部类的简化写法。它的本质是一个 带具体实现的 父类或者父接口的 匿名的 子类对象。 开发中,最常用到的内部类就是匿名内部类了。

  • 前提 匿名内部类必须继承一个父类或者实现一个父接口。

  • 格式

    new 父类名或者接口名(){
    // 方法重写
    @Override
    public void method() {
    // 执行语句
    }
    };
    
    
    对格式“new 接口名称() {...}”进行解析:
    1. new代表创建对象的动作
    2. 接口名称就是匿名内部类需要实现哪个接口
    3. {...}这才是匿名内部类的内容
    
    
  • 注意

    1. 匿名内部类,在【创建对象】的时候,只能使用唯一一次。
    如果希望多次创建对象,而且类的内容一样的话,那么就需要使用单独定义的实现类了。
    2. 匿名对象,在【调用方法】的时候,只能调用唯一一次。
    如果希望同一个对象,调用多次方法,那么必须给对象起个名字。
    3. 匿名内部类是省略了【实现类/子类名称】,但是匿名对象是省略了【对象名称】
    强调:匿名内部类和匿名对象不是一回事!!
    

局部内部类

  • 定义在方法中的内部类。

  • 特点

    不能使用任何的访问修饰符

    会生成两个.class文件,一个是Outer.class ,另一个是Outer$LocalInner.class。

    局部内部类只能访问方法中声明的final类型的变量

    “局部”:只有当前所属的方法才能使用它,出了这个方法外面就不能用了。

  • 定义格式:
    修饰符 class 外部类名称 {
        修饰符 返回值类型 外部类方法名称(参数列表) {
            class 局部内部类名称 {
                // ...
            }
        }
    }
    

    public > protected > (default) > private

    1. 外部类:public / (default)
    2. 成员内部类:public / protected / (default) / private
    3. 局部内部类:什么都不能写

Lamda表达式

推导
/**
 * 
 * @author 牧一
 *  Lamda表达式 
 * 1.推导 Lamda表达式
 * 
 */
public class TestLamda {
	// 2.0静态内部类
	static class Like2 implements Tlike {

		@Override
		public void Lamda() {
			// TODO Auto-generated method stub
			System.out.println("喜欢Lamda2");
		}

	}

	public static void main(String[] args) {
		// 1.0接口new实现类
		Tlike like = new Like();
		like.Lamda();
		like = new Like2();
		like.Lamda();
		// 3.0局部内部类
		class Like3 implements Tlike {

			@Override
			public void Lamda() {
				// TODO Auto-generated method stub
				System.out.println("喜欢Lamda3");
			}

		}
		like = new Like3();
		like.Lamda();
		// 4.0匿名内部类 ,没有类的名称,必须借助接口或者父类
		like = new Tlike() {

			@Override
			public void Lamda() {
				// TODO Auto-generated method stub
				System.out.println("喜欢Lamda4");
			}
		};
		like.Lamda();
		//5.0 Lamda简化
		like = ()-> {
			// TODO Auto-generated method stub
			System.out.println("喜欢Lamda5");
		};
		like.Lamda();
	}

}

//定义一个接口
interface Tlike {
	void Lamda();
}

// 实现类
class Like implements Tlike {

	@Override
	public void Lamda() {
		// TODO Auto-generated method stub
		System.out.println("喜欢Lamda");
	}

}

Lambda表达式的标准格式为:

(参数类型 参数名称) -> { 代码语句 }
  • 小括号内的语法与传统方法参数列表一致:无参数则留空;多个参数则用逗号分隔。
  • ->是新引入的语法格式,代表指向动作。
  • 大括号内的语法与传统方法体要求基本一致。
省略规则

在Lambda标准格式的基础上,使用省略写法的规则为:

  1. 小括号内参数的类型可以省略;
  2. 如果小括号内有且仅有一个参,则小括号可以省略;
  3. 如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号、return关键字及语句分号。
Lambda的使用前提
  1. 使用Lambda必须具有接口,且要求接口中有且仅有一个抽象方法
    无论是JDK内置的RunnableComparator接口还是自定义的接口,只有当接口中的抽象方法存在且唯一时,才可以使用Lambda。
  2. 使用Lambda必须具有上下文推断
    也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例。

备注:有且仅有一个抽象方法的接口,称为“函数式接口”。

异常

  • 异常 :指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。

  • 异常的根类是java.lang.Throwable,其下有两个子类:java.lang.Errorjava.lang.Exception

  • Throwable体系:

    • Error:严重错误Error,无法通过处理的错误,只能事先避免,好比绝症。
    • Exception:表示异常,异常产生后程序员可以通过代码的方式纠正,使程序继续运行,是必须要处理的。好比感冒、阑尾炎。

    Throwable中的常用方法:

    • public void printStackTrace():打印异常的详细信息。

      包含了异常的类型,异常的原因,还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace。

    • public String getMessage():获取发生异常的原因。

      提示给用户的时候,就提示错误原因。

    • public String toString():获取异常的类型和异常描述信息(不用)。

  • 异常分类

    • 编译时期异常:checked异常。在编译时期,就会检查,如果没有处理异常,则编译失败。(如日期格式化异常)
    • 运行时期异常:runtime异常。在运行时期,检查异常.在编译时期,运行异常不会编译器检测(不报错)。(如数学异常)
  • 异常的处理

    Java异常处理的五个关键字:try、catch、finally、throw、throws

    throw

    throw用在方法内,用来抛出一个异常对象,将这个异常对象传递到调用者处,并结束当前方法的执行。
    使用格式:
          throw new 异常类名(参数);
    

声明异常throws

​ 声明异常:将问题标识出来,报告给调用者。如果方法内通过throw抛出了编译时异常,而没有捕获处理(稍后讲解该方式),那么必须通过throws进行声明,让调用者去处理。

关键字throws运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常).

​ 声明异常格式:

修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2{   }	

捕获异常try…catch

​ 如果异常出现的话,会立刻终止程序,所以我们得处理异常:

1. 该方法不处理,而是声明抛出,由该方法的调用者来处理(throws)。
2. 在方法中使用try-catch的语句块来处理异常。

try-catch的方式就是捕获异常。

​ 捕获异常:Java中对异常有针对性的语句进行捕获,可以对出现的异常进行指定方式的处理

捕获异常语法如下:
try{
     编写可能会出现异常的代码
}catch(异常类型  e){
     处理异常的代码
     //记录日志/打印异常信息/继续抛出异常
}

**try:**该代码块中编写可能产生异常的代码。

**catch:**用来进行某种异常的捕获,实现对捕获到的异常进行处理。

注意:try和catch都不能单独使用,必须连用。

* `public String getMessage()`:获取异常的描述信息,原因(提示给用户的时候,就提示错误原因。


* `public String toString()`:获取异常的类型和异常描述信息(不用)* `public void printStackTrace()`:打印异常的跟踪栈信息并输出到控制台。
    *包含了异常的类型,异常的原因,还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace。*

finally 代码块

  • 有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。

  • try…catch…finally:自身需要处理异常,最终还得关闭资源。

  • 当只有在try或者catch中调用退出JVM的相关方法,此时finally才不会执行,否则finally永远会执行。

异常注意事项

try{
     编写可能会出现异常的代码
}catch(异常类型A  e){try中出现A类型异常,就用该catch来捕获.
     处理异常的代码
     //记录日志/打印异常信息/继续抛出异常
}catch(异常类型B  e){try中出现B类型异常,就用该catch来捕获.
     处理异常的代码
     //记录日志/打印异常信息/继续抛出异常
}

注意:这种异常处理方式,要求多个catch中的异常不能相同,并且若catch中的多个异常之间有子父类异常的关系,那么子类异常要求在上面的catch处理,父类异常在下面的catch处理。

* 运行时异常被抛出可以不处理。即不捕获也不声明抛出。

* 如果finally有return语句,永远返回finally中的结果,避免该情况. 

* 如果父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者是父类异常的子类或者不抛出异常。

* 父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出
  • Objects非空判断

    public static <T> T requireNonNull(T obj):查看指定引用对象不是null。

    源码:
    public static <T> T requireNonNull(T obj) {
        if (obj == null)
          	throw new NullPointerException();
        return obj;
    }
    

网络编程

软件结构
  • C/S结构 :全称为Client/Server结构,是指客户端和服务器结构。常见程序有QQ、迅雷等软件。
  • B/S结构 :全称为Browser/Server结构,是指浏览器和服务器结构。常见浏览器有谷歌、火狐等。
网络通信协议
  • **网络通信协议:**通过计算机网络可以使多台计算机实现连接,位于同一个网络中的计算机在进行连接和通信时需要遵守一定的规则,这就好比在道路中行驶的汽车一定要遵守交通规则一样。在计算机网络中,这些连接和通信的规则被称为网络通信协议,它对数据的传输格式、传输速率、传输步骤等做了统一规定,通信双方必须同时遵守才能完成数据交换。

  • TCP/IP协议: 传输控制协议/因特网互联协议( Transmission Control Protocol/Internet Protocol),是Internet最基本、最广泛的协议。它定义了计算机如何连入因特网,以及数据如何在它们之间传输的标准。它的内部包含一系列的用于处理数据通信的协议,并采用了4层的分层模型,每一层都呼叫它的下一层所提供的协议来完成自己的需求。

    TCP/IP协议中的四层分别是应用层、传输层、网络层和链路层,每层分别负责不同的通信功能。
    链路层:链路层是用于定义物理传输通道,通常是对某些网络连接设备的驱动协议,例如针对光纤、网线提供的驱动。
    网络层:网络层是整个TCP/IP协议的核心,它主要用于将传输的数据进行分组,将分组数据发送到目标计算机或者网络。
    运输层:主要使网络程序进行通信,在进行网络通信时,可以采用TCP协议,也可以采用UDP协议。
    应用层:主要负责应用程序的协议,例如HTTP协议、FTP协议等。
    
协议分类

TCP:传输控制协议 (Transmission Control Protocol)。TCP协议是面向连接的通信协议,即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。

在TCP连接中必须要明确客户端与服务器端,由客户端向服务端发出连接请求,每次连接的创建都需要经过“三次握手”。

  • 三次握手:TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠。
    • 第一次握手,客户端向服务器端发出连接请求,等待服务器确认。
    • 第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求。
    • 第三次握手,客户端再次向服务器端发送确认信息,确认连接

TCP通信的客户端:向服务器发送连接请求,给服务器发送数据,读取服务器回写的数据
    表示客户端的类:
        java.net.Socket:此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点。
        套接字:包含了IP地址和端口号的网络单位

    构造方法:
        Socket(String host, int port) 创建一个流套接字并将其连接到指定主机上的指定端口号。
        参数:
            String host:服务器主机的名称/服务器的IP地址
            int port:服务器的端口号

    成员方法:
        OutputStream getOutputStream() 返回此套接字的输出流。
        InputStream getInputStream() 返回此套接字的输入流。
        void close() 关闭此套接字。
CP通信的服务器端:接收客户端的请求,读取客户端发送的数据,给客户端回写数据
    表示服务器的类:
        java.net.ServerSocket:此类实现服务器套接字。

    构造方法:
        ServerSocket(int port) 创建绑定到特定端口的服务器套接字。

    服务器端必须明确一件事情,必须的知道是哪个客户端请求的服务器
    所以可以使用accept方法获取到请求的客户端对象Socket
    成员方法:
        Socket accept() 侦听并接受到此套接字的连接。

UDP:用户数据报协议(User Datagram Protocol)。UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。

由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输例如视频会议都使用UDP协议,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。

特点:数据被限制在64kb以内,超出这个范围就不能发送了。

网络编程三要素
协议
  • **协议:**计算机网络通信必须遵守的规则,已经介绍过了,不再赘述。
IP地址
  • IP地址:指互联网协议地址(Internet Protocol Address),俗称IP。IP地址用来给一个网络中的计算机设备做唯一的编号。假如我们把“个人电脑”比作“一台电话”的话,那么“IP地址”就相当于“电话号码”。

IP地址分类

  • IPv4:是一个32位的二进制数,通常被分为4个字节,表示成a.b.c.d 的形式,例如192.168.65.100 。其中a、b、c、d都是0~255之间的十进制整数,那么最多可以表示42亿个。

  • IPv6:由于互联网的蓬勃发展,IP地址的需求量愈来愈大,但是网络地址资源有限,使得IP的分配越发紧张。

    为了扩大地址空间,拟通过IPv6重新定义地址空间,采用128位地址长度,每16个字节一组,分成8组十六进制数,表示成ABCD:EF01:2345:6789:ABCD:EF01:2345:6789,号称可以为全世界的每一粒沙子编上一个网址,这样就解决了网络地址资源数量不够的问题。

常用命令

  • 查看本机IP地址,在控制台输入:
ipconfig
  • 检查网络是否连通,在控制台输入:
ping 空格 IP地址
ping 220.181.57.216

特殊的IP地址

  • 本机IP地址:127.0.0.1localhost
端口号

网络的通信,本质上是两个进程(应用程序)的通信。每台计算机都有很多的进程,那么在网络通信时,如何区分这些进程呢?

如果说IP地址可以唯一标识网络中的设备,那么端口号就可以唯一标识设备中的进程(应用程序)了。

  • **端口号:用两个字节表示的整数,它的取值范围是065535**。其中,01023之间的端口号用于一些知名的网络服务和应用,普通的应用程序需要使用1024以上的端口号。如果端口号被另外一个服务或应用所占用,会导致当前程序启动失败。

利用协议+IP地址+端口号 三元组合,就可以标识网络中的进程了,那么进程间的通信就可以利用这个标识与其它进程进行交互。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值