JAVA 学习笔记(一)
编程入门
概述
计算机包括硬件(hardware) 和 ==软件(software)==两部分。硬件包括计算机中可以看得见的物理部分。而软件提供看不见的指令。这些指令控制硬件并且使得硬件完成特定的任务。
程序设计
定义:创建(或开发)软件。软件包含了指令,告诉计算机做什么。
应用场景:软件遍布我们周围。除了个人计算机,飞机、汽车、手机甚至烤面包机中,同样运行着软件。
程序设计语言
软件开发人员在称为程序设计语言的强大工具的帮助下创建软件。
如何选择该学习哪种程序设计语言?
- 程序设计语言有很多种,每种语言都是为了实现某个特定的目的而发明的。
- 你会困惑哪种语言是最好的。事实上,没有“最好”的语言。每种语言都有它的长处和短处。
- 经验丰富的程序员知道各种语言擅长的应用场景,因此,会尽可能的掌握各种不同的程序设计语言。
- 如果你掌握了一种编程语言,应该会更容易上手其它的编程语言。关键是学习如何使用程序设计方法来解决问题。
计算机硬件介绍
冯·诺依曼体系结构是现代计算机的基础,现在大多计算机仍是冯·诺依曼计算机的组织结构,只是作了一些改进而已,并没有从根本上突破冯体系结构的束缚。冯·诺依曼也因此被人们称为“计算机之父”。
计算机硬件介绍-中央处理器
-
中央处理器(Central Processing Unit,CPU)是计算机的大脑。它从内存中获取指令,然后执行这些指令。
-
包括:控制单元(control unit)和算术/逻辑单元(arithmetic/login unit)。
- 控制单元:用于控制和协调其他组件的动作。
- 算术/逻辑单元:用于完成数值运算(+、-、*、/)和逻辑运算(比较)。
-
每台计算机都有一个内部时钟,该时钟以固定速度发射电子脉冲。时钟速度越快,在给定的时间段内执行的指令就越多。速度的计量单位是赫兹(Hz),1Hz相当于每秒1个脉冲。随着CPU速度不断提高,目前以千兆赫(GHz)来表述。
-
最初一个CPU只有一个核(core)。核是处理器中实现指令读取和执行的部分。一个多核CPU是一个具有两个或者更多独立核的组件。可提高CPU的处理能力。
IT定律之计算机行业发展规律
- 摩尔定律(Moore’s Law)
- 安迪-比尔定律(Andy and Bill’s Law)
- 反摩尔定律(Reverse Moore’s Law)
计算机硬件介绍-存储设备
-
内存中的信息在断电时会丢失。那我们可以考虑将程序和数据永久的保存在存储设备上。当计算机确实需要这些数据时,再移入内存,因为从内存中读取比从存储设备读取要快得多。
-
存储设备主要有以下三种:
-
磁盘驱动器:每台计算机至少有一个硬盘驱动器。硬盘(hard disk)用于永久的保存数据和程序。
-
光盘驱动器(CD和DVD)
- CD的容量可达700MB。
- DVD的容量可达4.7GB。
-
USB闪存驱动器
- USB: Universal Serial Bus,通用串行总线。
- 可以使用USB将打印机、数码相机、鼠标、外部硬盘驱动器连接到计算机上。
- USB闪存驱动器很小,可用于存储和传输数据的设备。
-
计算机硬件介绍:内存
比特(bit)和字节(byte)
-
在讨论内存前,先清楚数据是如何存储在计算机中的。
-
计算机就是一系列的电路开关。每个开关存在两种状态:关(off)和开(on)。如果电路是开的,它的值是1。如果电路是关的,它的值是0。
-
一个0或者一个1存储为一个比特(bit),是计算机中最小的存储单位。
-
计算机中是最基本的存储单元是字节(byte) 。每个字节由8个比特构成。
-
计算机的存储能力是以字节和多字节来衡量的。如下:
- 千字节(kilobyte,KB) = 1024B
- 兆字节(megabyte,MB) = 1024KB
- 千兆字节(gigabyte,GB) = 1024MB
- 万亿字节(terabyte,TB) = 1024GB
-
内存(也叫 Random-Access Memory,RAM):由一个有序的字节序列组成,用于存储程序及程序需要的数据。
-
一个程序和它的数据在被CPU执行前必须移到计算机的内存中。
-
每个字节都有一个唯一的地址。见右图。使用这个地址确定字节的位置,以便于存储和获取数据。
-
一个计算机具有的RAM越多,它的运行速度越快,但是此规律是有限制的。
-
内存与CPU一样,也构建在表面嵌有数百万晶体管的硅半导体芯片上。但内存芯片更简单、更低速、更便宜。
-
实测发现:内存存取数据的速度比硬盘的存取速度快10倍,在某些环境里,硬盘和内存之间的速度差距可能会更大。而CPU的速度比内存不知还要快多少倍。当我们把程序从硬盘放到内存以后,CPU就直接在内存运行程序,这样比CPU直接在硬盘运行程序就要快很多。
-
内存解决了一部分CPU运行过快,而硬盘数据存取太慢的问题。 提高了我们的电脑的运行
速度。内存就如同一条“高速车道”一般,数据由传输速度较慢的硬盘通过这条高速车道
传送至CPU进行处理! -
但内存是带电存储的(一旦断电数据就会消失),而且容量有限,所以要长时间储存程序或数据就需要使用硬盘
-
内存在这里起了两个作用:
- 保存从硬盘读取的数据,提供给CPU使用
- 保存CPU的一些临时执行结果,以便CPU下次使用或保存到硬盘
计算机硬件介绍:输入和输出设备
- 常见的输入设备:键盘(keyboard)和鼠标(mouse)
- 常见的输出设备:显示器(monitor)和打印机(printer)
- 显示器屏幕分辨率:是指显示设备水平和垂直方向上显示的像素(px)数。
- 分辨率可以手工设置。
- 分辨率越高,图像越锐化、越清晰。
计算公式:像素密度=√[(长度像素数)====2+(宽度像素数)2]/屏幕尺寸
计算机硬件介绍:通信设备
-
计算机可以通过通信设备进行联网。
-
常见的设备有:
- 拨号调制解调器:使用的是电话线,传输速度可达56 000bps(bps:每秒比特)
- DSL(数字用户线):使用的也是电话线,但传输速度叫上面的快20倍
- 电缆调制解调器:利用有线电视电缆进行数据传输,通常速度比DSL快。
- 网络接口卡(NIC):将计算机接入局域网(LAN)的设备。局域网通常用于大学、商业组织和政府组织。速度甚至可达1000Mbps
- 无线网络:在家庭、商业和学校中极其常见。计算机可通过无线适配器连接到局域网或internet上。
计算机发展史上的鼻祖
最近半个世纪以来,世界计算机科学界的重大进步,离不开图灵等人的理论奠基作用和多方面的开创性研究成果。图灵是当之无愧的计算机科学和人工智能之父。甚至认为,他在技术上的贡献及对未来世界的影响几乎可与牛顿、爱因斯坦等巨人比肩。
图灵论文中的“用有限的指令和有限的存储空间可算尽一切可算之物”理论让当时所有的科学家震惊
美国计算机学会(ACM)的年度“图灵奖”,自从1966年设立以来,一直是世界计算机科学领域的最高荣誉,相当于计算机科学界的诺贝尔奖。至今,中国人只有姚期智院士获该奖项。
20世纪最重要的数学家之一,在现代计算机、博弈论、核武器和生化武器等诸多领域内有杰出建树的最伟大的科学全才之一,被后人称为**“计算机之父”和“博弈论之父”**。
计算机基本工作原理是存储程序和程序控制,它是由世界著名数学家冯·诺依曼提出的。最简单的来说,冯诺依曼理论的要点是:数字计算机的数制采用二进制;计算机应该按照程序顺序执行。
同样有着“计算机之父”称号的冯·诺依曼的助手弗兰克尔在一封信中写到:“……计算机的基本概念属于图灵。按照我的看法,冯·诺依曼的基本作用是使世界认识了由图灵引入的计算机基本概念……”
根据冯诺依曼体系结构构成的计算机,必须具有如下功能:
- 把需要的程序和数据送至计算机中。
- 必须具有长期记忆程序、数据、中间结果及最终运算结果的能力。
- 能够完成各种算术、逻辑运算和数据传送等数据加工处理的能力。
- 能够根据需要控制程序走向,并能根据指令控制机器的各部件协调操作。
- 能够按照要求将处理结果输出给用户。
操作系统
操作系统(Operating System)是运行在计算机上的最重要的程序,它可以管理和控制计算机的活动。
- 硬件、操作系统、应用程序和用户之间的关系如右图。
- 操作系统的主要任务:
- 控制和监视系统的活动
- 分配和调配系统资源
- 调度操作
万维网
万维网(World Wide Web,www,环球信息网)常简称为Web,发明者蒂姆·伯纳斯·李。分为Web客户端和Web服务器程序。 WWW可以让Web客户端(常用浏览器)访问浏览Web服务器上的页面。 是一个由许多互相链接的超文本组成的系统,通过互联网访问。在这个系统中,每个有用的事物,称为一样“资源”;并且由一个全局“统一资源标识符”(URI)标识;这些资源通过==超文本传输协议(Hypertext Transfer Protocol)==传送给用户,而后者通过点击链接来获得资源。
万维网是无数个网络站点和网页的集合,它们在一起构成了因特网Internet最主要的部分(因特网也包括电子邮件、Usenet以及新闻组)。它实际上是多媒体的集合,是由超级链接连接而成的。我们通常通过网络浏览器上网观看的,就是万维网的内容。
职业发展与提升
Java 概述
Java 语言发展史
Java 语言
语言:人与人交流沟通的方式
计算机语言:人与计算机之间进行信息交流沟通的一种特殊语言
Java 语言是美国 Sun 公司(Stanford University Network)在 1995 年推出的计算机语言。
Java 之父:詹姆斯·高斯林(James Gosling)
Java 语言发展史
- 1995年,Sun公司发布Java语言
- 1996年,发布Java(1.0)
- 1997年,发布Java(1.1)
- 1998年,发布Java(1.2)
- 2000年,发布Java(1.3)
- 2002年,发布Java(1.4)
- 2004年,发布Java(5.0)
- 2006年,发布Java(6.0)
- 2009年,Oracle 甲骨文公司收购Sun公司
- 2011年,发布Java(7.0)
- 2014年,发布Java(8.0)
- 2017年9月,发布Java(9.0)
- 2018年3月,发布Java(10.0)
- 2018年9月,发布Java(11.0)
Java 语言跨平台原理
平台
指的是操作系统
- Windows
- Mac
- Linux
跨平台
Java 程序可以在任意操作系统上运行
跨平台原理
总结:在需要运行 Java 应用程序的操作系统上,安装一个与操作系统对应的 Java虚拟机(JVM Java Virtual Machine)即可。
JRE 和 JDK
JRE(Java Runtime Environment)
是 Java 程序的运行时环境,包含 JVM 和运行时所需要的核心类库。
我们想要运行一个已有的 Java 程序,那么只需要安装 JRE 即可。
JDK(Java Development Kit)
是 Java 程序开发工具包,包含 JRE 和开发人员使用的工具。
其中的开发工具:编译工具(javac.exe)和运行工具(java.exe)。
JDK、JRE 和 JVM 的关系
JDK 的下载和安装
傻瓜式安装,下一步即可。
建议:安装路径中不要包含中文和空格,所有的开发工具最好安装目录统一。
JDK 的安装目录
目录名称 | 说明 |
---|---|
bin | 该路径下存放了 JDK 的各种工具命令。javac 和 java 就放在这个目录 |
conf | 该路径下存放了 JDK 的相关配置文件 |
include | 该路径下存放了一些平台特定的头文件 |
jmods | 该路径下存放了 JDK 的各种模块 |
legal | 该路径下存放了 JDK 各模块的授权文档 |
lib | 该路径下存放了 JDK 工具的一些补充 IAR 包 |
其余文件为说明性文档。
第一个程序
常用 DOS 命令
打开命令提示符窗口
- 按下 win+R
- 输入cmd
- 按下回车键
常用命令
操作 | 说明 |
---|---|
盘符名称 | 盘符切换。E:+回车,表示切换到E盘 |
dir | 查看当前路径下的内容 |
cd 目录 | 进入单级目录 |
cd … | 回退到上一级目录 |
cd 目录1\目录2… | 进入多级目录 |
cd |回退到盘符目录 | |
cls | 清屏 |
exit | 退出命令提示符窗口 |
Path 环境变量的配置
为什么要配置 Path 环境变量
开发 Java 程序,需要使用 JDK 提供的开发工具,而这些开发工具在 JDK 安装目录的 bin 目录下。
为了在开发 Java 程序的时候,能够方便的使用 javac 和 java 这些命令,我们需要配置 Path 环境变量。
在系统变量中新建一个 JAVA_HOME
D:\java\jdk1.8.0_341
在 Path 中新建
%JAVA_HOME%\bin
提示:如果命令提示符窗口是配置环境变量前打开的,需要关闭该窗口,重新打开一个窗口测试。
HelloWorld 案例
Java 程序开发运行流程
开发 Java 程序,需要三个步骤:编写程序、编译程序、运行程序
HelloWorld 案例的编写
public class HelloWorld {
public static void main (String[] args) {
System.out.println("HelloWorld")
}
}
基础语法
注释
注释概述
- 注释是指在程序指定位置添加的说明性信息
- 注释不参与程序运行,仅起到说明作用
注释分类
- 单行注释
//注释信息
- 多行注释
/* 注释信息 */
- 文档注释
/** 注释信息 */
关键字
关键字概述
关键字:被 Java 语言赋予了特定含义的单词。
关键字的特点
- 关键字的字母全部小写
- 常见的代码编辑器,针对关键字有特殊的颜色标记,非常直观
常量
常量概述
常量:在程序运行过程中,其值不可以发生改变的量
常量分类
常量类型 | 说明 | 举例 |
---|---|---|
字符串常量 | 用双引号括起来的内容 | “HelloWord", "黑马程序员” |
整数常量 | 不带小数的数字 | 666, -88 |
小数常量 | 带小数的数字 | 13.14, -5.21 |
字符常量 | 用单引号括起来的内容 | ‘A’, ‘0’, ‘我’ |
布尔常量 | 布尔值,表示真假 | true, false |
空常量 | 一个特殊的值,空值 | 值是null |
数据类型
计算机存储单元
我们知道计算机是可以用来存放数据的,但是无论是内存还是硬盘,计算机存储设备的最小单元叫“位(bit)”,我们又称之为“比特位”,通常用小写字母“b”表示。而计算机中最小的存储单元叫“字节(byte)”,通常用大写字母“B”表示,字节是由连续的8个位组成的。
除了字节外还有一些常用的存储单位:
- 1B(字节)= 8bit
- 1KB = 1024B
- 1MB = 1024KB
- 1GB = 1024MB
- 1TB = 1024GB
数据类型
Java 语言是强类型语言,对于每一种数据都给出了明确的数据类型,不同的数据类型也分配了不同的内存空间,所以它们表示的数据大小也是不一样的。
数据类型内存占用和取值范围
数据类型 | 关键字 | 内存占用 | 取值范围 |
---|---|---|---|
整数 | byte | 1 | -128~127 |
整数 | short | 2 | -32768~32767 |
整数 | int (默认) | 4 | -2的31次方到2的31次方-1 |
整数 | long | 8 | -2的63次方到2的63次方-1 |
浮点数 | float | 4 | 负数:-3.042823E+38到-1.401298E-45 正数:1.401298E-45到3.042823E+38 |
浮点数 | double(默认) | 8 | 负数:-1.797693E+308到-4.9000000E-324 正数:4.9000000E-324到1.797693E+308 |
字符 | char | 2 | 0~65535 |
布尔 | boolean | 1 | true,false |
变量
变量概述
变量:在程序运行过程中,其值可以发生改变的量。
变量定义
- 格式:数据类型 变量名 = 变量值;
- 范例:
int a = 10;
变量的使用
变量的使用:取值和修改值
- 取值格式:变量名
- 范例:
a
- 修改值格式:变量名 = 变量值
- 范例:
a = 20;
变量使用的注意事项
- 名字不能重复
- 变量未赋值,不能使用
- long类型的变量定义的时候,为了防止整数过大,后面要加L
- float类型的变量定义的时候,为了防止类型不兼容,后面要加F
标识符
标识符概述
标识符:给类、方法、变量等起名字的符号。
标识符定义规则
- 由==数字、字母、下划线(_)和美元符($)==组成
- 不能以数字开头
- 不能是关键字
- 区分大小写
常见命名约定
小驼峰命名法:----->方法、变量
- 标识符是一个单词的时候,首字母小写,如name
- 标识符由多个单词组成的时候,第一个单词首字母小写,其他单词首字母大写,如firstName
大驼峰命名法:----->类
- 标识符是一个单词的时候,首字母大写,如Student
- 标识符由多个单词组成的时候,每个单词首字母大写,如GoodStudent
类型转换
类型转换分类
- 自动类型转换
- 强制类型转换
自动类型转换
把一个表示数据范围小的数值或者变量赋值给另一个表示数据范围大的变量。
范例:
double d = 10;
表示数据范围从小到大图:
强制类型转换
把一个表示数据范围大的数值或者变量赋值给另一个表示数据范围小的变量。
- 格式:目标数据类型 变量名 = (目标数据类型)变量名;
- 范例:
int k = (int)88.88;
不建议使用强制类型转换,会有数据的损失。
运算符
算数运算符
运算符和表达式
- 运算符:对常量或者变量进行操作的符号
- 表达式:用运算符把常量或者变量连接起来符合java语法的式子就可以称为表达式。
- 不同运算符连接的表达式体现的是不同类型的表达式。
算数运算符
符号 | 作用 | 说明 |
---|---|---|
+ | 加 | 将两个数据相加求和 |
- | 减 | 将两个数据相减求差 |
* | 乘 | 将两个数据相乘求积 |
/ | 除 | 将两个数据相除求商 |
% | 取余 | 将两个数据相除取余数 |
除法得到的是商,取余得到的是余数。
整数相除只能得到整数,要想得到小数,必须有浮点数的参与。
字符的“+”操作
拿字符在计算机底层对应的数值来进行计算。
‘A’ --> 65 A-Z是连续的
'a' --> 97 a-z是连续的
'0' --> 48 0-9是连续的
算术表达式中包含多个基本数据类型的值的时候,整个算术表达式的类型会自动进行提升。
提升规则:
- byte类型,short类型和char类型将会被提升到int类型
- 整个表达式的类型会自动提升到表达式中最高等级操作数同样的类型
- 等级顺序:byte,short,char----> int ----> long ----> float ----> double
字符串的“+”操作
- 当‘+’操作中出现字符串时,这个‘+’是字符串连接符,而不是算数运算符。
- 当‘+’操作中,如果出现了字符串,就是连接运算符,否则就是算术运算符。当连续进行‘+’操作时,从左到右逐个执行。
赋值运算符
符号 | 作用 | 说明 |
---|---|---|
= | 赋值 | a=10,将10赋值给变量a |
+= | 加后赋值 | a+=b,将a+b的值赋给a |
-= | 减后赋值 | a-=b,将a-b的值赋给a |
*= | 乘后赋值 | a*=b,将a*b的值赋给a |
/= | 除后赋值 | a/=b,将a/b的值赋给a |
%= | 取余后赋值 | a%=b,将a%b的值赋给a |
注意:扩展的赋值运算符底层隐含了强制类型转换。
自增自减运算符
符号 | 作用 | 说明 |
---|---|---|
++ | 自增 | 变量的值加1 |
– | 自减 | 变量的值减1 |
// 单独使用
int i = 10;
i++; // 11
++i; // 12
// 参与操作使用
int j = i++; // 先赋值再自增
int k = ++i; // 先自增再赋值
注意事项:
- ++和–既可以放在变量的后边,也可以放在变量的前边
- 单独使用的时候,++和–无论是放在变量的前边还是后边,结果都是一样的
- 参与操作的时候,如果放在变量的后边,先拿变量参与操作,后拿变量做++或者–
- 参与操作的时候,如果放在变量的前边,先拿变量做++或者–,后拿变量参与操作
最常见的用法:单独使用
关系运算符
符号 | 说明 |
---|---|
== | a==b,判断a和b的值是否相等,成立则为true,不成立为false |
!= | a!=b,判断a和b的值是否不相等,成立则为true,不成立为false |
>. | a>b,判断a是否大于b,成立则为true,不成立为false |
>= | a>=b,判断a是否大于等于b,成立则为true,不成立为false |
< | a<b,判断a是否小于b,成立则为true,不成立为false |
<= | a<=b,判断a是否小于等于b,成立则为true,不成立为false |
注意事项:
关系运算符的结果都是布尔类型,要么是true,要么是false
千万不要把“==”误写成“=”
逻辑运算符
逻辑运算符概述
逻辑运算符,是用来连接关系表达式的运算符。
逻辑运算符也可以直接连接布尔类型的常量或者变量。
逻辑运算符
符号 | 作用 | 说明 |
---|---|---|
& | 逻辑与 | a&b,a和b都是true,结果为true,否则为false |
逻辑或 | ||
^ | 逻辑异或 | a^b,a和b结果不同为true,相同为false |
! | 逻辑非 | !a,结果和a的结果相反 |
短路逻辑运算符
符号 | 作用 | 说明 |
---|---|---|
&& | 短路与 | a&&b,作用和&相同,但是有短路效果(有false则false) |
注意事项:
逻辑与**&,无论左边真假,右边都要执行
短路与&&,如果左边为真,右边执行;如果左边为假,右边不执行**
逻辑或**|,无论左边真假,右边都要执行
短路或||,如果左边为假,右边执行;如果左边为真,右边不执行**
最常用的逻辑运算符:&&,||,!
三元运算符
- 格式:关系表达式 ? 表达式1 : 表达h式2;
- 范例:
a > b ? a : b;
- 计算规则:
- 首先计算关系表达式的值
- 如果值为true,表达式1的值就是运算结果
- 如果值为false,表达式2的值就是运算结果
案例:两只老虎
需求:动物园里有两只老虎,已知两只老虎的体重分别为180kg、200kg,请用程序实现判断两只老虎的体重是否相同。
int weight1 = 180;
int weight2 = 200;
boolean b = weight1 == weight2 ? true : false;
System.out.println("b:" + b);
案例:三个和尚
需求:一座寺庙里住着三个和尚,已知他们的身高分别为150cm、210cm、165cm,请用程序实现获取这三个和尚的最高身高。
int height1 = 150;
int height2 = 210;
int height3 = 165;
int tempHeight = height1 > height2 ? height1 : height2;
int maxHeight = tempHeight > height3 ? tempHeight : height3;
System.out.println("maxHeight:" + maxHeight);
数据输入
Scanner 使用的基本步骤
- 导包
// 导包的动作必须出现在类定义的上边
import java.util.Scanner;
- 创建对象
// 格式中,只有sc是变量名,可以变,其他的都不允许变
Scanner sc = new Scanner(System.in);
- 接收数据
// 格式中,只有i是变量名,可以变,其他的都不允许变
int i = sc.nextInt();
案例:三个和尚
需求:一个寺庙里住着三个和尚,他们的身高必须经过测量得出,请用程序实现获取这三个和尚的最高身高。
Scanner sc = new Scanner(System.in);
System.out.println("请输入第一个和尚的身高:");
int height1 = sc.nextInt();
System.out.println("请输入第二个和尚的身高:");
int height2 = sc.nextInt();
System.out.println("请输入第三个和尚的身高:");
int height3 = sc.nextInt();
int tempHeight = height1 > height2 ? height1 : height2;
int maxHeight = tempHeight > height3 ? tempHeight : height3;
System.out.println("这三个和尚中身高最高的是:" + maxHeight + "cm");
分支语句
流程控制
流程控制语句分类
- 顺序结构
- 分支结构(if,switch)
- 循环结构(for,while,do…while)
顺序结构
顺序结构是程序中最基本的流程控制,没有特定的语法结构,按照代码的先后顺序,依次执行。
程序中大多数的代码都是这样执行的。
if 语句
if 语句格式1
格式:
if (关系表达式) {
语句体
}
执行流程:
- 首先计算关系表达式的值
- 如果关系表达式的值为true就执行语句体
- 如果关系表达式的值为false就不执行语句体
- 继续执行后面的语句内容
if 语句格式2
格式:
if (关系表达式) {
语句体1;
} else {
语句体2;
}
执行流程:
- 首先计算关系表达式的值
- 如果关系表达式的值为true就执行语句体1
- 如果关系表达式的值为false就执行语句体2
- 继续执行后面的语句内容
案例:奇偶数
需求:仍以给出一个整数,请用程序实现判断该整数是奇数还是偶数,并在控制台输出该整数是奇数还是偶数
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个整数:");
int a = sc.nextInt();
if (a % 2 == 0) {
System.out.println(a + "是偶数");
} else {
System.out.println(a + "是奇数");
}
if 语句格式3
格式:
if (关系表达式1) {
语句体1;
} else if (关系表达式2) {
语句体2;
}
...
else {
语句体n+1;
}
执行流程:
- 首先计算关系表达式1的值
- 如果值为true就执行语句体1;如果值为false就计算关系表达式2的值
- 如果值为true就执行语句体2;如果值为false就计算关系表达式3的值
- …
- 如果没有任何关系表达式的值为true,就执行语句体n+1
需求:键盘录入一个星期数(1,2,。。。。。。,7),输出对应的星期一,星期二,。。。,星期日
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个星期数(1~7):");
int a = sc.nextInt();
if (a == 1) {
System.out.println("星期一");
} else if (a == 2) {
System.out.println("星期二");
} else if (a == 3) {
System.out.println("星期三");
} else if (a == 4) {
System.out.println("星期四");
} else if (a == 5) {
System.out.println("星期五");
} else if (a == 6) {
System.out.println("星期六");
} else {
System.out.println("星期日");
}
System.out.println("结束");
案例:考试奖励
需求:小明快要期末考试了,小明的爸爸对他说,会根据他不同的考试成绩,送他不同的礼物,假如你可以控制小明的得分,请用程序实现小明到底该获得什么样的礼物,并在控制台输出。
奖励:
95~100 山地自行车一辆90~94 游乐场玩一次
80~89 变形金刚玩具一个
80以下 胖揍一顿
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个分数:");
int score = sc.nextInt();
if (score > 100 || score < 0) {
System.out.println("您输入的分数有误");
} else if (score >= 95 && score <= 100) {
System.out.println("山地自行车一辆");
} else if (score >= 90 && score <= 94) {
System.out.println("游乐场玩一次");
} else if (score >= 80 && score <= 89) {
System.out.println("变形金刚玩具一个");
} else {
System.out.println("胖揍一顿");
}
数据测试:正确数据、边界数据、错误数据
switch 语句
switch 语句格式
格式:
switch (表达式) {
case值1:
语句体1;
break;
case值2:
语句体2;
break;
...
default:
语句体n+1;
[break;]
}
格式说明:
- 表达式:取值为byte、short、int、char,JDK5以后可以是枚举,JDK7以后可以是string
- case: 后面跟的是要和表达式进行比较的值
- break:表示中断、结束的意思,用来结束switch语句
- default:表示所有情况都不匹配的时候,就执行该处的内容,和if语句的else相似
执行流程:
- 首先计算表达式的值
- 依次和case后面的值进行比较,如果有对应的值,就会执行相应的语句,在执行的过程中,遇到break就会结束
- 如果所有的case后面的值和表达式的值都不匹配,就会执行default里面的语句体,然后程序结束掉
//需求:键盘录入一个星期数(1~7),控制台输出对应的星期一、星期二、。。。、星期日
System.out.println("请输入一个星期数(1~7):");
Scanner sc = new Scanner(System.in);
int week = sc.nextInt();
switch (week) {
case 1:
System.out.println("星期一");
break;
case 2:
System.out.println("星期二");
break;
case 3:
System.out.println("星期三");
break;
case 4:
System.out.println("星期四");
break;
case 5:
System.out.println("星期五");
break;
case 6:
System.out.println("星期六");
break;
case 7:
System.out.println("星期日");
break;
default:
System.out.println("您输入的星期数有误");
}
案例:春夏秋冬
需求:一年有12个月,分属于春夏秋冬四个季节,键盘录入一个月份,请用程序实现判断该月份属于哪个季节,并输出
春:3、4、5
夏:6、7、8
秋:9、10、11
冬:12、1、2
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个月份:");
int month = sc.nextInt();
switch (month) {
case 1:
case 2:
case 12:
System.out.println("冬季");
break;
case 3:
case 4:
case 5:
System.out.println("春季");
break;
case 6:
case 7:
case 8:
System.out.println("夏季");
break;
case 9:
case 10:
case 11:
System.out.println("秋季");
break;
default:
System.out.println("您输入的月份有误");
}
注意事项:在switch语句中,如果case控制的语句体后面不写break,将会出现穿透现象,在不判断下一个case值的情况下,向下运行,直到遇到break,或者整体switch语句结束
循环语句
for 循环语句
循环结构
特征:
- 重复做某件事情
- 具有明确的开始和停止标志
循环结构的组成:
- 初始化语句: 用于表示循环开始时的起始状态,简单说就是循环开始的时候什么样
- 条件判断语句: 用于表示循环反复执行的条件,简单说就是判断循环是否能一直执行下去
- 循环体语句: 用于表示循环反复执行的内容,简单说就是循环反复执行的事情
- 条件控制语句: 用于表示循环执行中每次变化的内容,简单说就是控制循环是否能执行下去
循环结构对应的语法:
- 初始化语句: 这里可以是一条或者多条语句,这些语句可以完成一些初始化操作
- 条件判断语句: 这里使用一个结果值为boolean类型的表达式,这个表达式能决定是否执行循环体。例如:a < 3
- 循环体语句: 这里可以是任意语句,这些语句将反复执行
- 条件控制语句: 这里通常是使用一条语句来改变变量的值,从而达到控制循环是否向下执行的效果。常见i++,i–这样的操作
for 循环语句格式
格式:
for (初始化语句;条件判断语句;条件控制语句) {
循环体语句;
}
执行流程:
- 执行初始化语句
- 执行条件判断语句,判断其结果是true还是false
- 如果是false,循环结束
- 如果是true,继续执行
- 执行循环体语句
- 执行条件控制语句
- 回到2继续
//需求:在控制台输出5次"HelloWorld"
for (int i = 1; i <= 5; i++) {
System.out.println("HelloWorld");
}
案例:输出数据
需求:在控制台输出1-5和5-1的数据
for (int i = 1; i <= 5; i++) {
System.out.println(i);
}
System.out.println("----------------");
for (int i = 5; i >= 1; i--) {
System.out.println(i);
}
案例:求和
需求:求1-5之间的数据和,并把求和结果在控制台输出
int sum = 0;
for (int i = 1; i <= 5; i++) {
sum += i; //sum = sum + i
}
System.out.println("1-5之间的数据和是:" + sum);
案例:求偶数和
需求:求1-100之间的偶数和,并把求和结果在控制台输出
int sum = 0;
for (int i = 1; i <= 100; i++) {
if (i % 2 == 0) {
sum += i;
}
}
System.out.println("1-100之间的偶数和为:" + sum);
案例:水仙花
需求:在控制台输出所有的水仙花数
- 水仙花数是一个三位数
- 水仙花数的个位、十位、百位的数字立方和等于原数
for (int i = 100; i <= 999; i++) {
int a = i % 10; //个位
int b = i / 10 % 10; //十位
int c = i / 10 / 10 % 10; //百位
if (a * a * a + b * b * b + c * c * c == i) {
System.out.println(i);
}
}
任意数字的指定位上的数值如何求?
先使用整除操作将要求的数字移动到个位上,再使用取余操作取出最后一位上的值。
案例:统计水仙花数
需求:统计水仙花数一共有多少个,并在控制台输出个数
int count = 0;
for (int i = 100; i <= 999; i++) {
int a = i % 10;
int b = i / 10 % 10;
int c = i / 10 / 10 % 10;
if (a * a * a + b * b * b + c * c * c == i) {
count++;
}
}
System.out.println("水仙花数共有:" + count + "个");
while 循环语句
while 循环语句格式
基本格式:
while (条件判断语句) {
循环体语句;
}
完整格式:
初始化语句;
while (条件判断语句) {
循环体语句;
条件控制语句;
}
执行流程:
- 执行初始化语句
- 执行条件判断语句,判断其结果是true还是false
- 如果是false,循环结束
- 如果是true,继续执行
- 执行循环体语句
- 执行条件控制语句
- 回到2继续
//需求:在控制台输出5次HelloWorld
int i = 1;
while (i <= 5) {
System.out.println("HelloWorld");
i++;
}
案例:珠穆朗玛峰
需求:世界最高山峰珠穆朗玛峰(8844.43米=8844430毫米),假如我有一张足够大的纸,它的厚度是0.1毫米。请问,我折叠多少次,可以折成珠穆朗玛峰的高度?
int count = 0;
double paper = 0.1;
while (paper <= 8844430) {
paper *= 2;
count++;
}
System.out.println("需要折叠:" + count + "次");
do…while 循环语句
do…while 循环语句格式
基本格式:
do {
循环体语句;
} while (条件判断语句);
完整格式:
初始换语句;
do {
循环体语句;
条件控制语句;
} while (条件判断语句);
执行流程:
- 执行初始化语句
- 执行循环体语句
- 执行条件控制语句
- 执行条件判断语句,看其结果是true还是false
- 如果是false,循环结束
- 如果是true,继续执行
- 回到2继续
int i = 1;
do {
System.out.println("HelloWorld");
i++;
} while (i <= 5);
三种循环的区别
三种循环的区别:
- for循环和while循环先判断条件是否成立,然后决定是否执行循环体(先判断后执行)
- do…while循环先执行一次循环体,然后判断条件是否成立,是否继续执行循环体(先执行后判断)
for和while的区别:
- 条件控制语句所控制的自增变量,因为归属for循环的语法结构中,在for循环结束后,就不能再次被访问到了
- 条件控制语句所控制的自增变量,对于while循环来说不归属其语法结构中,在while循环结束后,该变量还可以继续使用
死循环格式:
for (; ;) {}
while (true) {}
do {} while (true);
while 的死循环格式是最常用的
在命令提示符窗口中可以按下ctrl+c强制停止死循环
跳转控制语句
continue
跳过某循环体执行,继续下一次的执行 使用是基于条件控制的break
终止循环体执行,结束当前整个循环 使用是基于条件控制的
for (int i = 1; i <= 5; i++) {
if (i % 2 == 0) {
continue;
}
System.out.println(i);
}
System.out.println("-------");
for (int j = 1; j <= 5; j++) {
if (j % 2 == 0) {
break;
}
System.out.println(j);
}
循环嵌套
循环语句中包含循环语句称为循环嵌套
//需求:在控制台输出一天的小时和分钟
for (int hour = 0; hour < 24; hour++) {
for (int minute = 0; minute < 60; minute++) {
System.out.println(hour + "时" + minute + "分");
}
System.out.println("-------");
}
Random
作用:用于产生一个随机数
使用步骤:
- 导包
import java.util.Random;
导包动作必须出现类定义的上面
- 创建对象
Random r = new Random();
上面这个格式里面,r是变量名,可以变,其他的都不允许变
- 获取随机数
int number = r.nextInt(10); // 获取数据的范围[0,10),包括0但不包括10
上面这个格式里面,number是变量名,可以变,数字10可以变,其他的都不允许变
Random r = new Random();
//用循环获取10个随机数
for (int i=0;i<10;i++) {
int number = r.nextInt(10);
System.out.println(number);
}
//需求:获取一个1-100之间的随机数
int x = r.nextInt(100) + 1;
System.out.println(x);
案例:猜数字
需求:程序自动生成一个1-100之间的数字,使用程序实现猜出这个数字是多少?
当猜错的时候,根据不同情况给出相应提示:
- 如果猜的数字比真实数字大,提示你猜的数据大了
- 如果猜的数字比真实数字小,提示你猜的数据小了
- 如果猜的数字与真实数字相等,提示恭喜你猜中了
Random r = new Random();
int number = r.nextInt(100) + 1;
while(true) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入你要猜的数字:");
int guessNumber = sc.nextInt();
if (guessNumber > number) {
System.out.println("你猜的数字" + guessNumber + "大了");
} else if (guessNumber < number) {
System.out.println("你猜的数字" + guessNumber + "小了");
} else {
System.out.println("恭喜你猜中了!");
break;
}
}
数组
数组定义格式
数组是一种用于存储多个相同类型数据的存储模型
- 格式一:数据类型 [] 变量名
- 定义了一个int类型的数组,数组名是arr
- 范例:
int [] arr
- 格式二:数据类型 变量名 []
- 定义了一个int类型的变量,变量名是arr数组
- 范例:
int arr []
推荐使用格式一定义数组。
数组初始化之动态初始化
java中的数组必须先初始化,然后才能使用
所谓初始化,就是为数组中的数组元素分配内存空间,并为每个数组元素赋值
动态初始化:初始化时只指定数组长度,由系统为数组分配初始值
- 格式: 数据类型 [] 变量名 = 数据类型[数组长度];
- 范例:
int [] arr = new int[3];
数组元素访问
-
数组变量访问方式
-
格式: 数组名
-
数组内部保存的数据的访问方式
-
格式: 数组名[索引]
-
索引是数组中数据的编号方式
-
作用:索引用于访问数组中的数据使用,数组名[索引]等同于变量名,是一种特殊的变量名
-
特征:
- 索引聪从0开始
- 索引是连续的
- 索引逐一增加,每次加1
int[] arr = new int[3];
//输出数组名
System.out.println(arr);
//输出数组中的元素
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
内存分配
java中的内存分配
java程序在运行时,需要在内存中分配空间,为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
数组在初始化时,会为内存空间添加初始值:
- 整数:默认值0
- 浮点数:默认值0.0
- 布尔值:默认值false
- 字符:默认值是空字符
- 引用数据类型:默认值是null
- 栈内存:存储局部变量
- 局部变量:定义在方法中的变量,如arr。使用完毕,立即消失。
- 堆内存:存储new出来的内容(实体,对象)
- 每一个new出来的东西都有一个地址值,使用完毕,会在垃圾回收器空闲时被回收
数组初始化之静态初始化
静态初始化:初始化时指定每个数组元素的初始值,由系统决定数组长度
- 格式:数据类型[] 变量名 = new 数据类型[] {数据1,数据2,数据3,…};
int[] arr = new int[] {1,2,3,......};
- 简化格式:数据类型[] 变量名 = {数据1,数据2,数据3,…};
int[] arr = [1,2,3,......];
int[] arr = {1, 2, 3};
System.out.println(arr);
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
数组操作的两个常见小问题
- 索引越界:访问了数组中不存在的索引对应的元素,造成索引越界问题
- 空指针异常:访问的数组已经不再指向堆内存的数据,造成空指针异常
int[] arr = new int[3];
System.out.println(arr[3]); // 索引越界
int[] arr2 = new int[3];
arr2 = null;
System.out.println(arr2[0]); // 空指针异常
数组常见操作
数组遍历
int[] arr = {11, 22, 33, 44, 55};
for (int x = 0; x <= 4; x++) {
System.out.println(arr[x]);
}
数组元素数量
- 格式:数组名.length
- 范例:
arr.length
int[] arr2 = {11, 22, 33, 44, 55};
for (int x = 0; x < arr.length; x++) {
System.out.println(arr2[x]);
}
最值
int[] arr3 = {12, 45, 98, 73, 60};
int max = arr3[0];
int min = arr3[0];
for (int y = 1; y < arr.length; y++) {
if (arr3[y] > max) {
max = arr3[y];
};
if (arr3[y] < min) {
min = arr3[y];
}
}
System.out.println("最大值为:" + max);
System.out.println("最小值为:" + min);
方法
方法概论
方法是将具有独立功能的代码块组织成为一个整体,使其具有特殊功能的代码集。
注意:
- 方法必须先创建才可以使用,该过程称为方法定义
- 方法创建后并不是直接运行的,需要手动使用后才执行,该过程称为方法调用
方法的定义和调用
- 方法定义格式:
public static void 方法名 () {
方法体;
}
- 方法调用格式:
方法名();
//需求:定义一个方法,在方法中定义一个变量,判断该数是否是偶数
//调用方法
isEvenNumber();
public static void isEvenNumber() {
//定义变量
int number = 10;
//判断该数据是否是偶数
if (number % 2 == 0) {
System.out.println(true);
} else {
System.out.println(false);
}
}
方法练习
需求:设计一个方法,用于打印两个数中的较大数。
public static void getMax() {
int a = 10;
int b = 20;
if (a > b) {
System.out.println(a);
} else {
System.out.println(b);
}
}
public static void main(String[] args) {
getMax();
}
带参数方法的定义和调用
- 带参数方法的定义格式:
public static void 方法名 (参数) {... ...}
- 单个参数:
public static void 方法名 (数据类型 变量名) {}
- 多个参数:
public static void 方法名 (数据类型 变量名, 数据类型 变量名, ......) {}
注意:
- 方法定义时,参数中的数据类型与变量名都不能少,缺少任意一个程序将报错
- 方法定义时,多个参数之间使用逗号分隔
- 带参数方法的调用格式:
方法名 (参数);
- 单个参数:
方法名 (变量名/常量值);
- 多个参数:
方法名 (变量名1/常量值1,变量名2/常量值2);
注意:
- 方法调用时,参数的数量与类型必须与方法定义中的设置相匹配,否则程序将报错
// 常量值调用
isEvenNumber(10);
// 变量调用
int number = 9;
isEvenNumber(number);
public static void isEvenNumber(int number) {
if (number % 2 == 0) {
System.out.println(true);
} else {
System.out.println(false);
}
}
形参和实参
- 形参:方法定义中的参数
- 实参:方法调用中的参数
带参数方法练习
需求:设计一个方法,用于打印两个数中的较大数,数据来自于方法参数
public static void main(String[] args) {
getMax(10, 20);
int a = 10;
int b = 20;
getMax(a, b);
}
public static void getMax(int a, int b) {
if (a > b) {
System.out.println(a);
} else {
System.out.println(b);
}
}
带返回值方法的定义和调用
带返回值方法的定义格式:
public static _1至75.数据类型 方法名 (参数) {
return 数据;
}
注意: 方法定义时,return后面的返回值与方法定义上的数据类型要匹配,否则程序将报错
带返回值方法调用的格式:
- 格式1:
方法名 (参数);
- 格式2:
数据类型 变量名 = 方法名 (参数);
注意: 方法的返回值通常会使用变量接收,否则返回值将无意义
public static void main(String[] args) {
isEvenNumber(10);
boolean flag = isEvenNumber(10);
System.out.println(flag);
}
public static boolean isEvenNumber(int number) {
if (number % 2 == 0) {
return true;
} else {
return false;
}
}
带返回值方法练习
需求:设计一个方法可以获取两个数的较大值,数据来自于参数
public static void main(String[] args) {
int max = getMax(10, 20);
System.out.println(max);
System.out.println(getMax(10, 20));
}
public static int getMax(int a, int b) {
if (a > b) {
return a;
} else {
return b;
}
}
方法的注意事项
- 方法不能嵌套定义
- void表示无返回值,可以省略return,也可以单独的书写return,后面不加数据
方法的通用格式
格式:
public static 返回值类型 方法名 (参数) {
方法体;
return 数据;
}
定义方法时,要做到两个明确:
- 明确返回值类型: 主要是明确方法操作完毕之后是否有数据返回,如果没有,写void;如果有,写对应的数据类型
- 明确参数: 主要是明确参数的类型和数量
调用方法时:
- void类型的方法,直接调用即可
- 非void类型的方法,推荐用变量接收调用
方法重载
方法重载指同一个类中定义多个方法之间的关系,满足下列条件的多个方法互相构成重载:
- 多个方法在同一个类中
- 多个方法具有相同的方法名
- 多个方法的参数不相同,类型不同或者数量不同
方法重载的特点:
- 重载仅对应方法的定义,与方法调用无关,调用方式参照标准格式
- 重载仅针对同一个类中方法的名称与参数进行识别,与返回值无关,换句话说不能通过返回值来判定两个方法是否相互构成重载
public static void main(String[] args) {
int result = sum(10, 20);
System.out.println(result);
double result2 = sum(10.0, 20.0);
System.out.println(result2);
int result3 = sum(10, 20, 30);
System.out.println(result3);
}
//需求1:求两个int类型数据和的方法
public static int sum(int a, int b) {
return a + b;
}
//需求2:求两个double类型数据和的方法
public static double sum(double a, double b) {
return a + b;
}
//需求3:求三个int类型数据和的方法
public static int sum(int a, int b, int c) {
return a + b + c;
}
方法重载练习
需求:使用方法重载的思想,设计比较两个整数是否相同的方法,兼容全整数类型(byte,int,short,long)
public static void main(String[] args) {
//需求:使用方法重载的思想,设计比较两个整数是否相同的方法,兼容全整数类型(byte,int,short,long)
System.out.println(compare(10, 20));
System.out.println(compare((byte) 10, (byte) 20));
System.out.println(compare((short) 10, (short) 20));
System.out.println(compare(10L, 20L));
}
public static boolean compare(int a, int b) {
System.out.println("int");
return a == b;
}
public static boolean compare(short a, short b) {
System.out.println("short");
return a == b;
}
public static boolean compare(byte a, byte b) {
System.out.println("byte");
return a == b;
}
public static boolean compare(long a, long b) {
System.out.println("long");
return a == b;
}
方法的参数传递
遂于基本数据类型的参数,形式参数的改变,不影响实际参数的值
public static void main(String[] args) {
int number = 100;
System.out.println("调用change方法前:" + number);
change(number);
System.out.println("调用change方法后:" + number);
}
public static void change(int number){
number = 200;
}
方法参数传递引用类型
对于引用类型的参数,形式参数的改变,影响实际参数的值
public static void main(String[] args) {
int[] arr = {10, 20, 30};
System.out.println("调用change方法前:" + arr[1]);
change(arr);
System.out.println("调用change方法后:" + arr[1]);
}
public static void change(int[] arr) {
arr[1] = 200;
}
案例:数组遍历
需求:设计一个方法用于数组遍历,要求遍历的结果是在一行上的。
public static void main(String[] args) {
int[] arr = {11, 22, 33, 44, 55};
arr_sort(arr);
}
public static void arr_sort(int[] arr) {
System.out.print("{");
for (int x = 0; x < arr.length; x++) {
if (x == arr.length - 1) {
System.out.print(arr[x]);
} else {
System.out.print(arr[x] + ", ");
}
}
System.out.print("}");
}
System.out.println(“内容”); 输出内容并换行
System.out.print(“内容”); 输出内容不换行
System.out.println(); 不输出内容,起换行作用
案例:数组最大值
需求:设计一个方法用于获取数组中元素的最大值,调用方法并输出结果
public static void main(String[] args) {
int[] arr = {11, 22, 33, 44, 55};
getMax(arr);
}
public static void getMax(int[] arr) {
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
System.out.println("数组中最大值为:" + max);
}
Debug
Debug是供程序员使用的程序调试工具,它可以用于查看程序的执行流程,也可以用于追踪程序执行过程来调试程序。
注意事项:
如果数据来自于键盘输入,一定要记住输入数据,不然就不能继续往下看了。
基础知识练习
减肥计划if版
需求:输入星期数,显示今天的减肥活动
周一:跑步
周二:游泳
周三:慢走
周四:动感单车
周五:拳击
周六:爬山
周日:好好吃一顿
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个星期数(1-7):");
int week = sc.nextInt();
if (week < 1 | week > 7) {
System.out.println("您输入的星期数有误");
} else if (week == 1) {
System.out.println("跑步");
} else if (week == 2) {
System.out.println("游泳");
} else if (week == 3) {
System.out.println("慢走");
} else if (week == 4) {
System.out.println("动感单车");
} else if (week == 5) {
System.out.println("拳击");
} else if (week == 6) {
System.out.println("爬山");
} else if (week == 7) {
System.out.println("好好吃一顿");
}
减肥计划switch版
需求:输入星期数,显示今天的减肥活动
周一:跑步
周二:游泳
周三:慢走
周四:动感单车
周五:拳击
周六:爬山
周日:好好吃一顿
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个星期数(1-7):");
int week = sc.nextInt();
switch (week) {
case 1:
System.out.println("跑步");
break;
case 2:
System.out.println("游泳");
break;
case 3:
System.out.println("慢走");
break;
case 4:
System.out.println("动感单车");
break;
case 5:
System.out.println("拳击");
break;
case 6:
System.out.println("爬山");
break;
case 7:
System.out.println("好好吃一顿");
break;
default:
System.out.println("您输入的星期数有误");
}
逢七过
需求:朋友聚会的时候可能会玩一个游戏:_1至75.逢七过。规则是:从任意一个数字开始报数,当你要报的数字包含7或者是7的倍数时都要说:过。为了帮助大家更好的玩这个游戏,这里我们直接在控制台打印出1-100之间满足逢七过规则的数据。
System.out.print("1-100内要喊过的数字有:");
for (int guo = 1; guo <=100; guo++) {
if (guo % 7 == 7 | guo / 10 % 10 == 7 | guo % 7 == 0) {
System.out.print(guo + " ");
}
}
不死神兔
需求:有一对兔子,从出生后第三个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问第20个月的兔子对数为多少?
int[] arr = new int[20];
arr[0] = 1;
arr[1] = 1;
for (int x = 2; x < arr.length; x++) {
arr[x] = arr[x - 2] + arr[x - 1];
}
System.out.println("第二十个月兔子的对数为:" + arr[19]);
百钱百鸡
需求:我国古代数学家张邱建在《算经》一书中提出的数学问题:鸡翁一值钱五,鸡母一值钱三,鸡雏三值钱一。百钱买百鸡,问鸡翁、鸡母、鸡雏各几何?
for (int x = 0; x <= 20; x++) {
for (int y = 0; y <= 33; y++) {
int z = 100 - x - y;
if (z % 3 == 0 && 5 * x + 3 * y + z / 3 == 100) {
System.out.println("鸡翁:" + x + "只");
System.out.println("鸡母:" + y + "只");
System.out.println("鸡雏:" + z + "只");
}
}
}
数组元素求和
需求:有这样一个数组,元素是{68,27,95,88,171,996,51,210}.求出该数组中满足要求的元素和,要求是:求和的元素个位和十位都不能是7,并且只能是偶数。
int[] arr = {68, 27, 95, 88, 171, 996, 51, 210};
int sum = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] % 10 != 7 && arr[i] / 10 % 10 != 7 && arr[i] % 2 == 0) {
sum += arr[i];
}
}
System.out.println("和为:" + sum);
数组内容相同
需求:设计一个方法,用于比较两个数组的内容是否相同
public static void main(String[] args) {
int[] arr = {11, 22, 33, 44, 55};
int[] arr2 = {11, 22, 33, 44, 55};
int[] arr3 = {11, 22, 33, 44, 5};
boolean result = arrCompare(arr, arr2);
System.out.println(result);
System.out.println("--------");
boolean flag = arrCompare(arr, arr3);
System.out.println(flag);
}
public static boolean arrCompare(int[] arr, int[] arr2) {
if (arr.length != arr2.length) {
return false;
}
for (int x = 0; x < arr.length; x++) {
if (arr[x] != arr2[x]) {
return false;
}
}
return true;
}
查找
需求:已知一个数组arr = {19,28,37,46,50},键盘录入一个数据,查找该数据在数组中的索引,并在控制台输出找到的索引值。
int[] arr = {19, 28, 37, 46, 50};
Scanner sc = new Scanner(System.in);
System.out.println("请输入您要查找的值:");
int a = sc.nextInt();
int index = -1;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == a) {
index = i;
System.out.println("您查找的值在数组中的索引值为:" + index);
break;
}
}
System.out.println("您查找的值在数组中不存在");
反转
需求:已知一个数组arr = {19,28,37,46,50};用程序实现把数组中的元素值交换,交换后的数组arr = {50,46,37,28,19};并在控制台输出交换后的数组元素。
public static void main(String[] args) {
int[] arr = {19, 28, 37, 46, 50};
for (int start = 0, end = arr.length - 1; start <= end; start++, end--) {
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
}
printArray(arr);
}
public static void printArray(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.print(arr[i]);
} else {
System.out.print(arr[i] + ", ");
}
}
System.out.print("]");
}
评委打分
需求:在编程竞赛中,有6个评委为参赛的选手打分,分数为0-100的整数分。
选手的最后得分为:去掉一个最高分和一个最低分后的4个评委平均值(不考虑小数部分)。
public static void main(String[] args) {
int[] arr = new int[6];
Scanner sc = new Scanner(System.in);
for (int x = 0; x < 6; x++) {
System.out.println("请输入第" + (x + 1) + "位评委的打分:");
arr[x] = sc.nextInt();
}
printArray(arr);
int max = getMax(arr);
int min = getMin(arr);
int sum = getSum(arr);
int score = (sum - max - min) / (arr.length - 2);
System.out.println();
System.out.println("选手的最终得分为:" + score);
}
public static void printArray(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.print(arr[i]);
} else {
System.out.print(arr[i] + ", ");
}
}
System.out.print("]");
}
public static int getMax(int[] arr) {
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
public static int getMin(int[] arr) {
int min = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] < min) {
min = arr[i];
}
}
return min;
}
public static int getSum(int[] arr) {
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
面向对象基础
类和对象
什么是类
类是对现实生活中一类具有共同属性和行为的事物的抽象。
类的特点:
- 类是对象的数据类型
- 类是具有相同属性和行为的一组对象的集合
什么是对象的属性
属性:对象具有的各种特征,每个对象的每个属性都拥有特定的值。
什么是对象的行为
行为:对象能够执行的操作。
类和对象的关系
- 类:类是对现实生活中一类具有共同属性和行为的事物的抽象
- 对象:是能够看得到摸得着的真实存在的实体
类是对象的抽象,对象是类的实体
类的定义
类的重要性:是 Java 程序的基本组成单位。
类的组成:属性和行为
- 属性:在类中通过成员变量来体现(类中方法外的变量)
- 行为:在类中通过成员方法来体现(和前面的方法相比去掉static关键字即可)
类的定义步骤:
- 定义类
- 编写类的成员变量
- 编写类的成员方法
class Phone {
String brand;
int price;
public void call() {
System.out.println("打电话");
}
public void sentMessage() {
System.out.println("发短信");
}
}
对象的使用
创建对象
- 格式:
类名 对象名 = new 类名();
- 范例:
Phone p = new Phone();
使用对象
-
使用成员变量
- 格式:
对象名.变量名
- 范例:
p.brand
-
使用成员方法
- 格式:
对象名.方法名()
- 范例:
p.call()
案例:学生类
需求:首先定义一个学生类,然后定义一个学生测试类,在学生测试类中通过对象完成成员变量和成员方法的使用
class Student {
String name;
int age;
public void study() {
System.out.println("好好学习,天天向上");
}
public void doHomework() {
System.out.println("键盘敲烂,月薪过万");
}
}
public static void main(String[] args) {
Student s = new Student();
System.out.println(s.name + "," + s.age);
s.name = "林青霞";
s.age = 30;
System.out.println(s.name + "," + s.age);
s.study();
s.doHomework();
}
成员变量和局部变量
- 成员变量:类中方法外的变量
- 局部变量:方法中的变量
成员变量和局部变量的区别:
区别 | 类中位置不同 | 内存中位置不同 | 生命周期不同 | 初始化值不同 |
---|---|---|---|---|
成员变量 | 类中方法外 | 堆内存 | 随着对象的存在而存在,随着对象的消失而消失 | 有默认的初始化值 |
局部变量 | 方法内或者方法声明上 | 栈内存 | 随着方法的调用而存在,随着方法的调用完毕而消失 | 没有默认的初始化值,必须先定义,赋值,才能使用 |
封装
private 关键字
private:
- 是一个权限修饰符
- 可以修饰成员(成员变量和成员方法)
- 作用是保护成员不被别的类使用,被
private
修饰的成员在本类中才能访问
针对
private
修饰的成员变量,如果需要被其它类使用,提供相应的操作:
- 提供“
get变量名()
”方法,用于获取成员变量的值,方法用public
修饰 - 提供“
set变量名(参数)
”方法,用于设置成员变量的值,方法用public
修饰
private 关键字的使用
class Student1 {
private String name;
private int age;
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 show() {
System.out.println(name + "," + age);
}
}
public static void main(String[] args) {
Student1 s = new Student1();
s.setName("林青霞");
s.setAge(30);
s.show();
System.out.println(s.getName() + "---" + s.getAge());
System.out.println(s.getName() + "," + s.getAge());
}
this 关键字
this
修饰的变量用于指代成员变量- 方法的形参如果与成员变量同名,不带
this
修饰的变量指的是形参,而不是成员变量 - 方法的形参没有与成员变量同名,不带
this
修饰的变量指的是成员变量
- 方法的形参如果与成员变量同名,不带
- 什么时候使用
this
? —— 解决局部变量隐藏成员变量 this
代表所在类的对象引用- 记住:方法被哪个对象调用,
this
就代表那个对象
- 记住:方法被哪个对象调用,
封装
封装概述:
- 是面向对象三大特征之一(封装、继承、多态)
- 是面向对象编程语言对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界是无法直接操作的
封装原则:
- 将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问成员变量
private
,提供对应的getXxx()
/setXxx()
方法
封装好处:
- 通过方法来控制成员变量的操作,提高了代码的安全性
- 把代码用方法进行封装,提高了代码的复用性
构造方法
构造方法是一种特殊的方法
作用:创建对象
格式:
public class 类名{
修饰符 类名(参数){
}
}
功能:主要是完成对象数据的初始化
注意事项:
-
构造方法的创建
- 如果没有定义构造方法,系统将给出一个默认的无参数构造方法
- 如果定义了构造方法,系统将不再提供默认的无参构造方法
-
构造方法的重载
- 如果定义了带参构造方法,还要使用无参数构造方法,就必须再写一个无参数构造方法
-
推荐的使用方式:
- 无论是否使用,都手工书写无参数构造方法
标准类制作
-
成员变量: 使用
private
修饰 -
构造方法:
- 提供一个无参构造方法
- 提供一个带多个参数的构造方法
-
成员方法:
- 提供每一个成员变量对应的
setXxx()
/getXxx()
- 提供一个显示对象信息的
show()
- 提供每一个成员变量对应的
-
创建对象并为其成员变量赋值的两种方式
- 无参构造方法创建对象后使用
setXxx()
赋值 - 使用带参构造方法直接创建带有属性值的对象
- 无参构造方法创建对象后使用
public class Student {
//成员变量
private String name;
private int age;
//构造方法
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//成员方法
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void show() {
System.out.println(name + "," + age);
}
}
public class test {
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("林青霞");
s1.setAge(30);
s1.show();
Student s2 = new Student("林青霞", 30);
s2.show();
}
}
字符串
API
API(Application Programing Interface): 应用程序编程接口
注意:
- 调用方法的时候,如果方法有明确的返回值,我们用变量接收
- 可以手动完成,也可以使用快捷键的方式完成(CTRL+ALT+V)
API 使用练习
需求:按照帮助文档的使用步骤学习Scanner类的使用,并实现键盘录入一个字符串,最后输出在控制台
public class api {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入你想打印的话:");
String line = sc.nextLine();
System.out.println(line);
}
}
String
String 构造
String类在java.lang包下,所以使用时不需要导包
String类代表字符串,java程序中的所有字符串文字(例如:“abc”)都被实现为此类的实例。也就是说,Java程序中所有的双引号字符串,都是String类的对象。
字符串的特点:
- 字符串不可变,它们的值在创建后不能被更改
- 虽然String的值是不可变的,但是它们可以被共享
- 字符串效果上相当于字符数组(char[]),但是底层原理是字节数组(byte[])(JDK8及以前是字符数组,JDK9及以后是字节数组)
构造方法:
构造方法 | 描述 |
---|---|
public String() | 创建一个空白字符串对象,不含有任何内容 |
public String(char[] chs) | 根据字符数组的内容,来创建字符串对象 |
public String(byte[] bys) | 根据字节数组的内容,来创建字符串对象 |
String s = “abc”; | 直接赋值的方式创建字符串对象,内容就是abc |
推荐使用直接赋值的方式得到字符串对象
String s1 = new String();
System.out.println("s1:" + s1); // s1:
char[] chs = {'a', 'b', 'c'};
String s2 = new String(chs);
System.out.println("s2:" + s2); // s2:abc
byte[] bys = {97, 98, 99};
String s3 = new String(bys);
System.out.println("s3:" + s3); // s3:abc
String s4 = "abc";
System.out.println("s4:" + s4); // s4:abc
String 对象特点
- 通过
new
创建的字符串对象,每一次==new
都会申请一个内存空间,虽然内容相同,但是地址值不同== - 以”“方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM都只会建立一个String对象,并在字符串池中维护
字符串比较
使用
==
作比较:
- 基本类型:比较的是数据值是否相同
- 引用类型:比较的是地址值是否相同
使用
equals()
方法比较:
- 字符串是对象,它比较内容是否相同,是通过一个方法来实现的,这个方法叫
equals()
public boolean equals(Object anObject)
:将此字符串与指定对象进行比较。由于我们比较的是字符串对象,所以参数直接传递一个字符串
案例:用户登录
需求:已知用户名和密码,请用程序实现模拟用户登录。总共给三次机会,登录之后,给出相应的提示。
import java.util.Scanner;
public class 用户登录 {
public static void main(String[] args) {
String username = "root";
String password = "123456";
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
System.out.println("请输入用户名:");
String name = sc.nextLine();
System.out.println("请输入密码:");
String pasw = sc.nextLine();
if (name.equals(username) && pasw.equals(password)) {
System.out.println("登录成功!");
break;
} else {
if (2 - i == 0) {
System.out.println("你的账户被锁定,请与管理员联系");
} else {
System.out.println("登录失败,你还有" + (2 - i) + "次机会");
}
}
}
}
}
案例:遍历字符串
需求:键盘录入一个字符串,使用程序实现在控制台遍历该字符串。
import java.util.Scanner;
public class 遍历字符串 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String s = sc.nextLine();
// s.length()获取字符串长度
for (int i = 0; i < s.length(); i++) {
// s.charAt()获取指定索引处的字符
System.out.println(s.charAt(i));
}
}
}
案例:统计字符次数
需求:键盘录入一个字符串,统计该字符串中大写字母字符,小写字母字符,数字字符出现的次数(不考虑其他字符)。
import java.util.Scanner;
public class 统计字符次数 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String line = sc.nextLine();
int bigCount = 0;
int smallCount = 0;
int numberCount = 0;
for (int i = 0; i < line.length(); i++) {
char ch = line.charAt(i);
if (ch >= 'A' && ch <= 'Z') {
bigCount++;
} else if (ch >= 'a' && ch <= 'z') {
smallCount++;
} else if (ch >= '0' && ch <= '9') {
numberCount++;
}
}
System.out.println("大写字母:" + bigCount + "个");
System.out.println("小写字母:" + smallCount + "个");
System.out.println("数字:" + numberCount + "个");
}
}
案例:字符串拼接
需求:定义一个方法,把int数组中的数据按照指定的格式拼接成一个字符串返回,调用该方法,并在控制台输出结果。例如:数组为int[] arr = {1,2,3};,执行该方法后输出的结果为:[1, 2, 3]。
public class 拼接字符串 {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
String s = arrayToStrijng(arr);
System.out.println(s); // [1, 2, 3]
}
public static String arrayToStrijng(int[] arr) {
String s = "";
s += "[";
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
s += arr[i];
} else {
s += arr[i];
s += ", ";
}
}
s += "]";
return s;
}
}
案例:字符串反转
需求:定义一个方法,实现字符串反转。键盘录入一个字符串,调用该方法后,在控制台输出结果。
例如:键盘录入abc,输出结果cba。
import java.util.Scanner;
public class 字符串反转 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String line = sc.nextLine();
String s = stringReverse(line);
System.out.println("字符串反转结果为:" + s);
}
public static String stringReverse(String s) {
String ss = "";
for (int i = s.length() - 1; i >= 0; i--) {
ss += s.charAt(i);
}
return ss;
}
}
通过帮助文档查看 String 中的方法
方法名 | 描述 |
---|---|
public bollean equals(Object anObject) | 比较字符串的内容,严格区分大小写(用户名和密码) |
public char charAt(int index) | 返回指定索引处的 char 值 |
public int length() | 返回此字符串的长度 |
StringBuilder
- StringBuilder是一个可变的字符串类,我们可以把它看成是一个容器。
- 这里的可变指的是StringBuilder对象中的内容是可变的。
String 和 StringBuilder 的区别:
- String:内容是不可变的
- StringBuilder:内容是可变的
构造方法:
构造方法 | 描述 |
---|---|
public StringBuilder() | 创建一个空白可变字符串对象,不含有任何内容 |
public StringBuilder(String str) | 根据字符串的内容,来创建可变字符串对象 |
StringBuilder sb = new StringBuilder();
System.out.println("sb:" + sb);
System.out.println("sb.length():" + sb.length());
StringBuilder sb2 = new StringBuilder("hello");
System.out.println("sb2:" + sb2);
System.out.println("sb2.length():" + sb2.length());
StringBuilder 的添加和反转方法
//创建对象
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("java");
sb.append(100);
*/
//链式编程
sb.append("hello").append("world").append("java").append(100);
System.out.println("sb:" + sb);
sb.reverse();
System.out.println("sb:" + sb);
StringBuilder 和 String 相互转换
-
StringBuilder转换为String
public StringToString()
:通过toString()
就可以实现把StringBuilder转换为String
-
String转换为StringBuilder
public StringBuilder(String s)
:通过构造方法就可以实现把String转换为StringBuilder
StringBuilder sb = new StringBuilder();
sb.append("hello");
String s = sb.toString();
System.out.println(s);
String str = "hello";
StringBuilder sb2 = new StringBuilder(str);
System.out.println(sb2);
案例:拼接字符串
需求:定义一个方法,把int数组中的数据按照指定的格式拼接成一个字符串返回,调用该方法,并在控制台输出结果。例如:数组为int[] arr = {1,2,3};,执行该方法后输出的结果为:[1, 2, 3]。
public static void main(String[] args) {
int[] arr = {1, 2, 3};
String s = arrayToString(arr);
System.out.println("s:" + s);
}
public static String arrayToString(int[] arr) {
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;
}
案例:字符串反转
需求:定义一个方法,实现字符串反转。键盘录入一个字符串,调用该方法后,在控制台输出结果。
例如:键盘录入abc,输出结果cba。
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String line = sc.nextLine();
String s = myReverse(line);
System.out.println("反转后的字符串为:" + s);
}
public static String myReverse(String s) {
/*StringBuilder sb = new StringBuilder(s);
sb.reverse();
String s1 = sb.toString();
return s1;*/
return new StringBuilder(s).reverse().toString();
}
集合基础
集合概述
编程的时候如果要存储多个数据,使用长度固定的数组存储格式,不一定能满足我们的需求,更适应不了变化的需求。此时,就应该使用集合。
集合的特点:
- 提供一种存储空间可变的存储模型,存储的数据容量可以发生改变
ArrayList
ArrayList<E>
- 可调整大小的数组实现
- :是一种特殊的数据类型,泛型
- 使用:在出现E的地方用引用数据类型替换即可
- 范例:
ArrayList<String>,ArrayList<Student>
构造方法和添加方法:
方法名 | 描述 |
---|---|
public ArrayList() | 创建一个空的集合对象 |
public boolean add(E e) | 将特定的元素追加到此集合的末尾 |
public void add(int index, E element) | 在此集合中的特定位置插入指定的元素 |
//public ArrayList() 创建一个空的集合对象
//ArrayList<String> array = new ArrayList<>();
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, "javase");
//输出集合
System.out.println("array:" + array);
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() | 返回集合中的元素个数 |
//创建集合
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"));
//public E remove(int index) 删除指定索引处的元素,返回被删除的元素
System.out.println(array.remove(1));
//public E set(int index, E element) 修改指定索引处的元素,返回被修改的元素
System.out.println(array.set(1, "javase"));
//public E get(int index) 返回指定索引处的元素
System.out.println(array.get(0));
//public int size() 返回集合中的元素个数
System.out.println(array.size());
//输出集合
System.out.println("array:" + array);
案例:存储字符串并遍历
需求:创建一个存储字符串的集合,存储3个字符串元素,使用程序实现在控制台遍历该集合。
ArrayList<String> array = new ArrayList<String>();
array.add("hello");
array.add("world");
array.add("java");
for (int i = 0; i < array.size(); i++) {
System.out.println(array.get(i));
}
案例:存储学生对象并遍历
需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合。
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
public class Demo {
public static void main(String[] args) {
//创建集合对象
ArrayList<Student> array = new ArrayList<Student>();
//创建学生对象
Student s1 = new Student("林青霞", 30);
Student s2 = new Student("风清扬", 33);
Student s3 = new Student("张曼玉", 18);
//添加学生对象到集合中
array.add(s1);
array.add(s2);
array.add(s3);
//遍历集合
for (int i = 0; i < array.size(); i++) {
Student s = array.get(i);
System.out.println(s.getName() + "," + s.getAge());
}
}
}
案例:存储学生对象并遍历升级版
需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合,学生的姓名和年龄来自键盘录入。
public class Student {
private String name;
private String age;
public Student() {
}
public Student(String name, String age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(String age) {
this.age = age;
}
public String getAge() {
return age;
}
}
public class Demo {
public static void main(String[] args) {
ArrayList<Student> array = new ArrayList<Student>();
/*Scanner sc = new Scanner(System.in);
System.out.println("请输入学生姓名:");
String name = sc.nextLine();
System.out.println("请输入学生的年龄:");
String age = sc.nextLine();
Student s = new Student();
s.setName(name);
s.setAge(age);
array.add(s);*/
addStudent(array);
addStudent(array);
addStudent(array);
for (int i = 0; i < array.size(); i++) {
Student s = array.get(i);
System.out.println(s.getName() + "," + s.getAge());
}
}
public static void addStudent(ArrayList<Student> array) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入学生姓名:");
String name = sc.nextLine();
System.out.println("请输入学生的年龄:");
String age = sc.nextLine();
Student s = new Student();
s.setName(name);
s.setAge(age);
array.add(s);
}
}
案例:学生管理系统
public class Student {
//学号
private String sid;
//姓名
private String name;
//年龄
private String age;
//居住地
private String address;
public Student() {
}
public Student(String sid, String name, String age, String address) {
this.sid = sid;
this.name = name;
this.age = age;
this.address = address;
}
public String getSid() {
return sid;
}
public void setSid(String sid) {
this.sid = sid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
import java.util.ArrayList;
import java.util.Scanner;
public class StudentManager {
public static void main(String[] args) {
//创建集合对象用于存储学生数据
ArrayList<Student> array = new ArrayList<Student>();
//用循环完成再次回到主界面
while (true) {
//主界面编写
System.out.println("--------欢迎来到学生管理系统--------");
System.out.println("1 添加学生");
System.out.println("2 删除学生");
System.out.println("3 修改学生");
System.out.println("4 查看所有学生");
System.out.println("5 退出");
System.out.println("请输入你的选择:");
//用Scanner实现键盘录入数据
Scanner sc = new Scanner(System.in);
String line = sc.nextLine();
//用switch语句完成操作的选择
switch (line) {
case "1":
//System.out.println("添加学生");
addStudent(array);
break;
case "2":
//System.out.println("删除学生");
deleteStudent(array);
break;
case "3":
//System.out.println("修改学生");
updateStudent(array);
break;
case "4":
//System.out.println("查看所有学生");
findAllStudent(array);
break;
case "5":
System.out.println("谢谢使用");
//break;
System.exit(0); //JVM退出
}
}
}
//定义一个方法,用于添加学生信息
public static void addStudent(ArrayList<Student> array) {
//键盘录入学生对象所需要的数据,显示提示信息,提示要输入何种信息
Scanner sc = new Scanner(System.in);
//为了让sid在循环外被访问到
String sid;
//为了让程序回到这里,用循环实现
while (true) {
System.out.println("请输入学生学号:");
sid = sc.nextLine();
boolean flag = isUsed(array, sid);
if (flag) {
System.out.println("该学号已被使用,请重新输入");
} else {
break;
}
}
System.out.println("请输入学生姓名:");
String name = sc.nextLine();
System.out.println("请输入学生年龄:");
String age = sc.nextLine();
System.out.println("请输入学生居住地:");
String address = sc.nextLine();
//创建学生对象,把键盘录入的数据赋值给学生对象的成员变量
Student s = new Student();
s.setSid(sid);
s.setName(name);
s.setAge(age);
s.setAddress(address);
//将学生对象添加到集合中
array.add(s);
//给出添加成功提示
System.out.println("添加学生成功!");
}
//定义一个方法,用于查看所有学生信息
public static void findAllStudent(ArrayList<Student> array) {
//判断集合中是否有数据,如果没有显示提示信息
if (array.size() == 0) {
System.out.println("无信息,请先添加信息再查询");
//为了让程序不再往下执行
return;
}
//显示表头信息
//\t 其实就是tab键的位置
System.out.println("学号\t\t姓名\t\t年龄\t\t居住地");
//将集合数据取出来按照对应格式显示学生信息,年龄显示补充“岁”
for (int i = 0; i < array.size(); i++) {
Student s = array.get(i);
System.out.println(s.getSid() + "\t\t" + s.getName() + "\t" + s.getAge() + "岁\t" + s.getAddress());
}
}
//定义一个方法,用于删除学生信息
public static void deleteStudent(ArrayList<Student> array) {
//键盘录入要删除的学生学号
Scanner sc = new Scanner(System.in);
System.out.println("请输入要删除的学生的学号:");
String sid = sc.nextLine();
//遍历集合将对应学生对象从集合中删除
int index = -1;
for (int i = 0; i < array.size(); i++) {
Student s = array.get(i);
if (s.getSid().equals(sid)) {
//array.remove(i);
index = i;
break;
}
}
if (index == -1) {
System.out.println("该学号不存在,请重新输入");
} else {
array.remove(index);
//给出删除成功的提示
System.out.println("删除学生成功!");
}
}
//定义一个方法,用于修改学生信息
public static void updateStudent(ArrayList<Student> array) {
//键盘录入要修改的学生学号,显示提示信息
Scanner sc = new Scanner(System.in);
System.out.println("请输入要修改的学生的学号:");
String sid = sc.nextLine();
//键盘录入要修改的学生信息
System.out.println("请输入新的学生姓名:");
String name = sc.nextLine();
System.out.println("请输入新的学生年龄:");
String age = sc.nextLine();
System.out.println("请输入新的学生居住地:");
String address = sc.nextLine();
//创建学生对象
Student s = new Student();
s.setSid(sid);
s.setName(name);
s.setAge(age);
s.setAddress(address);
//遍历集合,修改对应的学生信息
for (int i = 0; i < array.size(); i++) {
Student student = array.get(i);
if (student.getSid().equals(sid)) {
array.set(i, s);
break;
}
}
//给出修改成功提示
System.out.println("修改学生成功!");
}
//定义一个方法,判断学号是否被使用
public static boolean isUsed(ArrayList<Student> array, String sid) {
boolean flag = false;
for (int i = 0; i < array.size(); i++) {
Student s = array.get(i);
if (s.getSid().equals(sid)) {
flag = true;
break;
}
}
return flag;
}
}
ALT+INSERT 根据自己的需要进行选择
继承
继承概述
继承是面向对象三大特征之一,可以使得子类具有父类的属性和方法,还可以在子类中重新定义,追加属性和方法。
继承的格式
- 格式:
public class 子类名 extends 父类名 {}
- 范例:
public class Zi extends Fu {}
- Fu:父类,也被称为基类、超类
- Zi:子类,也被称为派生类
继承中子类的特点:
- 子类可以有父类的内容
- 子类还可以有自己特有的内容
继承的好处和弊处
-
继承好处:
- 提高了代码的复用性(多个类相同的成员可以放到同一个类中)
- 提高了代码的维护性(如果方法的代码需要修改,修改一处即可)
-
继承弊端:
- 继承让类与类之间产生了关系,类的耦合性增强了,当父类发生变化时子类实现也不得不跟着变化,削弱了子类的独立性
什么时候使用继承?
- 继承体现的关系: is a
- 假设法:我有两个类A和B,如果它们满足A是B的一种,或者B是A的一种,就说明它们存在继承关系,这个时候就可以考虑使用继承来体现,否则就不能滥用继承
继承中变量的访问特点
在子类方法中访问一个变量:
- 子类局部范围找
- 子类成员范围找
- 父类成员范围找
- 如果都没有就报错(不考虑父亲的父亲…)
Super关键字
super
关键字的用法和this
关键字的用法类似this
:代表本类对象的引用super
:代表父类存储空间的标识(可以理解为父类对象引用)
三种用法:
this.成员变量 访问本类成员变量
this(...) 访问本类构造方法
this.成员方法(...) 访问本类成员方法
super.成员变量 访问父类成员变量
super(...) 访问父类构造方法
super.成员方法(...) 访问父类成员方法
继承中构造方法的访问特点
继承中构造方法的访问特点:
- 子类中所有的构造方法默认都会访问父类中无参的构造方法
- 原因:
- 因为子类会继承父类中的数据,可能还会使用父类的数据,所以,子类初始化之前,一定要先完成父类数据的初始化
- 每一个子类构造方法的第一条语句默认都是:
super()
如果父类中没有无参构造方法,只有带参构造方法:
- 通过使用
super
关键字去显式调用父类的带参构造方法 - 在父类中自己提供一个无参构造方法
推荐:自己给出无参构造方法
继承中成员方法的访问特点
继承中成员方法的访问特点:
- 通过子类对象访问一个方法
- 子类成员范围找
- 父类成员范围找
- 如果都没有就报错(不考虑父亲的父亲…)
方法重写
方法重写概述:
子类中出现了和父类一模一样的方法声明
方法重写的应用:
当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,既沿袭了父类的功能,又定义了子类特有的内容
@Override
- 是一个注解
- 可以帮助我们检查重写方法的方法声明的正确性
注意事项:
- 私有方法不能被重写(父类私有成员子类是不能继承的)
- 子类方法访问权限不能更低(public > 默认 > 私有)
Java 中继承的注意事项
- Java 中类只支持单继承,不支持多继承
- Java 中类支持多层继承
修饰符
包
包的概述和使用:
- 包其实就是文件夹
- 作用:对类进行分类管理
包的定义格式:
- 格式:
package 包名;
(多级包用.
分开) - 范例:
package com.itheima;
导包
cn.itcast.Teacher t = new cn.itcast.Teacher();
import cn.itcast.Teacher;
Teacher t = new Teacher();
修饰符
权限修饰符
修饰符 | 同一个类中 | 同一个包中子类无关类 | 不同包的子类 | 不同包的无关类 |
---|---|---|---|---|
private | √ | |||
默认 | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
状态修饰符
final
(最终态)static
(静态)
final
final
(最终态) 关键字是最终的意思,可以修饰成员方法,成员变量,类
final
修饰的特点:
- 修饰方法:表明该方法是最终方法,不能被重写
- 修饰变量:表明该变量是常量,不能再次被赋值
- 修饰类:表明该类是最终类,不能被继承
final
修饰局部变量:
- 变量是基本类型:final修饰指的是基本类型的数据值不能发生改变
final int age = 20;
- 变量是引用类型:final修饰指的是引用类型的地址值不能发生改变,但是地址值里面的内容是可以发生改变的
final Student s = new Student();
static
static 关键字是静态的意思,可以修饰成员变量,成员方法
static修饰的特点:
- 被类的所有对象共享 这也是我们判断是否使用静态关键字的条件
- 可以使用类名调用,也可以使用对象名调用,推荐使用类名调用
static访问特点
-
非静态的成员方法:
- 能访问静态的成员变量
- 能访问非静态的成员变量
- 能访问静态的成员方法
- 能访问非静态的成员方法
-
静态的成员方法:
- 能访问静态的成员变量
- 能访问静态的成员方法
总结:静态成员方法只能访问静态成员
多态
多态概述
多态:同一个对象,在不同时刻表现出来的不同形态
多态的前提和体现:
- 有继承/实现关系
- 有方法重写
- 有父类引用指向子类对象
多态中成员访问特点
- 成员变量:编译看左边,执行看左边
- 成员方法:编译看左边,执行看右边
为什么成员变量和成员方法的访问不一样呢?
因为成员方法有重写,而成员变量没有。
多态的好处和弊端
- 多态的好处: 提高了程序的扩展性
- 具体体现:定义方法的时候使用父类型作为参数,将来在使用的时候,使用具体的子类型参加操作
- 多态的弊端: 不能使用子类的特有功能
多态中的转型
- 向上转型 从子到父 父类引用指向子类对象
Animal a = new Cat();
- 向下转型 从父到子 父类引用转为子类对象
Cat c = (Cat) a;
案例:猫和狗
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();
抽象类
抽象类概述
在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类。
抽象类特点
- 抽象类和抽象方法必须使用
abstract
关键字修饰public abstract void class 类名 {}
public abstract void eat();
- 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
- 抽象类不能直接实例化,但可以参照多态的方式,通过子类对象实例化,这叫抽象类多态
- 抽象类的子类,要么重写抽象类中的所有抽象方法,要么写成抽象类
抽象类的成员特点
- 成员变量:可以是变量,也可以是常量
- 构造方法:有构造方法,但是不能实例化,构造方法的作用是用于子类访问父类数据的初始化
- 成员方法:
- 可以有抽象方法:限定子类必须完成某些动作
- 也可以有非抽象方法:提高代码复用性
案例:猫和狗
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();
接口
接口概述
接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用。
Java中的接口更多的体现在对行为的抽象。
接口特点
- 接口用关键字
interface
修饰 ——public interface 接口名 {}
- 类实现接口用
implements
表示 ——public class 类名 implements 接口名 {}
- 接口不能直接实例化,要想实例化,需要参照多态的方式,通过实现类对象实例化,这叫接口多态。
- 多态的形式:具体类多态、抽象类多态、接口多态
- 多态的前提:有继承或者实现关系;有方法重写;有父(类/接口)引用指向(子/实现)类对象。
- 接口的实现类:
- 要么重写接口中的所以抽象方法
- 要么是抽象类
接口的成员特点
-
成员变量
- 只能是常量
- 默认修饰符:
public static final
-
构造方法
- 接口没有构造方法,因为接口主要是对行为进行抽象的,是没有具体存在。
- 一个类如果没有父类,默认继承自Object类
-
成员方法
- 只能是抽象方法
- 默认修饰符:
public abstract
类和接口的关系
类和类的关系:
继承关系,只能单继承,但是可以多层继承
public class Zi extends Fu {}
类和接口的关系:
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
public class InterImpl extends Object implements Inter1, Inter2, Inter3 {}
接口和接口的关系:
继承关系,可以单继承,也可以多继承
public interface Inter3 extends Inter1, Inter2 {}
抽象类和接口的区别
-
成员区别:
- 抽象类 —— 变量,常量;有构造方法;有抽象方法;也有非抽象方法
- 接口 —— 常量;抽象方法
-
关系区别:
- 类与类 —— 继承,单继承
- 类与接口 —— 实现,可以单实现,也可以多实现
- 接口与接口 —— 继承,单继承,多继承
-
设计理念没区别:
- 抽象类 —— 对类抽象,包括属性、行为
- 接口 —— 对行为抽象,主要是行为
形参和返回值
类名作为形参和返回值
- 方法的形参是类名,其实需要的是该类的对象
- 方法的返回值是类名,其实返回的是该类的对象
抽象类名作为形参和返回值
- 方法的形参是抽象类名,其实需要的是该抽象类的子类对象
- 方法的返回值是抽象类名,其实返回的是该抽象类的子类对象
接口名作为形参和返回值
- 方法的形参是接口名,其实需要的是该接口的实现类对象
- 方法的返回值是接口名,其实返回的是该接口的实现类对象
内部类
内部类概述
内部类:就是在一个类中定义一个类。
内部类的定义格式:
public class 类名 {
修饰符 class 类名 {
}
}
内部类的访问特点:
- 内部类可以直接访问外部类的成员,包括私有
- 外部类要访问内部类的成员,必须创建对象
public class Demo {
private int num = 10;
public class Inner {
public void show() {
System.out.println(num);
}
}
public void method() {
//show();
Inner i = new Inner();
i.show();
}
}
成员内部类
根据内部类在类中定义的位置不同,可以分为如下两种形式:
- 在类的成员位置:成员内部类
- 在类的局部位置:局部内部类
外部类创建对象使用内部类
- 格式:
外部类名.内部类名 对象名 = 外部类对象.内部类对象
- 范例:
Outer.Inner oi = new Outer().new Inner();
public class Outer {
private int num = 10;
/*public class Inner {
public void show() {
System.out.println(num);
}
}*/
private class Inner {
public void show() {
System.out.println(num);
}
}
public void method() {
Inner i = new Inner();
i.show();
}
}
public class InnerDemo {
public static void main(String[] args) {
//创建内部类对象,并调用方法
// piublic 修饰的内部类
// Outer.Inner oi = new Outer().new Inner();
// oi.show();
// private 修饰的内部类
Outer o = new Outer();
o.method();
}
}
局部内部类
- 局部内部类是在方法中定义的类,所以外界是无法直接使用的,需要要在方法内部创建对象并使用。
- 该类可以直接访问外部类的成员,也可以访问方法内的局部变量。
public class Outer {
private int num = 10;
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 Demo {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
匿名内部类
- 前提:存在一个类或接口,这里的类可以是具体类,也可以是抽象类。
- 格式:
new 类名或者接口名() {
重写方法;
};
- 本质:是一个继承了该类或者实现了该接口的子类匿名**对象**。
public class Outer {
public void method() {
new Inter() {
@Override
public void show() {
System.out.println("匿名内部类");
}
}.show();
new Inter() {
@Override
public void show() {
System.out.println("匿名内部类");
}
}.show();
System.out.println("--------");
Inter i = new Inter() {
@Override
public void show() {
System.out.println("匿名内部类");
}
};
i.show();
i.show();
}
}
public interface Inter {
void show();
}
public class Demo {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
匿名内部类在开发中的使用
JumppingOperator jo = new JumppingOperator();
jo.method(new Jumpping() {
@Override
public void jump() {
System.out.println("猫可以跳高了");
}
});
jo.method(new Jumpping() {
@Override
public void jump() {
System.out.println("狗可以跳高了");
}
});
常用API
Math
Math包含执行基本数字运算的方法。
Math类的常用方法:
方法名 | 描述 |
---|---|
public static int abs(int a) | 返回参数的绝对值 |
public static double ceil(double a) | 返回大于或等于参数的最小double值,等于一个整数 |
public static double floor(double a) | 返回小于或等于参数的最大double值,等于一个整数 |
public static int round(float a) | 按照四舍五入返回最接近参数的int |
public static int max(int a, int b) | 返回两个int值中的较大值 |
public static int min(int a, int b) | 返回两个int值中的较小值 |
public static double pow(double a, double b) | 返回a的b次幂的值 |
public static double random() | 返回值为double的正值,[0.0,1.0) |
//public static int abs(int a) 返回参数的绝对值
System.out.println(Math.abs(88));
System.out.println(Math.abs(-88));
System.out.println("--------");
//public static double ceil(double a) 返回大于或等于参数的最小double值,等于一个整数
System.out.println(Math.ceil(12.34));
System.out.println(Math.ceil(12.56));
System.out.println("--------");
//public static double floor(double a) 返回小于或等于参数的最大double值,等于一个整数
System.out.println(Math.floor(12.34));
System.out.println(Math.floor(12.56));
System.out.println("--------");
//public static int round(float a) 按照四舍五入返回最接近参数的int
System.out.println(Math.round(12.34));
System.out.println(Math.round(12.56));
System.out.println("--------");
//public static int max(int a, int b) 返回两个int值中的较大值
System.out.println(Math.max(66, 88));
System.out.println("--------");
//public static int min(int a, int b) 返回两个int值中的较小值
System.out.println(Math.min(66, 88));
System.out.println("--------");
//public static double pow(double a, double b) 返回a的b次幂的值
System.out.println(Math.pow(2.0, 3.0));
System.out.println("--------");
//public static double random() 返回值为double的正值,[0.0,1.0)
System.out.println(Math.random());
System.out.println((int) (Math.random() * 100) + 1);
System
System包含几个有用的类字段和方法,它不能被实例化。
System类的常用方法:
方法名 | 描述 |
---|---|
public static void exit(int status) | 终止当前运行的Java虚拟机,非零表示异常终止 |
public static long currentTimeMillis() | 返回当前时间(以毫秒为单位) |
System.out.println("开始");
//public static void exit(int status) 终止当前运行的Java虚拟机,非零表示异常终止
//System.exit(0);
System.out.println("结束");
//public static long currentTimeMillis() 返回当前时间(以毫秒为单位)
System.out.println(System.currentTimeMillis());
System.out.println(System.currentTimeMillis() * 1.0 / 1000 / 60 / 60 / 24 / 365 + "年");
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
System.out.println(i);
}
long end = System.currentTimeMillis();
System.out.println("共耗时:" + (end - start) + "毫秒");
Obiect类的toString方法
- Object是类层次结构的根,每个类都可以将Object类作为超类。所有类都直接或间接继承自该类。
- 构造方法:
public Object()
看方法的源码,选中方法按
CTRL+B
建议所有子类重写toString()
方法
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 String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Student s = new Student();
s.setName("林青霞");
s.setAge(30);
System.out.println(s);
System.out.println(s.toString());
Object类的equals方法
Object类的常用方法:
方法名 | 描述 |
---|---|
public String toString() | 返回对象的字符串表示形式。建议所有子类重写该方法,自动生成 |
public boolean equals(Object obj) | 比较对象是否相等,默认比较地址,重写可以比较内容,自动生成 |
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 String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
/*
this ---- s1
o ------ s2
*/
//比较地址是否相同,如果相同直接返回true
if (this == o) return true;
//判断参数是否为null 判断两个对象是否来自于同一个类
if (o == null || getClass() != o.getClass()) return false;
//向下转型
Student student = (Student) o; //student = s2
//判断age是否相同
if (age != student.age) return false;
//比较name是否相同
return name != null ? name.equals(student.name) : student.name == null;
}
}
Student s1 = new Student();
s1.setName("林青霞");
s1.setAge(30);
Student s2 = new Student();
s2.setName("林青霞");
s2.setAge(30);
//需求:比较两个对象的值是否相同
System.out.println(s1 == s2); // false 比较的是地址值
System.out.println(s1.equals(s2)); // true
冒泡排序
- 排序:将一组数据按照固定的规则进行排列
- 冒泡排序:一种排序方式,对要进行排序的数据中相邻的数据进行两两比较,将较大的数据放到后面,依次对所有的数据进行操作,直至所有数据按照要求完成排序。
冒泡排序特点:
- 如果有n个数据进行排序,总共需要比较n-1次
- 每一次比较完毕,下一次的比较就会少一个数据参与
public class Demo {
public static void main(String[] args) {
int[] arr = {24, 69, 80, 57, 13};
System.out.println("排序前:" + arrayToString(arr));
for (int x = 0; x < arr.length - 1; x++) {
for (int i = 0; i < arr.length - 1 - x; i++) {
if (arr[i] > arr[i + 1]) {
int temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
}
System.out.println("第" + x + "次排序后:" + arrayToString(arr));
}
System.out.println("排序后:" + arrayToString(arr)); // [13, 24, 57, 69, 80]
}
public static String arrayToString(int[] arr) {
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;
}
}
Arrays 类
Arrays类包含用于操作数组的各种方法
方法名 | 描述 |
---|---|
public static String toString(int[] a) | 返回指定数组的内容的字符串表示形式 |
public static void sort(int[] a) | 按照数字顺序排列指定的数组 |
工具类的设计思想:
- 构造方法用
private
修饰 - 成员用
public static
修饰
//定义一个数组
int[] arr = {24, 69, 80, 57, 13};
System.out.println("排序前:" + Arrays.toString(arr));
Arrays.sort(arr);
System.out.println("排序后:" + Arrays.toString(arr));
基本类型包装类
基本类型包装类
- 将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据
- 常用的操作之一:用于基本数据类型与字符串之间的转换
基本数据类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
//需求:判断一个数据是否在int范围内
System.out.println(Integer.MIN_VALUE);
System.out.println(Integer.MAX_VALUE);
Integer
Integer:包装一个对象中的原始类型int的值
方法名 | 描述 |
---|---|
public Integer(int value) | 根据int值创建Integer对象(过时) |
public Integer(String s) | 根据String值创建Integer对象(过时) |
public static Integer valueOf(int i) | 返回表示指定的int值的Integer实例 |
public static Integer valueOf(String s) | 返回一个保存指定值的Integer对象String |
//public Integer(int value) 根据int值创建Integer对象(过时)
Integer i1 = new Integer(100);
System.out.println(i1);
//public Integer(String s) 根据String值创建Integer对象(过时)
Integer i2 = new Integer("100"); //字符串必须是数字字符串
System.out.println(i2);
//public static Integer valueOf(int i) 返回表示指定的int值的Integer实例
Integer i3 = Integer.valueOf(200);
System.out.println(i3);
//public static Integer valueOf(String s) 返回一个保存指定值的Integer对象String
Integer i4 = Integer.valueOf("200");
System.out.println(i4);
int和String类型的相互转换
功能 | 方法名 | 描述 |
---|---|---|
int转换为String | public static String valueOf(int i) | 返回int参数的字符串表示形式。该方法是String类中的方法 |
String转换为int | public static int parseInt(String s) | 将字符串解析为int类型。该方法是Integer类中的方法 |
//int ----> String
int number = 100;
//方式一
String s1 = "" + number;
System.out.println(s1);
//方式二
//public static String valueOf (int i)
String s2 = String.valueOf(number);
System.out.println(s2);
System.out.println("--------");
//String ----> int
String s = "100";
//方式一
//String ----> Integer ----> int
Integer i = Integer.valueOf(s);
//public int intValue ()
int x = i.intValue();
System.out.println(x);
//方式二
//public static int parseInt (String s)
int y = Integer.parseInt(s);
System.out.println(y);
案例:字符串中数据排序
需求:有一个字符串:“91 27 46 38 50”,请写程序实现最终输出的结果是:“27 38 46 50 91”
String s = "91 27 46 38 50";
//把字符串中的数字数据存储到一个int类型的数组中
String[] strArray = s.split(" ");
for (int i = 0; i < strArray.length; i++) {
System.out.println(strArray[i]);
}
//定义一个int数组,把String[]数组中的每一个元素存储到int数组中
int[] arr = new int[strArray.length];
for (int i = 0; i < arr.length; i++) {
arr[i] = Integer.parseInt(strArray[i]);
}
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
//对int数组排序
Arrays.sort(arr);
//将排序后的int数组中的元素进行拼接得到一个字符串,这里拼接采用StringBuilder来实现
StringBuilder sb = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
if (arr[i] == arr.length - 1) {
sb.append(arr[i]);
} else {
sb.append(arr[i]).append(" ");
}
}
String result = sb.toString();
System.out.println("result:" + result); // "27 38 46 50 91"
自动装箱和拆箱
- 装箱:把基本数据类型转换为对应的包装类类型
- 拆箱:把包装类类型转换为对应的基本数据类型
注意:在使用包装类类型的时候,如果做操作,最好先判断是否为null
推荐只要是对象,在使用前就必须进行不为null的判断
//装箱
Integer i = Integer.valueOf(100);
//自动装箱
Integer ii = 100;
//拆箱
ii = ii.intValue() + 200;
System.out.println(ii);
//自动拆箱
ii += 200;
System.out.println(ii);
Integer iii = null;
if (iii != null) {
iii += 300; //NullPointerException 空指针
}
日期类
Date
Date代表了一个特定的时间,精确到毫秒
构造方法 | 描述 |
---|---|
public Date类() | 分配一个Date对象,并初始化,以便它代表它被分配的时间,精确到毫秒 |
public Date类(long date) | 分配一个Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数 |
//public Date类() 分配一个Date对象,并初始化,以便它代表它被分配的时间,精确到毫秒
Date d1 = new Date();
System.out.println(d1);
System.out.println("--------");
//public Date类(long date) 分配一个Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数
long date = 1000 * 60 * 60;
Date d2 = new Date(date);
System.out.println(d2);
Date 类中的常用方法
方法名 | 描述 |
---|---|
public long getTime() | 获取的是日期对象从1970年1月1日00:00:00到现在的毫秒值 |
public void setTime(long time) | 设置时间,给的是毫秒值 |
//创建日期对象
Date d = new Date();
//public long getTime() 获取的是日期对象从1970年1月1日00:00:00到现在的毫秒值
System.out.println(d.getTime());
System.out.println(d.getTime() * 1.0 / 1000 / 60 / 60 / 24 / 365 + "年");
System.out.println("--------");
//public void setTime(long time) 设置时间,给的是毫秒值
System.out.println(d);
System.out.println("-------");
long time = 1000*60*60;
d.setTime(time);
System.out.println(d);
System.out.println("-------");
time = System.currentTimeMillis();
d.setTime(time);
System.out.println(d);
SimpleDateFormat类
SimpleDateFormat类是一个具体的类,用于以区域设置敏感的方式格式化和解析日期。
日和时间格式由日期和时间模式字符串指定,在日期和时间模式字符串中,从 ‘A’ 到 ‘Z’ 以及从 ‘a’ 到 ‘z’ 引号的字母被解释为表示日期或时间字符串的组件的模式字母
常用的模式字母及对应关系如下:
- y —— 年
- M —— 月
- d —— 日
- H —— 时
- m —— 分
- s —— 秒
构造方法:
构造方法 | 描述 |
---|---|
public SimpleDateFormat() | 构造一个SimpleDateFormat,使用默认模式和日期格式 |
public SimpleDateFormat(String pattern) | 构造一个SimpleDateFormat使用给定的模式和默认的日期格式 |
-
格式化日期(Date —> String):
public final String format(Date date)
将日期格式化成日期/时间字符串
-
解析日期(String —> Date):
public Date parse(String source)
从给定字符串的开始解析文本以生成日期
//格式化
Date d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat();
String s = sdf.format(d);
System.out.println(s);
System.out.println("--------");
sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
s = sdf.format(d);
System.out.println(s);
System.out.println("--------");
//解析
String ss = "2022-05-06 14:54:30";
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d2 = sdf2.parse(ss);
System.out.println(d2);
案例:日期工具类
需求:定义一个日期工具类(DateUtils),包含两个方法:把日期转换为指定格式的字符串;把字符串解析为指定格式的日期。然后定义一个测试类,测试日期工具类的方法。
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtils {
private DateUtils() {}
public static String dateToString(Date date, String format) {
SimpleDateFormat sdf = new SimpleDateFormat(format);
String s = sdf.format(date);
return s;
}
public static Date stringToDate(String s, String format) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat(format);
Date d = sdf.parse(s);
return d;
}
}
import java.text.ParseException;
import java.util.Date;
public class Demo {
public static void main(String[] args) throws ParseException {
Date d = new Date();
String s1 = DateUtils.dateToString(d, "yyyy年MM月dd日 HH:mm:ss");
System.out.println(s1);
System.out.println("--------");
String s2 = DateUtils.dateToString(d, "yyyy年MM月dd日");
System.out.println(s2);
String s3 = DateUtils.dateToString(d, "HH:mm:ss");
System.out.println(s3);
System.out.println("--------");
String s = "2022-5-6 15:12:02";
Date dd = DateUtils.stringToDate(s, "yyyy-MM-dd HH:mm:ss");
System.out.println(dd);
}
}
Calendar
Calendar为某一时刻和一组日历字段之间的转换提供了一些方法,并为操作日历字段提供了一些方法。
Calendar提供了一个类方法getInstance
用于获取Calendar对象,其日历字段已使用当前日期和时间初始化:
Calendar rightNow = Calendar.getInstance();
//获取Calendar对象
Calendar c = Calendar.getInstance(); //多态的形式得到对象
// System.out.println(c);
//public int get(int field)
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH) + 1;
int day = c.get(Calendar.DATE);
System.out.println(year + "年" + month + "月" + day + "日");
Calendar常用方法:
方法名 | 描述 |
---|---|
public int get(int field) | 返回给定日历字段的值 |
public abstract void add(int field, int amount) | 根据日历的规则,将指定的时间量添加或减去给定的日历字段 |
public final void set(int year, int month, int date) | 设置当前日历的年月日 |
//获取日历类对象
Calendar c = Calendar.getInstance();
//public int get(int field)
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH) + 1;
int day = c.get(Calendar.DATE);
System.out.println(year + "年" + month + "月" + day + "日");
System.out.println("--------");
//public abstract void add(int field, int amount) 根据日历的规则,将指定的时间量添加或减去给定的日历字段
//10年后的5天前
c.add(Calendar.YEAR, 10);
c.add(Calendar.DATE, -5);
year = c.get(Calendar.YEAR);
month = c.get(Calendar.MONTH) + 1;
day = c.get(Calendar.DATE);
System.out.println(year + "年" + month + "月" + day + "日");
System.out.println("--------");
//public final void set(int year, int month, int date) 设置当前日历的年月日
c.set(2048, 11, 11);
year = c.get(Calendar.YEAR);
month = c.get(Calendar.MONTH) + 1;
day = c.get(Calendar.DATE);
System.out.println(year + "年" + month + "月" + day + "日");
案例:二月天
需求:获取任意一年的二月份有多少天
Scanner sc = new Scanner(System.in);
System.out.println("请输入你想查询的年份:");
int year = sc.nextInt();
//设置日历对象的年月日
Calendar c = Calendar.getInstance();
c.set(year, 2, 1);
//3月1日往前推一天就是2月的最后一天
c.add(Calendar.DATE, -1);
//获取这一天并输出
int date = c.get(Calendar.DATE);
System.out.println(year + "年的2月份有" + date + "天");
异常
异常概述
异常:就是程序出现了不正常的情况
异常体系
- Error:严重问题,不需要处理
- Exception:称为异常类,它表示程序本身可以处理的问题
- RuntimeException:在编译期间是不检查的,需要我们回来修改代码
- 非RuntimeException:编译期间就必须处理,否则程序不能通过编译,就更不能正常运行了
JVM的默认处理方案
如果程序出现了问题,我们没有做任何处理,最终JV吗会做默认的处理
- 把异常的名称,异常原因及异常出现的位置等信息输出在了控制台
- 程序停止执行
异常处理之try…catch
格式:
try {
可能出现异常的代码;
} catch(异常类名 变量名) {
异常的处理代码;
}
执行流程:
- 程序从try里面的代码开始执行
- 出现异常,会自动生成一个异常类对象,该异常对象将被提交给Java时系统
- 当Java运行时系统接收到异常对象时,会到catch中去找匹配的异常类,找到后执行异常的处理
- 执行完毕之后,程序还可以继续往下执行
public static void main(String[] args) {
System.out.println("开始");
method();
System.out.println("结束");
}
public static void method() {
try {
int[] arr = {1, 2, 3};
System.out.println(arr[3]);
} catch (ArrayIndexOutOfBoundsException e) {
// System.out.println("你访问的数组索引不存在");
e.printStackTrace();
}
}
Throwable的成员方法
方法名 | 描述 |
---|---|
public String getMessage() | 返回此throwable的详细消息字符串 |
public String toString() | 返回此可抛出的简短描述 |
public void printStackTrace() | 把异常的错误信息输出在控制台 |
public static void main(String[] args) {
System.out.println("开始");
method();
System.out.println("结束");
}
public static void method() {
try {
int[] arr = {1, 2, 3};
System.out.println(arr[3]);
} catch (ArrayIndexOutOfBoundsException e) {
// e.printStackTrace();
//public String getMessage() 返回此throwable的详细消息字符串
System.out.println(e.getMessage()); //Index 3 out of bounds for length 3 返回出现异常的原因
System.out.println("--------");
//public String toString() 返回此可抛出的简短描述
System.out.println(e.toString()); //java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
System.out.println("--------");
//public void printStackTrace() 把异常的错误信息输出在控制台
e.printStackTrace();
//java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
// at 异常_93.Throwable的成员方法_4.method(Throwable的成员方法_4.java:19)
// at 异常_93.Throwable的成员方法_4.main(Throwable的成员方法_4.java:12)
}
}
编译时异常和运行时异常的区别
- Java中的异常分为两大类:编译时异常和运行时异常,也被称为受检异常和非受检异常。
- 所有的RuntimeException类及其子类被称为运行时异常,其他的异常都是编译时异常。
- 编译时异常:必须显示处理,否则程序就会发生错误,无法通过编译
- 运行时异常:无需显示处理,也可以和编译时异常一样处理
public static void main(String[] args) {
method();
}
//编译时异常
public static void method2() {
try {
String s = "2048-08-09";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d = sdf.parse(s);
System.out.println(d);
} catch (ParseException e) {
e.printStackTrace();
}
}
//运行时异常
public static void method() {
int[] arr = {1, 2, 3};
try {
System.out.println(arr[3]);
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
}
}
异常处理之throws
格式:
throws 异常类名;
注意:这个格式是跟在方法的括号后面的
- 编译时异常必须要进行处理,两种处理方案:try…catch…或者throws,如果采用throws这种方案,将来谁调用谁处理
- 运行时异常可以不处理,出现问题后,需要我们回来修改代码
public static void main(String[] args) {
System.out.println("开始");
method();
try {
method2();
} catch (ParseException e) {
throw new RuntimeException(e);
}
System.out.println("结束");
}
//运行时异常
public static void method() throws ArrayIndexOutOfBoundsException {
int[] arr = {1, 2, 3};
System.out.println(arr[3]);
}
//编译时异常
public static void method2() throws ParseException {
String s = "2048-08-09";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d = sdf.parse(s);
System.out.println(d);
}
自定义异常
格式:
public class 异常类名 extends Exception {
无参构造
带参构造
}
throws | throw |
---|---|
用在方法声明后面,跟的是异常类名 | 用在方法体内,跟的是异常对象名 |
表示抛出异常,由该方法的调用者来处理 | 表示抛出异常,由该方法体内的语句处理 |
表示出现异常的一种可能性,并不一定会发生这些异常 | 执行throw一定抛出了某种异常 |
public class ScoreException extends Exception {
public ScoreException() {};
public ScoreException(String message) {
super(message);
}
}
public class Teacher {
public void checkScore(int score) throws ScoreException {
if (score < 0 || score > 100) {
// throw new ScoreException();
throw new ScoreException("你给的分数有误,分数应该在0-100之间");
} else {
System.out.println("分数正常");
}
}
}
public class Demo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入分数:");
int score = sc.nextInt();
Teacher t = new Teacher();
try {
t.checkScore(score);
} catch (ScoreException e) {
e.printStackTrace();
}
}
}