Markdown学习
标题
一级标题 :# + 空格 + 标题
二级标题 :## + 空格 + 标题
…
六级标题:###### + 空格 + 标题
字体
hello world
粗体:**hello world**
hello world
斜体:*hello world
hello world
加粗斜体:***hello world***
hello world
删除线:~~hello world~~
引用
选择阅读ying的博客,走向人生的巅峰
引用:> 选择阅读ying的博客,走向人生的巅峰
分割线
分割线:---
分割线:***
图片
)
超链接
列表
有序列表
- A
- B
- C
- D
1. + 空格 + 内容
2. + 空格 + 内容
3. + 空格 + 内容
4. + 空格 + 内容
无序列表
- A
- B
- C
- + 空格 + 内容
- + 空格 + 内容
- + 空格 + 内容
表格
名字 | 姓别 | 年龄 |
---|---|---|
张三 | 男 | 19 |
名字|姓别|年龄
--|--|--
张三|男|19
进入源代码将空格删去
或者直接右键插入表格
代码
print("hello world")
```python
print("hello world")
```
发布markdown语法博客
将上边的markdown的源码直接复制到csdn上或者其他支持markdown方法的网站上就可以了
什么是计算机
介绍
- Computer:电子计算机俗称电脑
- 能够按照程序运行,自动,高速处理海量数据的现代化只能电子设备
- 由硬件和软件组成
- 常见的形式:台式计算机,笔记本计算机,大型计算机
- 广泛应用在各种领域
计算机硬件
一些物理装置按系统要求构成一个有机整体为计算机软件运行提供物质基础
计算机硬件的组成:
- CPU
- 主板
- 内存
- 电源
- 主机箱
- 硬盘
- 显卡
- 键盘,鼠标
- 显示器
- 等
装机
最简单的计算机可以由:
- CPU
- Memory(内存)
- Motherboard(主板)
- IO设备
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aCSxZEWV-1628911268455)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210806014753463.png)]
冯诺依曼体系结构(计算机之父)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wqIA3JUY-1628911268456)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210806014919598.png)]
计算机软件
-
计算机软件可以使计算机按照事先预定好的顺序完成特定的功能
-
计算机软件按照其功能划分为系统软件和应用软件
-
系统软件:
- DOS,Windows,Linux,Unix
-
应用软件:
- WPS,QQ,微信
-
软件,开发,软件开发
-
人机交互
电脑常用快捷键
Alt + F4
关闭窗口
Enter
确定
Num
开启小键盘的使用
CapsLock
开启大小写
Ctrl + s
保存
Ctrl + c
复制
Ctrl + v
粘贴
Ctrl + z
撤销
Ctrl + x
剪切
Dos命令
开启Dos命令
- 开始里的Windows系统下的命令提示符
- Win键 + R 输入cmd打开控制台
- 在文件夹的路径下输入cmd可以在此目录下打开Dos命令
管理员方式打开
开始里的Windows系统下的命令提示符右键管理员打开
基础命令
`D:` 切换盘符
`dir` 查看当前目录下的所有文件
`cd` 切换目录
`cls` 清屏
`exit` 退出终端
`calc` 打开计算器
`mspaint`画图
`md 目录名` 创建文件夹
`rd 目录名` 移除文件
`cd> 文件名` 创建文件
`del 文件名` 删除文件
Java入门
Java帝国的诞生
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ON1nsVVa-1628911268458)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210809071720644.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yif6Ioy5-1628911268459)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210809071949011.png)]
Java特性和优势
- 简单性
- 面向对象
- 可移植性
- 高性能
- 分布式
- 动态性
- 多线程
- 安全性
- 健壮性
Java三大版本
- JavaSE:标准版(桌面程序,控制台开发)
JavaME:嵌入式开发(手机,小家电)- JavaEE:E企业级开发(web端,服务器开发)
JDK,JRE,JVM
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-59uOjLAT-1628911268460)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210809072916498.png)]
Java开发环境搭建
JDK下载与安装
卸载JDK
- 将jdk包删除
- 将JAVA_HOME删除
- 将path里面的java变量删除
- java -version查看是否删除
安装JDK8
- 百度搜索JDK8,找到下载地址
- 登录账户
- 下载电脑对应的版本
- 双击安装JDK
- 记住安装的路径
- 配置环境变量
- 我的电脑–>属性–>高级系统设置–>环境变量
- 系统变量–>新建
- 添加键为JAVA_HOME 值为刚刚的jdk路径
- 配置path变量 添加path值为 %JAVA_HOME%\bin
- 添加path变量 添加path值为 %JAVA_HOME%\jre\bin
- 检查安装情况
- 打开cmd
- 输入java -version
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ISCz9tJe-1628911268460)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210809073331430.png)]
Hello World 及简单语法规则
-
随便新建一个文件夹,存放代码
-
新建一个java文件
- 后缀名为.java
- Hello.java
-
编写Hello.java文件内容
public class Hello{ public static void main(String[] args){ System.out.println("Hello World"); } }
-
将java文件编译成字节码
javac 文件名(带后缀名)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w1K1L9uN-1628911268461)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210809075414299.png)]
-
运行class文件
java 文件名(不带后缀名)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jWLNmxJb-1628911268462)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210809075424144.png)]
可能遇到的问题
- 大小写不能出现问题,Java大小写敏感
- 尽量使用英文
- 文件名和类名必须一致,并且首字母大写
- 符号需要用英文
编译型和解释型
-
编译型
将程序进行直接全部编译
操作系统(速度快)
-
解释型
执行什么就解释什么
网页(不要求速度快)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vkdqvFti-1628911268463)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210809080246248.png)]
IDEA安装
-
什么是IDE介绍
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xi2OOZKd-1628911268465)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210809080605889.png)]
安装IDEA
- 去官网搜索IDEA
- 下载
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ah7cyLR8-1628911268466)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210809081157967.png)]
- 一直下一步就可以了
简单使用
-
打开软件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VIExziGq-1628911268467)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210809081936875.png)]
-
新建项目
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x2JTIfIU-1628911268467)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210809082027261.png)]
-
在src下创建一个Java类
-
写Java代码
// psvm生成 public static void main(String[] args) //sout生成 System.out.println();
Java基础语法
注释,标识符,关键字
注释
平时我们编写代码,在代码量比较少的时候可以看懂,但是项目结构一旦复杂起来,我们就需要用到注释了
注释并不会被执行,是给我们写代码的人看的
平时代码一定要注意规范
//为单行注释
/*为多行注释
123*/
/**
* 文档注释
*/
标识符
Java所有的组成部分都需要名字。类名,变量名以及方法名都被称为标识符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5ojgTT0c-1628911268468)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210809084806172.png)]
关键字
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8D0fIczU-1628911268468)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210809084602840.png)]
数据类型
-
强类型语言
- 要求变量的使用要严格符合规定,所有变量都必须先定义后才能使用
-
弱类型语言
-
Java的数据类型分为两大类
- 基本类型
- 整形
- byte
- sort
- int
- long
- 字符
- char
- 布尔
- boole
- 整形
- 引用类型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WSfGCKpF-1628911268469)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210809085307373.png)]
- 基本类型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HNKug8Ps-1628911268470)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210809112033282.png)]
拓展
整数拓展:
进制
- 十进制
- 123456
- 八进制(0)
- 010
- 十六进制(0x)
- 0x11
浮点数拓展:
float 有限 离散 舍入误差 接近但不等于
//最好完全使用浮点数进行比较
可以用BigDecimal类进行精确的比较 数学工具类
public class Demo03 { public static void main(String[] args) { float f = 0.1f; double d = 1.0/10; System.out.println(f); System.out.println(d); System.out.println(f==d); float d1 = 23232323232323f; float d2 = d1+1; System.out.println(d1==d2); }}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CjoryCYj-1628911268470)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210809113245966.png)]
字符拓展
char c1 = 'a';char c2 ='中';System.out.println((int)c1);System.out.println((int)c2);//所有的字符本质还是数字//编码 Unicode 2个字节// \u0061 ==> a// \t 制表符// \n 换行符
布尔值
boolean flag = true;if(flag){}//老手if(flag==true){}//新手// Less is More! 代码要精简易读
类型转换
由于Java是强类型语言,所以要进行有些运算的时候,需要用到类型转换
强制转换===> 高 --> 低
自动转换===> 低 --> 高
范围低----------------------------------------------->高byte, short ,char -> int -> long -> float -> double
强制类型转换,转换的时候一定要注意范围
int i =128;byte b =(byte)i;System.out.println(i);System.out.println(b);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XsqM5tDH-1628911268471)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210809115859216.png)]
自动转换
int i =128;double b =i;System.out.println(i);System.out.println(b);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dssf8Nos-1628911268471)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210809120156887.png)]
char c = 'a';int d = c+1;System.out.println(d);System.out.println((char)d);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xU4JwRdU-1628911268472)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210809120717691.png)]
注意点:
- 不能对布尔值进行转换
- 不能把对象类型转化为不相干的类型
- 把高容量转换为低容量时,强制转换
- 转换的时候可能存在内存溢出,或者精度问题
注意
操作比较大的数的时候注意溢出问题
JDK7新特性,数字之间可以用下划线分割
int money = 10_0000_0000;
int years = 20;
int total = money*years;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fNAPJ3wl-1628911268473)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210809121038477.png)]
int money = 10_0000_0000;
int years = 20;
long total = (long)money*years;
System.out.println(total);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zik9EI8W-1628911268474)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210809121203460.png)]
变量,常量
变量
命名规范
所有变量,方法,类名:见名知意
类成员变量:首字母小写和驼峰原则
局部变量:首字母小写和驼峰原则
常量:大写字母和下划线
类名:首字母大写和驼峰原则
方法名:首字母小写和驼峰原则
就是可以变化的量
Java是一种强类型的语言,每个变量都必须声明其类型。
Java变量是程序汇总最基本的存储单元,其要素包括变量名,变量类型和作用域
type varName [=value][{,varName[=value]}];//数据类型 变量名 =值 可以使用逗号隔开来声明多个同类型变量。
- 注意事项:
- 每个变量都有类型,类型可以是基本类型,也可以是引用类型
- 变量名必须是合法的标识符、
- 变量声明是一条完整的语句,因此每一个声明都必须以分号结束
变量作用域
-
类变量
添加个关键字staticstatic double salary = 2500;从属于类生命周期为类的开始到类的结束
-
实例变量
处于类里面方法的外边实例变量:从属于对象,可以不用初始化。为数据类型的默认值 0 0.0 false
-
局部变量
处于方法里面生命周期为 方法的开始到方法的结束必须初始化
常量
常量:初始化后不可以变的值!不会变动的值
所谓常量可以理解为一种特殊的变量,它的值被设定后不可以被改变,在程序运行的过程中不允许被改变。
final 常量名 = 值final double PI = 3.14
常量名一般为大写字母
运算符
-
Java语言支持如下运算符
-
算数运算符:+,-,*,/,%,++,–
-
赋值运算符: =
-
关系运算符: >,<,>=,<=,==,!=,instanceof
-
逻辑运算符:&&,||,!
-
位运算符:&,|,^,~,>>,<<,>>>
-
条件运算符: ? :
x ? y : z
x为真返回y
x为假返回z
-
扩展赋值运算符:+=,-=,*=,/=
-
幂运算2^3 Math.pow(2,3)
-
包机制
-
为了更好的组织类,java提供了包机制,用于区别类名的命名空间
-
包语句的语法格式为:
package pkg1[. pkg2[. pkg3…]];
-
一般利用红丝域名倒置作为包名
-
为了能够使用某一个包的成员,我们需要在Java程序中明确导入该包。使用import语句可以完成此功能
import package1[.package2...].(classname|*)
JavaDoc
Javadoc命令是用来生成自己的API文档的
-
参数信息
/*@author 作者@version 版本号@since 指明需要最早使用的jdk版本@param 参数名@return 返回值情况@throws 异常抛出情况 */
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tWHKWdDt-1628911268475)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210809140659632.png)]
生成自己的API文档
- 在工具栏中找到 tool >> Generate JAVADoc…
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5j5jeRdi-1628911268475)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/20160910175638053)]
- 然后弹出配置窗口
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vONfXiVV-1628911268476)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/20160910175738836)]
参数说明
\1. Whole project>>整个项目都生成
\2. Custom scope>>自定义范围,如下:project files 项目文件,project production files 项目产品文件,project test files 项目的测试文件, 未知范围,class hierarchy 类层
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8cROaVqO-1628911268477)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/20160910180409757)]
\3. include test source 包含测试目录
\4. include JDK and … 包含jdk和其他的第三方jar
\5. link to JDK documentation…链接到JDK api
\6. output directy 生成的文档存放的位置
\7. private、package、protected、public 生成文档的级别(类和方法)
\8. 右边的Generate…是选择生成的文档包含的内容,层级树、导航、索引…
\9. 再右边是生成的文档包含的内容信息,作者版本等信息
\10. Locale 语言类型,zh-CN
\11. Other command line arguments 其他参数
\12. Maximum heep… 最大堆栈
Java流程控制
用户交互Scanner
-
之前我们学的基础语法中我们并没有实现程序和人的交互,但是Java给我们提供了一个工具类,我们可以获取用户的输入。Java.util.Scanner是Java5的新特性。我们可以通过Scanner类来获取用户的输入
-
基本语法
Scanner s = new Scanner(System.in);
-
通过Scanner类的next与nextLine()方法获取输入的字符串,在读取前我们一般需要使用hasNext()与hasNextLine()判断是否还有输入的数据
import java.util.Scanner;public class Demo01 { public static void main(String[] args) { //创建一个扫描器,用于接收键盘输入 Scanner s = new Scanner(System.in); //判断用户有没有输入字符串 if (s.hasNext()){ //使用next方式接收 String str = s.next(); System.out.println("您输入的东西为:"+str); } s.close() }}
import java.util.Scanner;public class Demo01 { public static void main(String[] args) { //创建一个扫描器,用于接收键盘输入 Scanner s = new Scanner(System.in); //判断用户有没有输入字符串 if (s.hasNextLine()){ //使用next方式接收 String str = s.nextLine(); System.out.println("您输入的东西为:"+str); } s.close(); }}
- nest()
- 一定要读取到有效字符后才可以结束输入
- 对输入有效字符之前遇到的空白,next()方法会自动将其去掉
- 只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符
- next()不能得到带有空格的字符串
- nextLine()
- 以Enter为结束符,也就是说nextLine()方法返回的是输入回车之前的所有字符
- 可以获得空白
没有必要的话可以不用判断是否有输入
判断是否为xxx类型
例子:判断整数
import java.util.Scanner;public class Demo01 { public static void main(String[] args) { //创建一个扫描器,用于接收键盘输入 Scanner scanner = new Scanner(System.in); //从键盘接收数据 int i = 0; float f =0.0f; System.out.println("请输入整数:"); if(scanner.hasNextInt()){ i = scanner.nextInt(); System.out.println("整数数据:" + i); }else{ System.out.println("输入的不是整数"); } System.out.println("请输入小数:"); if(scanner.hasNextFloat()){ f = scanner.nextFloat(); System.out.println("输入的小数为:" + f); }else{ System.out.println("输入的不是小数"); } scanner.close(); }}
import java.util.Scanner;public class Demo01 { public static void main(String[] args) { //输入多个数字求和,输入数字回车确定,输入非数字结束 //创建一个扫描器,用于接收键盘输入 Scanner scanner = new Scanner(System.in); //f为接收输入的数,sum为求和,num为求输入了多少个数 double f = 0; double sum = 0; int num = 0; while (scanner.hasNextDouble()){ f = scanner.nextDouble(); sum += f; num ++; } System.out.println("输入的平均数为:"+sum/num); scanner.close(); }}
顺序结构
-
Java的基本结构就是顺序结构,除非特别指明,否则就按照顺讯一句一句执行。
-
顺序结构是最简单的算法结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wz3LRZeX-1628911268477)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210810134450117.png)]
-
语句与语句之间,框与框之间是按照从上到下的顺序进行的,它是由若干个依次执行的处理步骤组成的,它是任何一个算法都离不开的一种基本算法结构。
选择结构
-
if单选择结构
-
我们很多时候都要判断一个东西是否可行,然后我们才去执行,这样一个过程在程序中用if使用
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NCfWTMvh-1628911268478)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210810135758440.png)]
-
语法
if(布尔表达式){ //如果布尔表达式为真的时候需要执行的语句。}
-
//输入字符串是否等于Hello,如果等于则输出Hello不等于什么都不干。//字符串比较需要用equals,尽量不要用==import java.util.Scanner;public class Demo01 { public static void main(String[] args) { //创建一个扫描器,用于接收键盘输入 Scanner scanner = new Scanner(System.in); System.out.println("请输入内容:"); String s = scanner.nextLine(); //equals:判断字符串是否相等 if(s.equals("Hello")){ System.out.println(s); } System.out.println("End"); scanner.close(); }}
-
-
if双选择结构
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6EFYTsGk-1628911268479)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210810135827418.png)]
-
语法
if(布尔表达式){ //如果布尔表达式为真执行的语句}else{ //如果布尔表达式为假执行的语句}
-
import java.util.Scanner;public class Demo01 { public static void main(String[] args) { //创建一个扫描器,用于接收键盘输入 Scanner scanner = new Scanner(System.in); System.out.println("请输入成绩:"); int s = scanner.nextInt(); //equals:判断字符串是否相等 if(s>=60){ System.out.println("及格"); }else{ System.out.println("成绩不及格"); } scanner.close(); }}
-
-
if多选择结构
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UdvOVbUg-1628911268479)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210810140137315.png)]
-
语法
if(布尔表达式1){ //布尔表达式1成立执行的代码}else if(布尔表达式2){ //布尔表达式2成立执行的代码}else if(布尔表达式3){ //布尔表达式3成立执行的代码}else{ //布尔表达式都不成立执行的代码}
-
import java.util.Scanner;public class Demo01 { public static void main(String[] args) { //创建一个扫描器,用于接收键盘输入 Scanner scanner = new Scanner(System.in); System.out.println("请输入成绩:"); int s = scanner.nextInt(); //equals:判断字符串是否相等 if(s==100){ System.out.println("恭喜满分"); }else if(s>=80 && s<100){ System.out.println("成绩优秀"); }else if(s>=60 && s<80){ System.out.println("成绩良好"); }else if(s>=0&&s<60){ System.out.println("不及格"); }else{ System.out.println("输入的成绩有误"); } scanner.close(); }}
-
-
嵌套的if结构
-
使用嵌套的if…else语句时合法的。也就是说可以在另一个if或者else if语句中使用if或者else if语句。可以像if语句一样嵌套else if…else
-
语法
if(布尔表达式1){ //如果布尔表达式1成立执行的语句 if(布尔表达式2){ //如果布尔表达式2成立时执行语句 }}
-
-
switch多选择结构
-
switch智能匹配准确的一个值,而不能匹配一个范围
-
多选择结构还有一个实现的方式就是switch case语句
-
switch case语句判断一个变量与一系列值中的某个值是否相等,每个值称为一个分支
-
switch语句中的变量类型可以是:
- byte,short,int或者char
- 从Java SE 7开始,switch支持字符串String类型了,同时case标签必须是字符串常量或字面量
-
语法
switch(expression){ case value: //语句 break; case value: //语句 break; default: //语句}
-
循环结构
-
while 循环
-
只要布尔表达式为真则一直执行
-
我们大多数情况是让循环停下来,我们需要让表达式失效的方式来结束循环
-
少部分情况下需要一直循环,比如服务器的监听
-
循环一直为true的情况会造成无线循环【死循环】,我们正常的业务编程中应该尽量避免死循环,会影响程序的性能或者造成程序卡死崩溃
while(布尔表达式){ //循环执行的代码 }
import java.util.Scanner; public class Demo01 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int i = scanner.nextInt(); int sum = 0; while (sum<=i){ System.out.println(sum); sum++; } scanner.close(); } }
-
-
do…while 循环
- 先执行再判断
- 和while循环一样,不过至少执行一次代码
-
for 循环
-
虽然所有的循环结构都可以用while或者do…while表示,但Java提供了另一种语句–for循环,使一些循环结构变得更简单
-
for循环语句是支持迭代的一种通用结构,是最有效,最灵活的循环结构
-
for循环执行的次数在执行前就确定的,语法如下
for(初始化;布尔表达式;更新){ //代码语句}
-
求100以内奇数偶数
public class Demo01 { public static void main(String[] args) { int jishu=0; int oushu=0; for(int i=1;i<=100;i++){ if(i%2==0){ oushu += i; }else{ jishu += i; } } System.out.println("奇数为" + jishu); System.out.println("偶数为" + oushu); }}
-
求九九乘法表
public class Demo01 { public static void main(String[] args) { for(int i=1;i<=9;i++){ for(int j=1;j<=i;j++){ System.out.print(i+"*" + j +"="+i*j+" "); } System.out.println(); } }}
-
-
在Java5中引入了一种主要用于数组的增强型for循环
-
语法
for(声明语句 : 表达式){ //执行的代码}
-
例子
int[] num = {10,20,30,40,50};for(int x:num){ System.out.println(x);}
-
break&continue
-
break在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句(break语句也在switch中使用)
-
continue语句在循环语句体中,用于终止某次循环过程,即跳过循环体重尚未执行的语句,接着进行下一次是否执行循环的判定
-
goto关键字
-
goto容易出现问题
-
goto关键字很早就在程序设计语言中出现。尽管goto仍是Java中的一个保留字,但并未在语言中正式使用,Java中没有goto,然而在break和continue这两个关键字的身上我们可以看到一些goto的影子—带标签的break和continue、
-
"标签"是指后面跟着一个冒号的标识符例如:label:
-
对于Java来说唯一用到标签的地方是在循环语句之前,二在循环之前设置标签的唯一理由是:我们希望在其中嵌套另一个循环,由于break和continue关键字通常只终端当前的循环,弱随同标签使用,他们就可以终端到存在标签的地方
-
练习
-
打印三角形
-
public class Demo01 { public static void main(String[] args) { for (int i = 0; i < 5; i++) { for (int j = 5; j >= i; j--) { System.out.print(" "); } for (int j = 1; j <= 2*i+1; j++) { System.out.print("*"); } System.out.println(); } }}
-
Java方法
-
System.out.println(),它是什么
-
Java方法是语句的集合,它们在一起执行一个功能
- 方法是解决一类问题的步骤的有序组合
- 方法包含于类或对象中
- 方法在程序中被创建,在其他地方被引用
-
设计方法的原则:方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一个方法只能完成一个功能,这样利于我们后期的扩展。
-
加法方法
-
public class Demo01 { public static int add(int a,int b){ return a+b; } public static void main(String[] args) { int a = 1; int b = 5; int sum = add(1,2); System.out.println(sum); }}
-
-
Java的方法类似于其他语言的函数,是一段用来完成特定功能的代码,一般情况下,定义一个方法包含以下语法:
- 方法包含一个方法头和一个方法体,下面是一个方法的所有部分:
- 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型
- 返回值类型:方法可能会返回值。returnValueType是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType是关键字void。
- 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
- 参数类型:参数像是一个占位符。当方法被调用时,传递给参数,这个参数被称为实参或者变量。参数列表地是指方法的参数类型,顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
- 形式参数:在方法被调用时用于接收外界输入的数据
- 实参:调用方法时实际传给方法的数据
- 方法体:方法包含具体的语句,定义改方法的功能
- 方法包含一个方法头和一个方法体,下面是一个方法的所有部分:
-
语法:
修饰符 返回值类型 方法名(参数类型 参数名){ ... 方法体; ... return 返回值;}
-
方法调用:
-
调用方法:对象名.方法名(实参列表)
-
Java支持两种调用方法的方式,根据方法是否返回值来选择
-
当方法返回一个值的时候方法调用通常被当做一个值。例如:
int larger = max(30,40)
-
方法返回值是void,方法调用一定是一条语句。
System.out.println("Hello World")
-
方法重载
我们可以设置多个重名的方法,但是我们要确保每个方法的参数不一样。
- 重载就是在一个类中,有相同的函数名称,但形参不同的函数
- 方法的重载的规则
- 方法名称必须相同
- 参数列表必须不同(个数不同,类型不同,参数排列顺序不同等)
- 方法的返回类型可以相同也可以不同
- 仅仅返回类型不同不足以成为方法的重载
- 实现理论
- 方法名称相同时,编译器会根据调用方法的参数个数,参数类型等去逐个比较匹配,以选择对应的方法,如果匹配失败,则编译器报错
命令行传参
有时候希望运行一个程序时再传递给它消息。这要靠传递命令行参数给main()函数实现
-
例子
public class Demo01 { public static void main(String[] args) { for (int i = 0; i < args.length; i++) { System.out.println("args[" + i +"]:" + args[i]); } }}
这里需要注意一点的是,不能在此文件路径下运行否则会找不到主类,需要到idea最开始的路径下运行全路径文件地址才可以运行
可变参数
- 可能会存在传参数不确定的情况。我们可以用main的方法传递个可变的参数。
- JDK1.5开始,Java支持传递同类型的可变参数给一个方法。
- 在方法声明中,在指定参数类型后加一个省略号(…)
- 一个方法中只能指定一个可变参数,它必须是方法的最后一个参数,任何普通的参数必须在它之前声明
public class Demo01 { public void test(int... i){ for (int j:i) { System.out.println(j); } } public static void main(String[] args) { Demo01 demo01 = new Demo01(); demo01.test(1,2); }}
递归
-
A方法调用B方法,我们很容易理解
-
递归就是自己调用自己
-
利用递归可以用简单的程序来解决一些复杂的问题。它通常把一个大型的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需要少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于有限的语句来定义对象的无限集合、
-
递归结构分为两部分
- 递归头:什么时候不调用自身方法。如果没有头,将陷入死循环
- 递归体:什么时候需要调用自身方法
-
//求输入数的阶乘import java.util.Scanner;public class Demo01 { public static int f(int n){ if (n==1){ return 1; }else{ return n*f(n-1); } } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int num = scanner.nextInt(); System.out.println(f(num)); }}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pA85dGJj-1628911268480)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210810232142426.png)]
-
前阶段
-
边界条件
-
返回阶段
数组
数组概述
- 数组是相同类型数据的有序集合
- 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成
- 其中,每一个数据乘坐一个数组元素,每个数组元素可以通过一个下标来访问他们
数组声明创建
-
首先必须声明数组变量,才能再程序中使用数组,下面是声明数组变量的方法:
dataTyye[] arrayRefVar //首选的方法 int[] nums;dataType arrayRefvar[] //效果相同但是不是首选的方法 int nums[];
-
Java语言使用new操作符来创建数组,语法如下:
dataType[] arrayRefVar = new dataType[arraySize];int[] nums = new int[5]
-
数组的元素是通过索引访问的,数组索引从0开始
-
获取数组长度
arrays.length nums.length
public class Demo01 { public static void main(String[] args) { int[] nums; //声明数组 nums = new int[5]; //创建一个数组,开辟空间,这里可以存放5个int类型的数据 nums[0] = 1; nums[1] = 2; nums[2] = 3; nums[3] = 4; nums[4] = 5; }}
-
数组初始化
-
静态初始化
int[] a = {1,2,3};Man[] mans = {new Man(1,1),new Man(2,2)}
-
动态初始化
int[] a = new int[2]; a[0] = 1; a[1] = 2;
-
数组的默认初始化
//数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,每个元素也被按照实例变量同样的方式被隐式初始化
-
内存分析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MEQge6Nu-1628911268481)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210810234855168.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q2UxFnbo-1628911268482)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210810235139503.png)]
数组的特点
- 长度是确定的。数组一旦被创建,它的大小就是不可以改变的
- 其元素必须是相同类型,不允许出现混合类型
- 数组中的元素可以是任何元素类型,包括其基本类型和引用类型
- 数组变量属于引用类型,数组也可以看成对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。
- 下标的合法区间
[0,length-1]
如果越界就会报错
数组使用
-
For-Each循环
//For-Each遍历数组 public class Demo01 { public static void main(String[] args) { //没有下标 int[] nums = {1,2,3,4,5}; for (int i: nums) { System.out.println(i); } } }
-
数组做方法参数
//反转字符串public class Demo01 { public static void main(String[] args) { int[] nums = {1,2,3,4,5}; int[] result = reverse(nums); for (int i = 0; i < result.length; i++) { System.out.println(result[i]); } } public static int[] reverse(int[] arrays){ int[] result = new int[arrays.length]; for (int i = 0,j = arrays.length-1; i < arrays.length; i++,j--) { result[j] = arrays[i]; } return result; }}
多维数组
-
多维数组可以看成是数组的数组,比如二位数组就是一个特殊的一位数组,其每个元素都是一个一维数组。
-
二维数组
int a[][] = new int[2][5]
-
解析:以上二维数组a可以看成一个二行五列的数组
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i7fEoiLb-1628911268482)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210811001558381.png)]
public class Demo01 { public static void main(String[] args) { int[][] a = {{1,2},{3,4},{5,6},{7,8}}; }}
Arrays类
-
数组的工具类java.util.Arrays
-
由于数组对象本身并没有什么方法可以供我们使用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本操作。
-
查看JDK帮助文档
-
Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,二不用使用对象来调用(注意:是"不用"而不是"不能")
-
具有以下功能
-
对数组赋值:通过fill方法
-
对数组排序:通过sort方法,按升序
-
比较数组:通过equals方法比较数组中元素值是否相等
-
查找数组元素:通过binarySearch方法能够对排序好的数组进行二分查找
public class Demo01 { public static void main(String[] args) { int[] a={5,3,1,4,2}; System.out.println(a); //[I@1b6d3586 System.out.println(Arrays.toString(a)); //[5, 3, 1, 4, 2] Arrays.sort(a); System.out.println(Arrays.toString(a)); //[1, 2, 3, 4, 5] }}
-
冒泡排序
import java.util.Arrays;public class Demo01 { public static void main(String[] args) { int[] a = {5,1,3,7,4}; int[] b = buSort(a); System.out.println(Arrays.toString(b)); } public static int[] buSort(int[] arrays){ for (int i = 0; i < arrays.length-1; i++) { for (int j = 0; j < arrays.length-i-1; j++) { if(arrays[j]<arrays[j+1]){ int a = arrays[j]; arrays[j] = arrays[j+1]; arrays[j+1] = a; } } } return arrays; }}
稀疏数组
-
五子棋有存盘退出和续上盘的操作
以为存储了很多的0,所以记录了很多没有意义的数据
-
解决:稀疏数组
-
当一个数组中大部分元素为0,或者同一值的数组时,可以使用稀疏数组来保存该数组。
-
稀疏数组的处理方式是:
- 记录数组一个有几行几列,有多少个不同的值
- 把具有不停值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模
-
如下图:左边是原始数组,右边是稀疏数组
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6NDWuIpF-1628911268484)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210811003833824.png)]
import java.util.Arrays;public class Demo01 { public static void main(String[] args) { int[][] array1 = new int[11][11]; array1[1][2] = 1 ; array1[2][3] = 2 ; for(int[] anInt:array1){ for(int i:anInt){ System.out.print(i+" "); } System.out.println(); } int[][] result = xiShu(array1); for (int i = 0; i < result.length; i++) { System.out.println(Arrays.toString(result[i])); } } //将二维数组转为稀疏数组 public static int[][] xiShu(int[][] arrays){ int sum = 0; for (int i = 0; i < 11; i++) { for (int j = 0; j < 11; j++) { if(arrays[i][j] != 0){ sum++; } } } int[][] result = new int[sum+1][3]; result[0][0]= 11; result[0][1]= 11; result[0][2]= sum; int resnum = 1; for (int i = 0; i < 11; i++) { for (int j = 0; j < 11; j++) { if(arrays[i][j] != 0){ result[resnum][0] = i; result[resnum][1] = j; result[resnum][2] = arrays[i][j]; resnum++; } } } return result; }}
面向对象编程
面向过程 & 面向对象
- 面向过程思想
- 步骤清晰简单,第一步做什么,第二步做什么
- 面向过程适合处理一些较为简单的问题
- 面向对象思想
- 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后对某个分类下的细节进行面向过程的思索
- 面向对象适合处理复杂的问题,适合处理需要多人协作的问题!
- 对于描述复杂的事物,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是具体到微观操作,仍需要面向过程的思路去处理。
什么是面向对象
- 面向对象编程(OOP)
- 面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据
- 抽象
- 三大特性:
- 封装
- 继承
- 多态
- 从认识论角度考虑是现有对象后有类。对象,是具体事物。类,是抽象的,是对对象的抽象
- 从代码运行角度考虑是先有类后有对象。类是对象的模板
回顾方法的定义与调用
- 方法的定义
- 修饰符
- 返回类型
- break:跳出switch,结束循环 & return
- 方法名(驼峰,见名知意)
- 参数列表
- 异常抛出
- 方法的调用
- 静态方
- 类名.方法
- 非静态方法
- 先实例化,然后再用对象调用方法
- 形参和实参
- 值传递和引用传递
- this关键字
- 静态方
类与对象的关系
- 类是一种抽象的数据,它是对某一类事物整体描述/定义,但是并不代表某一个具体的事物
- 动物,植物,手机,电脑
- Person类,Pet类,Car类等,这些类都是描述/定义某一类事物应该具备的特点和行为
- 对象是抽象概念的具体实例
- 张三就是人的一个具体实例,张三家里的旺财就是狗的一个实例
- 能够体现出特点,展现出功能是具体的实例,而不是一个抽象的概念
创建与初始化对象
-
使用new关键字创建对象
-
使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用
一个类即使什么也没有,它也会存在一个构造器
使用new关键字,本质上实在调用构造器
-
类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:
- 必须和类的名字相同
- 必须没有返回类型,也不能写void
public class Student { public String name; public int age; public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } public void study(){ System.out.println(name + "正在学习"+",他今年"+age+"岁了"); }}/*public class Demo01 { public static void main(String[] args) { Student student = new Student(); student.name = "xxx"; student.age = 21; student.study(); System.out.println(); }} */
创建对象内存分析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NB8QR8VV-1628911268484)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210811120028462.png)]
简单小结与对象
-
类与对象
- 类是一个模板:抽象,对象是一个具体的实例
-
方法
- 定义,调用!
-
对象的引用
引用类型:基本类型(8个)
对象是通过引用来操作的:栈–>堆(地址)
-
属性:字段Field 成员变量
默认初始化
数字:0 0.0
char:u0000
boolean:false
引用:null
修饰符 属性类型 属性名 = 属性值!
-
对象的创建和使用
- 必须使用new关键字创建对象,构造器
Person newPerson = new Person()
- 对象的属性:newPerson.name
- 对象的方法:newPerson.sleep()
- 必须使用new关键字创建对象,构造器
-
类:
- 静态的属性 属性
- 动态的属性 方法
封装
- 该露的露,该藏的藏
- 我们程序设计要求追求"高内聚,低耦合"。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉,低耦合:仅暴露少量的方法给外部使用。
- 封装(数据的隐藏)
- 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏
- 属性私有:get/set
- 特点
- 提高程序安全性,保护数据
- 隐藏代码实现的细节
- 统一接口
- 系统可维护增加
public class Student { private String name; private int age; private char sex; public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public void setSex(char sex) { this.sex = sex; } public String getName() { return name; } public int getAge() { return age; } public char getSex() { return sex; }}/*public class Demo01 { public static void main(String[] args) { Student student = new Student(); student.setName("xxx"); student.setAge(21); student.setSex('男'); System.out.println(student.getName()); System.out.println(student.getAge()); System.out.println(student.getSex()); }} */
继承
- 继承的本质是对一批类的抽象,从而实现对现实世界更好的建模
- extands的意思是"扩展"。子类是父类的扩展
- JAVA中类只有单继承,没有多继承
- 继承是类与类之间的一种关系。除此之外,类和类之间的关系还有依赖,组合,聚合等
- 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。
- 子类和父类之间,从意义上来讲有is a的关系
//Student is 人 : 派生类:子类
//子类继承了父类的所有的方法和属性
//子类不能继承父类的私有属性值,但是其他的可以继承
//在Java中,所有的类都默认继承object类
public class Person {
String name;
int age;
public void say(){
System.out.println("说了一句话");
}
}
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.say();
}
}
public class Student extends Person{
}
-
super
//Student public class Student extends Person{ private String name ="Student"; public void test(String name){ System.out.println(name); System.out.println(this.name); System.out.println(super.name); } }
//Personpublic class Person { protected String name = "Person"; //private String name = "Person"是无法被继承的,如果是这样的话子类的super也访问不到该属性 protected int age; public void say(){ System.out.println("说了一句话"); }}
//Applicationpublic class Application { public static void main(String[] args) { Student student = new Student(); student.test("Application"); }}
//先执行父类的构造函数再执行子类的构造函数public class Person { public Person(){ super(); //隐藏的代码 }}// 父类必须有无参构造,否则子类也不能有无参构造
-
super注意点
- super调用父类的构造方法,必须在构造方法的第一行
- super必须只能出现在子类的方法或者构造方法中!
- super和this不能同时调用构造方法
-
Vs this
-
代表的对象不同:
this:本身调用这个对象
super:代表父类对象的应用
-
前提
this:没有继承也可以使用
super:只能在继承条件才可以使用
-
构造方法:
this():本类的构造
super():父类的构造
-
-
方法重写
-
A类继承B类。都写一个一样的方法。
//Applictionpublic class Application { public static void main(String[] args) { //方法的调用只和左边,定义的数据类型有关 Student a = new Student(); Person b = new Student();//父类的引用指向了子类 a.test();//走的是Student的方法 b.test();//走的是Person的方法 }}
//Personpublic class Person { public Person(){ super(); } public static void test(){ System.out.println("Person=>test()"); }}
//Studentpublic class Student extends Person{ public static void test(){ System.out.println("Student==>test()"); }}
//结果Student==>test()Person=>test()
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-brXJqmTb-1628911268484)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210811183209778.png)]
把static去掉后
这里就代表重载
重载只和非静态有关系。和静态没有关系
重写:需要有几成关系,子类重写父类的方法!
- 方法名必须相同
- 参数列表必须相同
- 修饰符:范围可扩大 public >protected>Default>private
- 抛出异常:范围可以被缩小,但不能扩大:ClassNotFoundException–>Exception(大)
重写,子类的方法和父类必要一直,方法体不同。
为什么重写:
- 父类的功能,子类不一定需要,或者不一定满足
多态
- 即统一方法可以根据发送对象的不同而采用多种不同的行为方式
- 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多
- 多态存在的条件:
- 有继承关系
- 子类重写父类的方法
- 父类引用指向子类对象
- 注意:多态是方法的多态,属性没有多态
public class Application { public static void main(String[] args) { //一个对象的实际类型是确定的 //可以指向的引用类型不确定 Student s1 = new Student(); //父类的引用指向子类 //都是学生表现出了不同的状态:多态 Person s2 = new Student(); Object s3 = new Student(); s2.test(); s3.test();//这里的s3.test()没有办法执行因为Object类中没有test()方法 }}
public class Person { public void test(){ System.out.println("Person=>test()"); }}
//Student is 人 : 派生类:子类//子类继承了父类的所有的方法和属性//子类不能继承父类的私有属性值,但是其他的可以继承//在Java中,所有的类都默认继承object类public class Student extends Person{ @Override public void test() { System.out.println("son"); }}
对象能执行哪些方法看左边的类型,和右边的关系不大。只能调用自己的或者从父类那里继承下来的
//多态注意的事项:/*多态是方法的多态,属性没有多态需要是父类和子类;要有联系;如果没有联系那么会报类型转换异常存在条件:继承关系,方法需要重写,父类的引用指向子类对象 static 修饰的方法,属于类,它不属于对象 final 在常量池里面的 private 私有的方法。没有办法重写*/
-
instanceof(类型转换) 引用类型之间的,判断一个对象是什么类型。
//判断object对象是不是Student,Person,Object,Teacher和String类型public class Application { public static void main(String[] args) { Object object = new Student(); System.out.println(object instanceof Student); System.out.println(object instanceof Person); System.out.println(object instanceof Object); System.out.println(object instanceof Teacher); System.out.println(object instanceof String); }}/*true,true,true,false,false.student 是Student,Person,Object类。但是和Teacher和String没有关系1. 父类引用指向子类对象2. 把子类转化为父类:向上转型;3. 把父类转化为子类,向下转型;强制转换4. 方便方法的调用,减少重复代码*/
我认为多态就是一个物体的子类的相同的方法之间有不同的表现形式。而重写就是实现多态的一个方法。通过在子类里面把父类的方法进行重写。变成自己的方法,运行起来表现出来不同的结果,这样就是多态。
static
//加在类中就是静态类,加在方法上就是静态方法
public class Student extends Person{ private static int age; //静态方法 private double score; //非静态方法 public static void main(String[] args) { Student s1 = new Student(); System.out.println(Student.age);// System.out.println(Student.score); 编译错误 System.out.println(s1.age); System.out.println(s1.score); }}
public class Student extends Person{ private static int age; //静态方法 private double score; //非静态方法 public void run(){ System.out.println("run"); go();//正确,以为对象创建的时候类已经创建成功了,静态方法也随着类的创建而创建了 } public static void go(){ System.out.println("go"); run();//错误,因为在类创建的时候非静态方法还没有创建。 } public static void main(String[] args) { new Student().run();// new Student().go; Student.go();// Student.run(); }}
public class Person { { //代码块(匿名代码块);程序在执行的时候并不能主动调用模块。创建对象的时候就执行;赋初始值 System.out.println("匿名代码块"); } static { //静态代码块(匿名代码块);我们可以在里面加载一些初始化的东西;类加载就执行,只执行一次; System.out.println("静态代码块"); } public Person() { System.out.println("构造方法"); } public static void main(String[] args) { Person person1 = new Person(); Person person2 = new Person(); }}/*运行结果静态代码块,匿名代码块,构造方法,匿名代码块,构造方法*/
import static java.lang.Math.random
静态导入包
抽象类
- abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法,如果修饰类,那么该类就是抽象类。
- 抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。
- 抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。
- 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
- 子类继承抽象类,那么必须要实现抽象类没有实现的抽象方法,否则子类也要声明为抽象类。
public class Student extends Person{ @Override public void doSomething() { System.out.println("doSomething"); } public static void main(String[] args) { System.out.println("doSomething"); new Student().doSomething(); }}
//abstarct 抽象类:类 extends 单继承~ (接口可以多继承)public abstract class Person { //作为一个约束~让别人帮我们实现 //只有方法的名字但是没有方法的实现 public abstract void doSomething();}
/*1. 抽象类不能new;只能靠子类去实现它:约束2. 一旦类里面有抽象方法,类必须是抽象类。3. 抽象类中可以写普通的方法4. 抽象的抽象是约束*/
接口
-
普通类:只有具体实现
-
抽象类:具体实现和规范(抽象方法)都有!
-
接口:只有规范!自己无法写方法专业的约束!约束和实现分离:面向接口编程
-
接口就是规范,定义的是一组规则,体现了现实世界中"如果你是…则必须能…"的思想。如果你是天使,则必须能飞
-
接口的本质是契约,就像我们人间的法律一样,制定好之后大家都遵循
-
OO(面向对象)的精髓,是对对象的抽象,最能体现这一点的是
//类 可以实现接口 implements 接口
//实现了接口的类,就需要写接口中的方法
//实现了多继承接口
public class UserServiceImpl implements UserService,TimeService{
@Override
public void timer() {
}
@Override
public void run(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
}
//interface 定义的关键字,接口都需要有实现类
public interface UserService {
//常量~ public static final
//一般在接口中不使用常量
int AGE = 99;
//接口中的所有定义都是抽象的 public abstract
public abstract void run(String name);
// void run(String name);
void delete(String name);
void update(String name);
void query(String name);
}
public interface TimeService {
void timer();
}
- 接口的作用:
- 约束
- 定义一些方法,让不同的人实现
- 接口中的所有定义都是抽象的 public abstract
- 常量~ public static final
- 接口不能被实例化;接口中没有构造方法~
- implements可以实现多个接口
- 必须要重写接口中的方法
内部类
-
内部类就是在一个类的内部再定义一个类
public class Outer { private int id=10; public void out(){ System.out.println("这是外部类方法"); } class Inner{ //可以获取外部类的私有属性 public void in(){ System.out.println("这是内部类"); } public void getId(){ System.out.println(id); } }}
public class Demo01 { public static void main(String[] args) { Outer outer = new Outer(); //通过外部类实例化内部类 Outer.Inner inner = outer.new Inner(); inner.in(); inner.getId(); }}
-
静态内部类
public class Outer { private int id=10; public void out(){ System.out.println("这是外部类方法"); } public static class Inner{ //可以获取外部类的私有属性 public void in(){ System.out.println("这是内部类"); } public void getId(){ System.out.println(id);//错误 } }
这里id就不能拿到,因为static是在外部类new的时候就创建了,这时候还没有id这个属性。所以访问不到
一个Java类中只能有一个public类,可以有多个类
异常
什么是异常
- 实际工作中遇到的情况不可能是非常完美的,写的代码不一定符合要求。打开文件的格式不对等
- 软件程序在运行过程中,非常可能遇到刚刚提到的这些异常问题我们叫异常,英文是Exception。
- 异常指程序运行汇总出现的不期而至的各种情况,如:文件找不到,网络连接失败,非法参数等
- 异常发生在程序运行期间,它影响了正常的程序执行流程
简单分类
- 要理解Java异常处理是如何工作的,你需要掌握以下三个异常类型
- 检查性异常:最具有代表性的检查性异常就是用户错误或问题引起的异常,这是程序员无法预见的。例如打开一个不存在的文件时,一个异常就会发生。这些异常在编译时不能被简单的忽略。
- 运行时异常:运行时异常时可能被程序员避免的异常。与检查异常相反,运行异常可以在编译时被忽略。
- 错误ERROR:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,他们在编译时也检查不到。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HsptCwAY-1628911268485)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210812125106651.png)]
Error
- Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。
- Java虚拟机运行错误,当JVM不再有继续执行操作所需的内存资源时,将出现OutOfMemoryError。这些异常发生时,Java虚拟机一般会选择线程终止。
- 还有发生在虚拟机试图执行应用时,如类定义错误,链接错误。这些错误是不可查的,因为他们在应用程序的控制和处理能力之外,而且绝大多数程序运行时不允许出现的状况。
Exception
- 在Exception分支中有一个非常重要的子类RuntimeException(运行时异常)
- ArrayIndexOutOfBoundsException(数组下标越界)
- NullPointerException(空指针异常)
- ArithmeticException(算数异常)
- MissingResourceException(丢失资源)
- ClassNotFoundException(找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理
- 这些异常一般是由程序的逻辑错误导致的,成都旭应该从逻辑角度尽可能避免这类异常发生
- Error和Exception的区别:Error通常指灾难性的致命错误,是程序无法控制和处理的,当出现这种异常时,Java虚拟机一般会选择终止线程;Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常
异常处理机制
-
抛出异常
-
捕获异常
-
五个关键字
- try,catch,finallly,throw,throws
-
public class Outer { public static void main(String[] args) { int a = 10; int b = 1; try {//监控区域 System.out.println(a/b); }catch (ArithmeticException e){//catch捕获异常 System.out.println("分母不能为0"); }finally {//无论出不出异常都会执行的代码(可以不要) System.out.println("finally"); } }}
public class Outer { public static void main(String[] args) { int a = 10; int b = 1; try {//监控区域 new Outer().a(); //捕获多个异常的时候需要对异常进行从小到大排序 }catch (Exception e1){//catch捕获异常 System.out.println("Exception"); }catch (Error e2){ System.out.println("Error"); }catch (Throwable e3){ System.out.println("Throwable"); }finally {//无论出不出异常都会执行的代码 System.out.println("finally"); } //Ctrl + Alt + t 会自动生成 try catch finally } public void a(){ b(); } public void b(){ a(); }}
public class Outer { public static void main(String[] args) { int a = 10; int b = 0; try { new Outer().test(a,1); } catch (ArithmeticException e) { e.printStackTrace(); } } //假设方法中,处理不了这个异常,方法上抛出异常 public void test(int a,int b) throws ArithmeticException{//throws是方法中使用的 if(b==0){ throw new ArithmeticException(); //主动捕获异常然后抛出异常 //一般在方法中使用 } System.out.println(a/b); }}
自定义异常
- 使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常,只需要继承Exception类即可。
- 在程序中使用自定义异常类,大题可以分为下列几个步骤:
- 创建自定义异常类
- 在方法中通过throw关键字抛出异常对象
- 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作
- 在出现异常方法的调用者中捕获并处理异常
public class Demo01 {
static void test(int a)throws MyException{
System.out.println("传递的值" + a);
if(a>10){
throw new MyException(a);
}
System.out.println("OK");
}
public static void main(String[] args) {
try {
test(11);
} catch (MyException e) {
System.out.println(e);
}
}
}
//自定义异常类
public class MyException extends Exception {
//传递数字>10
private int detail;
public MyException(int a) {
this.detail = a;
}
//toString:异常的打印信息
@Override
public String toString() {
return "MyException{" +
"detail=" + detail +
'}';
}
}
总结
- 处理运行异常时,采用逻辑去合理规避同时辅助 try-catch 处理
- 在多重catch块后面,可以加一个catch(Exception)来处理可以会被遗漏的异常
- 对于不确定的代码,也可以加上一个try-catch,处理潜在的异常
- 尽量去处理异常,切忌知识简单的调用printStackTrace()去打印输出
- 具体如何处理异常,要根据不同的业务需求和异常类型去决定
- 尽量添加finally语句去释放占用的资源
多线程
线程简介
任务
多线程
进程
- 说起进程,就不得不说下程序。程序时指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。
- 而进程则是政治性程序的一次执行过程,他是提个动态的概念。是系统资源分配的单位。
- 通常在一个进程中可以包含若干个线程,当然一个进程汇总至少有一个线程,不然没有存在的意义。线程是CPU调度和执行的单位。
注意:很多多线程是模拟出来的,真正的多线程是指有多个cpu,即多核,如服务器。如果模拟出来的多线程,即在一个cpu的情况下,在同一个时间点,cpu只能执行一个代码,因为切换的很快,所以就有同事执行的错局
进程 > 线程 > 任务
- 线程就是独立的执行路径
- 在程序运行时,及时没有自己创建的线程,后台也会有多个线程,如主线程,gc线程
- main()称之为主线程是系统的入口,用于执行整个程序
- 在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不能人为干预的。
- 对同一份资源操作时,会存在资源抢夺问题,需要加入并发控制;
- 线程会带来额外的开销,如cpu调度时间,并发控制开销
- 每个线程在自己的工作内存交互,内存控制不当会造成数据不一致
线程创建
-
三种创建方式
-
Thread class(继承Thread类)【重点】
-
Runnable接口(实现Runnable接口)【重点】
-
Callable接口(实现Callable接口)【了解】
-
Thread
- 自定义线程类继承Thread类
- 重写run()方法,编写线程执行体
- 创建线程对象,调用start()方法启动线程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RhcmwmCD-1628911268486)(Java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.assets/image-20210812235746099.png)]
案例
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
//联系Thread,实现多线程同步下载图片
public class TestThread2 extends Thread{
private String url;//网络地址
private String name;//保存文件名
public TestThread2(String url,String name) {
this.url = url;
this.name = name;
}
public static void main(String[] args) {
TestThread2 t1 = new TestThread2("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png","1.png");
TestThread2 t2 = new TestThread2("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png","2.png");
TestThread2 t3 = new TestThread2("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png","3.png");
t1.start();
t2.start();
t3.start();
}
//下载图片线程的执行体
@Override
public void run() {
WebDownloader webDownloader = new WebDownloader();
webDownloader.downloader(url,name);
System.out.println("下载的文件名为"+name);
}
}
class WebDownloader{
public void downloader(String url,String name){
try {
FileUtils.copyURLToFile(new URL(url),new File(name));
} catch (IOException e) {
e.printStackTrace();
System.out.println("IO异常,downloader方法出现问题");
}
}
}
//逻辑为先下1再2再3.
//但是由于是多线程随意顺序就不一定是什么了
实现Runnable
- 定义MyRunnable类实现Runnable接口
- 实现run()方法,编写线程执行体
- 创建线程对象,调用start()方法启动线程
//创建线程方式:实现runnable接口;重写run()方法,执行线程需要兑入runnable接口实现类,调用start方法
public class TestThread3 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("我在学习"+i);
}
}
public static void main(String[] args) {
TestThread3 testThread3 = new TestThread3();
//创建线程对象,通过线程对象来开启我们的线程,代理
new Thread(testThread3).start();
for (int i = 0; i < 200; i++) {
System.out.println("我在打游戏++++++++++++++"+i);
}
}
}
实现Callable接口(了解即可)
- 实现Callable接口,需要返回值类型
- 重写call方法,需要抛出异常
- 创建目标对象
- 创建执行服务:ExecutorService ser = Executors.newFixedThreadPool(1)
- 提交执行:Future result1 = ser.submit(t1);
- 获取结果:boolean r1 = result1.get();
- 关闭服务:ser.shutdownNow();
- 好处
- 可以定义返回值
- 可以抛出异常
- 好处
import com.ying.LearnThread.WebDownloader;
import java.util.concurrent.*;
//线程创建方式三:实现callable接口
public class TestCallable implements Callable<Boolean> {
private String url;//网络地址
private String name;//保存文件名
public TestCallable(String url,String name) throws ExecutionException, InterruptedException {
this.url = url;
this.name = name;
}
@Override
public Boolean call(){
WebDownloader webDownloader = new WebDownloader();
webDownloader.downloader(url,name);
System.out.println("下载的文件名为:"+name);
return true;
}
public static void main(String[] args) throws ExecutionException,InterruptedException{
TestCallable t1 = new TestCallable("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png","1.png");
TestCallable t2 = new TestCallable("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png","2.png");
TestCallable t3 = new TestCallable("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png","3.png");
TestCallable t4 = new TestCallable("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png","4.png");
ExecutorService ser = Executors.newFixedThreadPool(3);
Future<Boolean> r1 = ser.submit(t1);
Future<Boolean> r2 = ser.submit(t2);
Future<Boolean> r3 = ser.submit(t3);
Future<Boolean> r4 = ser.submit(t4);
boolean rs1 = r1.get();
boolean rs2 = r2.get();
boolean rs3 = r3.get();
boolean rs4 = r4.get();
ser.shutdownNow();
}
}
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
public class WebDownloader{
public void downloader(String url,String name){
try {
FileUtils.copyURLToFile(new URL(url),new File(name));
} catch (IOException e) {
e.printStackTrace();
System.out.println("IO异常,downloader方法出现问题");
}
}
}
小结
-
继承Thread类
- 子类继承Thread类具备多线程能力
- 启动线程:子类对象.start()
- 不建议使用:避免OOP单继承局限性
-
实现Runnable接口
-
实现接口Runnable具有多线程能力
-
启动线程:传入目标对象+Thread对象.start()
-
推荐使用:避免单继承的局限性,灵活方便,方便同一个对象被多个线程使用
-
初始并发问题
//多个线程同时操作同一个对象
//多个线程操作一个资源的情况下,出现了问题
public class TestThread4 implements Runnable{
int ticketNums = 10;
@Override
public void run() {
while (true){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "拿到了第"+ticketNums-- +"张票");
if(ticketNums<=0){
break;
}
}
}
public static void main(String[] args) {
TestThread4 t1 = new TestThread4();
new Thread(t1,"小明").start();
new Thread(t1,"小红").start();
new Thread(t1,"小刚").start();
}
}
案例:龟兔赛跑
//模拟龟兔赛跑
public class Race implements Runnable{
private static String winner;
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
if(Thread.currentThread().getName()=="兔子"&& i%10 == 5){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
boolean flag = gameOver(i);
if(flag){
//如果比赛结束就结束跑步
System.out.println("结束比赛");
break;
}
System.out.println(Thread.currentThread().getName()+"跑了"+i+"步");
}
}
//判断是否完成比赛
public boolean gameOver(int steps){
//判断是否有胜利者
if(winner!=null){
return true;
}else{
if(steps==100){
winner = Thread.currentThread().getName();
System.out.println("winner is "+winner);
return true;
}
}
return false;
}
public static void main(String[] args) {
Race race = new Race();
new Thread(race,"乌龟").start();
new Thread(race,"兔子").start();
}
}
静态代理
//静态代理总结:
/*
1. 代理角色和真实角色都要实现同一个接口
2. 代理对象要代理真实角色
好处:
代理角色可以做很多真实角色做不了的事情
真实角色只做专注的事情就可以
*/
public class StacticProxy {
public static void main(String[] args) {
You you = new You();
WeddingCompany weddingCompany = new WeddingCompany(you);
weddingCompany.HappyMarry();
}
}
interface Marry{
void HappyMarry();
}
//真实角色,你去结婚
class You implements Marry{
@Override
public void HappyMarry() {
System.out.println("xxx要结婚了");
}
}
//代理角色,代理
class WeddingCompany implements Marry{
//代理谁-->真实角色
private Marry target;
public WeddingCompany(Marry target) {
this.target = target;
}
@Override
public void HappyMarry() {
before();
this.target.HappyMarry();
after();
}
private void after() {
System.out.println("结婚之后收尾款");
}
private void before() {
System.out.println("结婚之前布置现场");
}
}
Lambda表达式
-
λ希腊字符表中第十一的字母
-
避免匿名内部类定义过多
-
其实质属于函数式编程的概念
(params)->expression[表达式] (params)->statement[语句] (params)->{statements} a-> System.out.println("i like lambda-->"+a);
new Thread(()->System.out.println("多线程学习....")).start()
为什么使用Lamdba表达式
- 避免匿名内部类定义过多
- 可以让代码看起来更简洁
- 去掉了一堆没有意义的代码,只留下核心的逻辑
-
理解Functional Interface(函数式接口)是学习Java8 lambda表达式的关键所在
-
函数式接口的定义
-
任何接口,如果只包含唯一一个抽象方法,那么它就是一个函数式接口
public interface Runnable { public abstract void run(); }
-
对于函数式接口,我们可以通过lambda表达式来创建该接口的对象
/* 推到lambda表达式 */ public class TestLambda { //3. 静态内部类 static class Like2 implements ILike{ @Override public void lambda() { System.out.println("I Like Lambda2"); } } public static void main(String[] args) { //接口new了一个实现类类 ILike like = new Like();//这里使用ILike是因为,如果使用Like的话,下面的new Like2();是不能赋值给like的,因为like是属于Like()方法的而不是Like2()方法。如果想赋值的话还需要再新建一个Like2 like才能赋值。 //这样的话是使用父亲创建的对象,这样new 一个Like2也可以赋值给like。因为like是用他父亲创建出来的,Like2里面实现了父亲的方法,体现了方法的重载 like.lambda(); like = new Like2(); like.lambda(); //4. 局部内部类 class Like3 implements ILike{ @Override public void lambda() { System.out.println("I Like Lambda3"); } } like = new Like3(); like.lambda(); //5. 匿名内部类,没有类的名称,必须借助接口或父类实现 like = new ILike() { @Override public void lambda() { System.out.println("I Like Lambda4"); } }; like.lambda(); //6. 用lambda简化 //必须是一个函数式接口,不然这个()不能区分是哪个方法,故就不可以用 like = ()->{ System.out.println("I Like Lambda5"); }; like.lambda(); } } //1. 定义一个函数式接口 interface ILike{ void lambda(); } //2. 实现接口 class Like implements ILike{ @Override public void lambda() { System.out.println("I Like Lambda"); } }
public class TestLambda2 { public static void main(String[] args) { Ilove love = (int n)-> { System.out.println("I love you-->"+n); }; love.love(2); } } interface Ilove{ void love(int n); }
public class TestLambda2 { //1.lambda表达式简化 public static void main(String[] args) { Ilove love = (int n)-> { System.out.println("I love you-->"+n); }; //简化1.参数类型 love = (a)->{ System.out.println("I love you-->"+a); }; //简化2.简化括号,多个参数不能去掉 love = a -> { System.out.println("I love you-->"+a); }; //简化3.去掉花括号 //代码只有一行的时候才能够去掉花括号,否则不能简化 love = a -> System.out.println("I love you-->"+a); love.love(2); //总结: //代码只有一行的时候才能够去掉花括号,否则不能简化;如果有多行则用代码块替代 //前提是接口为函数式接口 //多个参数也可以去掉参数类型,要去掉就都去掉,必须加上括号 } } interface Ilove{ void love(int n); }
-