JavaSE基础总结

JavaSE基础总结

JavaSE – JavaSE简介&JDK安装与配置


一、JavaSE体系介绍

1.1 JavaSE知识图解

在这里插入图片描述

1.2 JavaSE知识模块介绍

  • 第一部分:计算机编程语言核心结构:数据类型运算符流程控制数组、…
  • 第二部分:Java面向对象核心逻辑:类和对象封装继承多态抽象接口、…
  • 第三部分:JavaSE核心高级应用:集合I/O多线程网络编程反射机制、…
  • 第四部分:Java新特性:Lambda表达式函数式编程新Date/Time API接口的默认、静态和私有方法、…
  • 第五部分:MySQL/JDBC核心技术:SQL语句数据库连接池DBUtils事务管理批处理、…

二、Java语言介绍

2.1 Java语言的历史发展

  Java诞生于SUN(Stanford University Network),09年SUN被Oracle(甲骨文)收购。
  Java之父是詹姆斯.高斯林(James Gosling)。
  1996年发布JDK1.0版。

2.2 Java发布版本日期对应表

版本发布日期最终免费公开更新时间[3][4]最后延伸支持日期
JDK Beta1995??
JDK 1.01996 年 1 月??
JDK 1.11997 年 2 月??
J2SE 1.21998 年 12 月??
J2SE 1.32000 年 5 月??
J2SE 1.42002 年 2 月2008 年 10 月2013 年 2 月
J2SE 5.02004 年 9 月2009 年 11 月2015 年 4 月
Java SE 62006 年 12 月2013 年 4 月2018 年 12 月
Java SE 72011 年 7 月2015 年 4 月2022 年 7 月
Java SE 8 (LTS)2014 年 3 月Oracle 于 2019 年 1 月停止更新(商用) Oracle 于 2020 年 12 月停止更新(非商用) AdoptOpenJDK 于 2026 年 5 月或之前停止更新 Amazon Corretto 于 2023 年 6 月或之前停止更新2030 年 12 月
Java SE 92017 年 9 月OpenJDK 于 2018 年 3 月停止更新不适用
Java SE 102018 年 3 月OpenJDK 于 2018 年 9 月停止更新不适用
Java SE 11 (LTS)2018 年 9 月Amazon Corretto 于 2024 年 8 月或之前停止更新 AdoptOpenJDK 于 2022 年 9 月停止更新2026 年 9 月
Java SE 122019 年 3 月OpenJDK 于 2019 年 9 月停止更新不适用
Java SE 132019 年 9 月OpenJDK 于 2020 年 3 月停止更新不适用
Java SE 142020 年 3 月OpenJDK 于 2020 年 9 月停止更新不适用

2.3 计算机语言排行榜

在这里插入图片描述

2.4 Java技术体系平台

  • JavaSE(Java Platform, Standard
    Edition标准版):允许您在桌面和服务器上开发和部署Java应用程序。Java提供了丰富的用户界面、性能、多功能性、可移植性和当今应用程序所需的安全性。
  • JavaEE(Java Platform, Enterprise Edition企业版):是为开发企业环境下的应用程序提供的一套解决方案,主要针对于Web应用程序开发。
  • JavaME(Java Platform, Micro Edition 小型版):为互联网上的嵌入式和移动设备上运行的应用提供了一个健壮、灵活的环境:微控制器、传感器、网关、移动电话、个人数字助理(PDA)、电视机顶盒、打印机等等。JavaME包括灵活的用户界面、健壮的安全性、内置的网络协议,以及支持动态下载的网络和离线应用程序。基于JavaME的应用程序在许多设备上都是可移植的,但是利用了每个设备的本机功能。
    • Java Embedded: 用于解锁物联网的智能设备的价值:
      通过远程市场更新和刷新功能延长产品生命周期和价值;
      利用Java的可伸缩性、健壮性、可移植性和全套功能,提高生产效率,降低成本,缩短上市时间;
      在边缘启用快速数据功能;
    • Java Card:使安全元件(如智能卡和其他防篡改安全芯片)能够承载采用Java技术的应用程序。Java card提供了一个安全的、可互操作的执行平台,它可以在一个资源受限的设备上存储和更新多个应用程序,同时保持最高的认证级别和与标准的兼容性。
    • Java TV:是一种基于JavaME的技术,它为开发在tv和机顶盒设备上运行的java应用程序提供了一个性能良好、安全且易于实现的解决方案。使用JavaTV运行时,开发人员可以轻松创建应用程序,例如电子节目指南(EPG)、视频点播(VOD)客户端、游戏和教育应用程序、用于访问Internet数据的应用程序(例如天气、新闻播报器、社交网络)以及大多数蓝光光盘标题上的用户界面和奖金内容。

三、Java语言跨平台原理

3.1Java语言的特点

  • 完全面向对象:Java语言支持封装、继承、多态,面向对象编程,让程序更好达到高内聚低耦合的标准。
  • 支持分布式:Java语言支持Internet应用的开发,在基本的Java应用编程接口中有一个网络应用编程接口(java net),它提供了用于网络应用编程的类库,包括URL、URLConnection、Socket、ServerSocket等。Java的RMI(远程方法激活)机制也是开发分布式应用的重要手段。
  • 健壮型:Java的强类型机制、异常处理、垃圾的自动收集等是Java程序健壮性的重要保证。对指针的丢弃是Java的明智选择。
    -安全 Java通常被用在网络环境中,为此,Java提供了一个安全机制以防恶意代码的攻击。如:安全防范机制(类ClassLoader),如分配不同的名字空间以防替代本地的同名类、字节代码检查。
  • 跨平台性Java程序(后缀为java的文件)在Java平台上被编译为体系结构中立的字节码格式(后缀为class的文件),然后可以在实现这个Java平台的任何系统中运行。

3.2 Java语言的跨平台原理

  • 跨平台:任何软件的运行,都必须要运行在操作系统之上,而我们用Java编写的软件可以运行在任何的操作系统上,这个特性称为Java语言的跨平台特性。该特性是由JVM实现的,我们编写的程序运行在JVM上,而JVM运行在操作系统上。

  • JVM(Java Virtual Machine ):Java虚拟机,简称JVM,是运行所有Java程序的假想计算机,是Java程序的运行环境之一,也是Java 最具吸引力的特性之一。我们编写的Java代码,都运行在JVM 之上。
    在这里插入图片描述
    如图所示,Java的虚拟机本身是不具备跨平台功能的,每个操作系统下都有不同版本的虚拟机。

    • JRE (Java Runtime Environment) :是Java程序的运行时环境,包含JVM 和运行时所需要的核心类库
    • JDK (Java Development Kit):是Java程序开发工具包,包含JRE 和开发人员使用的工具。

开发一个全新的Java程序,那么必须安装JDK ,其内部包含JRE

在这里插入图片描述

四、 JDK安装&环境配置

4.1 JDK的安装

  • 双击jdk-8u202-windows-x64.exe文件,并单击下一步,如图所示:
    在这里插入图片描述

  • 取消独立JRE的安装,单击公共JRE前的下拉列表,选择此功能将不可用如图所示:
    在这里插入图片描述

  • 修改安装路径,单击更改,如图所示:
    在这里插入图片描述

  • 将安装路径修改为D:\develop\Java\jdk1.8.0_202\,并单击确定,如图所示:
    在这里插入图片描述

  • 单击下一步,如图所示:
    在这里插入图片描述

  • 稍后几秒,安装完成,如图所示:
    在这里插入图片描述

  • 目录结构,如图所示:
    在这里插入图片描述

4.2 配置环境变量(配置JAVA_HOME+path)

为什么配置path
希望在命令行使用javac.exe等工具时,任意目录下都可以找到这个工具所在的目录。
步骤

  • 打开桌面上的计算机,进入后在左侧找到计算机,单击鼠标右键,选择属性,如图所示:
    在这里插入图片描述

  • 选择高级系统设置,如图所示:
    在这里插入图片描述

  • 高级选项卡,单击环境变量,如图所示:
    在这里插入图片描述

  • 系统变量中,单击新建 ,创建新的环境变量,如图所示:
    在这里插入图片描述

  • 变量名输入JAVA_HOME,变量值输入 D:\develop\Java\jdk1.8.0_202 ,并单击确定,如图所示:
    在这里插入图片描述

  • 选中Path 环境变量,双击或者点击编辑 ,如图所示:
    在这里插入图片描述

  • 在变量值的最前面,键入%JAVA_HOME%\bin; 分号必须要写,而且还要是英文符号。如图所示:
    在这里插入图片描述

  • 环境变量配置完成,重新开启DOS命令行,在任意目录下输入javac 命令,运行成功。
    在这里插入图片描述

