java从零开始系统性学习完整超全资源+笔记(上)
前言
学习开始日期:2022.11.2
学习截止日期:进行中
**注意:**视频是基于eclipse进行编写的,最好还是用IDEA,eclipse老旧了,但是基本知识点还是不变的,等下学完这些视频,和IEDA里面有不同的地方再进行对比补充笔记。
文章目录
- java从零开始系统性学习完整超全资源+笔记(上)
- 前言
- 一、变量与数据类型
- Java语言概述
- 常用DOS命令
- HelloWorld案例
- 注释
- 关键字
- static
- 常量
- 变量
- 数据类型
- 标示符
- 命名规则
- 二、Eclipse/IDEA基本使用与配置
- **1:基本使用**
- **2:基本配置**
- 3:删除和导入项目
- 4.快捷键汇总
- IDEA快捷键
- 自定义快捷键模板输入
- 5.Debug
- 6.包里面再创建包
- 三、运算符和表达式
- 运算符
- 键盘录入
- 四、条件判断与循环语句
- 选择结构
- 循环结构
- 随机数
- 五、数组
- 一维数组&内存图解
- 二维数组
- 六、方法
- 方法定义及格式
- 形参和实参
- 方法重载
- 上半部分基础语法系统练习
- 1. 键盘录入月份,输出对应的季节(键盘录入+循环)
- 2.打印5位数中所有的回文数 (for+if训练)
- 3. 不死神兔问题
- 4. 求数组中满足要求的元素和
- 5. 裁判评分
- 6. 数组反转
- 7. 数组基本查找
- 8. 数据加密
- 七、面向对象基础
- 1.面向对象思想概述及举例
- 2.类与对象及其使用
- 3.对象内存存储机制
- 4.成员变量和局部变量的区别
- - private关键字
- 5.封装(private)
- 6.this关键字
- 7.构造方法
- 8.标准类的代码写法和测试
- 9.类名作为形式参数和返回值
- 八、java常用API
- API概述
- String
- **length与size的区别**
- equals和==的区别
- StringBuilder
- 九、java集合
- 1.对象数组的案例
- 2. ArrayList类的构造方法和成员方法
- 3. ArrayList类案例
- 4.学生管理系统
- 十、IO 流概念和FileWriter类
- 1.IO流
- **2.FileWriter写数据**
- 3.flush和close
- 4. 相对路径和绝对路径
- **5.FileReader读数据**
- 十一、上部分综合练习
- 题目一:学生信息存入文件中
- 题目二:学生管理系统最终版
- 十二、面向对象-static&代码块
- 1.static(静态)关键字
- **2.static的注意事项**
- **3.应用场景 Math类**
- **4.自定义工具类**
- 代码块
- 十三、面向对象-继承与抽象类
- 1.继承概述
- 2.继承的特点
- 3.继承中的成员变量
- 4.继承中的成员方法
- 5.方法的重写
- 方法重写与方法重载区别
- 6.继承中的构造方法
- 7.super关键字
- 9.抽象类概述(abstract)
- 十四、面向对象-接口与多态
- 接口概述(interface)
- 接口的成员
- 继承和实现
- 单继承和多实现
- 接口的优点
- 接口与抽象类异同
- 接口的思想
- 案例
- 匿名对象
- final关键字
- final修饰变量
- final和private
- 多态的概述( polymorphic )
- **多态举例**
- 多态的体现和前提
- 多态的成员特点
- 编译和运行的区别
- 多态中的类型转换
- 多态的优缺点
- 十五、面向对象-包&修饰符&内部类
- 包
- 不同包之间的互相访问
- 不同包之间的互相访问
- Java中常用的包
- 权限修饰符
- 内部类概述
- 成员内部类
- 成员内部类的修饰符
- 静态的成员内部类
- 局部内部类
- 匿名内部类(难理解多看几遍)
- 匿名内部类的应用场景
- 十六、 java常用的API高级
- API是什么
- Object
- toString
- equal
- System
- Date
- DateFormat
- Calendar
- 基本数据类型包装类(例如: Infeger)
- 正则表达式 常用的正则表达式字符
- 作业自主练习
- 1.自己动手定义一个Star(明星),明星有名字属性,自己手动重写Star的toString 和equals方法
- 2.通过System这个类的arraycopy方法将已知数组int [] arr ={12,234,45,324};中中间两个元素拷贝到另外一个新数组中;
- 3.通过System的currentTimeMillis()方法,计算出 输出一万次我爱你,所用时间;
- 4.通过date对象获取当前时间的毫秒值, 然后计算出明天这个时间的毫秒值,然后将明天的这个时候的毫秒值转成Date对象;
- 5.(1)将当前的时间解析成 xxxx年xx月xx日 xx:xx:xx 这种格式显示; (2)已知一个字符串时间String date = "2000_02_29#####23-23-23";
- 6.通过Calendar对象获取今天是多少年多少月多少日;
- 7.分别写出八种基本数据类型对应的包装类;
- 8.分析以下需求,并用代码实现
一、变量与数据类型
Java语言概述
1. java语言的跨平台原理
- 平台:指的是操作系统(Windows,Linux, Mac)
- 跨平台: Java程序可以在任意操作系统上运行,一次编写到处运行
- 原理:实现跨平台需要依赖Java的虚拟机JVM ( Java Virtual Machine)
2.JRE和JDK
JRE:java的运行环境
JDK:java的开发工具包
联系:使用JDK开发完成java程序,交给JRE去运行。
常用DOS命令
1. 打开控制台
win+ R,然后cmd回车;或者开始-搜索-输入cmd-回车。
常见DOS命令
-
d:回车盘符切换
-
dir(directory):列出当 前目录下的文件以及文件夹
-
cd (change directory)改变指定目录(进入指定目录)
-
进入cd目录; cd 目录名称,或者目录路径
同上图 -
回退cd…; cd
-
cls: (clear screen)清屏- exit:退出dos命令行
HelloWorld案例
1.Notepad++的使用
下载安装之后新建文件,点击上方的设置按钮——选择首选项——新建——格式:windows——语言:java——编码:ANSI。
2.HelloWorld案例编写
- 首先定义一个类
public class 类名 - 在类定义后加上一对大括号{}
- 在大括号中间添加一个主(main)方法/函数
public static void main(String [] args){ } - 在主方法的大括号中间添加一行输出语句
System.out.println(“HelloWorld”);
完整代码:
public class HelloWorld {
public static void main(String [] args) {
System.out.println(“HelloWorld”);
}
}
单词拼写注意问题:
注释
●注释概述
-用于解释说明程序的文字
●Java中注释分类
-单行注释
●格式: //注释文字
-多行注释
●格式:/注释文字/
-文档注释
●格式: /*注释文字/
●注释的作用
-解释说明程序,提高程序的阅读性
关键字
- 关键字概述
被Java语言赋予特定含义的单词 - 关键字特点
-组成关键字的字母全部小写
-常用的代码编辑器,针对关键字有特殊的颜色标记,非常直观,所以我们不需要去死记硬背,在今后的学习中重要的关键字也会不断的出来。
static
https://blog.csdn/fengyuzhengfan/article/details/38082999
常量
常量概述:
在程序执行的过程中,其值不可以发生改变的量
常量分类
-字符串常量
用双引号括起来的内容(“HelloWorld”)
-整数常量
所有整数(12,-23)
-小数常量
所有小数(12.34)
-字符常量.
用单引号括起来的内容(a,‘A’,‘0’)
-布尔常量.
较为特有,只有true和false
空常量
null(数组部分讲解)
public class HelloWorld{
public final static String CONSTANT = "HelloWorld";
public final static float PI = 3.14f;
/*主方法*/
public static void main(String[] args){
System.out.println(CONSTANT);
}
变量
-
变量概述
- 在程序执行的过程中,在某个范围内其值可以发生改变的量
- 从本质上讲,变量其实是内存中的一小块区域
-
变量定义格式
- 数据类型 变量名=初始化值;
- 注意:格式是固定的,记住格式,以不变应万变
-
计算机存储单元
变量是内存中的小容器,用来存储数据。那么计算机内存是怎么存储数据的呢?无论是内存还是硬盘,计算机存储设备的最小信息单元叫“位(bit)”,我们又称之为“比特位”,通常用小写的字母b表示。而计算机最小的存储单元叫“字节(byte)”,通常用大写字母B表示,字节是由连续的8个位组成。
除了字节外还有一些常用的存储单位,大家可能比较熟悉,我们一起来看看:
1B(字节) = 8bit
1KB = 1024B
1MB = 1024KB
1GB = 1024MB
1TB = 1024GB
数据类型
Java语言是强类型语言,对于每一种数据都给出了明确的数据类型,不同的数据类型也分配了不同的内存空间,所以它们表示的数据大小也是不一样的。
基本数据类型(4类8种)
标示符
- 作用
给包,类,方法,变量等起名字 - 组成规则
由字符,下划线_,美元符$组成 - 这里的字符采用的是unicode字符集,所以包括英文大小写字母,中文字符,数字字符等。
- 注意事项
- 不能以数字开头
- 不能是Java中的关键字
命名规则
-
基本要求
见名知意 -
常见命名的规则
-
包 (其实就是文件夹,用于对类进行管理)
全部小写,多级包用点隔开。
com,cn,com.demo
命名必须全部使用英文小写字母,禁止使用“下划线”等字符。(除常量外,Java命名 习惯中均不推荐使用下划线等字符)
项目包命名规则: …相关项目可使用…的命名法则。 -
类
- 一个单词首字母大写 Student,Car
- 多个单词,每个单词首字母大写 HelloWorld。
- 如果 Java 程序源代码里定义了一个 public 类,则该源文件的主文件名必须与该 public 类(也就是该类定义使用了 public 关键字修饰)的类名相同。
- 如果 Java 程序源代码里没有定义任何 public 类,那么 Java 程序源程序的主文件名可以是任意的。
- 一个 Java 源文件只定义一个类,不同的类使用不同的源文件定义。
- Class/Qbiect. terface
类和接口使用大驼峰命名法抽象类使用“ Abstract"做为类命名的开头Exception类命名使用“Exception” 做为类命名的结尾
Test类使用"Test" 做为类命名的结尾。
-
变量或者方法
- 一个单词首字母小写。 age,show()
- 多个单词,从第二个单词开始每个单词首字母大写 maxAge,getAge()
变量的定义和使用
- 变量定义的注意事项
- 变量未赋值,不能直接使用
- 引出变量的第二种使用格式
- 变量只在它所属的范围内有效。
- 变量在哪对大括号内,变量就属于哪对大括号
- 一行上可以定义多个变量,但是不建议
类型转换
- +是一个运算符, 我们应该能够看懂,做数据的加法。
boolean类型不能转换为其他的数据类型 - 默认转换
byte,short,char—int—long—float—double
byte,short,char相互之间不转换,他们参与运算首先转换为int类型 - 强制转换
目标类型 变量名=(目标类型)(被转换的数据);
二、Eclipse/IDEA基本使用与配置
1:基本使用
A:创建Java项目:
点击File或者在最左侧空白处,选择Java项目,在界面中写一个项目名称,然后Finish即可。
B:创建包:展开项目,在源包src下建立一个包com.itheima
C:创建类:在com.ithiema包下建立一个类HelloWorld
在界面中写一个类名:HelloWorld,然后finish即可。
D:编写代码
在HelloWorld类写main方法,在main方法中写一条输出语句:我是程序员,我骄傲,我自豪。
E:编译
自动编译,在保存的那一刻帮你做好了
F:运行
选择要运行的文件或者在要运行的文件内容中
右键 -- Run as - Java Application即可
2:基本配置
A:行号的显示和隐藏
显示:在代码区域的最左边的空白区域,右键 -- Show Line Numbers即可。
隐藏:把上面的动作再做一次。
B:字体大小及颜色
a:Java代码区域的字体大小和颜色:
window -- Preferences -- General -- Appearance -- Colors And Fonts -- Java -- Java Edit Text Font
b:控制台
window -- Preferences -- General -- Appearance -- Colors And Fonts -- Debug -- Console font
c:其他文件
window -- Preferences -- General -- Appearance -- Colors And Fonts -- Basic -- Text Font
C:窗体给弄乱了,怎么办?
window -- Perspective -- Reset Perspective
D:控制台找不到了,怎么办?
Window--Show View—Console
3:删除和导入项目
A:删除项目
选中项目 – 右键 – 删除
从项目区域中删除
从硬盘上删除
B:导入项目
在项目区域右键找到import
找到General,展开,并找到
Existing Projects into Workspace
点击next,然后选择你要导入的项目
注意:这里选择的是项目名称
创建eclipse程序如图
4.快捷键汇总
IDEA快捷键
SHIFT+CTRL+ATL+U选中某个类,点击SHIFT+CTRL+ATL+U 选中这个类以及这个类的依赖的类图
CTRL+ALT+L =====>>格式化java代码
Ctrl + X =====>>删除行
Ctrl + D =====>> 复制行
Ctrl + N =====>>查找类
Ctrl + F =====>>查找文本
Ctrl + J =====>>自动代码
Ctrl + H =====>>显示类结构图
Ctrl + Q =====>>显示注释文档
Ctrl + P =====>>方法参数提示
Ctrl + E =====>>最近打开的文件
Ctrl + R =====>>替换当前文本中的代码
Ctrl + End =====>>跳到文件结尾
Ctrl + Home =====>>跳到文件开头
Ctrl + Space =====>>代码提示
Ctrl + Shift + N =====>>查找文件
Ctrl + Shift + R =====>>項目中全局替換
Ctrl + Alt + L =====>>格式化代码
Ctrl + Alt + O =====>>优化导入的类和包
Ctrl + Shift + Space =====>>自动补全代码
Alt + Shift + C =====>>对比最近修改的代码
Alt + Insert =====>>生成代码(如构造函数等)
Ctrl + Alt + Space =====>>类名或接口名提示
Alt + Enter =====>>自动导包
Alt + left / right =====>>切换代码视图
Ctrl + B =====>>快速打开光标处的类或方法
Alt + Up / Down =====>>在方法间快速移动定位
F2 或 Shift + F2 =====>>高亮错误或警告快速定位
Ctrl + Shift + Up / Down =====>>代码向上 / 下移动
Ctrl+E 或者 Alt+Shift+C =====>>最近更改的代码
Ctrl + Shift + Alt + N =====>>查找类中的方法或变量
Ctrl + Alt + left / right =====>>返回至上次浏览的位置
Ctrl + / 或 Ctrl + Shift + / =====>>单行注释或多行注释; 取消单行或多行注释也是一样
fori + Tab 键 =====>>快速创建 for 循环
psvm + Tab 键 =====>>快速创建主函数
sout + Tab 键 =====>>快速创建输出语句
Alt + F7 键 =====>>查看方法在哪里被调用了
Alt + F8 键 =====>>预执行语句
Ctrl + Alt + T =====>>ry-catch 快捷键
Alt + Insert =====>>对字段生成 get 和 set 方法
Ctrl+ I =====>>快速实现接口中的方法
Ctrl+ Shift + Z =====>>恢复 Ctrl +Z去掉的内容
Ctrl+ Shift + Enter =====>>代码自动补全
Ctrl+ Shift + Alt + T =====>>重构代码
Shift + F6 =====>>重命名文件
Ctrl + Alt + V =====>>提取变量
Shift + Shift =====>>全局搜索
Ctrl + F12 =====>>查看当前类的所有方法
F3 =====>>前后移动到下一匹配处
Ctrl + W =====>>按照语法自动选中代码
ALT+ 7 =====>>查看一个类中的所有方法
————————————————
版权声明:本文为CSDN博主「江阿白」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn/weixin_43676842/article/details/100701424
自定义快捷键模板输入
1.使用live模板 setting-Live Template
2. psvm
public static void main(String[]args){
}
- sout
public class User{
public static void main(String[] args) {
//sout
System.out.println();
//soutp; 打印当前的形参
System.out.println("args = [" + args + "]");
//soutm; 打印当前的方法名
System.out.println("User.main");
//soutv; 打印当前的变量
int num = 10;
System.out.println("num = " + num);
}
}
- fori
for (int i = 0; i < ; i++) {
}
- 自己常用的
注释:Ctrl+/ | Ctrl+Shift+/ 前者将当前行注释掉(行首加上//) ,后者将当前选中的内容注释掉(两端打上/* … */)
内容辅助:Alt + / 自动写代码,类似代码提示。
方法定位:按住Ctr1+鼠标左键,可以快速定位到对应的变量、方法或者其他的类等。
格式化:ctrl+shift+F
或者设置保存(ctrl+S)的时候格式化
导包: CTRL + SHIFT + O
查找替换:CTRL+F
get set方法:Alt+Insert (有的电脑没有insert,按键盘上的【fn】+【f12】,那么此时即可在笔记本输入insert。)
格式化
- 生成get,set方法
idea:右击点击Generate or 也可以用快捷键Alt+Insert
注释多行代码:ctrl+shift+/
有用的快键键整理
来自:Eclipse快捷键大全
-
编辑
Ctrl+1 快速修复(最经典的快捷键,就不用多说了,可以解决很多问题,比如import类、try catch包围等)
Ctrl+Shift+F 格式化当前代码
Ctrl+Shift+M 添加类的import导入
Ctrl+Shift+O 组织类的import导入(既有Ctrl+Shift+M的作用,又可以帮你去除没用的导入,很有用)
Ctrl+Y 重做(与撤销Ctrl+Z相反)
==Alt+/ 内容辅助(帮你省了多少次键盘敲打,太常用了) ==
Ctrl+D 删除当前行或者多行
==Alt+↓ 当前行和下面一行交互位置(特别实用,可以省去先剪切,再粘贴了) ==
Alt+↑ 当前行和上面一行交互位置(同上)
Ctrl+Alt+↓ 复制当前行到下一行(复制增加)
Ctrl+Alt+↑ 复制当前行到上一行(复制增加)
Shift+Enter 在当前行的下一行插入空行(这时鼠标可以在当前行的任一位置,不一定是最后)
Ctrl+/ 注释当前行,再按则取消注释 -
选择
Alt+Shift+↑ 选择封装元素
Alt+Shift+← 选择上一个元素
Alt+Shift+→ 选择下一个元素
Shift+← 从光标处开始往左选择字符
Shift+→ 从光标处开始往右选择字符
Ctrl+Shift+← 选中光标左边的单词
Ctrl+Shift+→ 选中光标又边的单词 -
移动
Ctrl+← 光标移到左边单词的开头,相当于vim的b
Ctrl+→ 光标移到右边单词的末尾,相当于vim的e -
搜索
Ctrl+K 参照选中的Word快速定位到下一个(如果没有选中word,则搜索上一次使用搜索的word)
Ctrl+Shift+K 参照选中的Word快速定位到上一个
Ctrl+J 正向增量查找(按下Ctrl+J后,你所输入的每个字母编辑器都提供快速匹配定位到某个单词,如果没有,则在状态栏中显示没有找到了,查一个单词时,特别实用,要退出这个模式,按escape建)
Ctrl+Shift+J 反向增量查找(和上条相同,只不过是从后往前查)
Ctrl+Shift+U 列出所有包含字符串的行
Ctrl+H 打开搜索对话框
Ctrl+G 工作区中的声明
Ctrl+Shift+G 工作区中的引用 -
导航
Ctrl+Shift+T 搜索类(包括工程和关联的第三jar包)
Ctrl+Shift+R 搜索工程中的文件
Ctrl+E 快速显示当前Editer的下拉列表(如果当前页面没有显示的用黑体表示)
F4 打开类型层次结构
F3 跳转到声明处
Alt+← 前一个编辑的页面
Alt+→ 下一个编辑的页面(当然是针对上面那条来说了)
Ctrl+PageUp/PageDown 在编辑器中,切换已经打开的文件 -
调试
F5 单步跳入
F6 单步跳过
F7 单步返回
F8 继续
Ctrl+Shift+D 显示变量的值
Ctrl+Shift+B 在当前行设置或者去掉断点
Ctrl+R 运行至行(超好用,可以节省好多的断点) -
重构
(一般重构的快捷键都是Alt+Shift开头的了)
Alt+Shift+R 重命名方法名、属性或者变量名 (是我自己最爱用的一个了,尤其是变量和类的Rename,比手工方法能节省很多劳动力)
Alt+Shift+M 把一段函数内的代码抽取成方法 (这是重构里面最常用的方法之一了,尤其是对一大堆泥团代码有用)
Alt+Shift+C 修改函数结构(比较实用,有N个函数调用了这个方法,修改一次搞定)
Alt+Shift+L 抽取本地变量( 可以直接把一些魔法数字和字符串抽取成一个变量,尤其是多处调用的时候)
Alt+Shift+F 把Class中的local变量变为field变量 (比较实用的功能)
Alt+Shift+I 合并变量(可能这样说有点不妥Inline)
Alt+Shift+V 移动函数和变量(不怎么常用)
Alt+Shift+Z 重构的后悔药(Undo) -
其他
Alt+Enter 显示当前选择资源的属性,windows下的查看文件的属性就是这个快捷键,通常用来查看文件在windows中的实际路径
Ctrl+↑ 文本编辑器 上滚行
Ctrl+↓ 文本编辑器 下滚行
Ctrl+M 最大化当前的Edit或View (再按则反之)
Ctrl+O 快速显示 OutLine(不开Outline窗口的同学,这个快捷键是必不可少的)
Ctrl+T 快速显示当前类的继承结构
Ctrl+W 关闭当前Editer(windows下关闭打开的对话框也是这个,还有qq、旺旺、浏览器等都是)
Ctrl+L 文本编辑器 转至行
F2 显示工具提示描述 -
idea与eclipse快捷键对比
参考文章:IDEA和Eclipse的比较
IDEA快捷键汇总:
1.idea下设置main快捷键 自动输出 public static void main(String args[]){}方法
参考:idea下设置main快捷键 自动输出 public static void main(String args[]){}方法
查找 CTRL+ F
文件中查找 CTRL + SHIFT + F
5.Debug
1.双击侧边栏,打断点;
2.点击运行debug as;
取消断点:
参考:eclipse如何取消断点
- 方法一:
1.适合于在debug界面,更快速。也可以是在编辑界面切换到debug界面。2、成功进入debug界面之后,从右上角找到breakpoint选项(三个选项中的中间一个)。3、会看到一排图标,一个X号的表示取消选择的debug断点,两个X号的是取消所有断点。选择两个X号的,点击。4、弹出来的对话框,点击yes,就可以取消所有的断点了。 - 方法二:
在javaee等编辑界面,直接使用run–>removebreakpoint。就可以取消所有的断点。
6.包里面再创建包
1.先创建java文件
2.
三、运算符和表达式
运算符
代码
package com.yunSuanFu;
public class YunSuanFu {
/**
* Alt + / 自动写代码,类似代码提示
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//加法
int c = add(1,2);
System.out.println(c);
//减法
float d = substract(3, 2);
System.out.println(d);
//乘法
YunSuanFu yunsuanfu = new YunSuanFu(); //不能将静态的方法写在非静态的方法中
// 非静态的变量(动态的类)就要新建一个对象
int e = yunsuanfu.multiply(5, 6);
System.out.println(e);
//除法
float f = yunsuanfu.divide(33.3f, 3.0f);
System.out.println(f);
int h = yunsuanfu.divide(10, 5);
System.out.println("整数的除法" + h);
//取余
long g = yunsuanfu.mod(10, 3);
System.out.println(g);
}
/** 文档注释
* 两个整数相加
* @param a
* @param b
* return */
public static int add(int a,int b) {
int c = a + b;
return c;
}
/** 减法*/
public static float substract(float a,float b) {
float c = a - b;
return c;
}
/** 乘法*/
public int multiply(int a,int b) {
int c = a * b;
return c;
}
/** 除法*/
public float divide(float a,float b) {
return a/b;
}
public int divide(int a,int b) {
return a/b;
}
/** 取余*/
public long mod(long a,long b) {
return a % b;
}
}
运算符
- 对常量和变量进行操作的符号称为运算符
表达式 - 用运算符把常量或者变量连接起来符合java语法的式子就可以称为表达式。不同运算符连接的式子体现的是不同类型的表达式。
定义两个int类型的变量a,b,做加法(a+ b) - 常用运算符
算术运算符
赋值运算符
关系运算符
逻辑运算符
三元运算符
算术运算符
• +,-,*,/的基本使用
%的使用
– %和/的区别
• ++,–
自增自减
- 字符和字符串参与+运算
int i = 10;
int j = 5;
System.out.println(++i); //++放在前面的时候先加1再做其他运算
System.out.println(j++); //++放在后面的时候先调用它的值再加1
System.out.println(j);
输出结果:
11
5
6
• 字符参与运算
– 其实是拿该字符对应的数值来操作
– ‘a’ 97
– ‘A’ 65
– ‘0’ 48
• 字符串参与运算
– 这里其实做的不是加法运算,而是字符串拼接。
– 字符串和其他类型的数据做拼接,结果是字符串类型的。
- 赋值运算符
• 基本的赋值运算符: =
• 扩展的赋值运算符:+=,-=,*=,/=,…
关系运算符
• ==,!=,>,>=,<,<=
• 关系运算符的结果都是boolean型,也就是要么是true,要么是false。
• 注意事项
– 关系运算符“ ==”不能误写成“=” 。
-逻辑运算符
• 逻辑运算符用于连接布尔型表达式,在Java中不
可以写成3<x<6,应该写成x>3 && x<6 。
• &,|,^,!
• &&,||
– “&”和“&&”的区别:
• 单&时,左边无论真假,右边都进行运算;
• 双&时,如果左边为真,右边参与运算,如果左边为假,那么右边不参与运算。
• “|”和“||”的区别同理,双或时,左边为真,右边不参与运算。第一个左边为假判断右边第二个。
- 三元运算符
• 格式
– (关系表达式)?表达式1:表达式2;
– 如果条件为true,运算后的结果是表达式1;
– 如果条件为false,运算后的结果是表达式2;
• 示例:
– 获取两个数中大数。
– int x=3,y=4,z;
– z = (x>y)?x:y;//z变量存储的就是两个数的大数。
键盘录入
键盘录入数据概述
我们目前在写程序的时候,数据值都是固定的,但是实际开发中,数据值肯定是变化的,所以,把数据改进为键盘录入,提高程序的灵活性。
如何实现键盘录入数据呢?(目前先记住使用)
导包(位置放到class定义的上面)
import java.util.Scanner;
创建对象
Scanner sc = new Scanner(System.in);
接收数据
int x = sc.nextInt();
核心步骤:
//0.导入包
import java.util.Scanner;
// 1.创建键盘录入的对象
Scanner sc = new Scanner(System.in);
// 2.接收数据
System.out.println("请输入第一个数据:");
int a = sc.nextInt();
System.out.println("请输入第二个数据:");
int b = sc.nextInt();
练习:
键盘录入两个数据,并对这两个数据求和,输出其结果
键盘录入两个数据,获取这两个数据中的最大值
键盘录入两个数据,比较这两个数据是否相等
键盘录入三个数据,获取这三个数据中的最大值
代码:
package com.demo;
import java.util.Scanner;
/**
* 引入包 CTRL + SHIFT + O
*/
public class ScannerDemo {
public static void main(String[] args) {
// 1.创建键盘录入的对象
Scanner sc = new Scanner(System.in);
// 2.接收数据
System.out.println("请输入第一个数据:");
int a = sc.nextInt();
System.out.println("请输入第二个数据:");
int b = sc.nextInt();
// 对数据进行求和
int sum = a + b;
System.out.println("sum = " + sum);
// 三元组运算符判断两个数是否相等
boolean flag = ((a == b) ? true : false);
System.out.println("flag:" + flag);
System.out.println("请输入第三个数据:");
int c = sc.nextInt();
int temp = ((a > b) ? a : b);
int max = ((temp > c) ? temp : c);
System.out.println("max: " + max);
}
}
四、条件判断与循环语句
选择结构
- if
if语句有三种格式
if语句第一种格式:
if(关系表达式) {
语句体
}
执行流程
首先判断关系表达式看其结果是true还是false
如果是true就执行语句体
如果是false就不执行语句体
if语句第二种格式:
if(关系表达式) {
语句体1;
}else {
语句体2;
}
执行流程
首先判断关系表达式看其结果是true还是false
如果是true就执行语句体1
如果是false就执行语句体2
if语句第三种格式:
if(关系表达式1) {
语句体1;
}else if (关系表达式2) {
语句体2;
}
…
else {
语句体n+1;
}
- switch
switch语句格式:
switch(表达式) {
case 值1:
语句体1;
break;
case 值2:
语句体2;
break;
…
default:
语句体n+1;
break;
}
格式解释
switch表示这是switch语句
表达式的取值:byte,short,int,char
JDK5以后可以是枚举
JDK7以后可以是String
case后面跟的是要和表达式进行比较的值
语句体部分可以是一条或多条语句
break表示中断,结束的意思,可以结束switch语句
default语句表示所有情况都不匹配的时候,就执行该处的内容,和if语句的else相似。
循环结构
- for
for循环语句格式:
for(初始化语句;判断条件语句;控制条件语句) {
循环体语句;
}
执行流程
A:执行初始化语句
B:执行判断条件语句,看其结果是true还是false
如果是false,循环结束。
如果是true,继续执行。
C:执行循环体语句
D:执行控制条件语句
E:回到B继续
- while
while循环语句格式:
基本格式
while(判断条件语句) {
循环体语句;
}
改版格式
初始化语句;
while(判断条件语句) {
循环体语句;
控制条件语句;
}
- do … while
do…while循环语句格式:
基本格式
do {
循环体语句;
}while((判断条件语句);
改版格式
初始化语句;
do {
循环体语句;
控制条件语句;
} while((判断条件语句);
- for while do…while对比
虽然可以完成同样的功能,但是还是有小区别:
do…while循环至少会执行一次循环体。
for循环和while循环只有在条件成立的时候才会去执行循环体
for循环语句和while循环语句的小区别:
使用区别:控制条件语句所控制的那个变量,在for循环结束后,就不能再被访问到了,而while循环结束还可以继续使用,如果你想继续使用,就用while,否则推荐使用for。原因是for循环结束,该变量就从内存中消失,能够提高内存的使用效率。 - continue 与 break
-
continue的使用场景:
在循环语句中
离开使用场景的存在是没有意义的
continue的作用:
单层循环对比break,然后总结两个的区别
break 退出当前循环
continue 退出本次循环 -
break的使用场景:
在选择结构switch语句中
在循环语句中
离开使用场景的存在是没有意义的
break的作用:
跳出单层循环
-
随机数
作用:
用于产生一个随机数
使用步骤(和Scanner类似)
导包
import java.util.Random;
创建对象
Random r = new Random();
获取随机数
int number = r.nextInt(10);
//10表示随机数的范围0-10
产生的数据在0到10之间,包括0,不包括10。
Random r = new Random();
int number = r.nextInt(10);
如何获取一个1-100之间的随机数呢?
Random r = new Random();
int number = r.nextInt(10) + 1; //在结果出加1,随机数是默认范围从0开始。
综合练习
猜数字小游戏案例
系统产生一个1-100之间的随机数,请猜出这个数据是多少。
分析:
A:系统产生一个1-100之间的随机数
Random r = new Random();
int number = r.nextInt(100) + 1;
B:键盘录入我们要猜的数据
C:比较这两个数据,用if语句实现
大了:提示大了
小了:提示小了
猜中了:提示恭喜你,猜中了
D:多次猜数据,而我们不知道猜多少次,怎么办呢?
==while(true) {循环体语句;}==表示一直运行。
public class RandomTest {
public static void main(String[] args) {
//系统产生一个1-100之间的随机数
Random r = new Random();
//获取随机数
int number = r.nextInt(100) + 1;
//多次猜数据
while(true) { //while(true)表示一直运行
//键盘录入我们要猜的数据
Scanner sc = new Scanner(System.in);
//接收数据
System.out.println("请输入你要猜的数据(1-100):");
int guessNumber = sc.nextInt();
//比较这两个数据,用if语句实现
if(guessNumber > number) {
System.out.println("你猜的数据"+guessNumber+"大了");
}else if(guessNumber < number) {
System.out.println("你猜的数据"+guessNumber+"小了");
}else {
System.out.println("恭喜你,猜中了");
break; //跳出循环
}
}
}
}
五、数组
一维数组&内存图解
- 数组的概念
- 定义格式
格式1:数据类型[] 数组名;
格式2:数据类型 数组名[];
注意:这两种定义做完了,数组中是没有元素值的。
数组初始化概述:
Java中的数组必须先初始化,然后才能使用。
所谓初始化:就是为数组中的数组元素分配内存空间,并为每个数组元素赋值。
数组的初始化方式:
动态初始化:初始化时只指定数组长度,由系统为数组分配初始值。
格式:数据类型[] 数组名 = new 数据类型[数组长度];
数组长度其实就是数组中元素的个数。
举例:
int[] arr = new int[3];
解释:定义了一个int类型的数组,这个数组中可以存放3个int类型的值。
静态初始化:初始化时指定每个数组元素的初始值,由系统决定数组长度。
静态初始化:初始化时指定每个数组元素的初始值,由系统决定数组长度。
格式:
数据类型[] 数组名 = new 数据类型[]{元素1,元素2,…};
举例:
int[] arr = new int[]{1,2,3};
解释:定义了一个int类型的数组,这个数组中可以存放3个int类型的值,并且值分别是1,2,3。
其实这种写法还有一个简化的写法
int[] arr = {1,2,3};
java中的内存分配:
Java 程序在运行时,需要在内存中分配空间。为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
栈 存储局部变量
堆 存储new出来的东西
方法区 (面向对象进阶讲)
本地方法区 (和系统相关)
寄存器 (给CPU使用)
-
数组操作的两个常见小问题
1.数组索引越界
ArrayIndexOutOfBoundsException
访问到了数组中的不存在的索引时发生。
2.空指针异常
NullPointerException
数组引用没有指向对象,却在操作对象中的元素时。 -
内存图解1:
定义一个数组,输出数组名及元素。然后给数组中的元素赋值,再次输出数组名及元素。
-
内存图解2:
定义两个数组,分别输出数组名及元素。然后分别给数组中的元素赋值,分别再次输出数组名及元素。
-
内存图解3:
定义两个数组,先定义一个数组,赋值,输出。然后定义第二个数组的时候把第一个数组的地址赋值给第二个数组。然后给第二个数组赋值,再次输出两个数组的名及元素。
-
练习
一维数组遍历:
public class array {
public static void main(String[] args) {
// int[] arr = new int[6];
int[] arr = { 2, 4, 5, 6 };
// int array[3] = {2,4,5,6};
for (int i = 0; i <= 3; i++) {
System.out.println(arr[i]);
}
}
}
- 获取数值长度:数值名.length
- 数组获取最值(获取数组中的最大值最小值)
先画图,然后讲解
二维数组
- 定义格式
数据类型[][] 数组名;
数据类型 数组名[][]; 不推荐
数据类型[] 数组名[]; 不推荐 - 初始化方式
数据类型[][] 变量名 = new 数据类型[m][n];
数据类型[][] 变量名 = new 数据类型[][]{{元素…},{元素…},{元素…}};
简化版格式:数据类型[][] 变量名 = {{元素…},{元素…},{元素…}}; - 二维数组遍历
int[][] arr = {{1,2,3},{4,5,6},{7,8,9}};
六、方法
方法定义及格式
-
简单的说:方法就是完成特定功能的代码块
在很多语言里面都有函数的定义
函数在Java中被称为方法 -
格式:
修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数名2…) {
函数体;
return 返回值;
} -
方法格式解释
修饰符 目前记住 public static
返回值类型 用于限定返回值的数据类型
方法名 一个名字,为了方便我们调用方法
参数类型 用于限定调用方法时传入的数据的类型
参数名 用于接收调用方法时传入的数据的变量
方法体 完成功能的代码
return 结束方法,把返回值带给调用者 -
方法案例
写一个方法首先有两点需要明确
返回值类型 明确功能结果的数据类型
参数列表 明确有几个参数,以及参数的类型
按照格式和两个明确来完成如下功能
求两个数据之和的案例
形参和实参
参考:java形参和实参
1.形参:形参定义在方法(函数)中,只有调用所对应的函数时才会分配给形参内存单元,调用结束后释放所分配的内存单元,因此形参只可以在定义的函数内部使用。
2.实参:实参可以是变量,常量,表达式等等。从刚开始定义便有内存单元,所分配的内存单元与是否调用无关。
例如
package com.demo03;
/*
* 方法重载:在同一个类中,出现了方法名相同的情况。
* 方法重载的特点:
* 方法名相同,参数列表不同。与返回值无关。
* 参数列表不同:
* 参数的个数不同
* 参数对应的数据类型不同
*
* 注意:
* 在调用方法的时候,java虚拟机会通过参数列表的不同来区分同名的方法。
*/
public class MethodDemo {
public static void main(String[] args) {
float c = sum(1.2f,2.3f); //1.2f,2.3f实参
System.out.println(c);
}
//不能出现方法名相同,并且参数列表也相同的情况
// public static int sum(int x,int y) { //x,y形参
// return x + y;
// }
public static float sum(float a,float b) {
return a + b;
}
//求三个数据的和
/*
public static int sum2(int a,int b,int c) {
return a + b + c;
}
*/
public static int sum(int a,int b,int c) {
return a + b + c;
}
//求两个数据的和方法
public static int sum(int a,int b) {
//int c = a + b;
//return c;
return a + b;
}
}
package com.demo04;
/*
* 方法的参数如果是基本数据类型:形式参数的改变不影响实际参数。
*
* 形式参数:用于接收实际参数的变量
* 实际参数:实际参与运算的变量
*/
public class ArgsDemo {
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println("a:"+a+",b:"+b);//a:10,b:20
change(a,b);
System.out.println("a:"+a+",b:"+b);//??? a:10,b:20
}
public static void change(int a,int b) {//a=10,b=20
System.out.println("a:"+a+",b:"+b);//a:10,b:20
a = b;//a=20
b = a + b;//b=40
System.out.println("a:"+a+",b:"+b);//a:20,b:40
}
}
package com.demo04;
/*
* 如果参数是引用数据类型:
* 形式参数的改变直接影响实际参数
*/
public class ArgsDemo2 {
public static void main(String[] args) {
int[] arr = { 1, 2, 3, 4, 5 };
for (int x = 0; x < arr.length; x++) {
System.out. println(arr[x]);
}
System.out.println("-------------------------");
change(arr);
for (int x = 0; x < arr.length; x++) {
System.out.println(arr[x]);
}
}
public static void change(int[] arr) {
for (int x = 0; x < arr.length; x++) {
if (arr[x] % 2 == 0) {
arr[x] *= 2;
}
}
}
}
-
有明确返回值的方法调用
单独调用,没有意义
输出调用,有意义,但是不够好,因为我不一定非要把结果输出
赋值调用,推荐方式 -
有明确返回值的方法练习
键盘录入两个数据,返回两个数中的较大值
键盘录入两个数据,比较两个数是否相等
键盘录入三个数据,返回三个数中的最大值 -
没有明确返回值的方法定义和调用
写一个方法,在控制台输出10次HelloWorld案例。
没有明确返回值的函数调用:
其实就是void类型方法的调用
只能单独调用 -
没有明确返回值的方法练习
写一个方法,传递一个整数(大于1),在控制台打印1到该数据的值。
写一个方法,把所有的水仙花数打印在控制台
方法重载
方法重载概述
在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
方法重载特点
与返回值类型无关,只看方法名和参数列表
在调用时,虚拟机通过参数列表的不同来区分同名方法
- 方法重载练习
比较两个数据是否相等。参数类型分别为两个byte类型,两个short类型,两个int类型,两个long类型,并在main方法中进行测试
package com.demo03;
/*
* 比较两个数据是否相等。参数类型分别为两个byte类型,两个short类型,两个int类型,两个long类型,并在main方法中进行测试
*/
public class MethodTest {
public static void main(String[] args) {
//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));
}
//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;
}
}
-
方法参数传递问题
看程序写结果,并总结基本类型和引用类型参数的传递问题(代码在备注部分) -
方法练习
1.把遍历数组改进为方法实现,并调用方法
package fangFa;
public class printArray {
public static void main(String[] args) {
// int[] arr = new int[4];
int arr2[] = { 1, 2, 3 };
printArray2(arr2);
}
public static void printArray2(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] + ",");
}
}
}
}
2.把获取数组最值改进为方法实现,并调用方法
public class MethodTest2 {
public static void main(String[] args) {
//定义数组
int[] arr = {24,36,90,75,81};
/*
//定义参照物
int max = arr[0];
//遍历数组,获取元素,依次比较
for(int x=1; x<arr.length; x++) {
if(arr[x] > max) {
max = arr[x];
}
}
*/
//写方法实现获取数组中的最大值
int min = getMin(arr);
//输出结果
System.out.println("min:"+min);
}
/*
* 两个明确:
* 返回值类型:int
* 参数列表:int[] arr
*/
public static int getMin(int[] arr) {
//定义参照物
int min = arr[0];
//遍历数组,获取元素,依次比较
for(int x=1; x<arr.length; x++) {
if(arr[x] < min) {
min = arr[x];
}
}
return min;
}
}
写一个方法,用于对数组进行求和,并调用方法。
package com.demo05;
/*
* 写一个方法,用于对数组进行求和,并调用方法。
*/
public class MethodTest3 {
public static void main(String[] args) {
//定义数组
int[] arr = {1,2,3,4,5};
/*
//定义求和变量
int sum = 0;
//获取数组中的每一个元素
for(int x=0; x<arr.length; x++) {
//累加
sum += arr[x];
}
*/
//写方法实现
int sum = sum(arr);
//输出结果
System.out.println("sum:"+sum);
}
/*
* 两个明确:
* 返回值类型:int
* 参数列表:int[] arr
*/
public static int sum(int[] arr) {
//定义求和变量
int sum = 0;
//获取数组中的每一个元素
for(int x=0; x<arr.length; x++) {
//累加
sum += arr[x];
}
return sum;
}
}
上半部分基础语法系统练习
题目
- 键盘录入月份,输出对应的季节
2. 打印5位数中所有的回文数
3. 不死神兔问题
4. 求数组中满足要求的元素和
5. 裁判评分
6. 数组反转
7. 数组基本查找
8. 数据加密
1. 键盘录入月份,输出对应的季节(键盘录入+循环)
package com.demo1;
/*
* 需求:键盘录入一个月份,输出该月份对应的季节。
* 一年有四季
* 3,4,5 春季
* 6,7,8 夏季
* 9,10,11 秋季
* 12,1,2 冬季
*
*
* */
import java.util.Scanner;
public class jiJie {
public static void main(String[] args) {
// 键盘录入
Scanner sc = new Scanner(System.in);
// 接收数据
System.out.println("键盘输入月份:");
int month = sc.nextInt();
while ((month >= 1) && (month <= 12)) {
if ((month == 3) || (month == 4) || (month == 5)) {
System.out.println("春季");
break;
}
if ((month == 6) || (month == 7) || (month == 8)) {
System.out.println("夏季");
break;
}
if ((month == 9) || (month == 10) || (month == 11)) {
System.out.println("秋季");
break;
}
if ((month == 12) || (month == 1) || (month == 2)) {
System.out.println("冬季");
break;
}
}
}
}
2.打印5位数中所有的回文数 (for+if训练)
package com.demo;
/*
* 需求:打印5位数中的所有回文数。
* 什么是回文数呢?举例:12321是回文数,个位与万位相同,十位与千位相同。
*
* 分析:
* A:5位数告诉了我们数据的范围,用for循环实现
* B:拿到每一个5位数后,获取其个位,十位,千位,万位的数据
* 如何获取呢?假设x是一个5位数
* 个位:x%10
* 十位:x/10%10
* 千位:x/10/10/10%10
* 万位:x/10/10/10/10%10
* C:根据条件进行判断,把满足条件的数据输出即可
*/
public class Test3 {
public static void main(String[] args) {
//5位数告诉了我们数据的范围,用for循环实现
int i = 0;
for(int x=10000; x<100000; x++) {
//拿到每一个5位数后,获取其个位,十位,千位,万位的数据
int ge = x%10;
int shi = x/10%10;
int qian = x/10/10/10%10;
int wan = x/10/10/10/10%10;
//根据条件进行判断,把满足条件的数据输出即可
if((ge == wan) && (shi == qian)) {
System.out.println(x);
i++;
}
}
System.out.println(i);
}
}
3. 不死神兔问题
package com.demo;
/*
* 需求:
* 有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,
* 假如兔子都不死,问第二十个月的兔子对数为多少?
*
* 规律:
* 第一个月:1
* 第二个月:1
* 第三个月:2
* 第四个月:3
* 第五个月:5
* ...
*
* 规律:从第三个月开始,每个月的兔子对数是前两个月的兔子对数之和
* 第一个月和第二个月的兔子对数都是1
*
* 分析:
* A:由于数据比较多,所以我们就定义数组来实现了
* int[] arr = new int[20];
* B:给数组的元素赋值
* arr[0] = 1
* arr[1] = 2
* C:找规律
* arr[2] = arr[1] + arr[0];
* arr[3] = arr[2] + arr[1];
* arr[4] = arr[3] + arr[2];
* arr[5] = arr[4] + arr[3];
* ...
*/
public class Test4 {
public static void main(String[] args) {
//定义数组
int[] arr = new int[20];
//给数组的元素赋值
arr[0] = 1;
arr[1] = 1;
//找规律赋值
for(int x=2; x<arr.length; x++) {
arr[x] = arr[x-1] + arr[x-2];
}
//输出结果
System.out.println("第二十个月兔子的对数是:"+arr[19]);
}
}
4. 求数组中满足要求的元素和
package com.demo;
/*
* 需求:
* (1)定义一个int类型的一维数组,内容为{171,72,19,16,118,51,210,7,18}
* (2)求出该数组中满足要求的元素和。
* 要求:求和的元素的个位和十位不能包含7,并且只能为偶数。
*
* 分析:
* A:定义一个int类型的一维数组
* B:定义一个求和变量
* C:遍历数组,获取数组中的每一个元素
* D:判断该元素是否满足条件,如果满足条件就累加
* 假设该数据是x
* 个位不能是7:x%10 != 7
* 十位不能是7:x/10%10 != 7
* 必须是偶数:x%2 == 0
* E:输出求和结果
*/
public class Test5 {
public static void main(String[] args) {
//定义一个int类型的一维数组
int[] arr = {171,72,19,16,118,51,210,7,18};
//定义一个求和变量
int sum = 0;
//遍历数组,获取数组中的每一个元素
for(int x=0; x<arr.length; x++) {
//判断该元素是否满足条件,如果满足条件就累加
if((arr[x]%10 != 7) && (arr[x]/10%10 != 7) && (arr[x]%2 == 0)) {
sum += arr[x];
}
}
//输出求和结果
System.out.println("sum:"+sum);
}
}
5. 裁判评分
package com.demo;
import java.util.Scanner;
/*
* 需求:在编程竞赛中,有6个评委为参赛的选手打分,分数为0-100的整数分。
* 选手的最后得分为:去掉一个最高分和一个最低分后 的4个评委平均值。
* 请写代码实现。(不考虑小数部分)
*
* 分析:
* A:定义一个长度为6的数组
* B:键盘录入评委的分数
* C:写方法实现获取最高分,最低分
* D:写方法求评委的分数和
* E:平均分:(和-最高分-最低分)/(arr.length-2)
* F:输出平均分即可
*/
public class Test6 {
public static void main(String[] args) {
//定义一个长度为6的数组
int[] arr = new int[6];
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
//键盘录入评委的分数
for(int x=0; x<arr.length; x++) {
//接收数据
System.out.println("请输入第"+(x+1)+"个评委给出的分数(0-100):");
int score = sc.nextInt();
arr[x] = score;
}
//写方法实现获取最高分,最低分
//调用方法
int max = getMax(arr);
int min = getMin(arr);
//写方法求评委的分数和
int sum = sum(arr);
//平均分:(和-最高分-最低分)/(arr.length-2)
int avg = (sum-max-min)/(arr.length-2);
//输出平均分即可
System.out.println("该选手的最终得分是:"+avg);
}
/*
* 两个明确:
* 返回值类型:int
* 参数列表:int[] arr
*/
public static int sum(int[] arr) {
//定义求和变量
int sum = 0;
for(int x=0; x<arr.length; x++) {
sum += arr[x];
}
return sum;
}
/*
* 两个明确:
* 返回值类型:int
* 参数列表:int[] arr
*/
public static int getMin(int[] arr) {
//定义参照物
int min = arr[0];
for(int x=1; x<arr.length; x++) {
if(arr[x] < min) {
min = arr[x];
}
}
return min;
}
/*
* 两个明确:
* 返回值类型:int
* 参数列表:int[] arr
*/
public static int getMax(int[] arr) {
//定义参照物
int max = arr[0];
for(int x=1; x<arr.length; x++) {
if(arr[x] > max) {
max = arr[x];
}
}
return max;
}
}
6. 数组反转
package com.demo;
import java.util.Scanner;
/*
* 需求:
* (1)键盘录入5个int类型的数据存储数组arr中
* (2)定义方法将arr数组中的内容反转
* (3)定义方法对反转后的数组进行遍历
*
* 分析:
* A:定义一个长度为5的数组
* B:通过键盘录入数据给数组中的元素赋值
* C:定义方法将arr数组中的内容反转
* 什么是反转?如何实现反转
* D:定义方法对反转后的数组进行遍历
*/
public class Test7 {
public static void main(String[] args) {
//定义一个长度为5的数组
int[] arr = new int[5];
//通过键盘录入数据给数组中的元素赋值
Scanner sc = new Scanner(System.in);
for(int x=0; x<arr.length; x++) {
System.out.println("请输入"+(x+1)+"个元素值:");
int number = sc.nextInt();
arr[x] = number;
}
//反转前
printArray(arr);
//定义方法将arr数组中的内容反转
reverse(arr);
//定义方法对反转后的数组进行遍历
printArray(arr);
}
//遍历数组
public static void printArray(int[] arr) {
System.out.print("[");
for(int x=0; x<arr.length; x++) {
if(x==arr.length-1) {
System.out.println(arr[x]+"]");
}else {
System.out.print(arr[x]+", ");
}
}
}
/*
* 两个明确:
* 返回值类型:void
* 参数列表:int[] arr
*/
public static void reverse(int[] arr) {
for(int start=0,end=arr.length-1; start<=end; start++,end--) {
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
}
}
}
7. 数组基本查找
package com.demo;
import java.util.Scanner;
/*
* 需求:
* (1)键盘录入5个int类型的数据存储数组arr中
* (2)定义方法将arr数组中的内容反转
* (3)定义方法对反转后的数组进行遍历
*
* 分析:
* A:定义一个长度为5的数组
* B:通过键盘录入数据给数组中的元素赋值
* C:定义方法将arr数组中的内容反转
* 什么是反转?如何实现反转
* D:定义方法对反转后的数组进行遍历
*/
public class Test7 {
public static void main(String[] args) {
//定义一个长度为5的数组
int[] arr = new int[5];
//通过键盘录入数据给数组中的元素赋值
Scanner sc = new Scanner(System.in);
for(int x=0; x<arr.length; x++) {
System.out.println("请输入"+(x+1)+"个元素值:");
int number = sc.nextInt();
arr[x] = number;
}
//反转前
printArray(arr);
//定义方法将arr数组中的内容反转
reverse(arr);
//定义方法对反转后的数组进行遍历
printArray(arr);
}
//遍历数组
public static void printArray(int[] arr) {
System.out.print("[");
for(int x=0; x<arr.length; x++) {
if(x==arr.length-1) {
System.out.println(arr[x]+"]");
}else {
System.out.print(arr[x]+", ");
}
}
}
/*
* 两个明确:
* 返回值类型:void
* 参数列表:int[] arr
*/
public static void reverse(int[] arr) {
for(int start=0,end=arr.length-1; start<=end; start++,end--) {
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
}
}
}
8. 数据加密
package com.demo;
import java.util.Scanner;
/*
* 需求:键盘录入数据,要求数据是四位的整数,现需要对数据进行加密,加密规则如下:
* 每位数字都加上5,然后除以10的余数代替该数字,
* 再将第一位和第四位交换,第二位和第三位交换,
* 请把加密后的数据输出到控制台
*
* 分析:
* A:键盘录入一个4位数
* 举例:4567
* B:定义一个长度为4的数组
* int[] arr = new int[4];
* arr = {4,5,6,7};
* C:对数组中的数据进行加密规则的操作
* 每位数字都加上5,然后除以10的余数代替该数字
* arr[x] += 5;
* 结果:arr = {9,10,11,12};
* arr[x] %= 10;
* 结果:arr = {9,0,1,2};
* 再将第一位和第四位交换,第二位和第三位交换
* 结果:arr = {2,1,0,9};
* D:请把加密后的数据输出到控制台
*/
public class Test9 {
public static void main(String[] args) {
//键盘录入一个4位数
Scanner sc = new Scanner(System.in);
//接收数据
System.out.println("请输入一个4位数:");
int number = sc.nextInt();
//定义一个长度为4的数组
int[] arr = new int[4];
arr[0] = number/10/10/10%10;
arr[1] = number/10/10%10;
arr[2] = number/10%10;
arr[3] = number%10;
//对数组中的数据进行加密规则的操作
//每位数字都加上5,然后除以10的余数代替该数字
for(int x=0; x<arr.length; x++) {
arr[x] += 5;
arr[x] %= 10;
}
//再将第一位和第四位交换,第二位和第三位交换
int temp = arr[0];
arr[0] = arr[3];
arr[3] = temp;
temp = arr[1];
arr[1] = arr[2];
arr[2] = temp;
//请把加密后的数据输出到控制台
for(int x=0; x<arr.length; x++) {
System.out.print(arr[x]);
}
System.out.println();
}
}
七、面向对象基础
1.面向对象思想概述及举例
我们回想一下,这几天我们完成一个需求的步骤:首先是搞清楚我们要做什么,然后再分析怎么做,最后我们再代码体现。一步一步去实现,而具体的每一步都需要我们去实现和操作。这些步骤相互调用和协作,完成我们的需求。
在上面的每一个具体步骤中我们都是参与者,并且需要面对具体的每一个步骤和过程,这就是面向过程最直接的体现。
那么什么是面向过程开发呢? 面向过程开发,其实就是面向着具体的每一个步骤和过程,把每一个步骤和过程完成,然后由这些功能方法相互调用,完成需求。
面向过程的代表语言:C语言
- 面向对象思想特点
是一种更符合我们思考习惯的思想
可以将复杂的事情简单化
将我们从执行者变成了指挥者
角色发生了转换 - 面向对象思想举例(demo01)
买电脑
洗衣服
2.类与对象及其使用
-
类与对象的关系
我们学习编程语言,就是为了模拟现实世界的事物,实现信息化。比如:去超市买东西的计费系统,去银行办业务的系统。
我们如何表示一个现实世界事物呢:
属性 就是该事物的描述信息
行为 就是该事物能够做什么
举例:学生事物
我们学习的Java语言最基本单位是类,所以,我们就应该把事物用一个类来体现。
类:是一组相关的属性和行为的集合
对象:是该类事物的具体体现
举例:
类 学生
对象 班长就是一个对象 -
类的定义
现实世界的事物
属性 事物的描述信息
行为 事物能做什么 -
Java中用class描述事物也是如此
成员变量 就是事物的属性
成员方法 就是事物的行为
定义类其实就是定义类的成员(成员变量和成员方法) -
学生类
package com.demo02;
/*
* 类的定义:
* 类是用来描述现实世界的事物的
*
* 事物:
* 属性 事物的描述信息
* 行为 事物能够做什么
*
* 类是如何和事物进行对应的呢?
* 类:
* 成员变量
* 成员方法
*
* 需求:写一个学生类
*
* 学生事物:
* 属性:姓名,年龄...
* 行为:学习,吃饭...
*
* 学生类:
* 成员变量:姓名,年龄
* 成员方法:学习,吃饭
*
* 成员变量:和我们前面学习过的变量的定义是一样的。
* 位置不同:类中,方法外
* 初始化值:不需要给初始化值
* 成员方法:和我们前面学习过的方法的定义是一样的。
* 去掉static关键字
*/
public class Student {
//成员变量
//姓名
String name;
//年龄
int age;
//成员方法
//学习的方法
public void study() {
System.out.println("好好学习,天天向上");
}
//吃饭的方法
public void eat() {
System.out.println("学习饿了要吃饭");
}
}
- 学生类测试
package com.demo02;
/*
* Student是一个学生事物描述类,main方法不适合放在它里面。
*
* 使用一个类,其实就是使用该类的成员。(成员变量和成员方法)
* 而我们要想使用一个类的成员,就必须首先拥有该类的对象。
* 我们如何拥有一个类的对象呢?
* 创建对象就可以了?
* 我们如何创建对象呢?
* 格式:类名 对象名 = new 类名();
* 对象如何访问成员呢?
* 成员变量:对象名.变量名
* 成员方法:对象名.方法名(...)
*/
public class StudentDemo {
public static void main(String[] args) {
//格式:类名 对象名 = new 类名();
Student s = new Student();
//System.out.println("s:"+s); //com.demo02.Student@193c0cf
/*//直接输出成员变量值
System.out.println("姓名:"+s.name); //null
System.out.println("年龄:"+s.age); //0
System.out.println("----------");
//给成员变量赋值
s.name = "林青霞";
s.age = 28;
//再次输出成员变量的值
System.out.println("姓名:"+s.name); //林青霞
System.out.println("年龄:"+s.age); //28
System.out.println("----------");*/
//调用成员方法
s.study();
s.eat();
}
}
如何定义
按照事物到类的过程一步步分析
如何使用
创建对象:
类名 对象名 = new 类名();
对象名.成员变量
对象名.成员方法
3.对象内存存储机制
- 1个对象的内存
一个对象的基本初始化过程 - 2个对象的内存
方法的共用 - 2个对象的内存
两个引用指向同一个对象
对象指向一个地址
package com.demo03;
/*
* 手机类的测试类
*/
public class PhoneDemo3 {
public static void main(String[] args) {
Phone p = new Phone();
p.brand = "OPPO";
p.price = 2999;
p.color = "白色";
System.out.println("p:"+p);
System.out.println(p.brand+"---"+p.price+"---"+p.color);
Phone p2 = p; //把p的内存地址直接给了p2
p2.brand = "魅族";
p2.price = 1999;
p2.color = "蓝色";
System.out.println("再次输出p:"+p);
System.out.println("p2:"+p2);
System.out.println(p.brand+"---"+p.price+"---"+p.color);
System.out.println(p2.brand+"---"+p2.price+"---"+p2.color);
}
}
输出结果:
4.成员变量和局部变量的区别
- 在类中的位置不同
成员变量 类中方法外
局部变量 方法内或者方法声明上,离开方法就不能用了。 - 在内存中的位置不同
成员变量 堆内存
局部变量 栈内存 - 生命周期不同
成员变量 随着对象的存在而存在,随着对象的消失而消失
局部变量 随着方法的调用而存在,随着方法的调用完毕而消失 - 初始化值不同
成员变量 有默认的初始化值
局部变量 没有默认的初始化值,必须先定义,赋值,才能使用。
一个标准的案例的使用
package com.demo04;
/*
* 成员变量和局部变量的区别:
* A:在类中的位置不同
* 成员变量:类中,方法外
* 局部变量:方法中或者方法声明上(形式参数)
* B:在内存中的位置不同
* 成员变量:堆内存
* 局部变量:栈内存
* C:生命周期不同
* 成员变量:随着对象的创建而存在,随着对象的消失而消失
* 局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
* D:初始化值的问题
* 成员变量:有默认值
* 局部变量:没有默认值。必须先定义,赋值,最后使用
*/
public class Variable {
int x; //成员变量 堆内存
public void show(){
int y = 1; //局部变量 栈内存
System.out.println(x);
System.out.println(y);
}
public static void main(String[] args){
Variable v = new Variable();
v.show();
}
}
输出:
0
1
- private关键字
是一个权限修饰符。
可以修饰成员(成员变量和成员方法)
被private修饰的成员只在本类中才能访问。
- private最常见的应用:
把成员变量用private修饰
提供对应的getXxx()/setXxx()方法- setXxx() 赋值
- getXxx() 获取值
Student:
package demo2;
/*
* 学生类(私有)
*
* 通过对象直接访问成员变量,会存在数据安全问题
* 这个时候,我们就想能不能不让外界的对象直接访问成员变量呢?
* 能。
* 如何实现呢?
* private关键字
*
* private:
* 是一个修饰符
* 可以修饰成员变量,也可以修饰成员方法
* ==被private修饰的成员只能在本类中被访问==
*
* 针对private修饰的成员变量,我们会相应的提供getXxx()和setXxx()用于获取和设置成员变量的值,方法用public修饰
*/
public class Student {
String name;
// int age;
private int age;
public void show(){
System.out.println("姓名:" + name + "年龄是:" + age);
}
public void setAge(int a) {
if(a<0 || a>200){
System.out.println("给你的年纪有误");
}else{
age = a;
}
}
public int getAge() {
return age;
}
}
StudentDemo:
package demo2;
public class StudentDemo {
public static void main(String[] args){
Student s = new Student();
s.show();
s.name="小何"; //不是私有的所以可以直接访问
s.setAge(-24);
s.show();
}
}
5.封装(private)
- 封装概述
是面向对象三大特征之一。(其它两个是继承和多态)
是面向对象编程语言对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界无法直接操作和修改。就像刚才说的年龄。 - 封装原则:
将不需要对外提供的内容都隐藏起来。
把属性隐藏,提供公共方法对其访问。
成员变量private,提供对应的getXxx()/setXxx()方法 - 好处:
通过方法来控制成员变量的操作,提高了代码的安全性。
把代码用方法进行封装,提高了代码的复用性。
Student:
package demo3;
public class Student {
private String name; //成员变量
private int 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;
}
}
StudentDemo
package demo3;
public class StudentDemo {
public static void main(String[] args){
Student s = new Student();
s.setName("小何");
s.setAge(11);
System.out.println(s.getName() + s.getAge());
}
}
6.this关键字
- this:代表所在类的对象引用
记住:
方法被哪个对象调用,this就代表哪个对象
什么时候使用this呢?
局部变量隐藏成员变量
成员变量:在类中方法外。
局部变量:方法中或方法声明上。
package com.demo07;
/*
* 学生类
*
* 起名字我们要求做到见名知意。
* 而我们现在的代码中的n和a就没有做到见名知意,所以我要改进。
*
* 如果有局部变量名和成员变量名相同,在局部使用的时候,采用的是就近的原则。
*
* 我们有没有办法把局部变量的name赋值给成员变量的name呢?
* 有。
*
* 什么办法呢?
* 用this关键字就可以解决这个问题
*
* this:代表所在类的对象引用
* 方法被哪个对象调用,this就代表那个对象
*
* 使用场景:
* 局部变量隐藏成员变量
*/
public class Student {
private String name;
private int age;
public void setName(String name) { //"林青霞"
//name = n;
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
//age = age;
this.age = age;
}
public int getAge() {
return age;
}
}
7.构造方法
- 构造方法作用概述
给对象的数据进行初始化 - 构造方法格式
方法名与类名相同
没有返回值类型,连void都没有
没有具体的返回值 - 构造方法注意事项
如果你不提供构造方法,系统会给出默认构造方法
如果你提供了构造方法,系统将不再提供
构造方法也是可以重载的 - 标准类的代码写法和测试
- 类
- 成员变量
- 构造方法
无参构造方法
带参构造方法 - 成员方法
getXxx()
setXxx()
get方法是获得这个属性
set方法是给这个属性赋值
- 给成员变量赋值的方式
无参构造方法+setXxx()
带参构造方法
package com.demo08;
/*
* 构造方法:
* 给对象的数据进行初始化
*
* 格式:
* 方法名和类名相同
* 没有返回值类型,连void都不能写
* 没有具体的返回值
*
* 构造方法的注意事项:
* A:如果我们没有给出构造方法,系统将会提供一个默认的无参构造方法供我们使用。
* B:如果我们给出了构造方法,系统将不再提供默认的无参构造方法供我们使用。
* 这个时候,如果我们想使用无参构造方法,就必须自己提供。
* 推荐:自己给无参构造方法
* C:构造方法也是可以重载的
*
* 成员变量赋值:
* A:setXxx()方法
* B:带参构造方法
*/
public class Student {
private String name;
private int age;
/*
public Student() {
System.out.println("这是构造方法");
}
*/
public Student() {}
public Student(String name) {
this.name = name;
}
public Student(int age) {
this.age = age;
}
public Student(String name,int age) {
this.name = name;
this.age = age;
}
public void show() {
System.out.println(name+"---"+age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.demo08;
public class StudentDemo {
public static void main(String[] args) {
//如何调用构造方法呢?
//通过new关键字调用
//格式:类名 对象名 = new 构造方法(...);
//Student s = new Student();
//s.setName("张三");
//s.setAge(18);
//s.show();
//public Student(String name)
//Student s2 = new Student("林青霞");
//s2.show();
//public Student(int age)
/*Student s3 = new Student(28);
s3.show();*/
//public Student(String name,int age)
Student s4 = new Student("林青霞",28);
s4.show();
}
}
8.标准类的代码写法和测试
- 类
成员变量
构造方法- 无参构造方法
- 带参构造方法
成员方法
getXxx()
setXxx()
给成员变量赋值的方式 - 无参构造方法+setXxx()
- 带参构造方法
类名作为形式参数案例
要的其实是该类的对象
类名作为返回值案例
返回的其实是该类的对象
student
package com.demo09;
/*
* 学生类
*/
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;
}
/**
* 给年龄赋值
* @param age 年龄
*/
public void setAge(int age) {
this.age = age;
}
/**
* 获取年龄
* @return 年龄
*/
public int getAge() {
return age;
}
}
package com.demo09;
/*
* 学生类的测试类
*/
public class StudentDemo {
public static void main(String[] args) {
//无参+setXxx()
Student s = new Student();
s.setName("林青霞");
s.setAge(28);
System.out.println(s.getName()+"---"+s.getAge());
//带参构造
Student s2 = new Student("林青霞",28);
System.out.println(s2.getName()+"---"+s2.getAge());
}
}
9.类名作为形式参数和返回值
- 类名作为形式参数案例
要的其实是该类的对象 - 类名作为返回值案例
返回的其实是该类的对象
package com.demo10;
public class Student {
/**
* 学习
*/
public void study() {
System.out.println("好好学习,天天向上");
}
}
package com.demo10;
public class Teacher {
/**
* 调用学生类的学习方法
* @param s 学生对象
*/
public void test(Student s) {
s.study();
}
}
package com.demo10;
//需求: 调用Teacher的test方法
//类名作为形式参数:其实这里需要的是该类对象。
public class Test {
public static void main(String[] args) {
Teacher t = new Teacher();
Student s = new Student();
t.test(s);
}
}
package com.demo11;
public class Teacher {
public Student getStudent() {
Student s = new Student();
return s;
}
}
package com.demo11;
//需求: 通过Teacher得到Student对象,然后调用Student类的方法
//如果方法的返回值是类名:其实返回的是该类的对象
public class Test {
public static void main(String[] args) {
Teacher t = new Teacher();
Student s = t.getStudent();
//Student s = new Student();
s.study();
}
}
八、java常用API
API概述
API(Application Programming Interface)
应用程序编程接口
编写一个机器人程序去控制机器人踢足球,程序就需要向机器人发出向前跑、向后跑、射门、抢球等各种命令,没有编过程序的人很难想象这样的程序如何编写。但是对于有经验的开发人员来说,知道机器人厂商一定会提供一些用于控制机器人的Java类,这些类中定义好了操作机器人各种动作的方法。其实,这些Java类就是机器人厂商提供给应用程序编程的接口,大家把这些类称为API。本章涉及的Java API指的就是JDK中提供的各种功能的Java类。
-如何使用API
(1)打开帮助文档
点击显示,找到索引,看到输入框
你要找谁?
在输入框里输入,然后回车
例如:Scanner,点击第一个
CTRL+F查找
String s = sc.nextLine();
int month = sc.nextInt();
(2)看包
java.lang下的类不需要导包,其他需要
(3)看类的解释和说明
(4)学习构造方法
(5)使用成员方法
String
-
String类的概述及构造方法
String类概述
字符串是由多个字符组成的一串数据
字符串可以看成是字符数组
构造方法
public String(String original)
public String(char[] value)
public String(char[] value,int offset,int count)
直接赋值也可以是一个对象 -
String的特点
通过构造方法创建字符串对象
String s = new String(“hello”);
直接赋值创建字符串对象
String s = “hello”;区别是什么? -
String类的判断功能
boolean equals(Object obj) 判断字符串是否相等
boolean equalsIgnoreCase(String str) 不区分字符串大小写
boolean startsWith(String str) 判断以什么字符串为开始
boolean endsWith(String str) 以什么为结束,同endsEnd。
API中的equal:
Equal测试:
package com.demo03;
/*
* Object:是类层次结构中的根类,所有的类都直接或者间接的继承自该类。
* 如果一个方法的形式参数是Object,那么这里我们就可以传递它的任意的子类对象。
*
* String类的判断功能:
* boolean equals(Object obj):比较字符串的内容是否相同
* boolean equalsIgnoreCase(String str):比较字符串的内容是否相同,忽略大小写
* boolean startsWith(String str):判断字符串对象是否以指定的str开头
* boolean endsWith(String str):判断字符串对象是否以指定的str结尾
*/
public class StringDemo {
public static void main(String[] args) {
//创建字符串对象
String s1 = "hello";
String s2 = "hello";
String s3 = "Hello";
//boolean equals(Object obj):比较字符串的内容是否相同
/*System.out.println(s1.equals(s2));
System.out.println(s1.equals(s3));
System.out.println("-----------");*/
//boolean equalsIgnoreCase(String str):比较字符串的内容是否相同,忽略大小写
/*System.out.println(s1.equalsIgnoreCase(s2));
System.out.println(s1.equalsIgnoreCase(s3));
System.out.println("-----------");*/
//boolean startsWith(String str):判断字符串对象是否以指定的str开头
/*System.out.println(s1.startsWith("he"));
System.out.println(s1.startsWith("ll"));
*/
//boolean endsWith(String str):判断字符串对象是否以指定的str结束
System.out.println(s1.endsWith("ll"));
}
}
练习: 模拟用户登录
package demo5_api;
import java.util.Scanner;
/**
* 模拟用户登录 equal的用法 给三次机会,并提示还有几次。
* A 定义2个字符串对象,是正确的账号和密码
* B 键盘录入账号和密码,并规定3次机会
* C 判断输入的账号密码和正确的是否一样,一样:登陆成功,记得break跳出循环,不一样:失败还有2-x次机会;第三次:账号锁定,次数用完
*/
public class UserLogin {
public static void main(String[] args) {
// 1.定义两个字符串对象,用于存储已经存在的用户名和密码
String name = "admin";
String password = "123456";
// 2.键盘录入 3次机会
for (int x = 0; x < 3; x++) {
Scanner scanner = new Scanner(System.in);
System.out.println("输入账号:");
String userName = scanner.nextLine();
System.out.println("输入密码:");
String userPsd = scanner.nextLine();
if (userName.equals(name) && userPsd.equals(userPsd)) {
System.out.println("登陆成功");
break;
} else if ((2 - x) == 0) {
System.out.println("次数用完");
} else {
System.out.println("还剩余" + (2 - x) + "次机会");
}
}
}
}
- String类的获取功能
int length() 字符串的长度
char charAt(int index) 整型变量所在位置的字符
int indexOf(String str) 字符串在整个字符串中的位置
String substring(int start) 取子字符串,从start开始取字符串
String substring(int start,int end) 从start开始取字符串,到end结束,不包括第end个。
length与size的区别
java中的length属性是针对数组说的。比如你声明了一个数组(int[] a),想知道这个数组的长度则可以用到length这个属性。
java中的length()方法是针对字符串String说的,如果想看字符串的长度则可以用到length()这个方法
java中的size()方法是针对泛型集合说的,如果想看这个泛型有多少个元素,就调用次方法来查看.
举个例子:
public static void main(String[] args) {
String []list={“ma”,“cao”,“yuan”};
String a=“macaoyuan”;
System.out.println(list.length);
System.out.println(a.length());
List<Object> array=new ArrayList();
array.add(a);
System.out.println(array.size());
}
1
2
3
4
5
6
7
8
9
10
11
输出的值为:
3
9
1
————————————————
版权声明:本文为CSDN博主「zjpp2580369」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn/zjpp2580369/article/details/83544606
equals和==的区别
“”和equals 区别:
“”是运算符,如果等号两边是基本数据类型(八种基本数据类型),则比较的是存储的值;如果是引用数据类型,则比较的是所指向对象的地址值。
还可以如何区分基本类型和引用类型呢?可以看它存的是什么,如果是实体值就是基本类型,如果存的是地址就是引用类型,后文有详细区分;
equals是Object类中的方法,所有java类都直接或者间接继承object类,它比较的是所指向的对象的地址值,一般情况下,重写之后才比较的是对象存储的值(。
特别的:像String、Date、File、包装类中都重写了object中的equals()方法,这时候他们比较的就不是指向的地址值了,而是对象本身指向的实体内容。
总结:“==”是运算符
①如果比较的对象是基本数据类型,则比较的是其存储的值是否相等;
②如果比较的是引用数据类型,则比较的是所指向对象的地址值是否相等(是否是同一个对象)。
equals();
equals是Object类中的方法,如果没有被重写就是用来比较两个对象的地址值是否相等。
public boolean equals(Object obj) {
return (this == obj);
}
基本类型和引用类型的区别:
基本类型有八个:byte\ int\ double \float\ short\ long\ char \boolean
而引用类型,可以简单理解为就是对象(例如String、date类等)。
注意:
equals 方法不能用于比较基本数据类型,如果没有对 equals 方法进行重写,比较的是引用类型的变量所指向的对象的地址值。示例如下:
int a=1;
int b=1;
System.out.println(a.equals(b));//返回 false
//原因,equals没有被重写,比较的是地址值,a和b地址值不同
一般情况下,类会重写equals方法用来比较两个对象的实体内容(即对象具体的值)是否相等。比如String类中的equals()是被重写了,比较的是对象的值。
————————————————
版权声明:本文为CSDN博主「南斋孤鹤」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn/m0_64231944/article/details/125352503
- String类的转换功能
char[] toCharArray() 把字符串转换为字符数组
String toLowerCase() 把字符串转换为小写字符串
String toUpperCase() 把字符串转换为大写字符串
s.append(“[”); append表示追加。
package demo5_api;
public class StringDemo {
public static void main(String[] args){
String s = "helloWorld";
// int length();获取字符串的长度,字符字数
System.out.println(s.length());
// charAt(int index) 获取指定索引处的字符
System.out.println(s.charAt(1));
// int indexOf(String str) 获取str在字符串对象中第一次出现的索引
System.out.println(s.indexOf("l"));
System.out.println(s.indexOf("he"));
// String substring(int start):从start开始截取字符串
System.out.println(s.substring(0));
System.out.println(s.substring(4));
// String substring(int start,int end):从start开始,到end结束截取字符串,不包括最后一位
System.out.println(s.substring(3,6));
// String toUpperCase() 把字符串转换为**大写**字符串
System.out.println(s.toUpperCase());
// String toLowerCase() 把字符串转换为**小写**字符串
System.out.println(s.toLowerCase());
}
}
- String类的其他功能
String trim() 去除字符串两端空格
String s1 = "hekk";
System.out.println(s1.trim());
按照指定符号分割字符串
String[] split(String str)
- String类的练习
(1)把数组中的数据按照指定格式拼接成一个字符串
举例:int[] arr = {1,2,3}; 输出结果:[1, 2, 3]
package com.demo07;
/*
* 把数组中的数据按照指定格式拼接成一个字符串
* 举例:int[] arr = {1,2,3};
* 输出结果:[1, 2, 3]
*
* 分析:
* A:定义一个int类型的数组
* B:写方法实现把数组中的元素按照指定的格式拼接成一个字符串
* C:调用方法
* D:输出结果
*/
public class StringTest {
public static void main(String[] args) {
//定义一个int类型的数组
int[] arr = {1,2,3};
//写方法实现把数组中的元素按照指定的格式拼接成一个字符串
//调用方法
String s = arrayToString(arr);
//输出结果
System.out.println("s:"+s);
}
/*
* 两个明确:
* 返回值类型:String
* 参数列表:int[] arr
*/
public static String arrayToString(int[] arr) {
String s = "";
//[1, 2, 3]
s += "[";
for(int x=0; x<arr.length; x++) {
if(x==arr.length-1) {
s += arr[x];
}else {
s += arr[x];
s += ", ";
}
}
s += "]";
return s;
}
}
(2)2字符串反转
举例:键盘录入”abc” 输出结果:”cba”
package com.demo07;
import java.util.Scanner;
/*
* 字符串反转
* 举例:键盘录入”abc”
* 输出结果:”cba”
*
* 分析:
* A:键盘录入一个字符串
* B:写方法实现字符串的反转
* a:把字符串倒着遍历,得到的每一个字符拼接成字符串。
* b:把字符串转换为字符数组,然后对字符数组进行反转,最后在把字符数组转换为字符串
* C:调用方法
* D:输出结果
*/
public class StringTest2 {
public static void main(String[] args) {
//键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String s = sc.nextLine();
//写方法实现字符串的反转
//调用方法
String result = reverse(s);
//输出结果
System.out.println("result:"+result);
}
/*
把字符串倒着遍历,得到的每一个字符拼接成字符串。
两个明确:
返回值类型:String
参数列表:String s
*/
/*
public static String reverse(String s) {
String ss = "";
for(int x=s.length()-1; x>=0; x--) {
ss += s.charAt(x);
}
return ss;
}
*/
//把字符串转换为字符数组,然后对字符数组进行反转,最后再把字符数组转换为字符串
public static String reverse(String s) {
//把字符串转换为字符数组
char[] chs = s.toCharArray();
//对字符数组进行反转
for(int start=0,end=chs.length-1; start<=end; start++,end--) {
char temp = chs[start];
chs[start] = chs[end];
chs[end] = temp;
}
//最后再把字符数组转换为字符串
String ss = new String(chs);
return ss;
}
}
String拼接的过程图:缺点比较耗费内存。
StringBuilder
- StringBuilder类概述及其构造方法
- StringBuilder类概述
我们如果对字符串进行拼接操作,每次拼接,都会构建一个新的String对象,既耗时,又浪费空间。而StringBuilder就可以解决这个问题
- StringBuilder类概述
- StringBuilder和String的区别?
package com.demo01;
/*
* StringBuilder:是一个可变的字符串。字符串缓冲区类。
*
* String和StringBuilder的区别:
* String的内容是固定的。
* StringBuilder的内容是可变的。
*
* 构造方法:
* StringBuilder()
*
* 成员方法:
* public int capacity():返回当前容量
* public int length():返回长度(字符数)
*
* 容量:理论值
* 长度:实际值
*/
public class StringBuilderDemo {
public static void main(String[] args) {
//创建对象
StringBuilder sb = new StringBuilder();
System.out.println("sb:"+sb);
System.out.println("sb.capacity():"+sb.capacity());
System.out.println("sb.length():"+sb.length());
sb.append("asdfasdfasdfasdfasdfasdfasdfdfgdragtert");
System.out.println("sb.capacity():"+sb.capacity());
System.out.println("sb.length():"+sb.length());
}
}
- 构造方法
public StringBuilder() - StringBuilder类的常用方法
添加功能(字符串后面追加字符串)
public StringBuilder append(任意类型)
package com.demo02;
/*
* 添加功能
* public StringBuilder append(任意类型):添加数据,并返回自身对象
* 反转功能
* public StringBuilder reverse()
*/
public class StringBuilderDemo {
public static void main(String[] args) {
//创建对象
StringBuilder sb = new StringBuilder();
//public StringBuilder append(任意类型)
StringBuilder sb2 = sb.append("hello");
System.out.println("sb:"+sb);
System.out.println("sb2:"+sb2);
System.out.println(sb == sb2); //true
sb.append("hello");
sb.append("world");
sb.append(true);
sb.append(100);
System.out.println("sb:"+sb);
//链式编程
sb.append("hello").append("world").append(true).append(100);
System.out.println("sb:"+sb);
//public StringBuilder reverse()
sb.reverse();
System.out.println("sb:"+sb);
}
}
反转功能
public StringBuilder reverse()
- StringBuilder的练习
在这里插入代码片
- StringBuilder和String的相互转换
package com.demo03;
/*
* StringBuilder和String的相互转换
*
* StringBuilder -- String
* public String toString():通过toString()就可以实现把StringBuilder转成String
*
* String -- StringBuilder
* StringBuilder(String str):通过构造方法就可以实现把String转成StringBuilder
*/
public class StringBuilderTest {
public static void main(String[] args) {
//StringBuilder -- String
/*
StringBuilder sb = new StringBuilder();
sb.append("hello").append("world");
String s = sb.toString();
System.out.println(s);*/
//String -- StringBuilder
String s = "helloworld";
StringBuilder sb = new StringBuilder(s);
System.out.println(sb);
}
}
把数组拼接成一个字符串
package com.demo03;
/*
* 把数组拼接成一个字符串
* 举例:
* int[] arr = {1,2,3};
* 结果:
* [1, 2, 3]
*/
public class StringBuilderTest2 {
public static void main(String[] args) {
//定义一个数组
int[] arr = {1,2,3};
//写方法实现拼接
//调用方法
String s = arrayToString(arr);
//输出结果
System.out.println("s:"+s);
}
/*
* 两个明确:
* 返回值类型:String
* 参数列表:int[] arr
*/
public static String arrayToString(int[] arr) {
StringBuilder sb = new StringBuilder();
//[1, 2, 3]
sb.append("[");
for(int x=0; x<arr.length; x++) {
if(x==arr.length-1) {
sb.append(arr[x]);
}else {
sb.append(arr[x]).append(", ");
}
}
sb.append("]");
String result = sb.toString();
return result;
}
}
把字符串反转
注意:如果,用reverse方法的时候报错,修改:
1.类名和StringBuilder冲突了,换一个类名。
2.定义加上java.lang.
java.lang.StringBuilder k = new java.lang.StringBuilder(s);
package demo5_api;
import java.util.Scanner;
/*
* 判断一个字符串是否是对称字符串
* 例如"abc"不是对称字符串,"aba"、"abba"、"aaa"、"mnanm"是对称字符串
*
* 分析:
* A:键盘录入一个字符串
* B:写方法实现判断一个字符串是否是对称字符串
* 把字符串反转,和反转前的字符串进行比较,如果内容相同,就说明是对称字符串
* C:调用方法
* D:输出结果
*/
public class StringBuilder1 {
public static void main(String[] args) {
System.out.println("请输入一个字符串");
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine();
java.lang.StringBuilder k = new java.lang.StringBuilder(s);
System.out.println("字符串反转后的结果为" + k.reverse());
}
}
结果:
demo5_api.StringBuilder1
请输入一个字符串
heh
字符串反转后的结果为heh
- 判断一个字符串是否是对称字符串
例如"abc"不是对称字符串,“aba”、“abba”、“aaa”、"mnanm"是对称字符串
代码
package com.demo03;
import java.util.Scanner;
/*
* 判断一个字符串是否是对称字符串
* 例如"abc"不是对称字符串,"aba"、"abba"、"aaa"、"mnanm"是对称字符串
*
* 分析:
* A:键盘录入一个字符串
* B:写方法实现判断一个字符串是否是对称字符串
* 把字符串反转,和反转前的字符串进行比较,如果内容相同,就说明是对称字符串
* C:调用方法
* D:输出结果
*/
public class StringBuilderTest4 {
public static void main(String[] args) {
//键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String s = sc.nextLine();
//写方法实现判断一个字符串是否是对称字符串
//调用方法
boolean b = isSymmetry(s);
//输出结果
System.out.println("b:"+b);
}
/*
* 两个明确:
* 返回值类型:boolean
* 参数列表:String s
*/
public static boolean isSymmetry(String s) {
//把字符串反转,和反转前的字符串进行比较,如果内容相同,就说明是对称字符串
StringBuilder sb = new StringBuilder(s);
sb.reverse();
String result = sb.toString();
return result.equals(s);
}
}
本章节全部代码汇总:
package com.demo01;
import java.util.Scanner;
/*
* Scanner:用于获取键盘录入的数据。(基本数据类型,字符串数据)
* public String nextLine():获取键盘录入的字符串数据
*/
public class ScannerDemo {
public static void main(String[] args) {
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
//接收数据
System.out.println("请输入一个字符串数据:");
String s = sc.nextLine();
//输出结果
System.out.println("s:"+s);
}
}
demo02
package com.demo02;
/*
* String:字符串类
* 由多个字符组成的一串数据
* 字符串其本质是一个字符数组
*
* 构造方法:
* String(String original):把字符串数据封装成字符串对象
* String(char[] value):把字符数组的数据封装成字符串对象
* String(char[] value, int index, int count):把字符数组中的一部分数据封装成字符串对象
*
* 注意:字符串是一种比较特殊的引用数据类型,直接输出字符串对象输出的是该对象中的数据。
*/
public class StringDemo {
public static void main(String[] args) {
//方式1
//String(String original):把字符串数据封装成字符串对象
String s1 = new String("hello");
System.out.println("s1:"+s1);
System.out.println("---------");
//方式2
//String(char[] value):把字符数组的数据封装成字符串对象
char[] chs = {'h','e','l','l','o'};
String s2 = new String(chs);
System.out.println("s2:"+s2);
System.out.println("---------");
//方式3
//String(char[] value, int index, int count):把字符数组中的一部分数据封装成字符串对象
//String s3 = new String(chs,0,chs.length);
//char[] chs = {'h','e','l','l','o'};
String s3 = new String(chs,1,3);
System.out.println("s3:"+s3);
System.out.println("---------");
//方式4
String s4 = "hello";
System.out.println("s4:"+s4);
}
}
demo02
package com.demo02;
/*
* 通过构造方法创建的字符串对象和直接赋值方式创建的字符串对象有什么区别呢?
* 通过构造方法创建字符串对象是在堆内存。
* 直接赋值方式创建对象是在方法区的常量池。
*
* ==:
* 基本数据类型:比较的是基本数据类型的值是否相同
* 引用数据类型:比较的是引用数据类型的地址值是否相同
*/
public class StringDemo2 {
public static void main(String[] args) {
String s1 = new String("hello");
String s2 = "hello";
//System.out.println("s1:"+s1);
//System.out.println("s2:"+s2);
//System.out.println("s1==s2:"+(s1==s2)); //false
String s3 = "hello";
/*System.out.println("s1==s3:"+(s1==s3)); //false
System.out.println("s2==s3:"+(s2==s3)); //true
*/
System.out.println(s1.equals(s2));
}
}
demo03
package com.demo03;
/*
* Object:是类层次结构中的根类,所有的类都直接或者间接的继承自该类。
* 如果一个方法的形式参数是Object,那么这里我们就可以传递它的任意的子类对象。
*
* String类的判断功能:
* boolean equals(Object obj):比较字符串的内容是否相同
* boolean equalsIgnoreCase(String str):比较字符串的内容是否相同,忽略大小写
* boolean startsWith(String str):判断字符串对象是否以指定的str开头
* boolean endsWith(String str):判断字符串对象是否以指定的str结尾
*/
public class StringDemo {
public static void main(String[] args) {
//创建字符串对象
String s1 = "hello";
String s2 = "hello";
String s3 = "Hello";
//boolean equals(Object obj):比较字符串的内容是否相同
/*System.out.println(s1.equals(s2));
System.out.println(s1.equals(s3));
System.out.println("-----------");*/
//boolean equalsIgnoreCase(String str):比较字符串的内容是否相同,忽略大小写
/*System.out.println(s1.equalsIgnoreCase(s2));
System.out.println(s1.equalsIgnoreCase(s3));
System.out.println("-----------");*/
//boolean startsWith(String str):判断字符串对象是否以指定的str开头
/*System.out.println(s1.startsWith("he"));
System.out.println(s1.startsWith("ll"));
*/
//boolean endsWith(String str):判断字符串对象是否以指定的str结束
System.out.println(s1.endsWith("ll"));
}
}
demo03
package com.demo03;
import java.util.Scanner;
/*
* 模拟登录,给三次机会,并提示还有几次。
*
* 分析:
* A:定义两个字符串对象,用于存储已经存在的用户名和密码
* B:键盘录入用户名和密码
* C:拿键盘录入的用户名和密码和已经存在的用户名和密码进行比较
* 如果内容相同,提示登录成功
* 如果内容不同,提示登录失败,并提示还有几次机会
*/
public class StringTest {
public static void main(String[] args) {
//定义两个字符串对象,用于存储已经存在的用户名和密码
String username = "admin";
String password = "admin";
//给三次机会,用for循环实现
for(int x=0; x<3; x++) {
//键盘录入用户名和密码
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名:");
String name = sc.nextLine();
System.out.println("请输入密码:");
String pwd = sc.nextLine();
//拿键盘录入的用户名和密码和已经存在的用户名和密码进行比较
if(username.equals(name) && password.equals(pwd)) {
System.out.println("登录成功");
break;
}else {
if((2-x) ==0) {
System.out.println("用户名和密码被锁定,请与管理员联系");
}else {
System.out.println("登录失败,你还有"+(2-x)+"次机会"); //2,1,0
}
}
}
}
}
demo04
package com.demo04;
/*
* String类的获取功能:
* int length():获取字符串的长度,其实也就是字符个数
* char charAt(int index):获取指定索引处的字符
* int indexOf(String str):获取str在字符串对象中第一次出现的索引
* String substring(int start):从start开始截取字符串
* String substring(int start,int end):从start开始,到end结束截取字符串。包括start,不包括end
*/
public class StringDemo {
public static void main(String[] args) {
//创建字符串对象
String s = "helloworld";
//int length():获取字符串的长度,其实也就是字符个数
System.out.println(s.length());
/* System.out.println("--------");
//char charAt(int index):获取指定索引处的字符
System.out.println(s.charAt(0));
System.out.println(s.charAt(1));
System.out.println("--------");*/
//int indexOf(String str):获取str在字符串对象中第一次出现的索引
/*System.out.println(s.indexOf("l"));
System.out.println(s.indexOf("owo"));
System.out.println(s.indexOf("ak"));
System.out.println("--------");*/
/*//String substring(int start):从start开始截取字符串
System.out.println(s.substring(0));
System.out.println(s.substring(5));
System.out.println("--------");*/
//String substring(int start,int end):从start开始,到end结束截取字符串
System.out.println(s.substring(0, s.length()));
//System.out.println(s.substring(3,8));
}
}
demo04
package com.demo04;
/*
* 遍历字符串(获取字符串中的每一个字符)
*/
public class StringTest {
public static void main(String[] args) {
//创建一个字符串对象
String s = "abcde";
//原始做法
System.out.println(s.charAt(0));
System.out.println(s.charAt(1));
System.out.println(s.charAt(2));
System.out.println(s.charAt(3));
System.out.println(s.charAt(4));
System.out.println("---------");
//用for循环改进
for(int x=0; x<5; x++) {
System.out.println(s.charAt(x));
}
System.out.println("---------");
//用length()方法获取字符串的长度
for(int x=0; x<s.length(); x++) {
System.out.println(s.charAt(x));
}
}
}
demo04
package com.demo04;
import java.util.Scanner;
/*
* 统计一个字符串中大写字母字符,小写字母字符,数字字符出现的次数。(不考虑其他字符)
*
* 分析:
* A:键盘录入一个字符串数据
* B:定义三个统计变量,初始化值都是0
* C:遍历字符串,得到每一个字符
* D:拿字符进行判断
* 假如ch是一个字符。
* 大写:ch>='A' && ch<='Z'
* 小写:ch>='a' && ch<='z'
* 数字:ch>='0' && ch<='9'
* E:输出结果
*/
public class StringTest2 {
public static void main(String[] args) {
//键盘录入一个字符串数据
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串数据:");
String s = sc.nextLine();
//定义三个统计变量,初始化值都是0
int bigCount = 0;
int smallCount = 0;
int numberCount = 0;
//遍历字符串,得到每一个字符
for(int x=0; x<s.length(); x++) {
char ch = s.charAt(x);
//拿字符进行判断
if(ch>='A' && ch<='Z') {
bigCount++;
}else if(ch>='a' && ch<='z') {
smallCount++;
}else if(ch>='0' && ch<='9') {
numberCount++;
}else {
System.out.println("该字符"+ch+"非法");
}
}
//输出结果
System.out.println("大写字符:"+bigCount+"个");
System.out.println("小写字符:"+smallCount+"个");
System.out.println("数字字符:"+numberCount+"个");
}
}
demo05
package com.demo05;
/*
* String类的转换功能:
* char[] toCharArray():把字符串转换为字符数组
* String toLowerCase():把字符串转换为小写字符串
* String toUpperCase():把字符串转换为大写字符串
*
* 字符串的遍历:
* A:length()加上charAt()
* B:把字符串转换为字符数组,然后遍历数组
*/
public class StringDemo {
public static void main(String[] args) {
//创建字符串对象
String s = "abcde";
//char[] toCharArray():把字符串转换为字符数组
/*char[] chs = s.toCharArray();
for(int x=0; x<chs.length; x++) {
System.out.println(chs[x]);
}
System.out.println("-----------");*/
//String toLowerCase():把字符串转换为小写字符串
System.out.println("HelloWorld".toLowerCase());
//String toUpperCase():把字符串转换为大写字符串
System.out.println("HelloWorld".toUpperCase());
}
}
demo06
package com.demo06;
/*
* 去除字符串两端空格
* String trim()
* 按照指定符号分割字符串
* String[] split(String str)
*/
public class StringDemo {
public static void main(String[] args) {
//创建字符串对象
/*String s1 = "helloworld";
String s2 = " helloworld ";
String s3 = " hello world ";
System.out.println("---"+s1+"---");
System.out.println("---"+s1.trim()+"---");
System.out.println("---"+s2+"---");
System.out.println("---"+s2.trim()+"---");
System.out.println("---"+s3+"---");
System.out.println("---"+s3.trim()+"---");
System.out.println("-------------------");*/
//String[] split(String str)
//创建字符串对象
String s4 = "aa,bb,cc";
String[] strArray = s4.split(",");
for(int x=0; x<strArray.length; x++) {
System.out.println(strArray[x]);
}
}
}
demo07
package com.demo07;
/*
* 把数组中的数据按照指定格式拼接成一个字符串
* 举例:int[] arr = {1,2,3};
* 输出结果:[1, 2, 3]
*
* 分析:
* A:定义一个int类型的数组
* B:写方法实现把数组中的元素按照指定的格式拼接成一个字符串
* C:调用方法
* D:输出结果
*/
public class StringTest {
public static void main(String[] args) {
//定义一个int类型的数组
int[] arr = {1,2,3};
//写方法实现把数组中的元素按照指定的格式拼接成一个字符串
//调用方法
String s = arrayToString(arr);
//输出结果
System.out.println("s:"+s);
}
/*
* 两个明确:
* 返回值类型:String
* 参数列表:int[] arr
*/
public static String arrayToString(int[] arr) {
String s = "";
//[1, 2, 3]
s += "[";
for(int x=0; x<arr.length; x++) {
if(x==arr.length-1) {
s += arr[x];
}else {
s += arr[x];
s += ", ";
}
}
s += "]";
return s;
}
}
demo07
package com.demo07;
import java.util.Scanner;
/*
* 字符串反转
* 举例:键盘录入”abc”
* 输出结果:”cba”
*
* 分析:
* A:键盘录入一个字符串
* B:写方法实现字符串的反转
* a:把字符串倒着遍历,得到的每一个字符拼接成字符串。
* b:把字符串转换为字符数组,然后对字符数组进行反转,最后在把字符数组转换为字符串
* C:调用方法
* D:输出结果
*/
public class StringTest2 {
public static void main(String[] args) {
//键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String s = sc.nextLine();
//写方法实现字符串的反转
//调用方法
String result = reverse(s);
//输出结果
System.out.println("result:"+result);
}
/*
把字符串倒着遍历,得到的每一个字符拼接成字符串。
两个明确:
返回值类型:String
参数列表:String s
*/
/*
public static String reverse(String s) {
String ss = "";
for(int x=s.length()-1; x>=0; x--) {
ss += s.charAt(x);
}
return ss;
}
*/
//把字符串转换为字符数组,然后对字符数组进行反转,最后再把字符数组转换为字符串
public static String reverse(String s) {
//把字符串转换为字符数组
char[] chs = s.toCharArray();
//对字符数组进行反转
for(int start=0,end=chs.length-1; start<=end; start++,end--) {
char temp = chs[start];
chs[start] = chs[end];
chs[end] = temp;
}
//最后再把字符数组转换为字符串
String ss = new String(chs);
return ss;
}
}
九、java集合
1.对象数组的案例
首先须知道如何快速:IDEA自动生成构造、get、set方法
简要步骤:右击——Generate——get and set(选择就是带参数的,不选就不带)
Student:
package demo9_List;
/*
* Eclipse自动生成构造方法:
* 代码区域右键 -- Source -- Generate Constructors from Superclass... 无参构造方法
* 代码区域右键 -- Source -- Generate Constructor using Fields... 带参构造方法
* 自动生成getXxx()/setXxx():
* 代码区域右键 -- Source -- Generate Getters and Setters...
*
* 一个标准的类通常要拥有下面四个组成部分:
1.所有的成员变量都要使用private关键字修饰
2.为每一个成员变量编写一对儿Getter/Setter方法
3.编写一个无参数的构造方法
4.编写一个全参数的构造方法
这样标准的类也叫做Java Bean。
*/
public class Student {
private String name; //所有的成员变量都要使用private关键字修饰
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Student() {
super();
}
public String getName() {
return name;
}
public void setName(String name) { //为每一个成员变量编写一对儿Getter/Setter方法
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
StudentDemo:
package demo9_List;
/** 创建一个学生数组,存储三个学生对象并遍历
* 分析:
* A 定义学生类
* B 创建学生数组
* C 创建学生对象
* D 把学生对象作为元素赋值给学生数组
* E 遍历数组
*/
public class StudentDemo {
public static void main(String[] args) {
// 1.创建学生数组
Student[] students = new Student[3];
// 2.创建学生对象
Student s1 = new Student("小何",25);
Student s2 = new Student("小张",28);
Student s3 = new Student("小林",27);
// 把学生对象作为元素赋值给数组
students[0] = s1;
students[1] = s2;
students[2] = s3;
// 遍历学生数组
for (int i = 0;i<students.length;i++){
Student s= students[i];
System.out.println(s.getName()+"--"+s.getAge());
}
}
}
- 为什么出现集合类?
我们学习的是面向对象语言,而面向对象语言对事物的描述是通过对象体现的,为了方便对多个对象进行操作,我们就必须把这多个对象进行存储。
而要想存储多个对象,就不能是一个基本的变量,而应该是一个容器类型的变量,在我们目前所学过的知识里面,有哪些是容器类型的呢?数组和StringBuilder。
但是呢? StringBuilder的结果是一个字符串,不一定满足我们的要求,所以我们只能选择数组,这就是对象数组。而对象数组又不能适应变化的需求,因为数组的长度是固定的,这个时候,为了适应变化的需求,Java就提供了集合类供我们使用。由此可见集合的长度是可变的数组。
集合类的特点:长度可变。
ArrayList:
大小可变数组的实现
:是一种特殊的数据类型,泛型。
怎么用呢?
在出现E的地方我们使用引用数据类型替换即可
举例:ArrayList,ArrayList
2. ArrayList类的构造方法和成员方法
- 构造方法
ArrayList()
package demo9_List;
import java.util.ArrayList;
/*
* 为什么会出现集合类:
* 我们学习的是面向对象编程语言,而面向对象编程语言对事物的描述都是通过对象来体现的。
* 为了方便对多个对象进行操作,我们就必须对这多个对象进行存储,而要想对多个对象进行存储,
* 就不能是一个基本的变量,而应该是一个容器类型的变量。
* 到目前为止,我们学习过了哪些容器类型的数据呢?StringBuilder,数组。
* StringBuilder的结果只能是一个字符串类型,不一定满足我们的需求。
* 所以,我们目前只能选择数组了,也就是我们前面学习过的对象数组。
* 但是,数组的长度是固定的,适应不了变化的需求,那么,我们该如何选择呢?
* 这个时候,java就提供了集合类供我们使用。
* 构造方法:
* ArrayList()
*
* 添加元素:
* public boolean add(E e):添加元素
* public void add(int index,E element):在指定的索引处添加一个元素
*/
public class arrayListDemo1 {
public static void main(String[] args) {
// 创建集合对象
ArrayList<String> array = new ArrayList<String>(); //<String>表示泛型的意思,每一项都是String类型
// 添加元素 add(E e)
array.add("world");
array.add("hello");
array.add("java");
// 在指定的索引处添加对象
array.add(2, "android");
System.out.println("array:" + array);
}
}
输出结果:
array:[world, hello, android, java]
- 成员方法
添加元素
array.add(E e);
获取元素
array.get(int index);
集合长度
array.size();
删除元素
array.remove(int index);
修改元素
array.set(int index,E element);
package demo9_List;
import java.util.ArrayList;
/*
* 获取元素
* public E get(int index):返回指定索引处的元素
* 集合长度
* public int size():返回集合中的元素的个数
* 删除元素
* public boolean remove(Object o):删除指定的元素,返回删除是否成功
* public E remove(int index):删除指定索引处的元素,返回被删除的元素
* 修改元素
* public E set(int index,E element):修改指定索引处的元素,返回被修改的元素
*/
public class arrayListDemo2 {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<String>();
// 添加元素
arrayList.add("1world");
arrayList.add("2world");
arrayList.add("3world");
System.out.println(arrayList);
// 集合长度
System.out.println(arrayList.size());
// 删除指定元素,返回被删除的元素
System.out.println(arrayList.remove(1));
System.out.println("删除后的集合:" + arrayList);
// 修改元素
System.out.println(arrayList.set(0, "hello"));
}
}
集合遍历:
package com.demo01;
import java.util.ArrayList;
/*
* ArrayList集合的遍历
* 通过size()和get()配合实现的
*/
public class ArrayListDemo3 {
public static void main(String[] args) {
//创建集合对象
ArrayList<String> array = new ArrayList<String>();
//添加元素
array.add("hello");
array.add("world");
array.add("java");
//获取元素
//原始做法
System.out.println(array.get(0));
System.out.println(array.get(1));
System.out.println(array.get(2));
System.out.println("----------");
for(int x=0; x<3; x++) {
System.out.println(array.get(x));
}
System.out.println("----------");
//如何知道集合中元素的个数呢?size()
for(int x=0; x<array.size(); x++) {
System.out.println(array.get(x));
}
System.out.println("----------");
//最标准的用法
for(int x=0; x<array.size(); x++) {
String s = array.get(x);
System.out.println(s);
}
}
}
3. ArrayList类案例
存储字符串并遍历
给定一个字符串数组:{“张三丰”,“宋远桥”,“张无忌”,“殷梨亭”,“张翠山”,“莫声谷”},将数组中的元素添加到集合中,并把所有姓张的人员打印到控制台上。
存储自定义对象并遍历
创建一个集合,存储学生对象,学生对象的数据来自于键盘录入,最后,遍历集合。
package com.demo02;
import java.util.ArrayList;
/*
* 给定一个字符串数组:{“张三丰”,“宋远桥”,“张无忌”,“殷梨亭”,“张翠山”,“莫声谷”},将数组中的元素添加到集合中,并把所有姓张的人员打印到控制台上。
*
* 分析:
* A:定义字符串数组
* B:创建集合对象
* C:遍历字符串数组,获取到每一个字符串元素
* D:把获取到的字符串元素添加到集合
* E:遍历集合
* 要判断每一个字符串元素是否以"张"开头,如果是,就输出在控制台
*/
public class ArrayListTest2 {
public static void main(String[] args) {
//定义字符串数组
String[] strArray = {"张三丰","宋远桥","张无忌","殷梨亭","张翠山","莫声谷"};
//创建集合对象
ArrayList<String> array = new ArrayList<String>();
//遍历字符串数组,获取到每一个字符串元素
for(int x=0; x<strArray.length; x++) {
//把获取到的字符串元素添加到集合
array.add(strArray[x]);
}
//遍历集合
for(int x=0; x<array.size(); x++) {
String s = array.get(x);
//要判断每一个字符串元素是否以"张"开头,如果是,就输出在控制台
if(s.startsWith("张")) {
System.out.println(s);
}
}
}
}
结果:
张三丰
张无忌
张翠山
4.学生管理系统
package com.demo;
/*
* 这是我的学生类
*/
public class Student {
//学号
private String id; //成员变量
//姓名
private String name;
//年龄
private String age;
//居住地
private String address;
public Student() {
}
public Student(String id, String name, String age, String address) { //局部变量
this.id = id; // 局部变量隐藏成员变量的时候用this
this.name = name;
this.age = age;
this.address = address;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
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;
}
}
package com.demo;
import java.util.ArrayList;
import java.util.Scanner;
/*
* 这是我的学生管理系统的主类
*
* 步骤如下:
* A:定义学生类
* B:学生管理系统的主界面的代码编写
* C:学生管理系统的查看所有学生的代码编写
* D:学生管理系统的添加学生的代码编写
* E:学生管理系统的删除学生的代码编写
* F:学生管理系统的修改学生的代码编写
*/
public class StudentManagerTest {
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 sc = new Scanner(System.in);
String choiceString = sc.nextLine();
//用switch语句实现选择
switch(choiceString) {
case "1":
//查看所有学生
findAllStudent(array);
break;
case "2":
//添加学生
addStudent(array);
break;
case "3":
//删除学生
deleteStudent(array);
break;
case "4":
//修改学生
updateStudent(array);
break;
case "5":
//退出
System.out.println("谢谢你的使用");
System.exit(0); //JVM退出
break;
default:
break;
}
}
}
//修改学生
public static void updateStudent(ArrayList<Student> array) {
//修改学生的思路:键盘录入一个学号,到集合中去查找,看是否有学生使用的是该学号,如果有就修改该学生
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
System.out.println("请输入你要修改的学生的学号:");
String id = sc.nextLine();
//定义一个索引
int index = -1;
//遍历集合
for(int x=0; x<array.size(); x++) {
//获取每一个学生对象
Student s = array.get(x);
//拿学生对象的学号和键盘录入的学号进行比较
if(s.getId().equals(id)) {
index = x;
break;
}
}
if(index == -1) {
System.out.println("不好意思,你要修改的学号对应的学生信息不存在,请回去重新你的选择");
}else {
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.setId(id);
s.setName(name);
s.setAge(age);
s.setAddress(address);
//修改集合中的学生对象
array.set(index, s);
//给出提示
System.out.println("修改学生成功");
}
}
//删除学生
public static void deleteStudent(ArrayList<Student> array) {
//删除学生的思路:键盘录入一个学号,到集合中去查找,看是否有学生使用的是该学号,如果有就删除该学生
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
System.out.println("请输入你要删除的学生的学号:");
String id = sc.nextLine();
/*
//遍历集合
for(int x=0; x<array.size(); x++) {
//获取到每一个学生对象
Student s = array.get(x);
//拿这个学生对象的学号和键盘录入的学号进行比较
if(s.getId().equals(id)) {
array.remove(x); //根据索引删除
break;
}
}
//给出提示
System.out.println("删除学生成功");*/
//我们必须给出学号不存在的时候的提示
//定义一个索引
int index = -1;
//遍历集合
for(int x=0; x<array.size(); x++) {
//获取到每一个学生对象
Student s = array.get(x);
//拿这个学生对象的学号和键盘录入的学号进行比较
if(s.getId().equals(id)) {
index = x;
break;
}
}
if(index == -1) {
System.out.println("不好意思,你要删除的学号对应的学生信息不存在,请回去重新你的选择");
}else {
array.remove(index);
System.out.println("删除学生成功");
}
}
//添加学生
public static void addStudent(ArrayList<Student> array) {
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
//为了让id能够被访问到,我们就把id定义在了循环的外面
String id;
//为了让代码能够回到这里,用循环
while(true) {
System.out.println("请输入学生学号:");
//String id = sc.nextLine();
id = sc.nextLine();
//判断学号有没有被人占用
//定义标记
boolean flag = false;
//遍历集合,得到每一个学生
for(int x=0; x<array.size(); x++) {
Student s = array.get(x);
//获取该学生的学号,和键盘录入的学号进行比较
if(s.getId().equals(id)) {
flag = true; //说明学号被占用了
break;
}
}
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.setId(id);
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居住地");
for(int x=0; x<array.size(); x++) {
Student s = array.get(x);
System.out.println(s.getId()+"\t"+s.getName()+"\t"+s.getAge()+"\t"+s.getAddress());
}
}
}
运行结果:
"C:\Program Files\Java\jdk1.8.0_191\bin\java.exe" "-javaagent:D:\ruanJian\IDEA 2020-64bit\IntelliJ IDEA 2020.3.4\lib\idea_rt.jar=6380:D:\ruanJian\IDEA 2020-64bit\IntelliJ IDEA 2020.3.4\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_191\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\rt.jar;G:\代码编程资料\VIP项目孟哥998\ideaText\out\production\ideaText" demo9_List.StudentManagerTest
欢迎来到学生管理系统!
输入1:查看所有学生信息
输入2:添加学生信息
输入3:删除学生信息
输入4:修改学生信息
输入5:退出
请输入你的选择
1
没有数据,请添加数据再查询
2
请输入学号:
1
请输入学生的姓名
小何
请输入学生的年龄
23
请输入学生的地址
安徽
添加学生成功啦
4
不好意思,您要修改的学生信息不存在
1
学号 姓名 年龄 居住地
1 小何 23 安徽
4
1
请输入学生新姓名:
小丁
请输入学生新年龄:
21
请输入学生新居住地:
东北
修改成功
1
学号 姓名 年龄 居住地
1 小丁 21 东北
3
请输入想删除的学生的学号
1
删除成功
要删除的学生不存在
1
没有数据,请添加数据再查询
5
Process finished with exit code 0
十、IO 流概念和FileWriter类
1.IO流
功能
- 用来处理设备之间的数据传输
- 文件复制,上传和下载文件
IO流分类
- 输出流 FileWriter 从控制台写数据到文件中,所以是输出流FileWriter
- 输入流 FileReader 从文件中读取数据到控制台,所以是输入流FileReader
2.FileWriter写数据
• 构造方法
– FileWriter(String fileName)
• 成员方法
– void write(String str)
– void flush()
– void close()
往文件中写数据:
package com.demo01;
import java.io.FileWriter;
import java.io.IOException;
/*
* 需求:往文件中写数据
* 写数据--输出流--FileWriter
*
* FileWriter:
* FileWriter(String fileName):传递一个文件名称
*
* 输出流写数据的步骤:
* A:创建输出流对象
* B:调用输出流对象的写数据的方法
* C:释放资源
*/
public class FileWriterDemo {
public static void main(String[] args) throws IOException {
//创建输出流对象
FileWriter fw = new FileWriter("E:\\text\\first.txt");
/*
* 创建输出流对象做了哪些事情:
* A:调用系统资源创建了一个文件
* B:创建输出流对象
* C:把输出流对象指向文件
*/
//调用输出流对象的写数据的方法
//写一个字符串数据
fw.write("IO流你好,Hello");
//数据没有直接写到文件,其实是写到了内存缓冲区
fw.flush(); //刷新该流的缓冲
//释放资源
//通知系统释放和该文件相关的资源
fw.close(); //不释放内存就会一直占用内存
}
}
运行结果:
3.flush和close
public void flush()
throws IOException刷新该流的缓冲。
指定者:
接口 Flushable 中的 flush
指定者:
类 Writer 中的 flush
抛出: 用 throws IOException - 如果发生 I/O 错误,让Java虚拟机代替我们进行处理,因为可能会发生文件不存在等一些情况。
- close()和flush()方法的区别:
flush():刷新缓冲区。流对象还可以继续使用。
close():先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了。
4. 相对路径和绝对路径
- 相对路径:相对当前项目而言的,在项目的根目录下(a.txt)
- 绝对路径:以盘符开始的路径(d:\a.txt)
上一个案例中继续写入数据:
package com.demo01;
import java.io.FileWriter;
import java.io.IOException;
/*
* 输出流写数据的步骤:
* A:创建输出流对象
* B:调用输出流对象的写数据方法,并刷新缓冲区
* C:释放资源
*
* 相对路径:相对当前项目而言的,在项目的根目录下(a.txt)
* 绝对路径:以盘符开始的路径(d:\\a.txt)
*
* close()和flush()方法的区别:
* flush():刷新缓冲区。流对象还可以继续使用。
* close():先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了。
*/
public class FileWriterDemo2 {
public static void main(String[] args) throws IOException {
//创建输出流对象
//FileWriter fw = new FileWriter("d:\\a.txt");
FileWriter fw = new FileWriter("a.txt");
//调用输出流对象的写数据方法,并刷新缓冲区
fw.write("helloworld");
fw.flush();
fw.write("java");
fw.flush();
//释放资源
fw.close();
//Stream closed
fw.write("javaee");
fw.flush();
}
}
FileWriter写数据的方法
• void write(String str) 写一个字符串数据
• void write(String str,int index,int len) 写一个字符串中的一部分数据
• void wirte(int ch) 写一个字符数据,这里写int类型的好处是既可以写char类型的数据,也可以写char对应的int类型的值。‘a’,97
• void write(char[] chs) 写一个字符数组数据
• void write(char[] chs,int index,int len) 写一个字符数组的一部分数据
FileWriter写数据:
package IOandFile;
import java.io.FileWriter;
import java.io.IOException;
/**
* void write(String str):写一个字符串数据
* void write(String str,int index,int len):写一个字符串中的一部分数据
* void write(int ch):写一个字符数据,这里写int类型的好处是既可以写char类型的数据,也可以写char对应的int类型的值。'a',97
* void write(char[] chs):写一个字符数组数据
* void write(char[] chs,int index,int len):写一个字符数组的一部分数据
* 需求:用到上面的方法写数据
*/
public class FileWriterDataWay {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("e:\\text\\first.txt");
// fw.write("banana");
fw.write("constraint", 0, 10);
fw.write("\r\n");
fw.write("constrain", 2, 4);
fw.write("\r\n");
// void write(int ch):写一个字符数据,这里写int类型的好处是既可以写char类型的数据,也可以写char对应的int类型的值。'a',97
fw.write('a' + " ");
fw.write(97);
fw.write("\r\n");
// void write(char[] chs):写一个字符数组数据
char[] chs = {'a', 'b', 'c'};
// void write(char[] chs,int index,int len):写一个字符数组的一部分数据
fw.write(chs);
fw.write("\r\n");
fw.write(chs, 0, 1);
fw.flush();
fw.close();
}
}
运行结果:
FileWriter写数据常见问题
• 如何实现数据的换行?
fw.write(“\r\n”)
\n可以实现换行,但是windows系统自带的记事本打开并没有换行,这是为什么呢?因为windows识别的换行不是\n,而是\r\n
-
windows:\r\n
-
linux:\n
-
mac:\r
• 如何实现数据的追加写入?
FileWriter(String fileName, boolean append) 第二部分写 true / false 默认是false
代码示范:
package com.demo01;
import java.io.FileWriter;
import java.io.IOException;
/*
* 如何实现数据的换行?
* \n可以实现换行,但是windows系统自带的记事本打开并没有换行,这是为什么呢?因为windows识别的换行不是\n,而是\r\n
* windows:\r\n
* linux:\n
* mac:\r
* 如何实现数据的追加写入?
* FileWriter(String fileName, boolean append)
*/
public class FileWriterDemo4 {
public static void main(String[] args) throws IOException {
//创建输出流对象
//FileWriter fw = new FileWriter("c.txt");
FileWriter fw = new FileWriter("c.txt",true); //表示追加写入,默认是false c.txt 相对路径
for(int x=0; x<10; x++) {
fw.write("hello world"+x);
fw.write("\r\n");
}
//释放资源
fw.close();
}
}
运行结果:
5.FileReader读数据
• 构造方法
– FileReader(String fileName)
• 成员方法
– int read()
– int read(char[] cbuf)
无参数读取文件数据:System.out.print((char) ch);
package com.demo02;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/*
* 需求:从文件中读数据并显示到控制台
* 读数据--输入流--FileReader
*
* FileReader:
* FileReader(String fileName):传递文件名称
*
* 输入流读文件的步骤:
* A:创建输入流对象
* B:调用输入流对象的读数据方法
* C:释放资源
*
* java.io.FileNotFoundException: fr.txt (系统找不到指定的文件。)
*/
public class FileReaderDemo {
public static void main(String[] args) throws IOException {
//创建输入流对象
FileReader fr = new FileReader("FileWriterDemo.java");
int ch;
while ((ch = fr.read()) != -1) {
System.out.print((char) ch);
}
//释放资源
fr.close();
}
}
有参数的读取:System.out.print(new String(chs,0,len));
package com.demo02;
import java.io.FileReader;
import java.io.IOException;
/*
* 输入流读数据的步骤:
* A:创建输入流对象
* B:调用输入流对象的读数据方法
* C:释放资源
*/
public class FileReaderDemo2 {
public static void main(String[] args) throws IOException {
//创建输入流对象
//FileReader fr = new FileReader("fr2.txt");
FileReader fr = new FileReader("FileWriterDemo.java");
/*
//调用输入流对象的读数据方法
//int read(char[] cbuf):一次读取一个字符数组的数据,返回的是实际读取的字符个数
char[] chs = new char[5];
//第一次读数据
int len = fr.read(chs);
System.out.println("len:"+len);
//System.out.println(new String(chs));
System.out.println(new String(chs,0,len));
//第二次读数据
len = fr.read(chs);
System.out.println("len:"+len);
//System.out.println(new String(chs));
System.out.println(new String(chs,0,len));
//第三次读数据
len = fr.read(chs);
System.out.println("len:"+len);
System.out.println(new String(chs,0,len));
//我们发现读取代码的方式相似度很高,想用循环改进,但是不知道什么时候结束循环
len = fr.read(chs);
System.out.println("len:"+len);
len = fr.read(chs);
System.out.println("len:"+len);
//通过测试,我们知道,如果实际读取长度是-1的时候,说明没有数据了
*
*/
//char[] chs = new char[5];
char[] chs = new char[1024]; //这里可以是1024及其整数倍
int len;
//1:fr.read(chs)
//2:len=fr.read(chs)
//3:len != -1
while((len=fr.read(chs))!=-1) {
//System.out.println(new String(chs,0,len));
System.out.print(new String(chs,0,len));
}
//释放资源
fr.close();
}
}
IO流案例
• 复制文本文件
– 一次读写一个字符
– 一次读写一个字符数组
package com.demo03;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
* 需求:
* 把项目路径下的FileWriterDemo.java中的内容复制到项目路径下的Copy.java中
*
* 文件复制也是有规律可循的,也就是说有套路。
*
* 数据源:
* FileWriterDemo.java -- 读数据 -- FileReader
* 目的地:
* Copy.java -- 写数据 -- FileWriter
*/
public class CopyFileDemo {
public static void main(String[] args) throws IOException {
//创建输入流对象
FileReader fr = new FileReader("FileWriterDemo.java");
//创建输出流对象
FileWriter fw = new FileWriter("d:\\Copy.java");
//读写数据
int ch;
while((ch=fr.read())!=-1) {
fw.write(ch);
}
//释放资源
fw.close();
fr.close();
}
}
package com.demo03;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
* 需求:
* 把项目路径下的FileWriterDemo.java中的内容复制到项目路径下的Copy.java中
*
* 数据源:
* FileWriterDemo.java -- 读数据 -- FileReader
* 目的地:
* Copy.java -- 写数据 -- FileWriter
*/
public class CopyFileDemo2 {
public static void main(String[] args) throws IOException {
//创建输入流对象
FileReader fr = new FileReader("FileWriterDemo.java");
//创建输出流对象
FileWriter fw = new FileWriter("d:\\Copy.java");
//读写数据
char[] chs = new char[1024];
int len;
while((len=fr.read(chs))!=-1) {
fw.write(chs, 0, len);
}
//释放资源
fw.close();
fr.close();
}
}
运行结果:
有参数的复制:
package IOandFile;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
* 需求:
* 把项目路径下的FileWriterDemo.java中的内容复制到项目路径下的Copy.java中
*
* 文件复制也是有规律可循的,也就是说有套路。
*
* 数据源:
* FileWriterDemo.java -- 读数据 -- FileReader
* 目的地:
* Copy.java -- 写数据 -- FileWriter
*/
public class CopyFileDemo {
public static void main(String[] args) throws IOException {
// 创建输入流对象
FileReader fr = new FileReader("FileWriter1.java");
// 创建输出流对象
FileWriter fw = new FileWriter("e:\\copy2.java");
// 读写数据
int ch;
// 无参数读取
/*while ((ch = fr.read())!= -1){ //读取数据 输入
fw.write(ch);
}*/
// 有参数读取
char[] chs = new char[5];
int len;
while ((len = fr.read(chs)) != -1){
fw.write(chs,0,len);
}
// 释放资源
fr.close();
fw.close();
}
}
运行结果:
字符缓冲流
• BufferedWriter基本用法
• BufferedReader基本用法
基本用法代码:
package com.demo04;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
* BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
* BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
*/
public class BufferedStreamDemo {
public static void main(String[] args) throws IOException {
//创建输出缓冲流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
bw.write("hello");
bw.flush();
bw.close();
//创建输入缓冲流对象
BufferedReader br = new BufferedReader(new FileReader("FileWriterDemo.java"));
//一次读写一个字符
int ch;
while((ch=br.read())!=-1){
System.out.print((char)ch);
}
//一次读写一个字符数组
char[] chs = new char[1024];
int len;
while((len=br.read(chs))!=-1) {
System.out.print(new String(chs,0,len));
}
//释放资源
br.close();
}
}
• 字符缓冲流复制文本文件
package com.demo05;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
* 需求:
* 把项目路径下的FileWriterDemo.java中的内容复制到项目路径下的Copy.java中
*
* 数据源:
* FileWriterDemo.java -- 读数据 -- FileReader -- 高效的读数据 -- BufferedReader
* 目的地:
* Copy.java -- 写数据 -- FileWriter -- 高效的写数据 -- BufferedWriter
*/
public class CopyFileDemo {
public static void main(String[] args) throws IOException {
//创建输入缓冲流对象
BufferedReader br = new BufferedReader(new FileReader("FileWriterDemo.java"));
//创建输出缓冲流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java"));
//读写数据
String line;
while((line=br.readLine())!=null) {
bw.write(line);
bw.newLine();
bw.flush();
}
//释放资源
bw.close();
br.close();
}
}
• 特殊功能
– BufferedWriter
• void newLine()
– BufferedReader
• String readLine()
• 字符缓冲流特殊功能复制文本文件
代码:
package com.demo05;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
/*
* 缓冲流的特殊功能:
* BufferedWriter
* void newLine():写一个换行符,这个换行符由系统决定
* BufferedReader
* String readLine():一次读取一行数据,但是不读取换行符
*/
public class BufferedStreamDemo {
public static void main(String[] args) throws IOException {
/*
BufferedWriter bw = new BufferedWriter(new FileWriter("bw2.txt"));
for(int x=0; x<10; x++) {
bw.write("hello"+x);
//bw.write("\r\n");
bw.newLine();
bw.flush();
}
bw.close();
*/
BufferedReader br = new BufferedReader(new FileReader("br.txt"));
/*
String line = br.readLine();
System.out.println(line);
line = br.readLine();
System.out.println(line);
line = br.readLine();
System.out.println(line);
line = br.readLine();
System.out.println(line);
*/
String line;
//1:br.readLine()
//2:line=br.readLine()
//3:line != null
while((line=br.readLine())!=null) {
System.out.println(line);
}
br.close();
}
}
输入缓冲流复制
package com.demo05;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
* 需求:
* 把项目路径下的FileWriterDemo.java中的内容复制到项目路径下的Copy.java中
*
* 数据源:
* FileWriterDemo.java -- 读数据 -- FileReader -- 高效的读数据 -- BufferedReader
* 目的地:
* Copy.java -- 写数据 -- FileWriter -- 高效的写数据 -- BufferedWriter
*/
public class CopyFileDemo {
public static void main(String[] args) throws IOException {
//创建输入缓冲流对象
BufferedReader br = new BufferedReader(new FileReader("FileWriterDemo.java"));
//创建输出缓冲流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java"));
//读写数据
String line;
while((line=br.readLine())!=null) {
bw.write(line);
bw.newLine();
bw.flush();
}
//释放资源
bw.close();
br.close();
}
}
十一、上部分综合练习
题目一:学生信息存入文件中
(1)键盘录入3个学生信息(学号,姓名,年龄,居住城市)存入集合。然后遍历集合把每一个学生信息存入文本文件(每一个学生信息为一行,自己定义分割标记)
A:定义学生类
B:创建集合对象
C:写方法实现键盘录入学生信息,并把学生对象作为元素添加到集合
D:创建输出缓冲流对象
E:遍历集合,得到每一个学生信息,并把学生信息按照一定的格式写入文本文件
(2)把上一题的文本文件中的学生信息读取出来存储到集合中,然后遍历集合,在控制台输出。
思路:
A:定义学生类
B:创建输入缓冲流对象
C:创建集合对象
D:读取文件数据,并把数据按照一定的格式进行分割赋值给学生对象,然后把学生对象作为元素存储到集合
E:释放资源
F:遍历集合
第一题:
Student:
package com.itheima;
/*
* 标准的学生类
*/
public class Student {
//学号
private String id;
//姓名
private String name;
//年龄
private String age;
//居住地
private String address;
public Student() {
}
public Student(String id, String name, String age, String address) {
this.id = id;
this.name = name;
this.age = age;
this.address = address;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
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;
}
}
ArrayListToFile:
package com.itheima;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
/*
* 键盘录入3个学生信息(学号,姓名,年龄,居住地)存入集合。然后遍历集合把每一个学生信息存入文本文件(每一个学生信息为一行数据,自己定义分割标记)
*
* 分析:
* A:定义学生类
* B:创建集合对象
* C:写方法实现键盘录入学生信息,并把学生对象作为元素添加到集合
* D:创建输出缓冲流对象
* E:遍历集合,得到每一个学生信息,并把学生信息按照一定的格式写入文本文件
* 举例:heima001,向问天,30,北京
* F:释放资源
*/
public class ArrayListToFileTest {
public static void main(String[] args) throws IOException {
//创建集合对象
ArrayList<Student> array = new ArrayList<Student>();
//写方法实现键盘录入学生信息,并把学生对象作为元素添加到集合
addStudent(array);
addStudent(array);
addStudent(array);
//创建输出缓冲流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("d:\\array.txt"));
//遍历集合,得到每一个学生信息,并把学生信息按照一定的格式写入文本文件
for(int x=0; x<array.size(); x++) {
Student s = array.get(x);
//heima001,向问天,30,北京
StringBuilder sb = new StringBuilder();
sb.append(s.getId()).append(",").append(s.getName()).append(",").append(s.getAge()).append(",").append(s.getAddress());
bw.write(sb.toString());
bw.newLine();
bw.flush();
}
//释放资源
bw.close();
}
//添加学生
public static void addStudent(ArrayList<Student> array) {
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
//为了让id能够被访问到,我们就把id定义在了循环的外面
String id;
//为了让代码能够回到这里,用循环
while(true) {
System.out.println("请输入学生学号:");
//String id = sc.nextLine();
id = sc.nextLine();
//判断学号有没有被人占用
//定义标记
boolean flag = false;
//遍历集合,得到每一个学生
for(int x=0; x<array.size(); x++) {
Student s = array.get(x);
//获取该学生的学号,和键盘录入的学号进行比较
if(s.getId().equals(id)) {
flag = true; //说明学号被占用了
break;
}
}
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.setId(id);
s.setName(name);
s.setAge(age);
s.setAddress(address);
//把学生对象作为元素添加到集合
array.add(s);
//给出提示
System.out.println("添加学生成功");
}
}
结果:
第二题:
package com.itheima;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
/*
* 把上一题的文本文件中的学生信息读取出来存储到集合中,然后遍历集合,在控制台输出
*
* 分析:
* A:定义学生类
* B:创建输入缓冲流对象
* C:创建集合对象
* D:读取文件数据,并把数据按照一定的格式进行分割赋值给学生对象,然后把学生对象作为元素存储到集合
* heima001,向問天,30,北京
* E:释放资源
* F:遍历集合
*/
public class FileToArrayListTest {
public static void main(String[] args) throws IOException {
//B.创建输入缓冲流对象
BufferedReader br = new BufferedReader(new FileReader("d:\\array.txt"));
//C.创建集合对象
ArrayList<Student> array = new ArrayList<Student>();
//D.读取文件数据,并把数据按照一定的格式进行分割赋值给学生对象,然后把学生对象作为元素存储到集合
String line;
while((line=br.readLine())!=null) {
//分割字符串
String[] strArray = line.split(",");
//创建学生对象并赋值
Student s = new Student();
s.setId(strArray[0]);
s.setName(strArray[1]);
s.setAge(strArray[2]);
s.setAddress(strArray[3]);
//把学生对象作为元素存储到集合
array.add(s);
}
//E.释放资源
br.close();
//F.遍历集合
System.out.println("学号\t姓名\t年龄\t居住地");
for(int x=0; x<array.size(); x++) {
Student s = array.get(x);
System.out.println(s.getId()+"\t"+s.getName()+"\t"+s.getAge()+"\t"+s.getAddress());
}
}
}
结果
题目二:学生管理系统最终版
需求:实现从文件中读取数据,写入数据,增删改查的功能。
IO流思路:
文档数据库
student:
package upTest.StuManage;
public class student {
private String id;
private String name;
private String age;
private String address;
public student(){}
public student(String id,String name,String age,String address){
this.id = id;
this.name = name;
this.age = age;
this.address = address;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
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;
}
}
studentManageTest:
package upTest.StuManage;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
/*
* 这是我的学生管理系统的主类
*
* 步骤如下:
* A:定义学生类
* B:学生管理系统的主界面的代码编写
* C:学生管理系统的查看所有学生的代码编写
* D:学生管理系统的添加学生的代码编写
* E:学生管理系统的删除学生的代码编写
* F:学生管理系统的修改学生的代码编写
*/
public class StudentManageTest {
public static void main(String[] args) throws IOException{
//定义文件路径
String fileName = "student.txt";
//为了让程序能够回到这里来,我们使用循环
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 sc = new Scanner(System.in);
String choiceString = sc.nextLine();
//用switch语句实现选择
switch(choiceString) {
case "1":
//查看所有学生
findAllstudent(fileName);
break;
case "2":
//添加学生
addstudent(fileName);
break;
case "3":
//删除学生
deletestudent(fileName);
break;
case "4":
//修改学生
updatestudent(fileName);
break;
case "5":
default:
System.out.println("谢谢你的使用");
System.exit(0); //JVM退出
break;
}
}
}
//从文件中读数据到集合
public static void readData(String fileName,ArrayList<student> array) throws IOException {
//创建输入缓冲流对象
BufferedReader br = new BufferedReader(new FileReader(fileName));
String line;
while((line=br.readLine())!=null) {
String[] datas = line.split(","); //001,向问天,20,北京
student s = new student();
s.setId(datas[0]);
s.setName(datas[1]);
s.setAge(datas[2]);
s.setAddress(datas[3]);
array.add(s);
}
br.close();
}
//把集合中的数据写入文件
public static void writeData(String fileName,ArrayList<student> array) throws IOException {
//创建输出缓冲流对象
BufferedWriter bw = new BufferedWriter(new FileWriter(fileName));
for(int x=0; x<array.size(); x++) {
student s = array.get(x);
StringBuilder sb = new StringBuilder();
sb.append(s.getId()).append(",").append(s.getName()).append(",").append(s.getAge()).append(",").append(s.getAddress());
bw.write(sb.toString()); //001,向问天,20,北京
bw.newLine();
bw.flush();
}
bw.close();
}
//修改学生
public static void updatestudent(String fileName) throws IOException {
//创建集合对象
ArrayList<student> array = new ArrayList<student>();
//从文件中把数据读取到集合中
readData(fileName, array);
//修改学生的思路:键盘录入一个学号,到集合中去查找,看是否有学生使用的是该学号,如果有就修改该学生
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
System.out.println("请输入你要修改的学生的学号:");
String id = sc.nextLine();
//定义一个索引
int index = -1;
//遍历集合
for(int x=0; x<array.size(); x++) {
//获取每一个学生对象
student s = array.get(x);
//拿学生对象的学号和键盘录入的学号进行比较
if(s.getId().equals(id)) {
index = x;
break;
}
}
if(index == -1) {
System.out.println("不好意思,你要修改的学号对应的学生信息不存在,请回去重新你的选择");
}else {
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.setId(id);
s.setName(name);
s.setAge(age);
s.setAddress(address);
//修改集合中的学生对象
array.set(index, s);
//把集合中的数据重新写回到文件
writeData(fileName, array);
//给出提示
System.out.println("修改学生成功");
}
}
//删除学生
public static void deletestudent(String fileName) throws IOException {
//创建集合对象
ArrayList<student> array = new ArrayList<student>();
//从文件中把数据读取到集合中
readData(fileName, array);
//删除学生的思路:键盘录入一个学号,到集合中去查找,看是否有学生使用的是该学号,如果有就删除该学生
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
System.out.println("请输入你要删除的学生的学号:");
String id = sc.nextLine();
//我们必须给出学号不存在的时候的提示
//定义一个索引
int index = -1;
//遍历集合
for(int x=0; x<array.size(); x++) {
//获取到每一个学生对象
student s = array.get(x);
//拿这个学生对象的学号和键盘录入的学号进行比较
if(s.getId().equals(id)) {
index = x;
break;
}
}
if(index == -1) {
System.out.println("不好意思,你要删除的学号对应的学生信息不存在,请回去重新你的选择");
}else {
array.remove(index);
//把集合中的数据重新写回到文件
writeData(fileName, array);
System.out.println("删除学生成功");
}
}
//添加学生
public static void addstudent(String fileName) throws IOException {
//创建集合对象
ArrayList<student> array = new ArrayList<student>();
//从文件中把数据读取到集合中
readData(fileName, array);
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
//为了让id能够被访问到,我们就把id定义在了循环的外面
String id;
//为了让代码能够回到这里,用循环
while(true) {
System.out.println("请输入学生学号:");
//String id = sc.nextLine();
id = sc.nextLine();
//判断学号有没有被人占用
//定义标记
boolean flag = false;
//遍历集合,得到每一个学生
for(int x=0; x<array.size(); x++) {
student s = array.get(x);
//获取该学生的学号,和键盘录入的学号进行比较
if(s.getId().equals(id)) {
flag = true; //说明学号被占用了
break;
}
}
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.setId(id);
s.setName(name);
s.setAge(age);
s.setAddress(address);
//把学生对象作为元素添加到集合
array.add(s);
//把集合中的数据重新写回到文件
writeData(fileName, array);
//给出提示
System.out.println("添加学生成功");
}
//查看所有学生
public static void findAllstudent(String fileName) throws IOException {
//创建集合对象
ArrayList<student> array = new ArrayList<student>();
//从文件中把数据读取到集合中
readData(fileName, array);
//首先来判断集合中是否有数据,如果没有数据,就给出提示,并让该方法不继续往下执行
if(array!=null&&array.size() == 0) {
System.out.println("不好意思,目前没有学生信息可供查询,请回去重新选择你的操作");
return;
}
//\t 其实就是一个tab键的位置
System.out.println("学号\t姓名\t年龄\t居住地");
for(int x=0; x<array.size(); x++) {
student s = array.get(x);
System.out.println(s.getId()+"\t"+s.getName()+"\t"+s.getAge()+"\t"+s.getAddress());
}
}
}
运行结果:
upTest.StuManage.StudentManageTest
--------欢迎来到学生管理系统--------
1 查看所有学生
2 添加学生
3 删除学生
4 修改学生
5 退出
请输入你的选择:
1
学号 姓名 年龄 居住地
001 孙悟空 1000 水帘洞
002 令狐冲 23 上海
005 刘德华 48 香港
--------欢迎来到学生管理系统--------
1 查看所有学生
2 添加学生
3 删除学生
4 修改学生
5 退出
请输入你的选择:
2
请输入学生学号:
004
请输入学生姓名:
小欧
请输入学生年龄:
25
请输入学生居住地:
重庆
添加学生成功
--------欢迎来到学生管理系统--------
1 查看所有学生
2 添加学生
3 删除学生
4 修改学生
5 退出
请输入你的选择:
4
谢谢你的使用
Process finished with exit code 0
十二、面向对象-static&代码块
面向对象
1.static(静态)关键字
static是一个修饰符,用于修饰成员(成员变量 、成员方法)
static的特点
随着类的加载而加载
优先于对象存在
被类的所有对象共享
可以被类名调用
package demoStatic;
/**
* static 是一个关键字,用于修饰成员变量(方法外部)和成员方法
* 随着类的加载而加载
* 可以用类名调用
* 静态的加载优先于对象
* 被所有的对象共享
* */
public class staticDemo1 {
public static void main(String[] args) {
Person.graduateFrom = "安徽大学";
Person p = new Person();
p.age = 19;
p.name = "小曼";
p.speak();
Person.think();//只能类名调用不能对象名调用
// p.think();错误
}
}
class Person{
String name;
int age;
static String graduateFrom; //毕业学校
public void speak(){
System.out.println(name + "---" + graduateFrom);
}
public static void think(){
System.out.println("学会思考");
}
}
2.static的注意事项
- 静态方法只能访问静态成员
- 非静态方法既可以访问静态也可以访问非静态
- 非静态方法中不可以定义静态变量
- 静态方法中不可以定义this,super关键字
static的优点
对对象的共享数据提供单独空间的存储,节省空间,没有必要每一个对象都存储一份。
可以直接被类名调用,不用在堆内存创建对象。
static的弊端
访问出现局限性。(静态虽好,但只能访问静态)
package demoStatic;
/* static注意事项
* 静态方法:
* 1.可以调用静态的成员变量和成员方法
* 2.不可以调用非静态的成员变量和成员方法
* 3.静态方法只能调用静态的成员
* 非静态方法:
* 1.可以调用静态的成员变量和成员方法
* 2.可以调用非静态的成员变量和成员方法
* */
public class staticDemo2 {
public static void main(String[] args) {
Student s = new Student();
s.name = "小何";
s.age = 19;
Student.graduateFrom = "安徽大学";
s.eat();
System.out.println(s.name +" " + s.age);
}
}
class Student{
String name;
int age;
static String graduateFrom;
public static void sleep(){
System.out.println("sleep");
}
public void eat(){
System.out.println("eat");
System.out.println(graduateFrom); //非静态方法调用静态的成员变量
sleep(); //非静态的方法可以调用静态的方法
}
}
运行结果
eat
安徽大学
sleep
小何 19
3.应用场景 Math类
- Math类的学习和使用
Math 类包含用于执行基本数学运算的方法。数学操作常用的类。
import static java.lang.Math.*; //导入Math包
static double abs(double a) :返回绝对值
static double ceil(double a) 天花板 向上取整
static double floor(double a) 地板 向下取整
static long round(double a) :四舍五入
static double pow(double a, double b) :返回第一个参数的第二个参数次幂
static double random() :返回一个随机数,大于零且小于一
/*
* static double abs(double a) :返回绝对值
static double ceil(double a) 天花板 向上取整
static double floor(double a) 地板 向下取整
static long round(double a) :四舍五入
static double pow(double a, double b) :返回第一个参数的第二个参数次幂
static double random() :返回一个随机数,大于零且小于一
* */
import static java.lang.Math.*; //导入Math包
public class Math {
public static void main(String[] args) {
System.out.println(PI); //结果:3.141592653589793
System.out.println(ceil(3.2)); //向上取整
System.out.println(floor(3.2));//向下取整
System.out.println(round(3.2));//四舍五入
System.out.println(pow(3, 2));//返回第一个参数的第二个参数次幂
System.out.println((int) (random() * 100 + 1)); //获取1-100以内的随机整数 (int)强制类型转换
}
}
//结果
3.141592653589793
4.0
3.0
3
9.0
84
- Math类的使用
没有构造方法,我们如何使用呢? - Math类要掌握的功能
字段:PI
方法:abs ,max,min ,pow,ceil,floor,round,random
导入math包:
import static java.lang.Math.*;
想要省略代码块中的Math,需要导入Math包中的所有类java.lang.Math.*;需要加static关键字。
4.自定义工具类
自定义一个工具类里面可以存放好几种方法,一次调用。
MyArrays工具类:
/*static自定义工具类
数组工具类
**/
public class MyArrays {
/*返回数组中最大的元素*/
private MyArrays() {
}//不允许外界调用
public static int getMax(int[] arr) {
int max = arr[0];
if (arr.length == 0 || arr == null) {
return 0;
}
for (int i = 0; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
/*
* 返回数组中指定参数的索引
*/
public static int getIndex(int[] arr, int a) {
// 遍历数组
for (int i = 0; i < arr.length; i++) {
if (arr[i] == a) {
return i;
}
}
return -1; //查不到就返回-1
}
}
MyArrayDemo MyArrays的示范(demo)
package demoStatic;
//调用MyArray中的方法
public class MyArrayDemo {
public static void main(String[] args) {
int[] arr={1,3,2,6,5};
int max = MyArrays.getMax(arr);
System.out.println(max);
int index = MyArrays.getIndex(arr,2);
System.out.println(index);
}
}
运行结果:
6
2
代码块
- 在Java中,使用{}括起来的代码被称为代码块
- 代码块分类
局部代码块
构造代码块
静态代码块
同步代码块(多线程讲解)
- 应用场景
- 局部代码块
在方法中出现,控制变量生命周期,及早释放,提高内存利用率。
public static void main(String[] args) {
//局部代码块:存在于方法中,控制变量的生命周期(作用域)
{
for(int x = 0;x < 10;x++) {
System.out.println("我爱Java");
}
int num = 10;
}
}
- 构造代码块
在类中方法外出现,抽取构造方法中的共性,每次创建对象都会执行,并且在构造方法前执行。
class Teacher {
String name;
int age;
// 构造代码块:提取构造方法中的共性,每次创建对象都会执行,并在构造方法执行之前执行。
{
for (int i = 0; i < 10; i++) {
System.out.println("我爱Java1");
}
}
}
- 静态代码块
在类中方法外出现,并加上static修饰;用于给类进行初始化,在加载的时候就执行,并且只执行一次。
class Teacher {
String name;
int age;
// 静态代码块:随着类的加载而加载,只加载一次,加载类的时候需要做的一些初始化,如加载驱动
static {
System.out.println("我爱java2");
}
}
一般用于加载驱动。
blockDemo(代码块示范):
package demoStatic;
public class blockDemo {
public static void main(String[] args) {
//局部代码块:存在于方法中,控制变量的生命周期(作用域)
/*{
for(int x = 0;x < 10;x++) {
System.out.println("我爱Java");
}
int num = 10;
}*/
//System.out.println(num);
Teacher t = new Teacher();
Teacher t2 = new Teacher("王老师", 18);
}
}
class Teacher {
String name;
int age;
// 构造代码块:提取构造方法中的共性,每次创建对象都会执行,并在构造方法执行之前执行。
{
for (int i = 0; i < 2; i++) {
System.out.println("我爱Java1");
}
}
// 静态代码块:先执行。随着类的加载而加载,只加载一次,加载类的时候需要做的一些初始化,如加载驱动
static {
System.out.println("我爱java2");
}
public Teacher() {
System.out.println("我是无参构造");
}
public Teacher(String name, int age) {
System.out.println("我是有参构造");
this.name = name;
this.age = age;
}
}
---
我爱java2
我爱Java1
我爱Java1
我是无参构造
我爱Java1
我爱Java1
我是有参构造
package demoStatic;
/*Coder静态代码执行--Coder构造代码块执行——Coder无参构造代码块执行
* BlockTest静态代码块执行——> BlockTest主函数代码块执行
* ——> BlockTest静态代码块执行——> Coder静态代码块执行
* ——> Coder构造代码块执行——>Coder无参空构造执行
* ——>Coder构造代码块执行——>Coder无参空构造执行
* */
public class blockTest {
static {
System.out.println("BlockTest静态代码块执行");
}
{
System.out.println("BlockTest构造代码块执行");
}
public void BlockTest(){
System.out.println("BlockTest无参构造执行了");
}
public static void main(String[] args) {
System.out.println("BlockTest主函数执行了");
Coder c = new Coder();
Coder c2 = new Coder();
}
}
class Coder {
static { //静态代码块随着类的加载而加载,只执行一次
System.out.println("Coder静态代码块执行了");
}
{
System.out.println("Coder构造代码块执行了");
}
public Coder() {
System.out.println("Coder无参构造执行");
}
}
结果:
BlockTest静态代码块执行
BlockTest主函数执行了
Coder静态代码块执行了
Coder构造代码块执行了
Coder无参构造执行
Coder构造代码块执行了
Coder无参构造执行
十三、面向对象-继承与抽象类
2023/2/16-2/17
1.继承概述
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。
子类可以直接访问父类中的非私有的属性和行为。
通过 extends 关键字让类与类之间产生继承关系。
class SubDemo extends Demo{}
package ExtendsDemo;
/*继承:如果多个类有共同的成员变量和成员方法,就抽取相同的部分到一个父类当中,让多个类去继承这个父类,就可以多个类继承父类的成员了。
* */
public class ExtendsDemo1 {
public static void main(String[] args) {
DotA d = new DotA();
d.start();
LoL l = new LoL();
l.end();
}
}
class Game{
String name;
double version;
String agent;
public void start(){
System.out.println("游戏启动");
}
public void end(){
System.out.println("游戏结束");
}
}
class DotA extends Game{ //子类继承父类里面的成员变量和成员方法就可以省略
/* String name;
double version;
String agent;
public void start(){
System.out.println("游戏启动");
}
public void end(){
System.out.println("游戏结束");
}*/
}
class LoL extends Game{
}
运行结果:
游戏启动
游戏结束
2.继承的特点
Java只支持单继承,不支持多继承。
一个类只能有一个父类,不可以有多个父类。
class SubDemo extends Demo{} //ok
class SubDemo extends Demo1,Demo2...//error
Java支持多层继承(继承体系)
class A{}
class B extends A{}
class C extends B{}
package ExtendsDemo;
/**继承的特点:
* java只支持单继承,一个子类只能继承一个父类(一个儿子只能有一个亲爹)(一个子类有多个父类是C++)
* java支持多层继承,(一个儿子可以有一个爸爸和一个爷爷)
* */
public class ExtendsDemo2 {
public static void main(String[] args) {
Game2 game2 = new Game2();
game2.start();
DOTA2 dota2 = new DOTA2();
dota2.updata();
LOL l = new LOL();
l.updata();
}
}
class Game2{ //父类
public void start(){
System.out.println("游戏启动了");
}
}
class DOTA2 extends Game2{
public void updata(){
System.out.println("游戏更新了");
}
}
class LOL extends DOTA2{ //A,B继承A,C继承B
}
运行结果:
游戏启动了
游戏更新了
游戏更新了
继承的优缺点
优点
提高了代码的复用性
提高了代码的可维护性
缺点:
类的耦合性增强了
开发的原则:高内聚低耦合
内聚:就是自己完成某件事情的能力
耦合:类与类的关系
3.继承中的成员变量
如果子父类中出现非私有的同名成员变量时,子类要访问本类中的变量,用this;访问父类中的同名变量 用super。
super的使用和this的使用几乎一致。
this代表的是本类对象的引用;super当前子类对象父类的引用
4.继承中的成员方法
- 当子类出现和父类一模一样的方法时,当子类对象调用该方法,会运行子类方法的内容。如同父类的方法被覆盖一样。
- 这种情况是方法的另一个特性:
重写(覆盖)(override)
重载overload
package ExtendsDemo;
/*继承中成员变量的特点
子类只能获取父类的非私有成员变量
子父类中成员变量名字不一样,直接获取父类的成员变量
子父类中成员变量名字一样,获取的是子类的成员变量
就近原则:谁离我近我就用谁
* 如果有局部变量就使用局部变量
* 如果没有局部变量,有子类的成员变量就使用子类的成员变量
* 如果没有局部变量和子类的成员变量,有父类的成员变量就使用父类的成员变量
* 啥都没有,出错了!!!
*
* super:可以获取父类的成员变量和成员方法,用法和this是相似的
* */
public class ExtendsDemo4 {
public static void main(String[] args) {
Kid4 k = new Kid4();
k.eat();
}
}
class Dad4{
String name = "小何";
String superName = "父类中的成员变量";
}
class Kid4 extends Dad4{
String name = "小司";
public void eat(){
System.out.println(super.superName);
String name = "小吴";
System.out.println(super.name);
System.out.println(this.name);
System.out.println(name);
}
}
运行结果:
父类中的成员变量
小何
小司
小吴
5.方法的重写
- 子类中出现与父类一模一样的方法时,会出现覆盖操作,也称为重写或者复写。
- 父类中的私有方法可不可以被覆盖呢?子类根本就看不到父类的方法。
- 在子类覆盖方法中,继续使用被覆盖的方法可以通过super.方法名获取。
- 覆盖注意事项: 覆盖时,子类方法权限一定要大于等于父类方法权限。
- 覆盖的应用:
当子类需要父类的功能,而功能主体子类有自己特有内容时,可以复写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容。
package ExtendsDemo;
/*继承中成员方法(类中)的特点:
子类中没有这个方法调用父类的
子类中重写了这个方法,调用子类的
方法重写@override 在子类当中,子类和父类的方法完全一样,子类覆盖了父类的方法,重写之后,使用子类对象调用的就是子类的方法。
方法重载@overload 在一个类中有多个重名方法,但是方法参数不同(参数类型、数目,顺序),和返回值无关。
**/
public class Extendsdemo3 {
public static void main(String[] args) {
Dad3 d = new Dad3();
d.eat();
Kid3 k =new Kid3();
k.eat();
k.eat("小何");
}
}
class Dad3{
public void eat(){ //第1步调用 第2步调用
System.out.println("喝酒");
System.out.println("睡觉");
}
}
class Kid3 extends Dad3{
public void eat(){ //子类重写父类方法
super.eat(); //调用父类的eat方法,不写就不调用了
System.out.println("学习"); //第3步调用
}
public void eat(String name){ //方法重载 第4步调用
System.out.println("吃饭");
}
}
运行结果:
喝酒
睡觉
喝酒
睡觉
学习
吃饭
package ExtendsDemo;
import sun.rmi.runtime.NewThreadAction;
/*方法重写的应用场景: 当父类的方法不能完全满足子类的使用,就需要重写方法
方法重写的注意事项:不能重写父类的私有方法
权限必须大于父类方法的权限
* */
public class ExtendsDemo5 {
public static void main(String[] args) {
Phone p = new Phone();
p.call();
NewPhone np = new NewPhone();
np.call();
}
}
class Phone{
public void call(){
System.out.println("打电话");
}
}
class NewPhone extends Phone{
@Override
public void call(){
System.out.println("录音");
super.call();
}
}
打电话
录音
打电话
方法重写与方法重载区别
方法重写@override 在子类当中,子类和父类的方法完全一样,子类覆盖了父类的方法,重写之后,使用子类对象调用的就是子类的方法。
方法重载@overload 在一个类中有多个重名方法,但是方法参数不同(参数类型、数目,顺序),和返回值无关。
6.继承中的构造方法
- 在对子类对象进行初始化时,父类的构造方法也会运行,那是因为子类的构造方法默认第一行有一条隐式的语句super()
- super():会访问父类中的空参数构造方法。而且子类中所有的构造方法默认第一行都是super( )
package ExtendsDemo;
import javafx.scene.Parent;
/*
* 继承中构造方法的执行顺序
* 在子父类中,创建子类对象,调用子类的构造方法,
* 在子类的构造方法的第一行代码如果没有调用父类的构造或者没有调用子类的其他构造,则默认调用父类无参构造
* 为什么要调用父类构造?
* 因为需要给父类的成员变量初始化
* 肯定会先把父类的构造执行完毕,再去执行子类构造中的其他代码
*
* 我是父类无参构造 --- 我是子类有参构造 --- 我是子类无参构造
*/
public class ExtendDemo6 {
public static void main(String[] args) {
Son6 son6 = new Son6();
}
}
class Parent6{
public Parent6(){
System.out.println("父类无参构造"); //第一步
}
public Parent6(int num){
System.out.println("父类有参构造");
}
}
class Son6 extends Parent6{
public Son6(){
this(1);
System.out.println("我是子类无参构造");//第4步
}
public Son6(int num){ //子类的有参构造
this(1l);
// 默认调用父类无参构造
System.out.println("子类有参构造");//第3步
}
public Son6(long num){
// 默认调用父类无参构造
System.out.println("子类有参构造");//第2步
}
运行结果:
父类无参构造
子类有参构造
子类有参构造
我是子类无参构造
7.super关键字
- super和this的用法相像
- this代表对象的引用(谁调用就代表谁)
- super代表当前子类对象父类的引用
当子父类出现同名成员时,可以用super进行区分
子类要调用父类构造方法时,可以使用super语句
super和this的区别
- this :对象的引用(谁调用就代表谁)
- 使用this关键字引用成员变量。
- 使用this关键字在自身构造方法内部引用其他构造方法。
- 使用this关键字引用成员方法
- super :当前对象里面的父类的引用。
- 在子类的构造方法内部引用父类的构造方法。
- 在子类中调用父类中的成员方法。
- 在子类中调用父类中的成员变量。
package ExtendsDemo;
/*this和super的区别
this:当前对象的引用
调用子类的成员变量和成员方法
在子类构造方法第一行调用子类其他的构造方法
* */
public class ExtendDemo7 {
public static void main(String[] args) {
Son7 son7 = new Son7();
son7.function();
}
}
class Parent7{
int num = 10;
public Parent7(){
System.out.println("父类无参构造");
}
public Parent7(int num){
System.out.println("父类有参构造");
}
public void method(){
System.out.println("父类方法");
}
}
class Son7 extends Parent7{
int num = 30;
public Son7(){
System.out.println("子类无参构造");
}
public Son7(int num){
System.out.println("子类有参构造");
}
public void method(){
System.out.println("子类的方法");
}
public void function() {
this.num = 50;
System.out.println(num);
this.method();
super.num = 40;
super.method();
System.out.println(super.num);
System.out.println(this.num);
}
}
9.抽象类概述(abstract)
- 抽象定义
抽象是从多个事物中将共性的,本质的内容抽取出来。
例:狼和狗共性都是犬科,犬科就是抽象出来的概念。 - 抽象类
Java中可以定义没有方法体的方法,该方法的具体实现由子类完成,该方法称为抽象方法,包含抽象方法的类就是抽象类。 - 抽象方法(demo1)
- 抽象方法的由来
多个对象都具备相同的功能,但是功能具体内容有所不同,那么在抽取过程中,只抽取了功能定义,并未抽取功能主体,那么只有功能声明,没有功能主体的方法称为抽象方法。
例如:狼和狗都有吼叫的方法,可是吼叫内容是不一样的。所以抽象出来的犬科虽然有吼叫功能,但是并不明确吼叫的细节。
package AbstractTest;
/* 抽象类:有方法的定义,但是没有具体的功能,具体的功能需要具体的子类来确定。
java中可以定义没有方法体的方法,该方法具体实现由子类完成,该方法称为抽象方法,包括抽象方法的类就是抽象类
*抽象方法:没有功能主体的方法,多个对象都具备相同的功能,但功能具体内容不同,
* 在抽取过程中只抽取了功能定义,没有抽取功能主体,那么就只有功能声明,没有功能主体的方法就是抽象方法
* 基础班老师,就业班老师
* 共性:
* 属性 姓名,年龄,性别
* 行为 讲课,唱歌
*/
public class AbstractTest2 {
public static void main(String[] args) {
JobTeacher jobTeacher = new JobTeacher();
jobTeacher.name = "小红";
jobTeacher.teach();
MaryTeacher maryTeacher = new MaryTeacher();
maryTeacher.name = "小刚";
maryTeacher.teach();
}
}
abstract class Teacher{
String name;
int age;
String gender;
public abstract void teach();
}
class JobTeacher extends Teacher{
@Override
public void teach() {
System.out.println(name + "讲基础班");
}
}
class MaryTeacher extends Teacher{
@Override
public void teach(){
System.out.println(name + "讲高级班");
}
}
运行结果:
小红讲基础班
小刚讲高级班
-
抽象类的特点(demo2)
-
抽象方法一定在抽象类中
-
抽象方法和抽象类都必须被abstract关键字修饰
-
抽象类不可以用new创建对象,因为调用抽象方法没意义
-
抽象类中的抽象方法要被使用,必须由子类覆写其所有的抽象方法后,建立子类对象调用; 如果子类只覆盖了部分的抽象方法,那么该子类还是一个抽象类。
-
抽象类中可以有抽象方法也可以有非抽象方法
-
抽象类和一般类没有太大的不同: 该如何描述事物,就如何描述事物,只不过,该事物出现了一些看不懂得东西。这些不确定的部分,也是该事物的功能,需要明确出现。但是无法定义主体,也就是比一般类多了抽象方法而已.
**特殊:**抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象。
抽象类的成员特点
- 成员变量
可以有变量
可以有常量 - 构造方法
可以有构造方法 - 成员方法
可以有抽象方法
可以有非抽象方法
抽象类的案例
-
雇员(Employee)示例:
需求:
公司中
程序员(programmer)有姓名(name),工号(id),薪水(pay),工作内容(work)。
项目经理(Manager)除了有姓名(name),工号(id),薪水(pay),还有奖金(bonus),工作内容(work)员工:
属性 name,id,pay
行为 work
package AbstractTest;
/*雇员(Employee)示例:
需求:
公司中
程序员(programmer)有姓名(name),工号(id),薪水(pay),工作内容(work)。
项目经理(Manager)除了有姓名(name),工号(id),薪水(pay),还有奖金(bonus),工作内容(work)
员工:
属性 name,id,pay
行为 work
* */
public class AbstractTest1 {
public static void main(String[] args) {
Programmer programmer =new Programmer();
programmer.name = "小红";
programmer.work();
Manager manager = new Manager();
manager.name = "小明";
manager.work();
}
}
abstract class Worker{
String name;
int id;
double pay;
public abstract void work(); //共同的行为
}
class Programmer extends Worker{
@Override
public void work() {
System.out.println(name+"的工作内容");
}
}
class Manager extends Worker{
double bonus;
@Override
public void work() {
System.out.println(name+"盯着程序员写代码");
}
}
结果
小红的工作内容
小明盯着程序员写代码
- 学员示例(练习)
具体事物:基础班学员,就业班学员
共性:姓名,学习
package AbstractTest;
/*学员示例(练习)
具体事物:基础班学员,就业班学员
共性:姓名,学习
* */
public class AbstractTest3 {
public static void main(String[] args) {
BasicStudent basicStudent = new BasicStudent();
basicStudent.name = "小张";
basicStudent.study();
WorkStudent workStudent = new WorkStudent();
workStudent.name="小明";
workStudent.study();
}
}
abstract class Student{
String name;
public abstract void study();
}
class BasicStudent extends Student{
@Override
public void study() {
System.out.println(name + "是基础班学员");
}
}
class WorkStudent extends Student{
@Override
public void study() {
System.out.println(name+"是就业班学员");
}
}
小张是基础班学员
小明是就业班学员
抽象类的细节
- 抽象关键字abstract不可以和哪些关键字共存?
- 抽象类中是否有构造函数?
- 抽象类中可不可以没有抽象方法?
抽象类的思想
Writer和Reader
十四、面向对象-接口与多态
接口概述(interface)
定义:是抽象方法和常量值的集合
从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现
格式:
interface 接口名{}
例如
package com.demo01;
public interface Interface1 {
public static final float PI = 3.14f;
public abstract void method();
}
接口的出现将“多继承”通过另一种形式体现出来,即“多实现”。(implements)
新建接口文件:new-class-interface
接口的成员
接口中的成员修饰符是固定的
- 成员常量:public static final
接口里面定义变量是全局常量,而且上面三个关键字都可以省略,而且只能是 public static final - 成员函数:public abstract
接口里面定义的方法都是抽象的,而且上面的两个关键字也是可以省略的
接口中的成员都是public的
继承和实现
- 类与类之间称为继承:因为该类无论是抽象的还是非抽象的,它的内部都可以定义非抽象方法,这个方法可以直接被子类使用,所以子类继承就可以应用了
- 类与接口是实现关系:因为接口中的方法都是抽象的,必须由子类实现才可以实例化,所以就用了这个关键字implements
- 接口与接口之间是继承关系:一个接口可以继承另一个接口,并添加新的属性和抽象方法,并且接口可以多继承
- 根据上面的接口的这些特点,我有一个经典例子,就是女明星认干爹
单继承和多实现
- 类只能单继承,而接口可以多实现
java将多继承机制进行改良,通过多实现接口的形式来体现 - 为什么不支持多继承呢?
因为你继承的多个父类中定义了相同的方法,而方法内容不同,jvm无法判断选择哪个个父类的方法,有安全隐患
而多实现就没有这个问题,即使是多个接口中都有相同的方法,但是他们都没有方法体 - 多实现的好处,一个类继承另一个类的同时可以实现多个接口,一个女星只能有一个亲爹,但是干爹就可以有很多了.多实现的好处是扩展了功能
接口的出现打破了单继承的局限性(接口的好处)
接口的优点
- 接口是对外暴露的规则。
- 类与接口的关系是实现。
- 接口的出现降低耦合性。(实现了模块化开发,定义好规则,每个人实现自己的模块,大大提高了开发效率)。开发原则:高内聚低耦合
接口与抽象类异同
- 共性:都是不断抽取出来的抽象的概念 都有抽象方法
区别 1:与类的关系 抽象类是单继承,类只能接口
区别 2:
成员变量 接口里面只能是常量,不能有变量,因为是不能实现的。抽象类中可以有变量和常量
构造方法 抽象类中可以有构造方法,接口中不能有构造方法;
相同点:
1.抽象类和接口都不能直接实例化(创建对象);
2.抽象类的子类(或接口的实现类),都必须实现抽象类(或接口)中全部的抽象方法,才可以被实例化;否则,该类仍然为抽象类;
不同点:
1.关键字不同:抽象类子类使用extends关键字来继承抽象类,接口实现类使用关键字implements来实现接口;
2.抽象类中可以有构造方法,接口中不能有构造方法;
3.抽象类中既可以有抽象方法也可以有普通方法,接口中只能有抽象方法;
4.权限修饰不同:抽象方法可以有public、protected和default这些修饰符,接口方法只能是public ;
5.抽象类中的变量可以是普通变量,接口里定义的变量只能是公共的静态的常量;
6.抽象方法可以继承单个类和实现多个接口,接口可以多继承接口;
7.速度:抽象类比接口速度要快,接口是稍微有点慢的,需要时间去寻找在类中实现的方法;
注意:
1.一个类里如果有抽象方法,那么这个类只能是抽象类;
2.抽象方法要被实现,所以不能是静态的,也不能是私有的;
3.接口内只能含有未被实现的方法,也叫抽象方法,但是不用abstract关键字;
接口(interface)的应用场合:
类与类之前需要特定的接口进行协调,而不在乎其如何实现。
作为能够实现特定功能的标识存在,也可以是什么接口方法都没有的纯粹标识。
需要将一组类视为单一的类,而调用者只通过接口来与这组类发生联系。
需要实现特定的多项功能,而这些功能之间可能完全没有任何联系。 抽象类(abstract class)的应用场合:一句话,在既需要统一的接口,又需要实例变量或缺省的方法的情况下,就可以使用它。最常见的有:
定义了一组接口,但又不想强迫每个实现类都必须实现所有的接口。可以用abstract
class定义一组方法体,甚至可以是空方法体,然后由子类选择自己所感兴趣的方法来覆盖。
某些场合下,只靠纯粹的接口不能满足类与类之间的协调,还必需类中表示状态的变量来区别不同的关系。abstract的中介作用可以很好地满足这一点。
规范了一组相互协调的方法,其中一些方法是共同的,与状态无关的,可以共享的,无需子类分别实现;而另一些方法却需要各个子类根据自己特定的状态来实现特定的功能
————————————————
版权声明:本文为CSDN博主「段远山」的原创文章,遵循CC 4.0
BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn/weixin_45151795/article/details/105585721
package InterfaceDemo;
/*类与类 继承关系 单继承
类与接口 实现 类实现接口 多实现
接口与接口 继承关系 多继承
* */
public class InterfaceDemo {
public static void main(String[] args) {
}
}
interface InterA extends InterB{
public abstract void method();
}
interface InterB{
public abstract void function();
}
interface InterC extends InterA{
}
class Demo implements InterB,InterC,InterA{
@Override
public void method() {
}
@Override
public void function() {
}
}
接口的思想
Collection和List
Collection所有集合的最基础的接口 大方向
List常用的接口,更细致的规则
案例
篮球运动员和教练
乒乓球运动员和教练
现在篮球运动员和教练要出国访问,需要学习英语
请根据你所学的知识,分析出来哪些是类,哪些是抽象类,哪些是接口
Person:
package InterfaceDemo.Player;
public class Person {
String name;
int age;
String gender;
public Person(){} //无参构造
public Person(String name,int age,String gender){ //有参构造
this.name = name;
this.age = age;
this.gender = gender;
}
public void eat(){
}
public void sleep(){
}
}
player:
package InterfaceDemo.Player;
abstract class Player extends Person {
public abstract void study();
}
Coatcher:
package InterfaceDemo.Player;
abstract class Coatcher extends Person{
public abstract void teach();
}
basketballPlayer:
package InterfaceDemo.Player;
public class BasketballPlayer extends Player implements SpeackEnglish{
@Override
public void study() {
System.out.println(name+"学扣篮");
}
@Override
public void speck() {
System.out.println(name+"学英语");
}
}
basketballCoactch:
package InterfaceDemo.Player;
public class basketballCoactch extends Coatcher {
@Override
public void teach() {
}
}
PingPangPlayer
package InterfaceDemo.Player;
public class PingPangPlayer extends Player {
@Override
public void study() {
System.out.println(name+"是乒乓球运动员学习抽球");
}
}
PingpangCoatcher
package InterfaceDemo.Player;
public class PingpangCoatcher extends Coatcher implements SpeackEnglish{
@Override
public void teach() {
System.out.println("教抽球");
}
@Override
public void speck() {
System.out.println("说英语");
}
}
SpeackEnglish
package InterfaceDemo.Player;
public interface SpeackEnglish {
public abstract void speck(); //接口里面都是抽象的方法
}
InterfaceTest
package InterfaceDemo.Player;
public class InterfaceTest {
public static void main(String[] args) {
// 创建篮球对象
BasketballPlayer bbp = new BasketballPlayer();
bbp.name = "小明";
bbp.age = 18;
bbp.gender = "男";
bbp.study();
bbp.speck();
// 创建乒乓球对象
PingPangPlayer ppp = new PingPangPlayer();
ppp.name = "小红";
ppp.age = 17;
ppp.gender = "女";
ppp.study();
}
}
运行结果:
小明学扣篮
小明学英语
小红是乒乓球运动员学习抽球
匿名对象
匿名对象是对象的简化形式,是没有名字的对象.(只要是简化形式就有一定局限性)。
匿名对象应用场景:
匿名对象使用时需要注意的两种情况
当对对象方法仅进行一次调用的时候
匿名对象可以作为实际参数进行传递
匿名对象的问题:
匿名对象是否可以调用属性?解释一下可行性?
package AnonymousFinal;
/*匿名对象 对象的简化形式,没有名字的对象
应用场景:当方法只被调用一次的时候可以用匿名对象
可以当做参数传递,但是无法在传参之前做其他事情
注意:匿名对象可以调用成员变量并赋值,但是赋值没有意义
* */
public class AnonymousObjectDemo {
public static void main(String[] args) {
Student s = new Student();
s.study();
new Student(); //匿名对象,没有变量引用的对象
new Student().study();
new Student().age = 18;
System.out.println("学生年龄" + new Student().age); //因为new了一个新的对象,上面一个18和这个年纪无关
/*
Student s = new Student();
s.age = 18;
s.name = "张三";
method(s);同下方**/
method(new Student());
}
public static void method(Student s){
}
}
class Student{
String name;
int age;
public void study(){
System.out.println("好好学习");
}
}
好好学习
好好学习
学生年龄0
final关键字
- final可以修饰类,方法,变量。
- final修饰的类不可以被继承。
- final修饰的方法不可以被覆盖。
final修饰的变量是一个常量。只能被赋值一次。 什么时候将变量修饰成final呢? - 通常在程序中使用一些不会变化的数据.也就是常见的一些常量值.比如3.14,这个数直接使用是可以的,但并不利于阅读,所以一般情况下,都会被该数据起个容易阅读的名称, final修饰的常量定义一般都有书写规范,被final修饰的常量名称,所有字母都大写例如:double PI = 3.14;
- 如果由多个单词组成每个单词间用下划线连接 局部内部类只能访问被final修饰的局部变量。
package com.demo01;
/*
* final: 修饰符,可以用于修饰类、成员方法和成员变量
* final所修饰的类:不能被继承,不能有子类
* final所修饰的方法:不能被重写
* final所修饰的变量:是不可以修改的,是常量
*
* 常量:
* 字面值常量:1,2,3
* 自定义常量:被final所修饰的成员变量,一旦初始化则不可改变
*
* 注意:自定义常量必须初始化,可以选择显式初始化或者构造初始化
*
*
*/
public class FinalDemo {
public static void main(String[] args) {
//Animal a = new Animal();
//a.eat();
//Dog d = new Dog();
//d.eat();
//d.num = 20;
//System.out.println(d.NUM);
new FinalDemo().new Demo1();
}
private class Demo1{
}
}
final class Animal {
public void eat() {
System.out.println("吃东西");
}
}
/*class Dog extends Animal {
public void eat() {
final int test = 10;
class demo{
int b = test;
}
}
final int NUM_SECOND_THIRD;
public Dog() {
NUM_SECOND_THIRD = 10;
}
public Dog(int a) {
NUM_SECOND_THIRD = 20;
}
}*/
final修饰变量
- final int NUM = 15;
- NUM = 20//这样做不可以,final修饰意味着不可以改变
- final修饰成员变量,必须初始化,初始化有两种
1,显式初始化//final int NUM = 15;
2,构造函数初始化//final int NUM;通过构造函数初始化
但是不能两个一起初始化
一般定义把常量定义成final还需要定义成static的,为什么?定义成public static final int NUM = 15;//全局常量.
final和private
- 区别1
final修饰的类可以访问
private不可以修饰外部类,但可以修饰内部类,讲内部类的时候会演示(其实把外部类私有化是没有意义的) - 区别2
final修饰的方法不可以被子类重写
private修饰的方法表面上看是可以被子类重写的,其实不可以,子类是看不到父类的私有方法的 - 区别3
final修饰的变量只能在显式初始化或者构造函数初始化的时候赋值一次,以后不允许更改
private修饰的变量,也不允许直接被子类或一个包中的其它类访问或修改,但是它可以通过set和get方法对其改值和取值。
多态的概述( polymorphic )
定义:某一类事物的多种存在形态。
动态绑定:是指“在执行期间”(而非编译期间)判断所引用对象的实际类型,根据实际类型调用相应的方法。
多态举例
- 例:动物中猫,狗。
猫这个对象对应的类型是猫类型
猫 x = new 猫(); - 同时猫也是动物中的一种,也可以把猫称为动物。
动物 y = new 猫();
动物是猫和狗具体事物中抽取出来的父类型。
父类型引用指向了子类对象。
多态的体现和前提
- 程序中体现:
父类或者接口的引用指向或者接收自己的子类对象。 - 多态三个必要条件:
父类引用指向子类对象
要有覆盖操作,也就是重写
需要存在继承或者实现关系
多态的成员特点
- 成员变量:
编译时期:看的是引用型变量所属的类中是否有所调用的变量
运行时期:也是看引用型变量所属的类是否有调用的变量
成员变量无论编译还是运行都看引用型变量所属的类,简单记成员变量,编译和运行都看等号左边 - 成员函数:
编译时:要查看引用变量所属的类中是否有所调用的成员。
在运行时:要查看对象所属的类中是否有所调用的成员。如果父子出现同名的方法,会运行子类中的方法,因为方法有覆盖的特性
编译看左边运行看右边 - 静态函数:
编译时期:看的引用型变量所属的类中是否有所调用的变量
运行时期:也是看引用型变量所属的类是否有调用的变量
编译和运行都看等号左边
package PoymorphicDemo;
/*
* 多态的特点
* 成员变量 编译看左边 运行看左边
* 成员方法 编译看左边 运行看右边
* 静态方法 编译看左边 运行看左边
* */
public class PoymorphicDemo2 {
public static void main(String[] args) {
Dad dad = new Kid();
System.out.println(dad.num);
// dad.mehod();
((Kid) dad).function(); //使用变量去调用静态方法,其实相当于用变量类型的类名去调用
}
}
class Dad {
int num = 20; //成员变量
public void mehod() {
System.out.println("父类成员方法");
}
public static void method() {
System.out.println("父类静态方法");
}
}
class Kid extends Dad {
int num = 10;
@Override
public void mehod() {
System.out.println("子类成员方法");
}
public static void function() {
System.out.println("子类静态成员方法");
}
}
编译和运行的区别
1.编译就是将java代码交给编译器进行语法检查,如果没有错误就生成.class文件
2.运行就是将字节码文件(.class)交给java虚拟机执行,如果没有逻辑错误,就成功出现结果。
编译期和运行期内存的分配
1.编译期仅仅知道内存分配的位置和大小,不做具体的分配操作
2.运行期确定真正的分配,确定分配的大小以及位置
常见的错误
1.编译错误是常见的语法错误:缺少分号,大小写
2.运行错误是逻辑错误:空指针异常,越界访问,除数为0等
————————————————
版权声明:本文为CSDN博主「岛田悠米」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn/qq_44752641/article/details/107774202
多态中的类型转换
- 向上转型
子类转型成父类型
Animal a = new Dog(); - 向下转型
父类型转型成子类型
Dog d = (Dog)a;
package PoymorphicDemo;
/*多态中的向上转型和向下转型
引用类型之间的转换
向上转型 由小到大 子类向父类转型
向下转型 由大到小
基本数据类型转换
自动类型转换
由小到大
byte short char -- int -- long -- float --double
强制类型转换 由大到小
int a = 2;
char b = (char)a;
* */
public class PoymorphicDemo3 {
public static void main(String[] args) {
Animal2 a = new Dog(); //向上转型
a.eat();
// a.swim(); 不可以
Dog d = (Dog) a; //向上转型
d.swim();
/*Animal2 animal2 = new Animal2();
Dog dog = (Dog) animal2; //向下转型
dog.eat();*/
}
}
class Animal2{
public void eat(){
System.out.println("吃东西");
}
}
class Dog extends Animal2{
@Override
public void eat() {
System.out.println("啃骨头");
}
public void swim(){
System.out.println("狗刨");
}
}
运行结果:
啃骨头
狗刨
多态的优缺点
- 好处和作用:
多态的存在提高了程序的扩展性和后期可维护性 - 弊端:
父类调用的时候只能调用父类里的方法,不能调用子类的特有方法,因为你并不清楚将来会有什么样的子类继承。
package PoymorphicDemo;
/*多态的优缺点:
* 优点:提高代码的可拓展性和可维护性
* 缺点:
* 多态三个必要条件:
父类引用指向子类对象
要有覆盖操作,也就是重写
需要存在继承或者实现关系*/
public class PoymorphicDemo4 {
public static void main(String[] args) {
MiFactory miFactory = new MiFactory();
miFactory.make(new NoteMi());//条件1 父类的引用指向子类对象
miFactory.make(new RedMi());
miFactory.make(new HeiMi());
}
}
class MiFactory{
/* public void make(NoteMi p) {
p.call();
}
public void make(RedMi p) {
p.call();
}
public void make(HeiMi p) {
p.call();
}*/
public void make(Phone p){
p.call();
}
}
interface Phone{
public void call();
}
class NoteMi implements Phone{
@Override //条件2要有覆盖操作,也就是重写
public void call() {
System.out.println("NoteMi打电话");
}
}
class RedMi implements Phone{
@Override
public void call() {
System.out.println("RedMi打电话");
}
}
class HeiMi implements Phone{
@Override
public void call() { //需要存在继承或者实现关系
System.out.println("HeiMi打电话");
}
}
NoteMi打电话
RedMi打电话
HeiMi打电话
十五、面向对象-包&修饰符&内部类
包
- 对类文件进行分类管理。
- 给类提供多层命名空间。
- 写在程序文件的第一行。
- 类名的全称是 ****。
- 包也是一种封装形式。
包的特点
/*包的特点:
- 包可以有多层
- 包必须是代码的第一行
- 不同包里面可以有名字相同的文件
- *代表的是通配符,代表导入这个包下面的所有类,并没有导入子包下的类
- 类的全名“包名.类名
- */
如何定义包呢?
- 包在文件系统中体现就是文件夹
- 定义项目时,必须要有包,因为会有很多很多重名的类,为了区分就产生了包,北京有人民大街,长春也有人民大街,当你想表述哪个人民大街的时候,就会说北京的人民大街或长春的人民大街
-定义包通过一个关键字package定义
-包名规范:所有字母都小写 - 有了包以后,在编译的时候,可以指定任意目录,那么就可以完成java源文件和运行文件存储的分离,也可以定义多级目录
不同包之间的互相访问
当一个包中的类访问其他包中的类:
使用类的全名称,包.类
使用import关键字将类导入,让导入的类对当前类可见
不同包之间的互相访问
- 被访问的包中的类权限必须是public的。
- 注意:当类被public修饰,文件名和源文件必须一致,而且在一个文件写多个类的时候只能有一个类是public修饰的,这个被public修饰的还必须和文件名一致
- 类中的成员权限:public或者protected
protected是为其他包中的子类提供的一种权限
Java中常用的包
- java.lang
包含一些Java语言的核心类,如String、Math、Integer、System和Thread,提供常用功能。 - java
包含执行与网络相关的操作的类。 - java.io
包含能提供多种输入/输出功能的类。 - java.util
包含一些实用工具类,如定义系统特性、使用与日期日历相关的函数。
权限修饰符
default表示没有修饰符修饰的。
- 同一个类中
package PackageDemo;
/*权限修饰符:
public 当前类,相同包下不同的类,不同包下的类
default 当前类,相同包下不同的类
private 当前类
protected 当前类,相同包下不同的类
default:当前包下使用
protected:让子类对象使用*/
public class PremissionDemo {
public void publicMethod(){
System.out.println("publicMethod");
}
void defaultMethod(){
System.out.println("defaultMethod");
}
private void privateMehod(){
System.out.println("privateMehod");
}
protected void protectedMehod(){
System.out.println("protectedMehod");
}
public static void main(String[] args){
PremissionDemo premissionDemo = new PremissionDemo();
premissionDemo.publicMethod();
premissionDemo.protectedMehod();
premissionDemo.defaultMethod();
premissionDemo.privateMehod();
}
}
- 同一个包不同类
package PackageDemo;
public class PremissionDemo2 {
public static void main(String[] args) {
PremissionDemo pd = new PremissionDemo();
pd.publicMethod(); //通一个包下的不同子类public protected、default都可以访问
pd.protectedMehod();
pd.defaultMethod();
}
}
- 不同包中子类
package PackageDemo1.demo1;
import PackageDemo.PremissionDemo; //导入PremissionDemo这个包里面的PremissionDemo
//不同包中的子类只能public和protected访问
// public protected修饰的子类可以访问的方法 在另外一个包中写一个子类继承这个父类
public class PremissionDemo3 extends PremissionDemo{
public void function(){
super.publicMethod();
super.protectedMehod();
}
public static void main(String[] args) {
PremissionDemo3 premissionDemo3 = new PremissionDemo3();
premissionDemo3.function();
}
}
内部类概述
将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类,嵌套类)
- 访问特点:
内部类可以直接访问外部类中的成员,包括私有成员
外部类要访问内部类中的成员必须要建立内部类的对象(内部类静态成员除外) - 内部类分类
成员内部类
局部内部类
匿名内部类
共性:
内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号。
内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否是private的。
成员内部类
解释:成员内部类,在一个外部类中有成员变量,和成员方法,那么成员内部类就是把整个一个类当成了外部类的成员了.
位置:在类中并且在方法外定义的类.
成员内部类创建对象方式:
外部类名.内部类名 对象名 = 外部类对象.内部类对象
成员内部类之所以可以直接访问外部类的成员,那是因为内部类中都持有一个外部类对象的引用:外部类名.this
package InnerDemo.test1;
/*成员内部类
* 在类的位置中和成员变量以及成员方法所在的位置是一样的
* 在内部类中可以直接访问外部类的成员包括私有成员*/
public class InnerTest1 {
public static void main(String[] args) {
Outer.Inner i = new Outer().new Inner();
i.function();
}
}
class Outer{
private int num = 10;
class Inner{
//内部类
public void function(){
System.out.println(num);
}
public void method(){
Inner i = new Inner();
i.function();
}
}
}
10
成员内部类的修饰符
- 对于普通的类,可用的修饰符有final、abstract、public和default。
- 但是成员内部类更像一个成员变量或方法。
- 可用的修饰符有:final、abstract、public、private、protected和static等。
- 一旦用static修饰内部类,它就变成静态内部类了。
package com.demo01;
/*
* 成员内部类的修饰符:
* 我们可以使用权限修饰符修饰成员内部类,但是如果使用私有来修饰,则无法在其他类中访问
* 我们可以使用static修饰成员内部类,不用再创建外部类的对象了
*
* 我们可以使用abstract,final修饰成员内部类
*/
public class InnerDemo2 {
public static void main(String[] args) {
//外部类名.内部类名 对象名 = 外部类名.内部类对象
//通过创建对象访问
Outer2.Inner2 inner2 = new Outer2.Inner2();
int a = inner2.num;
inner2.function();
//外部类名.内部类名.成员
Outer2.Inner2.function();
}
}
class Outer2 {
static int num1 = 2;
public void method() {
Inner2 i = new Inner2();
}
static class Inner2 {
int num = 10;
public static void function() {
System.out.println("function");
//method();
int num2 = num1;
}
}
}
静态的成员内部类
解释:静态内部类就是给成员内部类加上static这个修饰符
访问方式
方式1:在外部类中访问静态内部类中的非静态成员
外部类名.内部类名 对象名 = 外部类名.内部类对象
通过创建对象访问
方式2:在外部类中访问静态内部类中的静态成员
可以通过上一种,也可以直接外部类名.内部类名.成员
我们把静态内部类看成一个类中的成员,既然是静态修饰的,就可以用类名.调用
**注意:**如果成员内部类用static修饰就出现了访问局限性,和静态方法是一个道理,就不能访问外部类的非静态成员了
静态内部类之所以可以直接访问外部类中的静态成员,其实是持有外部类名
局部内部类
位置:定义在方法中的类
注意:
方法内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。
方法内部类对象不能使用该内部类所在方法的非final局部变量。
与成员内部类不同,方法内部类更像一个局部变量,可以用于修饰方法内部类的只有final和abstract。
静态方法是没有this引用的,因此在静态方法内的内部类遭受同样的待遇,即:只能访问外部类的静态成员。
package com.demo02;
/*
* 局部内部类
* 在方法内,出了方法之后就无法使用
*
*
*/
public class InnerDemo3 {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
class Outer {
static int num2 =1;
public static void method() {
final int num = 10;
abstract class Inner {
public void function() {
int num1 = num2;
System.out.println("function");
}
}
class Inner1 extends Inner{
}
Inner i = new Inner1();
i.function();
}
public void test() {
//Inner i = new Inner();
//System.out.println(num);
}
}
匿名内部类(难理解多看几遍)
就是局部内部类的简化写法。
前提:
=内部类可以继承或实现一个外部类或者接口。
格式为:
new 外部类名或者接口名(){覆盖类或者接口中的代码,(也可以自定义内容。)}
简单理解:
就是建立一个带内容的外部类或者接口的子类匿名对象。
package com.demo03;
/*
* 匿名内部类:
* 可以把匿名内部类看成是一个没有名字的局部内部类
* 定义在方法当中
* 必须在定义匿名内部类的时候创建他的对象
* 格式:
* new 类/接口(){
* 如果是创建了继承这个类的子类对象,我们可以重写父类的方法
* 如果是创建了实现这个接口的子类对象,我们必须要实现该接口的所有方法
* };
* 原理:创建了继承这个类的子类对象或者是创建了实现这个接口的子类对象
*
*/
public class InnerDemo4 {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
interface Inner {
public abstract void function();
}
class Outer {
public void method() {
new Inner() {
@Override
public void function() {
System.out.println("function");
}
}.function();
}
}
匿名内部类的应用场景
通常在使用方法是接口类型参数、并且该接口中的方法不超过三个时,可以将匿名内部类作为参数传递。
简化书写,如果阅读实在费劲的话,可以写有名字的内部类
package InnerDemo.test2;
public interface Animal {
public abstract void eat();
}
package InnerDemo.test2;
public class Cat implements Animal{
@Override
public void eat() {
System.out.println("吃鱼");
}
}
package InnerDemo.test2;
public class Dog implements Animal{
@Override
public void eat() {
System.out.println("吃骨头");
}
}
package InnerDemo.test2;
/*
* 匿名内部类的应用场景:
* 作为参数进行传递
*通常在使用方法是接口类型参数、并且该接口中的方法不超过三个时,可以将匿名内部类作为参数传递。
*
*/
public class InnerDemo {
public static void main(String[] args) {
class Cat implements Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
method2(new Cat());
}
public static void method2(Animal animal){
animal.eat();
}
}
十六、 java常用的API高级
API是什么
API(Application Programming Interface)
应用程序编程接口
编写一个机器人程序去控制机器人踢足球,程序就需要向机器人发出向前跑、向后跑、射门、抢球等各种命令,没有编过程序的人很难想象这样的程序如何编写。但是对于有经验的开发人员来说,知道机器人厂商一定会提供一些用于控制机器人的Java类,这些类中定义好了操作机器人各种动作的方法。其实,这些Java类就是机器人厂商提供给应用程序编程的接口,大家把这些类称为API。本章涉及的Java API指的就是JDK中提供的各种功能的Java类。
Object
定义:类Object是类层次结构的根类,每个类都使用Object作为超类,所有对象(包括数组)都实现这个类的方法。
Object类要掌握的功能
- equal
- toString
toString
toString以文本表示该字符串
getClass
getClass (). getName() + '@’+ Integer. t oHexSt ring (hashCode () )
package MastAPI.APITest1;
/* String to String :
hasCode:返回对象的哈希码值(内部地址)
getClass:返回一个字节码对象
Integer.toHexString:返回指定参数的十六进制
包.文件名.类@哈希码 getClass (). getName() + '@’+ Integer. t oHexSt ring (hashCode () )
* */
public class ObjectDemo {
public static void main(String[] args) {
Student student = new Student();
student.name = "小明";
student.age = 18;
System.out.println(student.toString()); //返回该对象的字符串表示
System.out.println(student); //说明我们输出一个对象就是默认输出一个对象的toString 方法
}
}
class Student{
String name;
int age;
//选中类右击Gener生成toString()
/* @Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}*/
// 加了return输出的
// Student{name='小明', age=18}
//Student{name='小明', age=18}
}
equal
package com.demo01;
import java.util.ArrayList;
/*
* boolean equals(Object obj)
* 使用==来比较两个对象是否相等,则比较地址值是否相等
*/
public class ObjectDemo2 {
public static void main(String[] args) {
Person p = new Person("zhangsan",18);
//Person p2 = new Person("zhangsan",18);
//boolean flag = p.equals(p2);
boolean flag = p.equals(new ArrayList());
System.out.println(flag);
//System.out.println(p);
//System.out.println(p2);
}
}
class Person {
String name;
int age;
public Person(String name,int age) {
this.name = name;
this.age = age;
}
@Override //重写equal方法
public boolean equals(Object obj) {
//地址相同,直接返回true
if (this == obj)
return true;
if (obj == null)
return false;
//健壮性
if (getClass() != obj.getClass())
return false;
//向下转型
Person other = (Person) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
/* @override
public boolean equals(Object obj) {
if (this == obj) {
return (this == obj);
}
//健壮性
if(this.getClass()!=obj.getClass()) {
return false;
}
//向下转型
Person p = (Person) obj;
if(!this.name.equals(p.name)) {
return false;
}
if(this.age!=p.age) {
return false;
}
return true;
}*/
}
输出:false (两个对象地址不相等)
System
System类提供的设施中,有标准输入、标准输出和错误输出流;对外部定义的属性和环境变量的访问;加载文件和库的方法;还有快速复制数组的一部分的实用方法。
• System类要掌握的功能
– arraycopy
– exit
– currentTimeMillis
package com.demo02;
/*
* System:包含一些有用的类字段和方法。它不能被实例化
* static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
* static long currentTimeMillis()
* static void exit(int status)
static void gc()
*
*/
public class SystemDemo {
public static void main(String[] args) {
//System.err.println("错误信息");
//method();
//method2();
//method3();
//static void gc()
//Demo d = new Demo();
new Demo();
new Demo();
new Demo();
new Demo();
new Demo();
new Demo();
new Demo();
new Demo();
new Demo();
new Demo();
System.gc();
}
private static void method3() {
//static void exit(int status) :终止虚拟机
for (int i = 0; i < 100000; i++) {
System.out.println(i);
if(i == 100) {
System.exit(0);
}
}
}
private static void method2() {
/*
* static long currentTimeMillis() :以毫秒值返回当前系统时间
* 这个毫秒的时间是相对时间,相对于1970-1-1 00:00:00 : 0
* 1970-1-1 00:00:01 : 1000
* 1970-1-1 00:01:00: 1000 * 60
* 1970-1-1 01:00:00: 1000 * 60 * 60
* 1000毫秒 = 1秒
*
*/
//System.out.println(System.currentTimeMillis());
long start = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
System.out.println(i);
}
long end = System.currentTimeMillis();
System.out.println(end - start);
}
private static void method() {
/*
* static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
* 复制数组
* 参数1:源数组
* 参数2:源数组的起始索引位置
* 参数3:目标数组
* 参数4:目标数组的起始索引位置
* 参数5:指定接受的元素个数
*/
int[] src = {1,2,3,4,5};
int[] dest = new int[5];
System.arraycopy(src, 1, dest, 3, 2);
for (int i = 0; i < dest.length; i++) {
System.out.print(dest[i]);
}
}
}
class Demo {
@Override
protected void finalize() throws Throwable {
System.out.println("我被回收了");
}
}
Date
类 Date 表示特定的瞬间,精确到毫秒。
• Date类的构造方法
– 空构造
– 参数为毫秒值
• Date类要掌握的功能
–毫秒到日期的转换
–日期到毫秒的转换
package com.demo03;
import java.util.Date;
/*
* Date: 表示特定的瞬间,精确到毫秒,它可以通过方法来设定自己所表示的时间,可以表示任意的时间
* System.currentTimeMillis():返回的是当前系统时间,1970-1-1至今的毫秒数
*
* 构造方法:
* Date() :创建的是一个表示当前系统时间的Date对象
Date(long date) :根据"指定时间"创建Date对象
*/
public class DateDemo {
public static void main(String[] args) {
//Date()
//Date d = new Date();
//System.out.println(d);//Mon Apr 22 11:18:39 CST 2019
//System.out.println(System.currentTimeMillis());
//System.out.println(d.toLocaleString());
//Date(long date)
Date d2 = new Date(1000 * 60 * 60 * 24);//时区 有时差
System.out.println(d2.toLocaleString());
}
}
package com.demo03;
import java.util.Date;
/*
* Date的常用方法
毫秒值 --- Date
设置
返回值是void,参数long
void setTime(long time)
Date(long date)
Date --- 毫秒值
获取
返回long,无参数
long getTime()
*/
public class DateDemo2 {
public static void main(String[] args) {
Date d = new Date();//默认当前系统时间
d.setTime(1000 * 60 * 60 * 24 * 2);
System.out.println(d.toLocaleString());
System.out.println(d.getTime());//172800000
d.setTime(2147483647123456789L);
System.out.println(d.toLocaleString());
}
}
DateFormat
DateFormat类是对日期进行格式化的类
• DateFormat类的使用
–本身是一个抽象类,所以必须使用的时候使用的是其子类
SimpleDateFormat,并且在子类中有很多模式字母需要记住。
• DateFormat要掌握的功能
–从日期到字符串的转换
–从字符串到日期的转换
package com.demo04;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
* SimpleDateFormat:
* 格式化:
* Date --- String
* 2049-8-26 2049年8月26日
* String format(Date date)
* 解析:
* String --- Date
* "2049-8-26"
* Date parse(String source)
*
* 构造方法:
* SimpleDateFormat() :使用默认的模式进行对象的构建
* SimpleDateFormat(String pattern) :使用的指定的模式进行对象的构建
*
* 注意:Exception in thread "main" java.text.ParseException: Unparseable date: "49年9月26日 下午1:29"
* 解析的字符串,模式必须和构建对象的模式一样
*
*/
public class SimpleDateFormatDemo {
public static void main(String[] args) throws ParseException {
//method();
method2();
//使用指定的模式进行对象的构建
//1999年9月1日 10:10:10
/*SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
//格式化
Date date = new Date();
String s = sdf.format(date);
System.out.println(s);//2049年08月26日 13:39:12
//解析
Date d = sdf.parse("2049年08月26日 13:39:12");
System.out.println(d.toLocaleString());
*/
}
/**
* 使用默认模式进行对象的构建
*/
private static void method() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat();
//创建日期对象
Date date = new Date();
//格式化 把日期对象转换成字符串
String s = sdf.format(date);
System.out.println(s);//49-8-26 下午1:29
//解析 把字符串转换成日期对象
Date d = sdf.parse("49年9月26日 下午1:29");
//Date d = sdf.parse("2019/4/22 下午12:16");
System.out.println(d.toLocaleString());
}
/**
* 使用指定的模式进行对象的构建
*/
private static void method2() throws ParseException {
//1999年9月1日
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日hh:mm:ss");
//格式化
/*Date date = new Date();
String s = sdf.format(date);
System.out.println(s);//2049年08月26日
*/
//解析
Date d = sdf.parse("2049年08月26日01:01:01");
System.out.println(d.toLocaleString());
}
}
Calendar
Calendar类是日历类,用于替代Date类的使用。它里面提
供了很多功能来单独获取日历的某个数据。
• Calendar类的使用
–抽象类,但是提供方法用于获取子类对象
• Calendar类的练习:
–获取任意一年的2月有多少天?
–获取昨天的现在这个时刻并输出?
package com.demo05;
import java.util.Calendar;
/*
* Calendar:日历,提供了一些操作年月日时的方法
*
* 获取
* 修改
* 增减
*
*
*/
public class CalendarDemo {
public static void main(String[] args) {
Calendar c = Calendar.getInstance();
//修改
c.set(Calendar.YEAR, 2030);
c.set(Calendar.MONTH,8);
//增减
c.add(Calendar.HOUR_OF_DAY, 3);
//获取
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH)+1;
int day = c.get(Calendar.DAY_OF_MONTH);
int hour = c.get(Calendar.HOUR_OF_DAY);
System.out.println(year+"年"+month+"月"+day+"日"+hour+"点");
}
}
基本数据类型包装类(例如: Infeger)
我们前面学过了8种基本数据类型,但是我们只能对它们做一些简单的操作,如果想做一些复杂的操作,做不了。
为了帮助我们实现这个想法,java就对基本数据类型进行了封装。也就是说每一种基本数据类型都对应着一个对象了。方便我们使用更多的功能。
• 举例:封装类的好处。
比如说,我说我们要判断一个数据在int所表示的范围内,我们要计算2的31次方的值
package com.demo06;
/*
* 需求:判断一个数是否符合int类型的范围
* 由于基本数据类型只能做一些简单的操作和运算,所以Java为我们封装了基本数据类型,为每种基本数据类型提供了包装类
* 包装类就是封装了基本数据类型的类,为我们提供了更多复杂的方法和一些变量
*
* byte Byte
* short Short
* char Character
* int Integer
* long Long
* float Float
* double Double
* boolean Boolean
*
* Integer:
* String --- int
* 方式1:int intValue()
* 方式2: static int parseInt(String s)
* int --- String
* 方式1: + ""
* 方式2:String toString()
*
* 构造方法:
* Integer(int value)
* Integer(String s)
*/
public class IntegerDemo {
public static void main(String[] args) {
//int n=2;
/*for (int i = 0; i < 30; i++) {
n *=2;
}
n--;*/
//n = (int)(Math.pow(2, 31)-1);
//System.out.println(n);
String n = "10";
Integer i = new Integer(n);
System.out.println(i);
Integer a = Integer.parseInt("10");
System.out.println(a);
int b = a.intValue();
System.out.println(b);
String c = 1+"";
String d = a.toString();
System.out.println(d);
String e = Integer.toString(30);
System.out.println(e);
}
}
package com.demo06;
import java.util.ArrayList;
/*
* JDK1.5特性:自动装箱和拆箱
*
*/
public class IntegerDemo2 {
public static void main(String[] args) {
//Integer i = new Integer(10);
//自动装箱
//相当于: Integer i = new Integer(10);
//Integer i = 10;
//自动拆箱
//相当于 int a = i.intValue();
//Integer i = 10;
//int a = i;
Integer i = 10;
Integer i2 = 20;
Integer i3 = i + i2;
// Integer i3 = new Integer(i.intValue() + i2.intValue());
ArrayList list = new ArrayList();
list.add(1);//自动装箱,list.add(new Integer(1));
}
}
正则表达式 常用的正则表达式字符
正则表达式:是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串。其实就是一种规则。有自己特殊的应用
• 匹配功能
使用String类中的matches方法。
先去学习Pattern类,了解规则。
字符类,预定义字符类,边界匹配器,数量词
package com.demo07;
/*
* 校验qq号码
* 要求必须是5-15位
* 0不能开头
* 必须都是数字
正则表达式:就是一套规则,可以用于匹配字符串
boolean matches(String regex) :判断当前字符串是否匹配指定的正则表达式,如果匹配则返回true,否则返回false
*
*
*/
public class RegexDemo {
public static void main(String[] args) {
String qq = "12a345";
boolean flag = checkQQ(qq);
System.out.println(flag);
boolean flag1 = qq.matches("[^0]\\d{4,14}");
System.out.println(flag1);
}
public static boolean checkQQ(String qq) {
int length = qq.length();
//要求必须是5-15位
if(length < 5 || length > 15) {
return false;
}
//0不能开头
if(qq.startsWith("0")) {
return false;
}
//必须都是数字
for (int i = 0; i < length; i++) {
//得到参数的每一个字符
char c = qq.charAt(i);
if(c < '0' || c > '9') {
return false;
}
}
return true;//符合要求
}
}
字符
x 字符 x
\\ 反斜线字符
字符类
[abc] a、b 或 c(简单类)
[^abc] 任何字符,除了 a、b 或 c(否定)
[a-zA-Z] a 到 z 或 A 到 Z,两头的字母包括在内(范围
预定义字符类
. 任何字符(与行结束符可能匹配也可能不匹配)
\d 数字:[0-9]
\D 非数字: [^0-9]
\s 空白字符:[ \t\n\x0B\f\r]
\S 非空白字符:[^\s]
\w 单词字符:[a-zA-Z_0-9]
\W 非单词字符:[^\w]
Greedy 数量词
X? X,一次或一次也没有
X* X,零次或多次
X+ X,一次或多次
X{n} X,恰好 n 次
X{n,} X,至少 n 次
X{n,m} X,至少 n 次,但是不超过 m 次
作业自主练习
1.自己动手定义一个Star(明星),明星有名字属性,自己手动重写Star的toString 和equals方法
package MastAPI.APITest1.Practice;
import java.util.ArrayList;
import java.util.Objects;
//1.自己动手定义一个Star(明星),明星有名字属性,自己手动重写Star的toString 和equals方法
public class Star {
public static void main(String[] args) {
NewStar star = new NewStar("小明");
System.out.println(star.toString()); // 输出 NewStar{name='小明'}
boolean flag = star.equals(new ArrayList<>());
System.out.println(flag); //输出false 两个对象地址不相等
}
// String name;
}
class NewStar{
String name;
public NewStar(String name){
this.name = name;
}
@Override //重写toString方法
public String toString() { //返回以文本方式表示此对象的字符串
return "NewStar{" +
"name='" + name + '\'' +
'}';
}
@Override //重写equal方法
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof NewStar)) return false;
NewStar newStar = (NewStar) o;
return Objects.equals(name, newStar.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
2.通过System这个类的arraycopy方法将已知数组int [] arr ={12,234,45,324};中中间两个元素拷贝到另外一个新数组中;
package MastAPI.APITest1.Practice;
/*2.通过System这个类的arraycopy方法将已知数组int [] arr ={12,234,45,324};中中间两个元素拷贝到另外一个新数组中;
* arraycopy(Object src,int srcPos,Object dest,int destPos,int length)
* 从指定的源数组复制一个数组,从指定的位置开始到目标数组指定的位置结束
* 参数1:源数组
* 参数2:源数组的起始索引位置
* 参数3:目标数组
* 参数4:目标数组的起始索引位置
* 参数5:指定接受的元素个数
* */
public class Test2 {
public static void main(String[] args) {
copy();
}
public static void copy(){
int[] arr = {12,234,45,324};
int[] newArr = new int[5];
System.arraycopy(arr,1,newArr,1,2);
// 遍历新数组并输出
for (int i = 0; i < newArr.length; i++) {
System.out.print(newArr[i]+" ");
}
}
}
0 234 45 0 0
3.通过System的currentTimeMillis()方法,计算出 输出一万次我爱你,所用时间;
public static void CurTime(){
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
System.out.println("我爱你");
}
long end = System.currentTimeMillis();
System.out.println(end-start);
}
输出:42
4.通过date对象获取当前时间的毫秒值, 然后计算出明天这个时间的毫秒值,然后将明天的这个时候的毫秒值转成Date对象;
// 第4问 通过date对象获取当前时间的毫秒值, 然后计算出明天这个时间的毫秒值,然后将明天的这个时候的毫秒值转成Date对象;
public static void method2(){
// 获取当前时间的毫秒值
Date now = new Date();
long nowMillis = now.getTime();
// 计算明天此时的毫秒值
long tomorrowMillis = nowMillis+24*60*60*1000;
// 将明天此时的毫秒值转化成Date对象
Date tomorrow = new Date(tomorrowMillis);
System.out.println("当前的时间的毫秒值为:"+ nowMillis +" 明天的时间的毫秒值为"+ tomorrowMillis +" 明天的日期和时间为"+ tomorrow);
}
}
运行:当前的时间的毫秒值为:1678197782196/t 明天的时间的毫秒值为1678284182196 明天的日期和时间为Wed Mar 08 22:03:02 CST 2023
5.(1)将当前的时间解析成 xxxx年xx月xx日 xx:xx:xx 这种格式显示; (2)已知一个字符串时间String date = “2000_02_29#####23-23-23”;
(1)将当前的时间解析成 xxxx年xx月xx日 xx:xx:xx 这种格式显示;
(2)已知一个字符串时间String date = “2000_02_29#####23-23-23”;
a. 请将字符串时间转成一个date对象
b.然后通过对象获取出以上date对象明天这个时候的毫秒值
c.然后通过获取通过刚才获取的毫秒值获取出明天的date对象;
d.然后将获取出新的date对象的时间以xxxx年xx月xx日 xx:xx:xx 这种格式显示出来;
public class Test3 {
public static void main(String[] args) throws ParseException {
method3();
}
public static void method3() throws ParseException{
// SimpleDateFormat sdf = new SimpleDateFormat();
SimpleDateFormat sdf1 = new SimpleDateFormat("2023年1月22日 HH:mm:ss");
Date date = new Date();
String s = sdf1.format(date); //格式化 把日期对象转换成字符串
System.out.println(s);
// 字符串转换成日期对象
Date d = sdf1.parse("23年3月7日 下午1:20");
System.out.println(d.toLocaleString());
}
}
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
String formatted = now.format(formatter);
System.out.println(formatted);
}
}
2023年1月22日 22:44:19
(2)已知一个字符串时间String date = "2000_02_29#####23-23-23";
a. 请将字符串时间转成一个date对象
b.然后通过对象获取出以上date对象明天这个时候的毫秒值
c.然后通过获取通过刚才获取的毫秒值获取出明天的date对象;
d.然后将获取出新的date对象的时间以xxxx年xx月xx日 xx:xx:xx 这种格式显示出来;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class Main {
public static void main(String[] args) throws Exception {
String strTime = "2000_02_29#####23-23-23";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy_MM_dd#####HH-mm-ss");
Date date = formatter.parse(strTime);
// Add one day to the date
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.DAY_OF_YEAR, 1);
Date tomorrow = calendar.getTime();
// Format the new date
SimpleDateFormat newFormatter = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String newFormatted = newFormatter.format(tomorrow);
System.out.println(newFormatted);
}
}
Output:
yaml
Copy code
2000年03月01日 23:23:23
6.通过Calendar对象获取今天是多少年多少月多少日;
(1)获取今天在一年中是第几周;
(2)获取单前月份在一年中是第几个月;
import java.util.Calendar;
public class Main {
public static void main(String[] args) {
// 创建Calendar对象
Calendar calendar = Calendar.getInstance();
// 获取年月日
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1; // 月份从0开始,因此要加1
int day = calendar.get(Calendar.DAY_OF_MONTH);
// 获取今天在一年中是第几周
int weekOfYear = calendar.get(Calendar.WEEK_OF_YEAR);
// 获取当前月份在一年中是第几个月
int monthOfYear = calendar.get(Calendar.MONTH) + 1;
// 输出结果
System.out.println("今天是" + year + "年" + month + "月" + day + "日");
System.out.println("今天在一年中是第" + weekOfYear + "周");
System.out.println("当前月份在一年中是第" + monthOfYear + "个月");
}
}
输出结果如下:
Copy code
今天是2023年3月7日
今天在一年中是第10周
当前月份在一年中是第3个月
7.分别写出八种基本数据类型对应的包装类;
Java的八种基本数据类型和它们对应的包装类如下:
byte:Byte
short:Short
int:Integer
long:Long
float:Float
double:Double
boolean:Boolean
char:Character
在Java中,这些包装类提供了许多有用的方法,可以在实际编程中使用。例如,可以使用这些包装类将基本数据类型转换为字符串,或者将字符串转换为基本数据类型。还可以使用这些类来执行各种数学计算,比较等等。在Java 5及以后的版本中,还引入了自动装箱和自动拆箱的特性,使得使用基本数据类型和对应的包装类更加方便。
写出代码
下面是一个例子,演示如何使用基本数据类型和对应的包装类:
java
Copy code
public class Main {
public static void main(String[] args) {
// 基本数据类型
int x = 10;
double y = 3.14;
boolean z = true;
// 自动装箱(Autoboxing)
Integer a = x;
Double b = y;
Boolean c = z;
// 手动装箱
Integer d = new Integer(x);
Double e = new Double(y);
Boolean f = new Boolean(z);
// 自动拆箱(Unboxing)
int g = a;
double h = b;
boolean i = c;
// 手动拆箱
int j = a.intValue();
double k = b.doubleValue();
boolean l = c.booleanValue();
}
}
在这个例子中,我们首先定义了三个基本数据类型变量 x,y和z,分别代表整数、浮点数和布尔值。然后,我们使用自动装箱和手动装箱将它们转换为对应的包装类对象 a,b和c。
接下来,我们使用自动拆箱和手动拆箱将这些包装类对象转换回基本数据类型。这里的自动装箱和自动拆箱是Java 5及以后版本中的新特性,它们使得代码更简洁,更易读。如果你使用的是Java 5以下版本,那么你需要手动进行装箱和拆箱。
8.分析以下需求,并用代码实现
(1)从键盘录入一个日期字符串,格式为 xxxx-xx-xx,代表该人的出生日期
(2)利用人出生日期到当前日期所经过的毫秒值计算出这个人活了多少天
下面是Java代码,实现了从键盘录入一个日期字符串,并计算出这个人活了多少天:
java
Copy code
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入您的出生日期(格式:xxxx-xx-xx):");
String birthDateStr = scanner.nextLine();
scanner.close();
LocalDate birthDate = LocalDate.parse(birthDateStr, DateTimeFormatter.ISO_LOCAL_DATE);
LocalDate now = LocalDate.now();
long days = ChronoUnit.DAYS.between(birthDate, now);
System.out.println("您已经活了 " + days + " 天!");
}
}
代码解释:
首先创建一个 Scanner 对象,用于从键盘读取输入。
然后打印提示信息,要求用户输入出生日期。
读取用户输入的出生日期字符串,并关闭 Scanner 对象。
使用 LocalDate.parse 方法将字符串转换为 LocalDate 对象,这个方法使用指定的格式解析字符串。
使用 LocalDate.now 方法获取当前日期。
使用 ChronoUnit.DAYS.between 方法计算出两个日期之间相差的天数。
最后将计算出的天数打印出来。
更多推荐
java从零开始系统性学习完整超全资源+笔记(上)
发布评论