JavaSE基础 – DOS命令


一、什么是DOS?

Java语言的初学者,学习一些DOS命令,会非常有帮助。DOS是一个早期的操作系统,现在已经被Windows系统取代,对于我们开发人员,目前需要在DOS中完成一些事情,因此就需要掌握一些必要的命令。。

二、进入DOS操作窗口

  1. 按下Windows+R键,打开运行窗口,输入cmd回车,进入到DOS的操作窗口。
    在这里插入图片描述

  2. 打开DOS命令行后,看到一个路径 C:\Users\... 就表示我们现在操作的磁盘是C盘的Users的final目录。
    在这里插入图片描述

三、常用命令

查看当前目录下有什么 输入命令:dir
在这里插入图片描述
在这里插入图片描述
进入目录命令:cd
(1)回到根目录

cd / 或 cd
在这里插入图片描述

(2)切换到上一级

cd ..

在这里插入图片描述
(3)当前盘的其他目录下
绝对路径:从根目录开始定位,例如:cd d:\test200\1 或者 cd d:/test200/1

相对路径:从当前目录开始定位,例如:…\…\…\test200\1 或者 …/…/…/test200/1

例如:现在在d:/test100/hello/a目录,要切换到d:/test200/1目录

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
切换盘符命令
(1)直接盘符:

例如:要切换到D盘,直接d:

(2)使用cd命令

例如:要切换到E盘,可以使用cd /D e:

使用 /D 开关,除了改变驱动器的当前目录之外,还可改变当前驱动器。
在这里插入图片描述
新建目录命令:md (make directory)

//在当前目录下创建hello文件夹
md hello
//在当前目录下创建a,b,c三个文件夹
md a b c
//在d盘test200下创建ok200文件夹
md d:\test200\ok200

在这里插入图片描述
新建空文件命令:type nul

type nul > 文件名.扩展名

追加内容到文件命令:echo

echo 内容 > 文件名.扩展名
在这里插入图片描述

*复制(copy)或移动(move)文件

copy 源文件 目标目录\新文件名.扩展名
move 源文件 目标目录
在这里插入图片描述

删除文件命令:del

//删除指定文件
del 文件名.扩展名

在这里插入图片描述
在这里插入图片描述

del 目标目录\文件名.扩展名
删除所有文件并询问

del .
删除所有文件不询问
del /Q .

在这里插入图片描述
删除目录命令:rd(remove directory)

//删除空目录
rd 空目录名

//删除目录以及下面的子目录和文件,带询问
rd /S 非空目录名

//删除目录以及下面的子目录和文件,不带询问
rd /S/Q 非空目录名

在这里插入图片描述
查看某个目录的下一级目录结构:tree

tree 目录
tree /F 目录
/F 显示每个文件夹中文件的名称。

清屏命令:cls

cls

退出命令:exit

exit

JavaSE --入门


一、 程序开发步骤说明

Java程序开发三步骤:编写编译运行
在这里插入图片描述

二、编写Java源程序

2.1 编写 HelloWorld

  1. D:\atguigu\javaee\JavaSE20190624\code\day01_code 目录下新建文本文件,完整的文件名修改为HelloWorld.java,其中文件名为HelloWorld,后缀名必须为.java
  2. 用记事本或notepad++等文本编辑器打开。
  3. 在文件中键入文本并保存,代码如下:
public class HelloWorld {
  	public static void main(String[] args) {
    	System.out.println("HelloWorld");
  	}
}

友情提示:
每个字母和符号必须与示例代码一模一样。(具体原因请往后看)

第一个HelloWord 源程序就编写完成了,但是这个文件是程序员编写的,JVM是看不懂的,也就不能运行,因此我们必须将编写好的Java源文件 编译成JVM可以看懂的字节码文件 ,也就是.class文件。

2.2 编译源文件

在DOS命令行中,进入D:\atguigu\javaee\JavaSE20190624\code\day01_code目录,使用javac 命令进行编译。
命令

javac Java源文件名.后缀名
注意: 此处编译必须要加上文件的后缀名

举例:

javac HelloWorld.java

在这里插入图片描述
编译成功后,命令行没有任何提示。打开D:\atguigu\javaee\JavaSE20190624\code\day01_code目录,发现产生了一个新的文件 HelloWorld.class,该文件就是编译后的文件,是Java的可运行文件,称为字节码文件,有了字节码文件,就可以运行程序了。

Java源文件的编译工具`javac.exe

2.3 运行Java程序

在DOS命令行中,进入Java源文件的目录,使用java 命令进行运行。
命令:

java 类名字

举例:

java HelloWorld

注意事项:
java HelloWord 注意此处不要加文件的后缀名

在这里插入图片描述

Java字节码文件的运行工具:java.exe

三、小常识类

3.1 常见错误

  1. Java是一门严格区分大小写的语言
  2. 不能用中文符号,英文半角的标点符号(正确)
  3. 括号问题,成对出现

3.2 Java程序的格式

结构:

{
    方法{
        语句;
    }
}

格式:
(1)每一级缩进一个Tab键

(2){}的左半部分在行尾,右半部分单独一行,与和它成对的"{"的行首对齐

3.3 Java程序的入口

Java程序的入口是main方法

public static void main(String[] args){
    
}

3.4 编写Java程序时应该注意的问题

  1. 字符编码问题
    当cmd命令行窗口的字符编码与.java源文件的字符编码不一致,如何解决?
    在这里插入图片描述
    解决方案一:

在Notepad++等编辑器中,修改源文件的字符编码
在这里插入图片描述

解决方案二:

在使用javac命令式,可以指定源文件的字符编码
javac -encoding utf-8 Review01.java

  1. 大小写问题
    (1)源文件名:

    不区分大小写,我们建议大家还是区分

    (2)字节码文件名与类名

    区分大小写

    (3)代码中:

    区分大小写

3.4 标识符

1.什么是标识符
给类、变量、方法、包等命名的字符序列,称为标识符。
2.标识符的命名规则
a.Java的标识符只能使用26个英文字母大小写,0-9的数字,下划线_,美元符号$
b.不能使用Java的关键字(包含保留字)和特殊值
c.数字不能开头
d.不能包含空格
e.严格区分大小写
3. 标识符的命名规范
a.见名知意
b.类名、接口名等:每个单词的首字母都大写,形式:XxxYyyZzz,
c.变量、方法名等:从第二个单词开始首字母大写,其余字母小写,形式:xxxYyyZzz,
d.包名等:每一个单词都小写,单词之间使用点.分割,形式:xxx.yyy.zzz,
e.常量名等:每一个单词都大写,单词之间使用下划线_分割,形式:XXX_YYY_ZZZ

四 数据类型

1. 数据类型分类

基本数据类型:包括 整数浮点数字符布尔
** 引用数据类型**:包括 数组接口

2.基本数据类型

2.1 四类八种基本数据类型:
Java中的默认类型:整数类型是int 、浮点类型是double
在这里插入图片描述
2.2 常量(constant
常量:在程序执行的过程中,其值不可以发生改变的量

3.变量

3.1 变量的概念
变量:在程序执行的过程中,其值可以发生改变的量
变量的作用:用来存储数据,代表内存的一块存储区域,这块内存中的值是可以改变的。
3.2 变量的三要素
1、数据类型 2、变量名 3、值
3.3 使用注意事项
a. 先声明后使用(如果没有声明,会报“找不到符号”错误)
b. 在使用之前必须初始化(如果没有初始化,会报“未初始化”错误)
c.变量有作用域(如果超过作用域,也会报“找不到符号”错误)
d.在同一个作用域中不能重名

4. 输出语句

换行输出语句**:输出内容,完毕后进行换行,格式如下:

System.out.println(输出内容);

直接输出语句**:输出内容,完毕后不做任何处理,格式如下:

System.out.print(输出内容);

5. 进制

5.1 进制的分类

a.十进制: 数字组成:0-9

进位规则:逢十进一

b.二进制:数字组成:0-1

进位规则:逢二进一

c.八进制:数字组成:0-7
>进位规则:逢八进一

d.十六进制: 数字组成:0-9,a-f

与二进制换算规则:每四位二进制是一位十六进制值

5.2 进制的换算

在这里插入图片描述
5.3 在代码中如何表示四种进制的值

(1)十进制:正常表示

System.out.println(10);

(2)二进制:0b或0B开头

System.out.println(0B10);

(3)八进制:0开头

System.out.println(010);

(4)十六进制:0x或0X开头

System.out.println(0X10);

5. 计算机存储单位

6.1 计算机存储单位

  • 字节(Byte):**是计算机信息技术用于计量存储容量的一种计量单位,一字节等于八位。
  • (bit):**是数据存储的最小单位。也就是二进制。二进制数系统中,每个0或1就是一个位,叫做bit(比特),其中8 bit 就称为一个字节(Byte)。
  • **转换关系:
    - 8 bit = 1 Byte
    - 1024 Byte = 1 KB
    - 1024 KB = 1 MB
    - 1024 MB = 1 GB
    - 1024 GB = 1 TB

6.2 Java的基本数据类型的存储范围
1、整型系列
(1)byte:字节类型

  • 占内存:1个字节
  • 存储范围:-128~127

(2)short:短整型类型

  • 占内存:2个字节
  • 存储范围:-32768~32767

(3)int:整型

  • 占内存:4个字节
  • 存储范围:-2的31次方 ~ 2的31次方-1

(4)long:整型

  • 占内存:8个字节

  • 存储范围:-2的63次方 ~ 2的63次方-1

    2、浮点型系列(小数)
    (1)float:单精度浮点型

  • 占内存:4个字节

  • 精度:科学记数法的小数点后6~7位

注意:如果要表示某个常量小数是float类型,那么需要在数字后面加F或f,否则就是double类型

(2)double:双精度浮点型

  • 占内存:8个字节
  • 精度:科学记数法的小数点后15~16位
    3、单字符类型:char
    占内存:2个字节
    4、布尔类型
    boolean:只能存储true或false

6.基本数据类型转换

6.1 自动类型转换(隐式类型转换)
取值范围小的类型自动提升为取值范围大的类型
在这里插入图片描述
6.2 强制类型转换(显示类型转换)
取值范围大的类型强制转换成取值范围小的类型
注意:

自动转换是Java自动执行的,而强制转换需要我们自己手动执行。
6.3 特殊的数据类型转换

  • 任意数据类型的数据与String类型进行“+”运算时,结果一定是String类型
  • 但是String类型不能通过强制类型()转换,转为其他的类型

五.运算符

5.1 概念

  • 运算符的分类:
    按照功能分:算术运算符、赋值运算符、比较运算符、逻辑运算、条件运算符…
  • 按照操作数个数分:一元运算符(单目运算符)、二元运算符(双目运算符)、三元运算符 (三目运算符)

5.2 算术运算符

在这里插入图片描述
注意:

  • ++在前,先自加,后使用;
  • ++在后,先使用,后自加。

5.3 赋值运算符

所有的赋值运算符的=左边一定是一个变量
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210321161818755.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzUyNTQ1MTU5,size_16,color_FFFFFF,t_70)

5.4 关系运算符/比较运算符

![在这里插入图片描述](https://img-blog.csdnimg.cn/20210321161848574.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzUyNTQ1MTU5,size_16,color_FFFFFF,t_70)

小结

-比较运算符,是两个数据之间进行比较的运算,运算结果一定是boolean值true或者false
-其中>,<,>=,<=不支持boolean,String类型,==和!=支持boolean和String

5.5 逻辑运算符

  a. 逻辑运算符,是用来连接两个布尔类型结果的运算符(`!`除外),运算结果一定是boolean值`true`或者`false`

在这里插入图片描述
b.&&和&区别,||和|区别

  • &&&结果一样,&&有短路效果,左边为false,右边不执行;&`左边无论是什么,右边都会执行。
  • |||结果一样,||有短路效果,左边为true,右边不执行;|`左边无论是什么,右边都会执行。

5.6 条件运算符

a. 条件运算符格式:

条件表达式?结果1:结果2

b.条件运算符计算方式:

条件判断的结果是true,条件运算符整体结果为结果1,赋值给变量。
判断条件的结果是false,条件运算符整体结果为结果2,赋值给变量。

5.7 位运算符

在这里插入图片描述

5.8 运算符优先级

算术->位–>比较–>逻辑–>三元–>赋值

六. 流程控制语句

6.1 概念

  不论哪一种编程语言,都会提供两种基本的流程控制结构:分支结构和循环结构。其中分支结构用于实现根据条件来选择性地执行某段代码,循环结构则用于实现根据循环条件重复执行某段代码

6.2 顺序结构

顺序结构就是程序从上到下逐行地执行,中间没有任何判断和跳转

6.2.1 分支结构:if语句第一种格式

1.格式

  • if语句第一种格式: if
if(条件表达式){
  	语句体;

2.执行流程

  • 首先判断条件表达式看其结果是true还是false

  • 如果是true就执行语句体

  • 如果是false就不执行语句体

在这里插入图片描述

6.2.2 分支结构:if语句第一种格式

1.格式

if(关系表达式) { 
  	语句体1;
}else {
  	语句体2;
}

2.执行流程

  • 首先判断关系表达式看其结果是true还是false
  • 如果是true就执行语句体1
  • 如果是false就执行语句体2
    在这里插入图片描述
6.2.3 分支结构:if语句第三种格式

1.格式

if (判断条件1) {
  	执行语句1;
} else if (判断条件2) {
  	执行语句2;
}
...
}else if (判断条件n) {
 	执行语句n;
} else {
  	执行语句n+1;
}

2.执行流程

  • 首先判断关系表达式1看其结果是true还是false
  • 如果是true就执行语句体1,然后结束当前多分支
  • 如果是false就继续判断关系表达式2看其结果是true还是false
  • 如果是true就执行语句体2,然后结束当前多分支
  • 如果是false就继续判断关系表达式…看其结果是true还是false
  • 如果没有任何关系表达式为true,就执行语句体n+1,然后结束当前多分支。

在这里插入图片描述

6.2.4 分支结构:if…else嵌套

a.概念
在if的语句块中,或者是在else语句块中,
又包含了另外一个条件判断(可以是单分支、双分支、多分支)
b.执行的特点:
(1)如果是嵌套在if语句块中的
只有当外部的if条件满足,才会去判断内部的条件
(2)如果是嵌套在else语句块中的
只有当外部的if条件不满足,进入else后,才会去判断内部的条件

6.2.5 分支结构:switch选择结构

a.语法格式

switch(表达式){
    case 常量值1:
        语句块1;break;case 常量值2:
        语句块2;break;】   
    。。。
   【default:
        语句块n+1;break;】
     】
}

b.执行过程:
(1)入口

①当switch(表达式)的值与case后面的某个常量值匹配,就从这个case进入;

②当switch(表达式)的值与case后面的所有常量值都不匹配,寻找default分支进入;不管default在哪里

(2)一旦从“入口”进入switch,就会顺序往下执行,直到遇到“出口”,即可能发生贯穿

(3)出口

①自然出口:遇到了switch的结束}

②中断出口:遇到了break等

注意:

(1)switch(表达式)的值的类型,只能是:4种基本数据类型(byte,short,int,char),两种引用数据类型(JDK1.5之后枚举、JDK1.7之后String)
(2)case后面必须是常量值,而且不能重复

6.2.6 循环结构:while循环
  1. .while循环语句标准格式:
while (循环条件语句①) {
    循环体语句②;
}
while(true){
     循环体语句;//如果此时循环体中没有跳出循环的语句,也是死循环
}

流程

  • 第一步:执行循环条件语句①,看循环条件语句的值是true,还是false;
    • 如果是true,执行第二步;
    • 如果是false,循环语句中止,循环不再执行。
  • 第二步:执行循环体语句②;
  • 第三步:循环体语句执行完后,重新从第一步开始再执行一遍
    2.while循环语句扩展格式:
初始化语句①;
while (循环条件语句②) {
    循环体语句③;
    迭代语句④;
}

执行流程:

  • 第一步:执行初始化语句①,完成循环变量的初始化;
  • 第二步:执行循环条件语句②,看循环条件语句的值是true,还是false;
    • 如果是true,执行第三步;
    • 如果是false,循环语句中止,循环不再执行。
  • 第三步:执行循环体语句③
  • 第四步:执行迭代语句④,针对循环变量重新赋值
  • 第五步:根据循环变量的新值,重新从第二步开始再执行一遍
6.2.7 循环结构:do…while循环

1、do…while循环语句标准格式:

do {
    循环体语句①;
} while (循环条件语句②)

执行流程:

  • 第一步:执行循环体语句①;
  • 第二步:执行循环条件语句②,看循环条件语句的值是true,还是false;
    • 如果是true,执行第三步;
    • 如果是false,循环语句终止,循环不再执行。
  • 第三步:循环条件语句执行完后,重新从第一步开始再执行一遍

2.do…while循环语句扩展格式:

初始化语句①
do {
    循环体语句②;
    迭代语句③;
} while (循环条件语句④)

流程:

  • 第一步:执行初始化语句①,完成循环变量的初始化;
  • 第二步:执行循环体语句②;
  • 第三步:执行迭代语句③,针对循环变量重新赋值;
  • 第四步:执行循环条件语句④,看循环条件语句的值是true,还是false;
    • 如果是true,根据循环变量的新值,重新从第二步开始再执行一遍;
    • 如果是false,循环语句中止,循环不再执行。
6.2.8 循环语句:for循环

1、for循环语句格式:

for(初始化语句①; 循环条件语句②; 迭代语句④){
	循环体语句③
}
for(;;){
    循环体语句块;//如果循环体中没有跳出循环体的语句,那么就是死循环
}

执行流程

  • 第一步:执行初始化语句①,完成循环变量的初始化;
  • 第二步:执行循环条件语句②,看循环条件语句的值是true,还是false;
    • 如果是true,执行第三步;
    • 如果是false,循环语句中止,循环不再执行。
  • 第三步:执行循环体语句③
  • 第四步:执行迭代语句④,针对循环变量重新赋值
  • 第五步:根据循环变量的新值,重新从第二步开始再执行一遍
6.2.9 循环语句的区别
  • 从循环次数角度分析
    • do…while循环至少执行一次循环体语句
    • for和while循环先循环条件语句是否成立,然后决定是否执行循环体,至少执行零次循环体语句
  • 从循环变量的生命周期角度分析
    • for循环的循环变量在for()中声明的,在循环语句结束后,不可以被访问;
    • while和do…while循环的循环变量因为在外面声明的,所以while和do…while结束后可以被继续使用的;
  • 如何选择
    • 遍历有明显的循环次数(范围)的需求,选择for循环
    • 遍历没有明显的循环次数(范围)的需求,循环while循环
    • 如果循环体语句块至少执行一次,可以考虑使用do…while循环
    • 本质上:三种循环之间是可以互相转换的,都能实现循环的功能
  • 三种循环结构都具有四要素:
    • (1)循环变量的初始化表达式
    • (2)循环条件
    • (3)循环变量的修改的迭代表达式
    • (4)循环体语句块

6.3 控制语句

6.3.1 break

1.使用场景:终止switch或者当前循环

  • 在选择结构switch语句中
  • 在循环语句中
  • 离开使用场景的存在是没有意义的

2.continue
使用场景:结束本次循环,继续下一次的循环
3. 嵌套循环
所谓嵌套循环**,是指一个循环的循环体是另一个循环。比如for循环里面还有一个for循环,就是嵌套循环。总共的循环次数=外循环次数*内循环次数。当然可以是三种循环任意互相嵌套。

    for(初始化语句①; 循环条件语句②; 迭代语句⑦) {
    for(初始化语句③; 循环条件语句④; 迭代语句⑥) {
      	循环体语句⑤;
    }
}

七.数组

7.1 数组的概念

数组概念: 数组就是用于存储数据的长度固定的容器,保证多个数据的数据类型要一致。
数组的特点:
1、数组的长度一旦确定就不能修改

2、创建数组时会在内存中开辟一整块连续的空间。

3、存取元素的速度快,因为可以通过[下标],直接定位到任意一个元素。

7.2数组的声明与初始化

7.2.1 方式一:静态初始化
  1. 格式
数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3...};
或
数据类型[] 数组名;
数组名 = new 数据类型[]{元素1,元素2,元素3...};

2.举例

int[] arr = new int[]{1,2,3,4,5};//正确

int[] arr;
arr = new int[]{1,2,3,4,5};//正确

7.2.2 方式三:动态初始化

1.格式:

 数组存储的元素的数据类型[] 数组名字 = new 数组存储的元素的数据类型[长度];

  或

 数组存储的数据类型[] 数组名字;
 数组名字 = new 数组存储的数据类型[长度];
  1. 数组定义格式详解:
  • 数组存储的元素的数据类型: 创建的数组容器可以存储什么数据类型的数据。
  • 元素的类型可以是任意的Java的数据类型。例如:int, String, Student等
  • [] : 表示数组。
  • 数组名字:为定义的数组起个变量名,满足标识符规范,可以使用名字操作数组。
  • new:关键字,创建数组使用的关键字。因为数组本身是引用数据类型,所以要用new创建数组对象。
  • [长度]:数组的长度,表示数组容器中可以存储多少个元素。
  • 注意:数组有定长特性,长度一旦指定,不可更改。
    • 和水杯道理相同,买了一个2升的水杯,总容量就是2升,不能多也不能少。

7.3 数组元素的访问

  • 索引:** 每一个存储到数组的元素,都会自动的拥有一个编号,从0开始,这个自动编号称为数组索引(index),可以通过数组的索引访问到数组中的元素。

  • 索引范围:[0, 数组的长度-1]

  • 索引访问数组中的元素:**

  • 数组名[索引]=数值,为数组中的元素赋值

  • 变量=数组名[索引],获取出数组中的元素

7.4 数组的遍历

- 数组的长度属性: 每个数组都具有长度,而且是固定的,Java中赋予了数组的一个属性,可以获取到数组的长度,语句为:数组名.length ,属性length的执行结果是数组的长度,int类型结果。由次可以推断出,数组的最大索引值为数组名.length-1

  • 数组遍历: 就是将数组中的每个元素分别获取出来,就是遍历。遍历也是数组操作中的基石。
public static void main(String[] args) {
  	int[] arr = new int[]{1,2,3,4,5};
  	//打印数组的属性,输出结果是5```
  	System.out.println("数组的长度:" + arr.length);
    
    //遍历输出数组中的元素
    System.out.println("数组的元素有:");
    for(int i=0; i<arr.length; i++){
        System.out.println(arr[i]);
    }
}

7.5 数组元素的默认值

在这里插入图片描述

7.6 数组内存图

7.6.1 内存概述

内存是计算机中重要的部件之一,它是与CPU进行沟通的桥梁。其作用是用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据。

7.6.2 Java虚拟机的内存划分

在这里插入图片描述
在这里插入图片描述

八.面向对象基础

8.1 面向对象思想概述

1、概述
Java语言是一种面向对象的程序设计语言,而面向对象思想(OOP)是一种程序设计思想,我们在面向对象思想的指引下,使用Java语言去设计、开发计算机程序。
2、面向对象与面向过程的区别
面向过程:POP: Process-Oriented Programming

​ 以函数(方法)为最小单位

​ 数据独立于函数之外

​ 以过程,步骤为主,考虑怎么做

面向对象:OOP: Object Oriented Programming

​ 以类/对象为最小单位,类包括:数据+方法

​ 以对象(谁)为主,考虑谁来做,谁能做

面向对象仍然包含面向过程,只不过关注点变了,关注谁来做

程序员的角色:

面向过程:程序员是具体执行者

面向对象:程序员是指挥者

面向对象思想是一种更符合我们思考习惯的思想,它可以将复杂的事情简单化,并将我们从执行者变成了指挥者。

3、面向对象的基本特征

面向对象的语言中,包含了三大基本特征,即封装、继承和多态。

8. 2 类和对象

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

8.3 类的定义和对象的创建

8.3.1 类的定义格式
public class ClassName {
  //成员变量
  //成员方法 
}
  • 定义类**:就是定义类的成员,包括成员变量成员方法
  • 成员变量:和以前定义变量几乎是一样的。只不过位置发生了改变。在类中,方法外
  • 成员方法:和以前写的main方法格式类似。只不过功能和形式更丰富了。在类中,方法外。
public class Person {
  	//成员变量
  	String name;//姓名
    int age;//年龄
    boolean isMarried;
    
    public void walk(){
        System.out.println("人走路...");
    }
    public String display(){
        return "名字是:" + name + ",年龄是:" + age + ",Married:" + isMarried;
    }
}
8.3.2 对象的创建
new 类名()//也称为匿名对象

//给创建的对象命名
//或者说,把创建的对象用一个引用数据类型的变量保存起来
类名 对象名 = new 类名();

示例

class Student{
    
}
public class TestStudent{
    //Java程序的入口
    public static void main(String[] args){
        System.out.println(new Student());//Student@7852e922

        Student stu = new Student();
        System.out.println(stu);//Student@4e25154f
        
        int[] arr = new int[5];
		System.out.println(arr);//[I@70dea4e
    }
}

8.4 成员变量

8.4.1 声明成员变量
【修饰符】 class 类名{
    【修饰符】 数据类型  属性名;    //属性有默认值
    【修饰符】 数据类型  属性名 =; //属性有初始值
}
8.4.2 成员变量默认值

在这里插入图片描述

8.5 成员方法

8.5.1 方法的概念

方法也叫函数,是一个独立功能的定义,是一个类中最基本的功能单元。

把一个功能封装为方法的目的是,可以实现代码重用,从而简少代码量。

8.5.2 方法的原则

方法的使用原则:

(1)必须先声明后使用

类,变量,方法等都要先声明后使用

(2)不调用不执行,调用一次执行一次。

8.5.3 成员方法的分类

成员方法分为两类:

  • 实例方法:没有static修饰的方法,必须通过实例对象来调用。
  • 静态方法:有static修饰的方法,也叫类方法,可以由类名来调用。
8.5.4 声明方法
【修饰符】 返回值类型 方法名(【参数列表:参数类型1 参数名1,参数类型2 参数名, ......){
        方法体;
        【return 返回值;}
  • 返回值类型: 表示方法运行的结果的数据类型,方法执行后将结果返回到调用者
    • 基本数据类型
    • 引用数据类型
    • 无返回值类型:void
  • 方法名:给方法起一个名字,见名知意,能准确代表该方法功能的名字
  • 参数列表:方法内部需要用到其他方法中的数据,需要通过参数传递的形式将数据传递过来,可以是基本数据类型、引用数据类型、也可以没有参数,什么都不写
  • 方法体:特定功能代码
  • return:结束方法,并将方法的结果返回去,
8.5.5 如何在其他类中调用方法

(1)实例方法

对象名.普通方法(【实参列表】) //必须通过对象来访问

(2)类方法

类名.类方法(【实参列表】) //推荐

8.5.6 形参和实参
  • 形参:在定义方法时方法名后面括号中声明的变量称为形式参数(简称形参)即形参出现在方法定义时。
  • 实参:调用方法时方法名后面括号中的使用的值/变量/表达式称为实际参数(简称实参)即实参出现在方法调用时。
8.5.7 方法的参数传递机制

方法的参数传递机制:实参给形参赋值

  • 方法的形参是基本数据类型时,形参值的改变不会影响实参;
  • 方法的形参是引用数据类型时,形参地址值的改变不会影响实参,但是形参地址值里面的数据的改变会影响实参,例如,修改数组元素的值,或修改对象的属性值。
8.5.8 成员变量与局部变量的区别

1、声明位置和方式
(1)静态变量:在类中方法外,并且有static修饰
(2)实例变量:在类中方法外,没有static修饰
(3)局部变量:在方法体{}中或方法的形参列表、代码块中

2、在内存中存储的位置不同
(1)静态变量:方法区
(2)实例变量:堆
(3)局部变量:栈

3、生命周期
(1)静态变量:和类的生命周期一样,因为它的值是该类所有对象共享的,早于对象的创建而存在。
(2)实例变量:和对象的生命周期一样,随着对象的创建而存在,随着对象被GC回收而消亡,
而且每一个对象的实例变量是独立的。
(3)局部变量:和方法调用的生命周期一样,每一次方法被调用而在存在,随着方法执行的结束而消亡,
而且每一次方法调用都是独立。

4、作用域
(1)静态变量和实例变量:不谈作用域
在本类中,唯一的限制,静态方法或静态代码块中不能使用非静态的,其他都可以直接使用。
在其他类中,能不能使用看修饰符(public,protected,private等)
(2)局部变量:有作用域
出了作用域就不能使用

5、修饰符(后面来讲)
(1)静态变量:很多
public,protected,private,final,volatile等,一定有的是static
(2)实例变量
public,protected,private,final,volatile,transient等
(3)局部变量
final

public,protected,private:权限修饰符
final:是否是常量,即值是否可以修改
volatile:和多线程有关
transient:是否序列化,和IO有关

6、默认值
(1)静态变量:有默认值
(2)实例变量:有默认值
(3)局部变量:没有,必须初始化
其中的形参比较特殊,靠实参给它初始化。

8.5.8 方法重载
  • 方法重载**:指在同一个类中,允许存在一个以上的同名方法,只要它们的参数列表不同即可,与修饰符和返回值类型无关。
  • 参数列表:数据类型个数不同,数据类型不同,数据类型顺序不同。
  • 重载方法调用:JVM通过方法的参数列表,调用不同的方法。
public class Method_Demo6 {
    public static void main(String[] args) {
        //定义不同数据类型的变量
        byte a = 10;
        byte b = 20;
        short c = 10;
        short d = 20;
        int e = 10;
        int f = 10;
        long g = 10;
        long h = 20;
        // 调用
        System.out.println(compare(a, b));
        System.out.println(compare(c, d));
        System.out.println(compare(e, f));
        System.out.println(compare(g, h));
    }
    // 两个byte类型的
    public static boolean compare(byte a, byte b) {
        System.out.println("byte");
        return a == b;
    }

    // 两个short类型的
    public static boolean compare(short a, short b) {
        System.out.println("short");
        return a == b;
    }

    // 两个int类型的
    public static boolean compare(int a, int b) {
        System.out.println("int");
        return a == b;
    }

    // 两个long类型的
    public static boolean compare(long a, long b) {
        System.out.println("long");
        return a == b;
    }
}

8.6 封装

8.6.1 封装

1 .概念
隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。通俗的讲,把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想。
2.如何实现封装呢?
就是依赖访问控制修饰符,也称为权限修饰符来控制。
在这里插入图片描述
外部类:public和缺省

成员变量:public,protected,缺省,private

成员方法:public,protected,缺省,private

构造器:public,protected,缺省,private

8.6.2 成员变量/属性私有化问题

1、成员变量封装的目的

  • 隐藏类的实现细节
  • 让使用者只能通过事先预定的方法来访问数据,从而可以在该方法里面加入控制逻辑,限制对成员变量的不合理访问。还可以进行数据检查,从而有利于保证对象信息的完整性。
  • 便于修改,提高代码的可维护性

2、实现步骤

public class Chinese {
  	private static String country;
    private String name;
  	private int age;
    private boolean marry;
    
    public static void setCountry(String c){
        country = c;
    }
    
    public static String getCountry(){
        return country;
    }

	public void setName(String n) {
		name = n;
    }

    public String getName() {
        return name;
	}

    public void setAge(int a) {
        age = a;
    }

    public int getAge() {
        return age;
    }
    
    public void setMarry(boolean m){
        marry = m;
    }
    
    public boolean isMarry(){
        return marry;
    }
}

3、如何解决局部变量与成员变量同名问题
当局部变量与类变量(静态成员变量)同名时,在类变量前面加“类名.";

当局部变量与实例变量(非静态成员变量)同名时,在实例变量前面加“this.”

8.6.3 包(Package)

1、包的作用
(1)可以避免类重名:有了包之后,类的全名称就变为:包.类名

(2)分类组织管理众多的类
2、声明包的语法格式

package 包名;

包的命名规范和习惯:
(1)所有单词都小写,每一个单词之间使用.分割
(2)习惯用公司的域名倒置

8.6.4 构造器(Constructor)

1、构造器的作用
在创建对象的时候为实例变量赋初始值。

注意:构造器只为实例变量初始化,不为静态类变量初始化

2、构造器的语法格式

构造器又称为构造方法,那是因为它长的很像方法。但是和方法还有有所区别的。

【修饰符】 构造器名(){
    // 实例初始化代码
}
【修饰符】 构造器名(参数列表){
	// 实例初始化代码
}

注意事项

  1. 构造器名必须与它所在的类名必须相同。
  2. 它没有返回值,所以不需要返回值类型,甚至不需要void
  3. 如果你不提供构造器,系统会给出无参数构造器,并且该构造器的修饰符默认与类的修饰符相同
  4. 如果你提供了构造器,系统将不再提供无参数构造器,除非你自己定义。
  5. 构造器是可以重载的,既可以定义参数,也可以不定义参数。
  6. 构造器的修饰符只能是权限修饰符,不能被其他任何修饰
8.6.5 标准JavaBean

JavaBean 是 Java语言编写类的一种标准规范。符合JavaBean 的类,要求:

(1)类必须是具体的和公共的,

(2)并且具有无参数的构造方法,

(3)成员变量私有化,并提供用来操作成员变量的setget 方法。

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

8.6 继承

8.6.1继承

1.概念
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类中无需再定义这些属性和行为,只需要和抽取出来的类构成某种关系
在这里插入图片描述

其中,多个类可以称为子类,也叫派生类;多个类抽取出来的这个类称为父类超类(superclass)或者基类

继承的好处

  • 提高代码的复用性
  • 提高代码的扩展性
  • 类与类之间产生了关系,是学习多态的前提

2 继承的格式
1.格式

【修饰符】 class 父类 {
	...
}
【修饰符】 class 子类 extends 父类 {
	...
}

3 继承的特点一:成员变量
1、父类成员变量私有化(private)

  • 父类中的成员,无论是公有(public)还是私有(private),均会被子类继承。
  • 子类虽会继承父类私有(private)的成员,但子类不能对继承的私有成员直接进行访问,可通过继承的get/set方法进行访问
/*
* 定义动物类Animal,做为父类
*/
class Animal {
   // 定义name属性
   private String name; 
   // 定义age属性
   public int age;
   // 定义动物的吃东西方法
   public void eat() {
   	System.out.println(age + "岁的" + name + "在吃东西");
   }
}

/*
* 定义猫类Cat 继承 动物类Animal
*/
class Cat extends Animal {
   // 定义一个猫抓老鼠的方法catchMouse
   public void catchMouse() {
   	System.out.println("抓老鼠");
   }
}

/*
* 定义测试类
*/
public class ExtendDemo01 {
   public static void main(String[] args) {
       // 创建一个猫类对象
   	Cat cat = new Cat()// 为该猫类对象的name属性进行赋值
   	//cat.name = "Tom";// 编译报错
     
     	// 为该猫类对象的age属性进行赋值
   	cat.age = 2;
       
       // 调用该猫的catchMouse()方法
   	cat.catchMouse();
   	
     	// 调用该猫继承来的eat()方法
     	cat.eat();
   }
}

2.父子类成员变量重名
(1)当父类的成员变量私有化时,在子类中是无法直接访问的,所以是否重名不影响,如果想要访问父类的私有成员变量,只能通过父类的get/set方法访问;

(2)当父类的成员变量非私有时,在子类中可以直接访问,所以如果有重名时,就需要加“super."进行区别。

4 继承的特点二:成员方法
1、方法重写

class Phone {
	public void sendMessage(){
		System.out.println("发短信");
	}
	public void call(){
		System.out.println("打电话");
	}
	public void showNum(){
		System.out.println("来电显示号码");
	}
}

//智能手机类
class NewPhone extends Phone {
	
	//重写父类的来电显示号码功能,并增加自己的显示姓名和图片功能
	public void showNum(){
		//调用父类已经存在的功能使用super
		super.showNum();
		//增加自己特有显示姓名和图片功能
		System.out.println("显示来电姓名");
		System.out.println("显示头像");
	}
}

public class ExtendsDemo06 {
	public static void main(String[] args) {
      	// 创建子类对象
      	NewPhone np = new NewPhone()// 调用父类继承而来的方法
        np.call();
      
      	// 调用子类重写的方法
      	np.showNum();

	}
}

2、方法的重载
(1)同一个类中

class Test{
	public int max(int a, int b){
		return a > b ? a : b;
	}
	public double max(double a, double b){
		return a > b ? a : b;
	}
	public int max(int a, int b,int c){
		return max(max(a,b),c);
	}
}

(2)父子类中

class Father{
	public void print(int i){
		System.out.println("i = " + i);
	}
}
class Son extends Father{
	public void print(int i,int j){
		System.out.println("i = " + i  ",j = " + j);
	}
}

5 继承的特点三:构造方法
构造方法的定义格式和作用。

  1. 构造方法的名字是与类名一致的。

    所以子类是无法继承父类构造方法的。

  2. 构造方法的作用是初始化实例变量的,而子类又会从父类继承所有成员变量

    所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构造方法中默认有一个super() ,表示调用父类的实例初始化方法,父类成员变量初始化后,才可以给子类使用。

class Fu {
  private int n;
  Fu(){
    System.out.println("Fu()");
  }
}
class Zi extends Fu {
  Zi(){
    // super(),调用父类构造方法
    super();
    System.out.println("Zi()");
  }  
}
public class ExtendsDemo07{
  public static void main (String args[]){
    Zi zi = new Zi();
  }
}

小结

  • super():表示调用父类的无参实例初始化方法,要求父类必须有无参构造,而且可以省略不写;
  • super(实参列表):表示调用父类的有参实例初始化方法,当父类没有无参构造时,子类的构造器首行必须写super(实参列表)来明确调用父类的哪个有参构造(其实是调用该构造器对应的实例初始方法)
  • super()和super(实参列表)都只能出现在子类构造器的首行

6 继承的特点四:单继承限制
1.Java只支持单继承,不支持多继承。

//一个类只能有一个父类,不可以有多个父类。
class C extends A{} 	//ok
class C extends A,B...	//error

2.Java支持多层继承(继承体系)。

class A{}
class B extends A{}
class C extends B{}
  顶层父类是Object类。所有的类默认继承Object,作为父类。
  1. 子类和父类是一种相对的概念。
  2. 一个父类可以同时拥有多个子类
8.6.2final关键字

1、修饰类
表示这个类不能被继承,没有子类

2、修饰方法
表示这个方法不能被子类重写

3、声明常量
final修饰某个变量(成员变量或局部变量),表示它的值就不能被修改,即常量,常量名建议使用大写字母。

8.6.3 this和super关键字

1 this关键字
1、this的含义
this代表当前对象
2、this使用位置

  • this在实例初始化相关的代码块和构造器中:表示正在创建的那个实例对象,即正在new谁,this就代表谁
  • this在非静态实例方法中:表示调用该方法的对象,即谁在调用,this就代表谁。
  • this不能出现在静态代码块和静态方法中
    3、this使用格式

(1)this.成员变量名

  • 当方法的局部变量与当前对象的成员变量重名时,就可以在成员变量前面加this.,如果没有重名问题,就可以省略this.
  • this.成员变量会先从本类声明的成员变量列表中查找,如果未找到,会去从父类继承的在子类中仍然可见的成员变量列表中查找

(2)this.成员方法

  • 调用当前对象的成员方法时,都可以加"this.",也可以省略,实际开发中都省略
  • 当前对象的成员方法,先从本类声明的成员方法列表中查找,如果未找到,会去从父类继承的在子类中仍然可见的成员方法列表中查找

(3)this()或this(实参列表)

  • 只能调用本类的其他构造器

  • 必须在构造器的首行

  • 如果一个类中声明了n个构造器,则最多有 n - 1个构造器中使用了"this(【实参列表】)",否则会发生递归调用死循环

2 super关键字
1、super的含义
super代表当前对象中从父类的引用的
2、super使用的前提

  • 通过super引用父类的xx,都是在子类中仍然可见的
  • 不能在静态代码块和静态方法中使用super
    3、super的使用格式
    (1)super.成员变量
    在子类中访问父类的成员变量,特别是当子类的成员变量与父类的成员变量重名时。
public class Person {
	private String name;
	private int age;
	//其他代码省略
}
public class Student extends Person{
	private int score;
	//其他成员方法省略
}
public class Test{
    public static void main(String[] args){
    	Student stu = new Student();
    }
}

(2)super.成员方法
在子类中调用父类的成员方法,特别是当子类重写了父类的成员方法时

public class Test{
    public static void main(String[] args){
    	Son s = new Son();
    	s.test();
    }
}
class Father{
	public void method(){
		System.out.println("aa");
	}
}
class Son extends Father{
	public void method(){
		System.out.println("bb");
	}
	public void test(){
		method();//bb
		this.method();//bb
		super.method();//aa
	}
}

(3)super()或super(实参列表)
在子类的构造器首行,用于表示调用父类的哪个实例初始化方法

super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现。
3 就近原则和追根溯源原则
1、找变量

  • 没有super和this
    • 在构造器、代码块、方法中如果出现使用某个变量,先查看是否是当前块声明的局部变量,
    • 如果不是局部变量,先从当前执行代码的本类去找成员变量
    • 如果从当前执行代码的本类中没有找到,会往上找父类的(非private,跨包还不能是缺省的)
  • this :代表当前对象
    • 通过this找成员变量时,先从当前执行代码的本类中找,没有的会往上找父类的(非private,跨包还不能是缺省的)。
  • super :代表父类的
    • 通过super找成员变量,直接从当前执行代码所在类的父类找
    • super()或super(实参列表)只能从直接父类找
    • 通过super只能访问父类在子类中可见的(非private,跨包还不能是缺省的)

注意:super和this都不能出现在静态方法和静态代码块中,因为super和this都是存在与对象中的

2、找方法

  • 没有super和this
    • 先从当前对象(调用方法的对象)的本类找,如果没有,再从直接父类找,再没有,继续往上追溯
  • this
    • 先从当前对象(调用方法的对象)的本类找,如果没有,再从父类继承的可见的方法列表中查找
  • super
    • 直接从当前对象(调用方法的对象)的父类继承的可见的方法列表中查找

3、找构造器

  • this()或this(实参列表):只从本类中,不会再往上追溯
  • super()或super(实参列表):只从直接父类找,不会再往上追溯

8.7 抽象类

1 由来
在父类中又无法给出具体的实现,而是应该交给子类各自具体实现。那么父类在声明这些方法时,就只有方法签名,没有方法体,我们把没有方法体的方法称为抽象方法。Java语法规定,包含抽象方法的类必须是抽象类
2 语法格式

  • 抽象方法 : 没有方法体的方法。
  • 抽象类:被abstract所修饰的类。
    抽象类的语法格式
【权限修饰符】 abstract class 类名{
   
}
【权限修饰符】 abstract class 类名 extends 父类{
}

抽象方法的语法格式

【其他修饰符】 abstract 返回值类型  方法名(【形参列表】);

3 注意事项
a.抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
b.抽象类中,也有构造方法,是供子类创建对象时,初始化父类成员变量使用的。
c.抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
d.抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。

8.8 多态

多态是继封装、继承之后,面向对象的第三大特性。

8.8.1 定义

1、格式

父类类型 变量名 = 子类对象;
父类类型:指子类对象继承的父类类型,或者实现的父接口类型。

示例

class Person{
	private String name;
	private int age;
	
    Person(String name, int age){
        this.name = name;
        this.age = age;
    }
    
	public void speak(){
		System.out.println(name + "说:我今年" + age);
	}
}
class Man extends Person{
    Man(String name, int age){
        super(name,age);
    }
}
class Woman extends Person{
    Woman(String name, int age){
        super(name,age);
    }
}
class Test{
	public static void main(String[] args){
		Person[] arr = new Person[2];
		arr[0] = new Man("张三",23);
		arr[1] = new Woman("aa",18);
		
		for(int i=0; i<arr.length; i++){
			arr[i].speak();
		}
		System.out.println("------------------------");
		
		show(new Man("张三",23));
		show(new Woman("aa",18));
	}
	
	public static void show(Person p){
		p.speak();
	}
}

2、编译时类型与运行时类型不一致问题

  • 编译时,看“父类”,只能调用父类声明的方法,不能调用子类扩展的方法;
  • 运行时,看“子类”,一定是执行子类重写的方法体;
8.8.2 父子类之间的类型转换

1、向上转型

  • 当父类引用指向一个子类对象时,便是向上转型。这个过程是自动完成的
  • 使用格式:
父类类型  变量名 = new 子类类型();
如:Animal a = new Cat();

2、向下转型

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

使用格式:

子类类型 变量名 = (子类类型) 父类变量名;:Cat c =(Cat) a;  
8.8.3 instanceof运算符

为了避免ClassCastException的发生,Java提供了 instanceof 关键字,给引用变量做类型的校验,只要用instanceof判断返回true的,那么强转为该类型就一定是安全的,不会报ClassCastException异常。

格式如下:

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

代码实例如下

public class Test {
    public static void main(String[] args) {
        // 向上转型  
        Animal a = new Cat();  
        a.eat();               // 调用的是 Cat 的 eat

        // 向下转型  
        if (a instanceof Cat){
            Cat c = (Cat)a;       
            c.catchMouse();        // 调用的是 Cat 的 catchMouse
        } else if (a instanceof Dog){
            Dog d = (Dog)a;       
            d.watchHouse();       // 调用的是 Dog 的 watchHouse
        }
    }  
}

8.9 枚举

1.语法格式:

【修饰符】 enum 枚举类名{
    常量对象列表
}

【修饰符】 enum 枚举类名{
    常量对象列表;
    
    其他成员列表;
}

2.枚举类的要求和特点:

  • 枚举类的常量对象列表必须在枚举类的首行,因为是常量,所以建议大写。
  • 如果常量对象列表后面没有其他代码,那么“;”可以省略,否则不可以省略“;”。
  • 编译器给枚举类默认提供的是private的无参构造,如果枚举类需要的是无参构造,就不需要声明,写常量对象列表时也不用加参数,
  • 如果枚举类需要的是有参构造,需要手动定义private的有参构造,调用有参构造的方法就是在常量对象名后面加(实参列表)就可以。
  • 枚举类默认继承的是java.lang.Enum类,因此不能再继承其他的类型。
  • JDK1.5之后switch,提供支持枚举类型,case后面可以写枚举常量名。
  • 枚举类型如有其它属性,建议(不是必须)这些属性也声明为final的,因为常量对象在逻辑意义上应该不可变。
    3.枚举类型常用方法
    1.toString(): 默认返回的是常量名(对象名),可以继续手动重写该方法!
    2.name():返回的是常量名(对象名) 【很少使用】
    3.ordinal():返回常量的次序号,默认从0开始
    4.values():返回该枚举类的所有的常量对象,返回类型是当前枚举的数组类型,是一个静态方法
    5.valueOf(String name):根据枚举常量对象名称获取枚举对象
public class TestEnum {
	public static void main(String[] args) {
		Season[] values = Season.values();
		for (int i = 0; i < values.length; i++) {
			switch(values[i]){
			case SPRING:
				System.out.println(values[i]+":春暖花开,万物复苏");
				break;
			case SUMMER:
				System.out.println(values[i]+":百花争艳,郁郁葱葱");
				break;
			case AUTUMN:
				System.out.println(values[i]+":菊桂飘香,百树凋零");
				break;
			case WINTER:
				System.out.println(values[i]+":梅花独开,大地一色");
				break;
			}
		}
	}
}
enum Season{
	SPRING,SUMMER,AUTUMN,WINTER
}

8.10 包装类

1.Java提供了两个类型系统,基本类型与引用类型,使用基本类型在于效率,然而当要使用只针对对象设计的API或新特性(例如泛型),那么基本数据类型的数据就需要用包装类来包装。
在这里插入图片描述
2 装箱与拆箱
装箱:把基本数据类型转为包装类对象。
拆箱:把包装类对象拆为基本数据类型。
注意:JDK1.5之后,可以自动装箱与拆箱,只能与自己对应的类型之间才能实现自动装箱与拆箱。
3.基本数据类型和字符串之间的转换
(1)把基本数据类型转为字符串

int a = 10;
//String str = a;//错误的
//方式一:
String str = a + "";
//方式二:
String str = String.valueOf(a);

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

  • public static int parseInt(String s):将字符串参数转换为对应的int基本类型。
  • public static long parseLong(String s):将字符串参数转换为对应的long基本类型。
  • public static double parseDouble(String s):将字符串参数转换为对应的double基本类型。

或把字符串转为包装类,然后可以自动拆箱为基本数据类型

  • public static Integer valueOf(String s):将字符串参数转换为对应的Integer包装类,然后可以自动拆箱为int基本类型
  • public static Long valueOf(String s):将字符串参数转换为对应的Long包装类,然后可以自动拆箱为long基本类型
  • public static Double valueOf(String s):将字符串参数转换为对应的Double包装类,然后可以自动拆箱为double基本类型
    4.数据类型的最大最小值
Integer.MAX_VALUE和Integer.MIN_VALUE
Long.MAX_VALUE和Long.MIN_VALUE
Double.MAX_VALUE和Double.MIN_VALUE

5.字符转大小写

Character.toUpperCase('x');
Character.toLowerCase('X');

6.整数转进制

Integer.toBinaryString(int i) 
Integer.toHexString(int i)
Integer.toOctalString(int i)
  1. 包装类对象的缓存问题
    在这里插入图片描述

8.10 接口

8.10.1 定义格式

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

【修饰符】 interface 接口名{
    //接口的成员列表:
    // 静态常量
    // 抽象方法
    // 默认方法
    // 静态方法
    // 私有方法
}

示例代码:

interface Usb3{
    //静态常量
	long MAX_SPEED = 500*1024*1024;//500MB/s
    
    //抽象方法
	void read();
    void write();
    
    //默认方法
    public default void start(){
        System.out.println("开始");
    }
    public default void stop(){
        System.out.println("结束");
    }
    
    //静态方法
    public static void show(){
        System.out.println("USB 3.0可以同步全速地进行读写操作");
    }
}

2、接口的成员说明
接口定义的是多个类共同的公共行为规范,这些行为规范是与外部交流的通道,这就意味着接口里通常是定义一组公共方法。

在JDK8之前,接口中只允许出现:

(1)公共的静态的常量:其中public static final可以省略

(2)公共的抽象的方法:其中public abstract可以省略

理解:接口是从多个相似类中抽象出来的规范,不需要提供具体实现

在JDK1.8时,接口中允许声明默认方法和静态方法:

(3)公共的默认的方法:其中public 可以省略,建议保留,但是default不能省略

(4)公共的静态的方法:其中public 可以省略,建议保留,但是static不能省略

在JDK1.9时,接口又增加了:

(5)私有方法

除此之外,接口中不能有其他成员,没有构造器,没有初始化块,因为接口中没有成员变量需要初始化。
3.实现接口

接口的使用,它不能创建对象,但是可以被实现(implements ,类似于被继承)。

类与接口的关系为实现关系,即类实现接口,该类可以称为接口的实现类,也可以称为接口的子类。实现的动作类似继承,格式相仿,只是关键字不同,实现使用 implements关键字。
4.实现接口语法格式

【修饰符】 class 实现类  implements 接口{
	// 重写接口中抽象方法【必须】,当然如果实现类是抽象类,那么可以不重写
  	// 重写接口中默认方法【可选】
}

【修饰符】 class 实现类 extends 父类 implements 接口{
    // 重写接口中抽象方法【必须】,当然如果实现类是抽象类,那么可以不重写
  	// 重写接口中默认方法【可选】
}

注意:

  1. 如果接口的实现类是非抽象类,那么必须重写接口中所有抽象方法。
  2. 默认方法可以选择保留,也可以重写。

5.如何调用对应的方法

  • 对于接口的静态方法,直接使用“接口名.”进行调用即可
    • 也只能使用“接口名."进行调用,不能通过实现类的对象进行调用
  • 对于接口的抽象方法、默认方法,只能通过实现类对象才可以调用
    • 接口不能直接创建对象,只能创建实现类的对象
public class TestInteface {
	public static void main(String[] args) {
		//创建实现类对象
		MobileHDD b = new MobileHDD();
		
		//通过实现类对象调用重写的抽象方法,以及接口的默认方法,如果实现类重写了就执行重写的默认方法,如果没有重写,就执行接口中的默认方法
		b.start();
		b.read();
		b.stop();
		
		//通过接口名调用接口的静态方法
		MobileHDD.show();
	}
}

6.接口的多实现
在继承体系中,一个类只能继承一个父类。而对于接口而言,一个类是可以实现多个接口的,这叫做接口的多实现。并且,一个类能继承一个父类,同时实现多个接口。
实现格式:

【修饰符】 class 实现类  implements 接口1,接口2,接口3。。。{
	// 重写接口中所有抽象方法【必须】,当然如果实现类是抽象类,那么可以不重写
  	// 重写接口中默认方法【可选】
}

【修饰符】 class 实现类 extends 父类 implements 接口1,接口2,接口3。。。{
    // 重写接口中所有抽象方法【必须】,当然如果实现类是抽象类,那么可以不重写
  	// 重写接口中默认方法【可选】
}

7 接口的多继承
一个接口能继承另一个或者多个接口,接口的继承也使用 extends 关键字,子接口继承父接口的方法。

小结:

子接口重写默认方法时,default关键字可以保留。
子类重写默认方法时,default关键字不可以保留。

九.Object根父类

9.1 如何理解根父类

java.lang.Object是类层次结构的根类,即所有类的父类。每个类都使用 Object 作为超类。

  • Object类型的变量与除Object以外的任意引用数据类型的对象都多态引用
  • 所有对象(包括数组)都实现这个类的方法。
  • 如果一个类没有特别指定父类,那么默认则继承自Object类。例如:
public class MyClass /*extends Object*/ {
  	// ...
}

9.2Object类的API

API(Application Programming Interface),应用程序编程接口。Java API是一本程序员的字典 ,是JDK中提供给我们使用的类的说明文档。
1.toString()
public String toString()
①默认情况下,toString()返回的是“对象的运行时类型 @ 对象的hashCode值的十六进制形式"

②通常是建议重写,如果在eclipse中,可以用Alt +Shift + S–>Generate toString()

③如果我们直接System.out.println(对象),默认会自动调用这个对象的toString()

示例

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

    @Override
    public String toString() {
        return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
    }

    // 省略构造器与Getter Setter
}

2.getClass()
public final Class<?> getClass():获取对象的运行时类型

public static void main(String[] args) {
		Object obj = new String();
		System.out.println(obj.getClass());//运行时类型
	}

3.finalize()
protected void finalize():用于最终清理内存的方法

public class TestFinalize {
	public static void main(String[] args) {
		for (int i = 0; i < 10; i++) {
			MyData my = new MyData();
		}
		
		System.gc();//通知垃圾回收器来回收垃圾
		
		try {
			Thread.sleep(2000);//等待2秒再结束main,为了看效果
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
class MyData{

	@Override
	protected void finalize() throws Throwable {
		System.out.println("轻轻的我走了...");
	}
	
}

4.hashCode()
public int hashCode():返回每个对象的hash值。
hashCode 的常规协定:

  • ①如果两个对象的hash值是不同的,那么这两个对象一定不相等;
  • ②如果两个对象的hash值是相同的,那么这两个对象不一定相等。
public static void main(String[] args) {
		System.out.println("Aa".hashCode());//2112
		System.out.println("BB".hashCode());//2112
	}

5.equals()
public boolean equals(Object obj):用于判断当前对象this与指定对象obj是否“相等”

①默认情况下,equals方法的实现等价于与“==”,比较的是对象的地址值

②我们可以选择重写,重写有些要求:

A:如果重写equals,那么一定要一起重写hashCode()方法,因为规定:

​ a:如果两个对象调用equals返回true,那么要求这两个对象的hashCode值一定是相等的;

​ b:如果两个对象的hashCode值不同的,那么要求这个两个对象调用equals方法一定是false;

​ c:如果两个对象的hashCode值相同的,那么这个两个对象调用equals可能是true,也可能是false

B:如果重写equals,那么一定要遵循如下几个原则:

​ a:自反性:x.equals(x)返回true

​ b:传递性:x.equals(y)为true, y.equals(z)为true,然后x.equals(z)也应该为true

​ c:一致性:只要参与equals比较的属性值没有修改,那么无论何时调用结果应该一致

​ d:对称性:x.equals(y)与y.equals(x)结果应该一样

​ e:非空对象与null的equals一定是false

class User{
	private String host;
	private String username;
	private String password;
	public User(String host, String username, String password) {
		super();
		this.host = host;
		this.username = username;
		this.password = password;
	}
	public User() {
		super();
	}
	public String getHost() {
		return host;
	}
	public void setHost(String host) {
		this.host = host;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	@Override
	public String toString() {
		return "User [host=" + host + ", username=" + username + ", password=" + password + "]";
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((host == null) ? 0 : host.hashCode());
		result = prime * result + ((password == null) ? 0 : password.hashCode());
		result = prime * result + ((username == null) ? 0 : username.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		User other = (User) obj;
		if (host == null) {
			if (other.host != null)
				return false;
		} else if (!host.equals(other.host))
			return false;
		if (password == null) {
			if (other.password != null)
				return false;
		} else if (!password.equals(other.password))
			return false;
		if (username == null) {
			if (other.username != null)
				return false;
		} else if (!username.equals(other.username))
			return false;
		return true;
	}
	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值