第一章:了解(chapter)
复习方法: 找到视频 每个章节 结合笔记。
https://www.bilibili.com/video/BV1fh411y7R8?p=266&spm_id_from=pageDriver&vd_source=5c60787a1cdddc0e6d23d53b2b6bb1c4
第一阶段:建立编程思想(包括:基本语法、数组、排序和查找、面向对象编程、零钱通、房屋出租系统、迷宫、八皇后、汉诺塔 )
第二阶段:提升编程能力(包括: 枚举和注解、Exception、常用类、集合、泛型、线程、IO流、坦克大战)
第三阶段: 增强分析需求,代码实现能力(包括: 网络编程、反射、Mysql、JDBC和连接池、正则表达式、Java8 Java11 新特性、马踏棋盘、满汉楼、多用户通信系统)
如何快速学习Java新技术.(重点!!)
步骤1:需求步骤2:解决方法步骤3:引出新技术和知识点步骤5:快速入门:(基本的程序:CRUD)先进行增删改查工作需求 跳槽 技术控1. 能否使用旧技术.能解决,但不完美\解决不了,新技术有是什么优势.步骤4: 学习新技术和知识点的基本原理和基本语法(不要考虑细节.)先会用再考虑血肉.步骤6:开始考虑研究技术细节\注意事项\使用规范\如何优化. 优化永无止境. 这个才是拉开差距的地方.每个人看到的点不一样.第一小节: 1~3
1. JAVA就业方向
- JavaEE软件工程师
- 大数据软件工程师
- Android软件工程师
2.JAVA开发场景-ssm android hadoop(大数据) 程序员角度
- Spring(轻量级的容器框架)
- SpringMVC(分层的web开发框架)
- MyBatis(持久性框架)
- android(安卓)
- hadoop(大数据)
3.应用方面
- 企业级应用
- 软件系统\各类型网站\金融\电信\交通\电子商务等.
- Android平台应用
- 移动(嵌入式开发)领域:
- 嵌入式开发 pos机\汽车通讯设备\机顶盒\大屏幕投影娱乐设备等.
4.程序是什么
程序是: 计算机执行某些操作或解决某些问题而编写的一系列有序指令的集合.
编程上 输入->计算->输出这样的步骤.
计算机上, 编程文件->javac 讲java文件转录成class文件 ->再运行class文件,才能实现.
第二小节:
JVM的主要组成部分及其作用有哪些 - 编程语言 - 亿速云 (yisu.com) 细看这部分
1.java 概述
- java8和java11 是LTS 公共版本
java8 23-可扩展到30-年
java11 23-可扩展到26-年
- java95年第一个版本,GOSLING(gosling)为创始人
- javaSE(标准版)JAVAEE(企业版)\JAVAME(移动终端和编程.)没用了已经
2.java特点
- Java是面向对象的(oop)
- java是健壮的.强类型机制 \异常处理 \垃圾自动回收等是其健壮性的重要保障
- java语言是跨平台性的.(主要因为JVM)
Test.java文件编译成Test.class文件. 这个class文件可以在Windows和Linux操作系统下运行.这就是跨平台性.
根本原因是JVM.不同操作系统,使用不一样的JVM.
- java语言是解释型语言.
- 解释性语言:javascript\PHP\java
- 编译性语言:c\c++
区别:
解释性语言: 编译后的代码,不能直接被机器执行,需要解释器来执行,( javac )(就是转化为class文件).
编译性语言:可以直接被机器执行.
所以难怪 性能差一些.
3.java运行机制及运行过程
- java核心机制\java虚拟机[JVM java virtual machine]
- 基本介绍:
1.)JVM 是一个虚拟的计算机,具有指令集并使用不用的存储区域. 负责执行指令 \管理数据 \内存 \寄存器\都包含在JDK**中
2.)对于不同的平台,有不同的虚拟机.
3.)java虚拟机机制屏蔽了地城运行平台的差别,实现了"一次编译,到处运行"
<img alt="1663845135788" loading="lazy">

运行过程 :
集成开发工具写的java文件 通过javac(编译器编译)成class文件(字节码文件) 然后加载到jvm中 先加载类装载器(装载类和静态类等) 然后开始运行程序- java文件通过编译器变成了.class文件,接下来类加载器又将这些.class文件加载到JVM中。 其实可以一句话来解释:类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个 java.lang.Class对象,用来封装类在方法区内的数据结构。
复制代码 最后由解释器

4.什么是JDK\JRE
JDK:
- JDK全称(Java Development kit) java开发工具包
- JDK= JRE + java的开发工具 (java,javac,javadoc,javap等)
- JDK是提供给Java开发人员使用的,其中包含了java的开发工具,也包括了JRE,所以安装了JDK就不用单独安装JRE了.
JRE:
- JRE(Java Runtime Environment) java 运行环境
- 包括Java虚拟机(JVM java virtual Machine)和java 程序所需的核心类库
- 需要运行JAVA程序 就只要安装JRE就可以了,因为已经编译过了.'
JDK = JRE + java开发工具
JRE = JVM + 核心类库
jre 就是jvm + 核心类库 保障java程序运行
jdk 在jre的基础上添加了开发工具 java javac javadoc javap等等
5.JDK 安装
公共JRE eclipse有时候要使用公共JRE. 可以不安装.
环境变量的作用,是为了在dos的任何目录都能使用java和javac
环境变量界面有两个
一个是用户变量
一个用系统变量
分别有不同的作用域
仅当前用户
和使用该电脑的所有用户
第三小节:
1.java入门.
第一个java文件. 打印 "Hello,World".
源文件字节码文件结果先编写 .java文件javac编译 成 .class 文件运行 类 结果
运行问题:, 中文编码报错.
因为cmd控制台使用的GBK格式, 右键cmd控制台查看控制台的属性
需要更改为GBK格式 才能使用,也可以使用GB18030,
2.java的格式问题
- 源文件 必须是 java为拓展名
- main方法有固定格式不能更改
public static void main(String[] args){}
- 严格区分大小写\分号";"结尾\大括号成对出现
- 一个源文件中有且只有一个public类,文件名也需要按这个类名命名.其他类个数不限,
可以将main写在非public类中,然后指定运行非public类,入口方法就是非public的main方法了.
一个java文件有多个类,编译后,没一个类 都会生成一个.class文件.
每个非public类中都可以使用主方法,因为生成的独立的class文件, 只要调用对应的类的class文件.
<img alt="1663865117916" loading="lazy">
<img alt="1663865137832" loading="lazy">
第四小节
1.转义字符
Tab键在DOS可以自动补全。
\t == table 制表符
'\r' 回车,回到当前行的行首,而不会换到下一行,如果接着输出的话,本行以前的内容会被逐一覆盖;
'\n' 换行,换到当前位置的下一行,而不会回到行首- Unix系统里,每行结尾只有“<换行>”,即"\n";Windows系统里面,每行结尾是“<回车><换行>”,即“\r\n”;Mac系统里,每行结尾是“<回车>”,即"\r";。
复制代码 一个直接后果是,Unix/Mac系统下的文件在Windows里打开的话,所有文字会变成一行;而Windows里的文件在Unix/Mac下打开的话,在每行的结尾可能会多出一个^M符号。- // \t:制表位\实现对齐的功能. 空四个字节.
- System.out.println("北京\t深圳\t上海");
- // \n: 换行符
- System.out.println("jack\nsmith\nmary");
- // \\: 一个\
- System.out.println("\\t"+"\n双斜杠"+"\\\\t");
- // ": 一个"
- // \': 一个'
- //跳过
- // \r:一个回车
- //1. 会先输出黄烘南,\r后面的字 会替换掉前面的黄烘南三个字
- System.out.println("黄烘南\r好");
- //好烘南
-
- //回车加换行.
- System.out.println("黄烘南\r\n好好学习");
- //黄烘南
- //好好学习
- //练习
- System.out.println("书名\t作者\t价格\t销量\n三国\t罗贯中\t120\t1000");
- //书名 作者 价格 销量
- //三国 罗贯中 120 1000
复制代码 2.容易产生的错误
1与l
0和o
中英文符号问题
拼写错误
非法字符错误问题
3.注释(comment)
做好注释.
多行快捷键是ctrl +shift+/ 单行快捷键是ctrl+/
多行注释不可以在嵌套多行注释.
单行\多行\文档- //单行注释 comment
- /*多行注释
- 多行快捷键是ctrl +shift+/ 单行快捷键是ctrl+/
- 多行注释不可以在嵌套多行注释.
- */
复制代码 文档注释:
注释内容可以被JDK提供的工具 javadoc所解析,生成一套网页文件形式体现的程序说明文档,一般写在类的前面
了解基本格式\如何生成\实例- /**
- * @author hhn
- * @version 1.0
- *
- * */
- public class Hello{
- //编写一个主方法 程序入口
- public static void main(String[] args){
- //输出
- System.out.println("黄烘南 is studying java ");
- }
- }
复制代码 <img alt="1663872587923" loading="lazy">
javadoc附录:
标签描述示例@author标识一个类的作者,一般用于类注释@author description@deprecated指名一个过期的类或成员,表明该类或方法不建议使用@deprecated description指明当前文档根目录的路径Directory Path@exception可能抛出异常的说明,一般用于方法注释@exception exception-name explanation从直接父类继承的注释Inherits a comment from the immediate surperclass.插入一个到另一个主题的链接插入一个到另一个主题的链接,但是该链接显示纯文本字体Inserts an in-line link to another topic.@param说明一个方法的参数,一般用于方法注释@param parameter-name explanation@return说明返回值类型,一般用于方法注释,不能出现再构造方法中@return explanation@see指定一个到另一个主题的链接@see anchor@serial说明一个序列化属性@serial description@serialData说明通过 writeObject() 和 writeExternal() 方法写的数据@serialData description@serialField说明一个 ObjectStreamField 组件@serialField name type description@since说明从哪个版本起开始有了这个函数@since release@throws和 @exception 标签一样.The @throws tag has the same meaning as the @exception tag.显示常量的值,该常量必须是 static 属性。Displays the value of a constant, which must be a static field.@version指定类的版本,一般用于类注释@version info4.java代码规范
- 类、方法的注释,要以javadoc的方式来写
- 非java Doc的注释,往往是给代码的维护者观看,如何修改等问题
- 使用tab操作,实现缩进,默认整体向右移动,使用shift+tab整体左移
- 运算符和 = 两边习惯性各加一个空格 比如: int = 1 + 1; 要每个都分开
- 源文件使用utf-8编码
- 行宽不超过80 一行不超过80
- 代码编写次行风格和行尾风格.
次行: 每次进行大括号都进行换行
行尾: 大括号在行尾.
5.DOS命令
DOS原理:
指令--->发送给DOS系统, (1.接受指令,2.解析指令,3.执行指令.)--->最终体现在windows操作系统中
颜色:- ·命令:color f0
- 帮助:color ?
- 作用:改变背景及字体颜色
- ·命令:cls
- 作用:清屏
复制代码 目录- ·命令:dir
- 作用:浏览当前文件夹的内容(带<dir>标识的为文件夹,否则为文件)
- 其他用法:
- dir 指定路径
- dir d:\
- dir d:\pic
- dir /a #浏览所有内容,包括隐藏内容
- ·命令:盘符:
- 作用:切换分区, 如:c: d: e:
- ·命令:cd ..
- 作用:退出一级目录
- ·命令:cd 文件夹名
- 作用:进入文件夹
- ·Tab键:补全路径功能
- ·命令:cd \
- 作用:直接退到根目录
- 命令: tree 加目录名
- 作用:生成子级目录树
- ·路径:
- 相对路径:针对当前路径有效,如: ..\456
- 绝对路径:从根开始写路径,如: \123\345
-
- ·注释:
- fsutil fsinfo drives #可以查看当前系统的分区列表
复制代码 文件操作:- ·命令:md 文件夹 [文件夹 文件夹 ....]
- ·命令:rd 文件夹 [文件夹 文件夹 ....]
- 作用:删除空文件夹
- 命令:rd 文件夹 /s/q
- (/s是递归删除,/q是无提示删除)
- 作用:无提示递归删除非空文件夹
- ·创建文件方法:
- echo 字符串 >>[路径\]文件名.扩展名
- 注释:>>和>都可以将命令的输出内容输入到某文件中,若文件不存在,则同时创建该文件
- ·>>为追加
- ·>为覆盖
- ·>nul为不显示回显
- ·2>为错误信息输出并覆盖
- ·2>>为错误信息输出并追加
- ·2>nul 经典用法:屏幕上不要有任何的报错
- 如:rd . /s/q 2>nul
- ·显示文件内容命令:
- type 文件名.扩展名
- 作用:浏览一个文件的内容
- ·命令:del 文件名.扩展名
- 作用:删除文件
- ·del *.txt #删除所有txt结尾的文件
- ·del *.* #删除所有文件
- ·del *.* /s /q #无提示删除所有文件
- 注释:*为通配符,代表任意字符,任意长度
- ?为单字符匹配
- ·ren 原名 新名 #重命名,可以重命名文件和文件夹。
- ·命令:copy [路径\]源文件全名 目标路径[\新文件全名]
- 作用:复制文件
- ·命令:move [路径\]源文件全名 目标路径[\新文件全名]
- 作用:移动文件
复制代码 6.相对\绝对路径
相对路径:
从当前目录开始定位,形成的一个路径.
只有单个目录
"java快速学习\javacode"
从顶层开始定位,形成的路径.
"C:\Users\qianl\Desktop\java快速学习\javacode"
例子:
<img alt="1663908387066" loading="lazy">
从当前目录访问另一个目录的文件.
相对路径:
"cd ..\..\abc2\test200\hello.txt"
绝对路径:
"cd d:"
"\abc2\test200\hello.txt"
<img alt="1663909559916" loading="lazy">
第二章:变量
第一小节:
1.字符串拼接
- 57 是一个常量
- "57" 是一个字符串常量(5和7这两个字符的序列)
复制代码 计算时:- System.out.println("57 + 32 = " + (57 + 32));
复制代码 1.先计算小括号,再由于是字符串 + 数字 (或者数字 + 字符串)都会将 数字 变成 字符串. 最终拼和成"57 + 32 = 89".
如果不加括号,则会变成: 字符串 + 57 然后 字符串 + 32 .变成"57 + 32 = 5732"
如果计算放在前面,那么就没有关系. 因为从左往右进行.
2.变量的声明
变量三大要素:
类型+名称+值
int x = 1; 声明和赋值 (声明加初始化 也是初始值)
int类型 名为x的盒子 盒子里的值为 1;
integer 整数
3.数据类型
类型名称关键字占用内存取值范围字节型byte1 字节-128~127短整型short2 字节-32768~32767整型int4 字节-2147483648~2147483647长整型long8 字节-9223372036854775808L~9223372036854775807L单精度浮点型float4 字节+/-3.4E+38F(6~7 个有效位)双精度浮点型double8 字节+/-1.8E+308 (15 个有效位)字符型char2 字节ISO 单一字符集布尔型boolean1 字节true 或 false
1.整数类型
long类型需要注意加 "l" 或者: "L" 通常大写- int x = 1; int只有8个字节
- int x = 1L; long有16个字节,范围超了.
- int x = (int)(1L);
复制代码 2.浮点类型
默认是double类型
浮点数 = 符号位 + 指数位 + 尾数位.
因为小数,精度丢失 (所以都是近似值)
**d也可以使用d为结尾 ** 可加可不加 小数默认是double
即: double d1 = 3d; //ok的 d1 = 3.0- float f = 1.1f; 4个字节
- double d = 1.1; 8个字节
- //如果是0开头的小数可以省略
- double d1 = 0.123
- double d2 = .123
- //也可以使用科学计数法
- 5.12e2 //512.0
- 5.12e-2 // 0.0512
-
- 使用陷阱:就是分数问题.
- double num1 = 2.7;
- double num2 = 8.1/3; // 计算是2.7 输出的是 2.69999999997
- num2 是一个接近2.7的小数,是近似值.
-
- 原因是 8.1这个数被转变为二进制的时候,最小二倍数法,取得的小数是很长的,超过了double的精度,所以这个数被截断了,除于3的时候就变成了一个不足2.7的数了.
复制代码 原因是 8.1这个数被转变为二进制的时候,最小二倍数法,取得的小数是很长的,超过了double的精度,所以这个数被截断了,除于3的时候就变成了一个不足2.7的数了. 之后再用乘二取余法
应该以两个数的差值的绝对值,在某个进度范围内进行判断.
Math.abs() 获取绝对值
使用Math类的方法
<img alt="1663942965256" loading="lazy">
3.char类型
单个字符使用char 长字符串使用String类
char 单引号, String使用双引号 这里的String是"类" 首字母大写才是类
char的本质是"ISO 单一字符集"; 也就是一串数字
char类型也是可以计算的,本质是数字,所以计算的结果也是一串数字对应的字符
存储:
比如:'a'是97 会转换成二进制(110 0001),然后进行存储.- char c1 = 'a';
- char c2 = '黄';
- char c3 = '\t'; //表示制表符的四个空格
- char c4 = 97; //表示ISO单一字符集
- System.out.println(c1);
- System.out.println(c2);
- System.out.println(c3);
- System.out.println(c4);
- a
- 黄
- a
复制代码 只有英文字符,不用汉字就不用那么多个字符了.
<img alt="1663946294241" loading="lazy">
注意,utf-8 是一个可变长的所以不是所有汉字都是3个字节(1到6个字节)
<img alt="1663947025784" loading="lazy">
4.boolean类型
注意点: java中不能使用0或者非0整数来替代true和false python 非强制性语言可以 默认是False- boolean bool = true;
- if (bool == true) {
- System.out.println("考试通过了,恭喜");
- }else {
- System.out.println("下次努力");
- }
复制代码 <img alt="1663951074030" loading="lazy">
4.二进制
byte是一个8位的数,
第一个是符号位,后面为实际存储
十进制转二进制:
最小二倍数法
首位为符号位, 指数位+尾数位, 进行科学计数法以后,小数点浮点,所以叫浮点数. 通过补码来进行数据还原.
取出来的叫原码 要转化为反码 反码+1 变补码 然后java都是补码进行计算的
二进制转十进制:
乘2取余法
乘2 整数位大于1舍去,取余数
5.java8 在线API
https://www.matools.com/api/java8
按包——》找类——》找方法。也可以直接检索
API的结构 :注意 每个包内 接口,类,异常有很多个。
<img alt="1663943466628" loading="lazy">- java基础包
- java.applet Applet所需的类和接口
- java.awt 图形用户界面所需的类和接口
- java.beans Java bean所需的类和接口
- ♥ java.io 系统输入/输出所需的类和接口
- ♥ java.lang Java语言编程的基础类和接口
- java.math 支持任意精度整数和任意精度小数的类和接口(与lang下的math类更专业)
- ♥ java.net 网络应用的类和接口
- java.nio 定义缓冲区,它们是数据容器,并提供其他NIO包的概述
- java.rmi 远程调用(RMI)的类和接口
- java.security 用于安全框架的类和接口
- ♥ java.sql 访问和处理数据源中数据的类和接口
- java.text 支持按与语言无关方式处理文本、数据、数字和消息的类和接口
- java.time 日期,时间,瞬间和持续时间的主要API
- ♥ java.util 集合框架、事件模型、日期和时间机制、国际化等的类和接口
- java扩展包等
- javax.accessibility 定义用户界面组件与提供对这些组件的访问的辅助技术之间的合同
- javax.activity 包含ORB机械在解组时抛出的活动服务相关异常
- javax.annotation.processing 用于声明注释处理器和允许注释处理器与注释处理工具环境通信的设施
- javax.crypto 提供加密操作的类和接口
- javax.imageio Java Image I / O API的主要包………
- javax.rmi 支持RMI-IIOP的类和接口
- javax.serverlet 支持serverlet编程的类和接口
- javax.sound 支持音频设备数字接口(MIDI)的类和接口
- javax.swing 扩充和增强基本图形用户界面功能的类和接口
- javax.transaction 包含有几个关于事务上下文异常的类
- org.omg.CORBA 支持OMG CORBA API到Java语言映射的类和接口
- 等等
复制代码 6.类型转换
小范围转变成大范围能自动转型,大变小需要强制转换.
小类能自动继承大类的方法, 但是大类没有小类的方法.
1.自动转换:
精度小的类型自动转换为精度大的数据类型,这就是自动转换 精度(容积)
<img alt="1663951537957" loading="lazy">
auto == automatic (自动化)
表示自动化的意思
注意事项:
所以没声明具体类型的数字 默认为 int类型
- 多类型数据混合计算,自动转换为容量最大的类型,然后计算
- byte, short 和char之间不能互相自动转换
- byte ,short和char之间可以计算,会先转换为int类型, 因为char算是数字 (int类型).
- boolean不参与转换.
- 表达式结果,自动提升为操作数中最大的类型.
<img alt="1663952809170" loading="lazy">
2.强制类型转换
基本方法:- int x = (int)(1L);
- 需要的值类型 = (需要的值类型)(被转换的类型);
复制代码 两种可能:
1.精度缺失,
没有四舍五入 int等整型 直接去除小数点后的数
2.数据溢出
不再声明的范围内的数 溢出
<img alt="1663953226425" loading="lazy">
细节说明:
<img alt="1663953551515" loading="lazy">
主要是char和int变量之间,需要强制转换,.
<img alt="1663953707739" loading="lazy">
我的结果:
<img alt="1663954155862" loading="lazy">
正确结果:
注意:
1.第一和第二题, 9和11 都默认为int类型,计算取最高的类型.
2.第三题,计算全部转换成了最高的float类型 可以自动转换给double.
3.第四题, byte和short进行计算会自动变成int类型 这时候 就不能再自动转给byte short 和char了
<img alt="1663954266304" loading="lazy">
3.String类型转换成基本数据类型
基本数据类型转String ,加双引号
<img alt="1663954538648" loading="lazy">
String转基本数据类型, 需要使用包装类
每一个数据类型都有一个包装类,也就是将基本数据类型变成对应的"类"
parse 解析
基础类型与对应包装类编写区别
除了int Integer
char Character
其他都是首字母大写
<img alt="1663954850274" loading="lazy">
String转换char类型,
使用 String.charAt( index ) 方法,返回在index位置的char字符。(返回值:char )
使用 String.toCharArray( ) 方法,将String 转化为 字符串数组。(返回值:char[] )
也可以转换成字符串数组
<img alt="1663955021405" loading="lazy">
char转换成String类型- //1.效率最高得到一种方法
- String s = String.valueOf('c');
- //2.将字符串数组转化为字符串
- String s = String.valueOf(new char[] {'G','e','o','o','o'});
- //3.用 Character 的 toString(char) 方法 ==> 实际上还是调用了String.valueOf(char)
- String s = Character.toString('c');
- //4.new 一个 Character 调用 toString()
- String s = new Character('c').toString();
- //5.直接用 空 String 拼接 'c'
- String s = "" + 'c' ;
- //第5种方法效率最低,因为String类是 final 属性
- // "" + 'c' 时候需要创建新的 String 类 ,如果进行很多次拼接则要创建很多个类虚拟机栈可能会溢出
复制代码 注意事项:
- String的数据是非数字的时候,转换成整数的话,就会抛出异常.程序会中止.那么捕获和处理方法需要写出.
7.键盘输入规范
注意点:
1.导入包 import java.util.Scanner;
2.固定格式: Scanner stdIn = new Scanner(System.in);
3.不能以 Scanner为类名, 会重写Scanner方法.
4.限制输入的数据类型 ,靠next+类型 来限制.- //注意导入类(文本扫描)
- import java.util.Scanner;
- public class Inport{
- public static void main(String[] args) {
- // 固定格式
- Scanner stdIn = new Scanner(System.in);
- System.out.println("请输入要计算的值");
- System.out.println("x:");
- int x = stdIn.nextInt();
- System.out.println("y:");
- int y = stdIn.nextInt();
-
- System.out.println("x + y = " + (x + y));
- System.out.println("x - y = " + (x - y));
- System.out.println("x * y = " + (x * y));
- System.out.println("x / y = " + (x / y));
-
- }
- }
复制代码 8.生成随机数(Random)
也可以使用Math方法进行,注意看API的 Random的方法- //注意导入类 随机数类
- import java.util.Random;
- public class Random01{
- public static void main(String[] args) {
- // 固定格式
- Random Rand = new Random();
- int lucky = Rand.nextInt(10); //0~9的随机数.
- System.out.println("今天的幸运数字是:" + lucky + ".");
-
- // 1. 1~9的随机数
- // 2. -9~-1的随机数
- // 3. 10~99的随机数
- int one = 1;
- int num = Rand.nextInt(10); //1~9的随机数.
- System.out.println("今天的幸运数字是:" + (num + one) + ".");
- int num1 = Rand.nextInt(9);//0到 8
- System.out.println("今天的负数是:" + (-(num1 + one)) + "."); //- (1到9)
- int num2 = Rand.nextInt(90);// 0到89
- System.out.println("今天的正数是:" + (num2 + 10) + ".");//+10 变成10-99
- }
- }
复制代码- //Math.Random 是生成随机数,会生成一个 double类型的数 [0.0,1.0)
- //任务,一直生成1到100的数
复制代码- for (; ; ) {
- //加1才能成为1到100
- i = (int)(Math.random()*100) + 1;
- System.out.println(i);
- j++;
- if (i == 97){
- System.out.println(i + "次数" + j);
- break;
- }
复制代码 第三章:运算符
1.算术运算符
加减乘除 求余 自增自减(按照顺序进行计算.)
有两个操作数的也叫二元运算符
<img alt="1663994625676" loading="lazy">
除法计算问题:
记住一个问题:
计算以最高精度的数为准,整数默认int 小数默认double
所以下面的 10 / 4 = 2 10.0 / 4 = 2.5
<img alt="1663995183098" loading="lazy">
取模问题:
取模有一个公式:
本质: m % n = m - (int)(m / n) * n
注意:余值结果符号和 m (被模数) 符号有关,m为负数则余值为负数,m为正数则余值为正数。 同时注意,(m/n的结果 是会被化为int类型的)
<img alt="1663995795235" loading="lazy">
自加问题:
注意 :
int j = 8;
int k = j++; //取值后运算.
以后输出的k = 8, j = 9;
<img alt="1663996009001" loading="lazy">
原理:
使用了中间数 temp 来进行临存储 值
替换成 j与k- int j = 1;
- k = j++;
- // temp = j; k = temp; j = j + 1;
- // 1 1 结果 k = 1 j = 2
- //这样更符合 先赋值,后运算.
- int j = 1;
- k = ++j;
- // j = j + 1; temp = j; k = temp;
- // j=2 temp = 2 k = 2
- //这样更符合 先赋值,后运算.
复制代码 <img alt="1663996196114" loading="lazy">
1.先赋值后计算:
i = 10; i1 = 11; i2 = 20
2.先计算后赋值
i2 = 19 ; i = i2 = 19; i1 = 11 ;
<img alt="1663996735809" loading="lazy">
除法计算:
由于5/9 都是默认int类型,得到的小于1 所以直接舍去小数位,变成0 后面什么都是0
<img alt="1663997219015" loading="lazy">
更改方法:
改为5.0以后, 因为计算变成全部都是double类型, 所以变成了有小数位的,得到的结果也就有小数了.
<img alt="1663997241705" loading="lazy">
2. 关系运算符
结果都是boolean类型 ,只有true和false两种结果
通常在if的判断语句中使用
= (表示赋值)
== 表示比较
<img alt="1663998439488" loading="lazy">
hsp 是不是String类中的对象
3.逻辑运算符
分组学习:
<img alt="1664000686632" loading="lazy">
短路 && || !
短路:
判断条件时 , 判断第一个条件就可能可以得到结果, 作用与& 和 | 相同,右边的情况将不再执行. && 的时候 左边为false 则短路 (只要有一个是假 就整个是假)
|| 的时候 左边为true 则短路 (只要有一个真 就整个是真)

如下: 短路&& 由于a>> 叫无符号位移 没有= 2 && name.length() 20) { this.balance = balance; } else { System.out.println("余额不能少于20 默认值为0"); } } public String getPassword() { return password; } public void setPassword(String password) { if (password.length() == 6) { this.password = password; } else { System.out.println("密码必须为6位 默认密码000000"); this.password = "000000"; } } public void showInfo() { //密码可以增加权限的校验 System.out.println("账号信息 name=" + name + "余额" + balance + "密码" + password); }}[/code]5.(重点)继承 extends(继承 扩展)
类的属性与方法很多相同, 使用继承 只写自己需要新加的 从重复的类中抽象出父类.
父类又叫 超类 基类
继承的关系示意图
<img alt="1666119794512" loading="lazy">
继承测试:
父类:- if(条件表达式){
- 执行代码块; (判断为 true时执行,否则跳过)
- }
- 如果只有一条语句代码块 , 可以不用{}, 到那时还是建议使用
-
复制代码 子类 puplic- Scanner stdIn = new Scanner(System.in);
- System.out.println("请输入年龄");
- int age = stdIn.nextInt();
- if(age>18){
- System.out.println("送进监狱");
- }else {
- System.out.println("送进管教所");
- }
复制代码 子类: graduate- 价格 money
- 获取月份
- 获取年龄
- if(month 为 旺季){
- if (18 < age){
- 票价 money/2
- }else if( 18<= age && age <=60){
- 票价 money
- }else{
- money/3
- }
- }else{
- if ( 18<= age && age <=60 ){
- 票价 = 40
- }else {
- 票价 = 20
- }
-
- }
复制代码 测试类 Test- //固定格式:
- Scanner stdIn = new Scanner(System.in);
- System.out.println("请输入a-g");
- char day = stdIn.next().charAt(0);
- switch(day){
- case 'a':
- System.out.println("今天星期一");
- break;
- case 'b':
- System.out.println("今天星期二");
- break;
- case 'c':
- System.out.println("今天星期三");
- break;
- case 'd':
- System.out.println("今天星期四");
- break;
- case 'e':
- System.out.println("今天星期五");
- break;
- case 'f':
- System.out.println("今天星期六");
- break;
- case 'g':
- System.out.println("今天星期日");
- break;
- default:
- System.out.println("无效字符");
- break;
- }
复制代码 细节:
1.子类继承了父类的全部属性和方法, 但是私有的属性和方法不能在子类直接访问,需要通过公共的方法去访问. (子类不能直接访问私有属性与方法, 但是能间接使用)
使用get方法 获得private属性
使用callTest400的方法去调用私有方法.
下面是运行逻辑
先是生成父类构造器 然后子类构造器
然后调用子类方法 输出 public protected 默认
通过getN4 获得私有属性
然后通过方法调用 public protected 和默认 的方法
使用公共方法调用私有方法- for(int i = 1;i <= 10;i++){ // 1 到 10次 输出完 不满足条件就跳出.
- System.out.println("Hello,World");
- }
复制代码 2.子类必须调用父类的构造器,完成父类的初始化
看上面的例子 创建子类 Sub 先完成了父类的构造器 Base;
3.创建子类对象,不管使用子类的哪个构造器,默认调用父类无参, 没有提供无参则必须在子类构造器用 super去指定使用父类的哪个构造器 完成父类的初始化工作 否则编译不通过.
在子类中先会有super(); 去调用父类的无参构造器. 要不就不写 默认调用无参- public class For01{
- public static void main(String[] args) {
- int sumNum = 0;
- int j = 0;
- int start = 1;
- int end = 100; //将初始值和条件 变成 可以赋值的变量, 从解决个案问题 变成解决共性问题
- int number = 9;
- for(int i = start; i <= end; i++){
- if(i % number == 0){
- sumNum += i;
- j += 1;
- System.out.println("9的倍数:" + i );
- }
- }
- System.out.println("个数:" + j);
- System.out.println("和:" + sumNum);
- }
- }
复制代码 子类调用有参构造器 然后由于父类的无参被有参构造器覆盖 (默认的无参也就没有了) 所以需要用super(参数); 写明调用父类的哪个有参构造器
<img alt="1666194629545" loading="lazy">
4.如果需要指定父类的某一个构造器, 需要super(参数列表)显式的调用
5.super必须在构造器的第一行
6.super() 和this()都只能放在第一行 所以二者不能共存于一个构造器中
7.java中所有类 都是Object类的子类 ( ctrl + H 可以看到继承关系) 所以 一定是先运行Object类才往下运行其他的子类.
8.父类构造器的调用不限于直接父类,可以一致追溯到Object类 (顶级父类 ) 比如重写equals方法等.
9.子类最多只能继承一个父类(直接继承) java中是单继承机制, 如何A类继承B类和C类 (再写一级父类 或者接口)
10.不能滥用继承 子类和父类之间必须满足is-a的逻辑关系. (is-a 是一种)
Person is a Music?
Music extends Person
Animal
Cat extends Animal
继承的本质分析(重要)
主要注意内存的布局
先加载 再分配地址 和创建对象.
会将子类和父类之间的查找关系给建立好
1,先找到Object 等父类 从高到低 加载到方法区,
2.依据继承关系 在常量池创建 各个父类子类的存储空间. 存储基本数据
3,创建新对象的时候 将在堆中创建一个 内存, 将数据指向常量池.
4.最后将堆内地址指向son 这个对象名.
数据调用时遵循"就近原则"
son.name = " 大头儿子"
如果没有该数据 则返回上一级父类.
例如: son.age = 39 返回的是父类的数据.
son.habby = "旅游"
- **如果 在父类有私有属性 age 而爷爷类有公有属性 age 不会跳过父类 而是直接报错 **
Object类都没有这个属性也会报错.
<img alt="1666212156609" loading="lazy">
继承课堂练习1:
1.B(); 调用的B() 然后自动super(); 由于有this(" abc") 传进了第二个构造器
2.调用默认空构造器 输出: a
3.输出构造器 B(String name) b name
4.输出B()的空构造器 b
<img alt="1666260640592" loading="lazy">
继承课堂练习2:
1,进C();
2,进C(String name);
3,super("hahah") 进B(String Nmae);
4,进A();
所以输出 先是 : A类 ---> hahah B类有参数-----> C类的有参-----> C类的无参构造
<img alt="1666261452559" loading="lazy">
继承课堂练习 3:
题目如下:
<img alt="1666263126503" loading="lazy">
输出结果:
cpu=i7Memory30Hard_disk50brandintercolorblue- for(int i = 1;i <= 9;i++){
- for(int j = 1 ;j <= i;j++){
- System.out.print(j + "x" + i + "=" + i*j + "\t"); //print 不换行,+\t 排版
- }
- System.out.println(""); //打印完一轮开始换行
- }
复制代码 6.super关键字
基本介绍:
super代表父类的引用,用于访问父类的属性\方法\构造器,
访问父类的属性,但不能访问父类的private属性 super.属性名
访问父类的方法,不能访问父类的private属性 super.方法名(形参列表)
访问父类的构造器 只能放在构造器的第一句,只能出现一句 不能和this公用.
不能调用私有属性,私有方法
<img alt="1666266298898" loading="lazy">
调用父类构造器的好处,
分工明确,父类属性由父类初始化,子类属性由子类初始化.
子类中有父类中的成员(属性和方法) 重名的时候, 为了访问父类成员,必须使用super 没有重名 则super this 直接访问 都是一样的效果.
构造器不能一起用,但是调用属性是可以的
<img alt="1666267198165" loading="lazy">
找方法的过程
<img alt="1666276572606" loading="lazy">
<img alt="1666266769301" loading="lazy">
super() 是一级一级往上找 找到为止, 当然也可能被 private方法截胡
<img alt="1666277551780" loading="lazy">
7.(重点)重写方法
注意事项 返回类型 方法名(形参列表) 全都要一样. 或者返回类型是父类的子类才行.
2,子类不能缩小父类方法的访问权限, 就是public --> protected ----> 默认 ----->private .
名称范围方法名形参列表返回类型修饰符overload(重载)本类一致类型,个数,顺序至少一个不同无要求无要求override(重写)父子类一致相同子类重写的返回类型与父类一致.或者是其子类(例如 返回类型String是Object的子类)不能缩小范围<img alt="1666279237788" loading="lazy">
重写方法练习override
1.编写一个Person类 包括属性/perivate(name age) 构造器\方法 say(返回自我介绍的字符串)
2,编写一给Student类 继承Person类,增加id score属性(private) 以及构造器,定义say方法(返回自我介绍的信息,)
3.在main中 分别创建Person和Student对象,调用say方法输出自我介绍.
使用super.方法来复用
<img alt="1666289363340" loading="lazy">
<img alt="1666289336415" loading="lazy">
8.(重点)多态
对象: 属性看编译类型 方法看运行类型(向上找)
主要解决同一事件 不同对象的调用问题
多态的具体体现
1.方法的多态 () 使用重写和重载体现)
传入不同的参数 可以调用不同的sum方法, 就体现了多态.
使用A.say() 方法 或者B.say()方法 也是一种多态
<img alt="1666291917260" loading="lazy">
2.对象的多态(重点) 一个父类 多个子类 父类的引用(引用类型)指向(接收)子类的对象
(1) 一个对象的编译类型和运行类型可以不一致, (也可以一致)
(2)编译类型在定义对象时,就确定了,不能改变
(3)运行类型是可以变化的
(4)编译类型看定义时=号的左边,运行类型看 = 号的右边
Animal animal = new Dog(); 父类的引用 指向子类的对象 new的才是对象,
animal的编译类型是Animal 运行类型是Dog();
animal = new Cat() animal的运行类型变成了Cat ,编译类型还是Animal;
父类- //打印*金字塔 1 3 5 7 9 个星 空格 星 与行数的关系
- for(int i = 1;i <= 5; i++){
- for(int k = 1;k <= (5-i);k++){ // 这里的0 需要注意,要和i互动
- System.out.print(" ");
- }
- for (int j = 1;j <= (2*i-1); j++) { //这里也是 需要与i互动
- System.out.print("*");
- }
- System.out.println("");
- }
复制代码 子类- //可以将i=5 替换成变量,获得一个想多大就多大的空心金字塔
- //打印空心*金字塔 1 3 5 7 9 个星 空格 星 与行数的关系
- for(int i = 1;i <= 5; i++){
- for(int k = 1;k <= (5-i);k++){ // 这里的0 需要注意,要和i互动
- System.out.print(" ");
- }
- for (int j = 1;j <= (2*i-1); j++) { //这里也是 需要与i互动
- /* if(i == 5){
- System.out.print("*");
- }else if (j == 1 || j == (2*i-1)) { //使得第一个星和最后一个星正常打印,同时排除最后一层金字塔
- System.out.print("*");
- }else{
- System.out.print(" ");
- }*/
- if (j == 1 || j == (2*i-1) || i == 5) { //使得第一个星和最后一个星正常打印,同时排除最后一层金字塔
- System.out.print("*");
- }else{
- System.out.print(" ");
- }
- }
- System.out.println("");
- }
复制代码 子类- //Math.Random 是生成随机数,会生成一个 double类型的数 [0.0,1.0)
- //任务,一直生成1到100的数
- int i = 0; //收集随机数
- int j = 0;//收集次数
- for (; ; ) {
- System.out.println((int)(Math.random()*100) + 1); //加1才能成为1到100
- i = (int)(Math.random()*100);
- j++;
- if (i == 97){
- System.out.println(i + "次数" + j);
- break;
- }
-
- }
复制代码 运行- int sum = 0;
- int num = 20;
- int i = 1; //作用域扩大了
- for(;i <= 100; i++){
- sum += i;//累积
- if(sum > num){
- System.out.println("和>20时候 当前数i+" + i);
- break;
- }
- }
- System.out.println("当前数=" + i);//当前数
复制代码 3.多态的细节:
1.多态的前提 封装和继承
2.向上转型(自动)
向上转型
本质:父类的引用指向子类的对象
<img alt="1666299656488" loading="lazy">
父类:- public static void main(String[] args) {
- double money = 100000;
- int number = 0;
- while(true){
- if (money > 50000) {
- money *= 0.95;
- number++;
- }else if (money >= 1000) {
- money -= 1000;
- number++;
- }else{
- break;
- }
- }
- System.out.println("剩下多少钱" + money + "次数" + number);
- }
复制代码 子类- System.out.println(number1 + "次数" + number2);*/
- int number1 = 0;//水仙花数
- int number2 = 0;//非水仙花数
- for(int d = 100;d < 1000;d++){
- int d1=d % 10;
- int d2 =d / 10 % 10;
- int d3 =d / 100 % 10;
- if((d1 * d1 * d1 + d2 * d2 * d2 + d3 * d3 * d3) == d){
- System.out.println(d);
- number1++;
- }else{
- number2++;
- }
- }
- System.out.println(number1 + "次数" + number2);
复制代码 运行:- //每行输出5个1-100之间不能被5整除的数
- int num = 0;
- for(int d = 1;d < 100;d++){
- if((d % 5 != 0 )){
- num++;
- System.out.print(d+"\t");
- if ( num % 5 == 0 ) {
- System.out.println();
- }
- }
- }
复制代码 向下转型
子类的引用指向父类引用
1.只能强转父类引用 ,不能强转对象 (对象不能改变,只能改变引用.)
2.要求父类的引用必须指向的是当前目标类型的对象
3.可以调用子类的类型中所有成员
<img alt="1666299766508" loading="lazy">
接续上面的- //数组类型 数组名 数据 0到5 就是六个数
- double[] hens = {3,5,1,3.4,2,50};
- //可以遍历
- double total = 0;
- for(int i = 0; i < hens.length; i++){
- //下标访问数组
- total +=hens[i];
- }
- System.out.println(total + "平均" + total/6);
复制代码 细节:
(1) 属性没有重写, 属性的值看编译类型.
(2) 使用instanceOf比较操作符,判断对象的类型是否位XX类型或者XX类型的子类型.
(1)!!!!!!!
向上转型 属性看编译类型.- 数据类型 数据名[] = new 数据类型[大小] ;
- //这是为了给c/c++程序员的写法。
- //java中还是放在前面
- // 数据类型[] 数据名 = new 数据类型[大小];
- dataType[] arrayRefVar = new dataType[arraySize];
复制代码 <img alt="1666302618993" loading="lazy">
(2)!!!!!!!!!!!!!!!!!!!!!!!
instanceOf 判断类是不是某一个类 或其子类
<img alt="1666302804353" loading="lazy">
还是判断的编译类型 都是true.
<img alt="1666302872053" loading="lazy">
不是该类或者子类 所有 false
<img alt="1666302953214" loading="lazy">
多态练习:
练习1
- 可以
- 可以 double 强转 long
- 结果为 13
- 可以
- int类型强转boolean 不行 boolean是true和flase
- 可以 "Hello" 是String类型 是Object的子类
- 向下转型 obj原本就是指向 String类型 所有可以强转
- "Hello"
- 可以 Integer(5) 就是int类型的包装类, 是Object的子类
- 不可以 因为objPri原本指向Integer类型
- 可以. 向下转型
<img alt="1666303272371" loading="lazy">
练习2
属性看编译类型, 方法看运行类型
s.count 编译类型是Sub
所以输出的是 20
方法看的是运行类型
s.display 调用的是自己的方法,返回 this.count
输出的还是 20
编译类型转成了Base类型
b == s true 指向的是同一个对象 Sub();
输出 10 属性看编译类型
方法调用 是看运行类型 所有输出的是Sub的方法 输出20
20 20 true 10 20
<img alt="1666303603243" loading="lazy">
9.动态绑定机制
属性看编译类型, 方法看运行类型
原则如下:
1,当调用对象方法的时候,该方法会和该对象内存地址/运行类型绑定.
2.当调用对象属性时,没有动态绑定机制, 哪里声明,哪里使用
3.当方法内使用属性的时候 (不是调用的情况 ) 依据就近原则. 获取属性.- //第二种:
- //先声明 再赋值.
- double[] a; //还没使用内部空间,只是一个空值,
- a = new double[10];// new了以后才开辟空间 一共10个 8个字节的数据.
复制代码 10.多态的应用(多态数组)
父类:- // 第二种方法: 直接赋值.
- dataType[] arrayRefVar = {value0, value1, ..., valuek};
复制代码 子类:- //1,创建一个char类型的26个元素的数组,分明放置'A'-'Z'.使用for循环访问所以元素并打印出来.
- //1 先查找A的对应数字是多少.
- char a = 'A';
- System.out.println((int)a); // 65
- // 创建可以容纳26个字母的数组
- char[] array1 = new char[26];
- //赋值与打印数组
- //方法一:
- for(int i = 0;i < array1.length; i++){
- array1[i] = (char)(65+i);
- System.out.println(array1[i]);
- }
- //方法二:
- int i = 0;
- for(char element: array1){
- element = (char)(65+i);
- i++;
- System.out.println(element);
- }
复制代码 子类:- //2.请写出一个数组int[] 的最大值{4,-1,9,10,23},并得到对应的下标.
- //比较大小 需要一个中间值来进行
- int[] intArray = {3,-1,9,23,10};
- int sum = 0; //sum = intArray[0]; 假设第一个数就是最大值
- int subscript = 0;
- System.out.println(intArray.length);//5
- for(int i = 0; i < intArray.length; i++ ){ // int i = 1; 这样可以直接从第二个数开始比较
- if(sum < intArray[i]){
- sum = intArray[i];
- subscript = i;
- }
- }
- System.out.println("最大值"+sum + "下标为"+subscript);
复制代码 结果 : 就是使用instanceof 判断是不是某个子类 然后继续调用其特有方法- //数值拷贝
- int n1 =2; int n2 = n1;
- //这个时候 n1 = 2 , n2 = 2;
复制代码 多态 多态参数
注意点:
1.调用当前类的方法 创建一个当前类的对象 去引用方法
2.父类的方法在子类改写后 是调用父类方法 super.getAnnual();
那么 计算使用的数据还是 子类传输的数据.
//计算年工资
public double getAnnual() {
return monthlySalary * 12;
}
方法中的这个形参指向父类的属性 但是实际参数是使用子类传递的参数.
也是就 方法定义的形参类型 为父类类型 ,实参类型 允许为子类类型- //assign(分配)
- int[] arr1 = {1,2,3};
- int[] arr2 = arr1;
- arr2[0] = 10;
- for(int element:arr1){
- System.out.println(element);
- }
- 10
- 2
- 3
复制代码 第十章:Object类详解
Object 是类层次结构的跟类,每个类都使用Object作为超类,所以所有对象(数组) 都可以实现这个类的方法.
Modifier and TypeMethod and Descriptionprotected Objectclone()创建并返回此对象的副本。booleanequals(Object obj)指示一些其他对象是否等于此。protected voidfinalize()当垃圾收集确定不再有对该对象的引用时,垃圾收集器在对象上调用该对象。classgetClass()返回此 Object的运行时类。inthashCode()返回对象的哈希码值。voidnotify()唤醒正在等待对象监视器的单个线程。voidnotifyAll()唤醒正在等待对象监视器的所有线程。StringtoString()返回对象的字符串表示形式。voidwait()导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法。voidwait(long timeout)导致当前线程等待,直到另一个线程调用 notify()方法或该对象的 notifyAll()方法,或者指定的时间已过。voidwait(long timeout, int nanos)导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法,或者某些其他线程中断当前线程,或一定量的实时时间。<img alt="1666463320979" loading="lazy">
1.== 运算符与equals
== 是一个比较运算符
== 判断基本类型 是值相等
== 判断引用类型 是引用相等 地址
== 既可以判断基本类型, 也可以判断引用类型- //数组拷贝 创建数组2成为同样长度的数组
- int[] arr1 = {10,20,30};
- int[] arr2 = new int[arr1.length];
- int x = 0;
- for(int i1:arr1){
- arr2[x] = i1;
- x++;
- }
- //测试拷贝是否成功,修改数组2
- arr2[0] = 19;
- //打印数组1
- for(int i1:arr1){
- System.out.println(i1);
- }
- // 10 20 30
- //打印数组2
- for(int i2:arr2){
- System.out.println(i2);
- }
- // 19 20 30
复制代码 equals方法
只能比较引用类型 只比较地址 所以子类通常都会自行重写equals方法
String equals源码- //数组反转
- int[] arr = {11,22,33,44,55,66};
- //反转数组 使用中间变量
- //使用变量
- int reverse = 0;
- for(int i = 0;i < arr.length/2; i++){ //因为是同时替换两端的数,所以只要进行一半。 3.
- reverse = arr[i];
- arr[i] = arr[arr.length-1-i];
- arr[arr.length-1-i] = reverse;
- }
- for (int i:arr ) {
- System.out.println(i);
- }
-
复制代码 Object equal源码- 注意: 第一 arr 逆序取值,赋值给arr2 (正向取值)
- 取值为下标时 长度-1
- 最后进行数组赋值,指向同一个地址.
- arr原有的指向空间会被指定为垃圾, jvm空间不足时进行销毁
复制代码 Integer equal源码
//直接判断值是否相等- //数组扩容
- int[] arr = {1,2,3};
- int[] arr1 = new int[arr.length + 1];
- int reverse = 0;
- for(int i = 0;i < arr.length; i++){
- arr1[i] = arr[i];
- }
- arr1[arr1.length-1] = 4;
- arr = arr1;
- for (int i:arr ) {
- System.out.println(i);
- }
复制代码 练习: 注意 == 基本类型就是比较值 == 引用类型 就是比较对象的地址
equals 只有引用类型 比较的是地址- //数组扩容 用户决定是否继续添加
- Scanner stdIn = new Scanner(System.in);
- int[] arr = new int[0];
- for(;;){
- System.out.println("请问是否继续添加值 y/n");
- char result = stdIn.next().charAt(0);
- if(result == 'y'){
- System.out.println("请问输入要增加的数字");
- int number = stdIn.nextInt();
- int[] arr1 = new int[arr.length + 1];
- int reverse = 0;
- for(int i = 0;i < arr.length; i++){
- arr1[i] = arr[i];
- }
- arr1[arr1.length-1] = number;
- arr = arr1;
- for (int i:arr ) {
- System.out.println(i);
- }
- }else{
- System.out.println("程序结束");
- break;
- }
- }
- for (int i:arr ) {
- System.out.println(i);
- }
复制代码 equals的重写练习- //冒泡排序 需要交换,就需要一个中介.
- //需要注意的就是 判断条件 (1.循环结束,2.if判断条件)
- int[] BubbleSort = {24,69,80,57,13};
- int num = 0;
- for(int i = 0;i < BubbleSort.length-1; i++){ //次数 进行4次就可以了
- for(int j = 1; j < BubbleSort.length-i; j++){ // 小于(长度-i) 因为第一次就会筛出最大的一个
- //有问题肯定是判断出问题
- if(BubbleSort[j-1] > BubbleSort[j]){
- num = BubbleSort[j-1];
- BubbleSort[j-1] = BubbleSort[j];
- BubbleSort[j] = num;
- }
- }
- }
- for(int i = 0; i < BubbleSort.length; i++){
- System.out.println(BubbleSort[i]);
- }
复制代码 重点: 判断练习1:
总结: 比较方法 是== 还是 equals 没有意义 主要还是
1.看equals 有没有重写(基本数据类型的包装类都是重写过的) 2.比较双方是什么类型
1.p1 == p2 p1 与 p2 都是引用类型 所以 比较地址 false
2.p1.name.equals(p2.name) 使用的是String的比较方法 比较值 所以 true
3.p1.equals(p2) 使用的Object的方法 ( == ) 引用类型 所以比较的是地址 false
4,s1.equals(s2) 比较方法是 String的方法 比较值 true
5.s1 == s2 比较的是引用类型 比较地址 false
<img alt="1666470634698" loading="lazy">
注意: 基本数据类型 是忽略小数点.
<img alt="1666471280234" loading="lazy">
2.hashCode方法
集合 :Map hashTable
1、提高具有哈希结构的容器的效率
2,两个引用,如果指向的是同一个对象,则哈希值 肯定是一样的
3,两个引用, 如果指向的是不同对象,则哈希值是不一样的
4,哈希值主要根据地址号来的, 不能完全将哈希值等价于地址.
5.案例演示(HashCode_.java):obj.hashCode() [测试: A obj1= new A(); A obj2 = new A(); A obj3 = obj1 ]
6.集合 中 HashCode 需要的话 也会重写.
Hash值 :散列
Hash :散列,通过关于键值(key)的函数,将数据映射到内存存储中一个位置来访问。这个过程叫做Hash,这个映射函数称做散列函数,存放记录的数组称做散列表(Hash Table),又叫哈希表。JAVA函数hashCode()即请求对象的哈希值。 (键值对)
映射 注意B中唯一的元素 也就是 内存存储中 只有唯一一个元素与 散列的值对应
两个非空集合A与B间存在着对应关系f,而且对于A中的每一个元素a,B中总有唯一的一个元素b与它对应,就这种对应为从A到B的映射,记作f:A→B。其中,b称为元素a在映射f下的像 ,记作:b=f(a)。a称为b关于映射f的原像。集合A中所有元素的像的集合称为映射f的值域,记作f(A)。- //冒泡排序 需要交换,就需要一个中介.
- //需要注意的就是 判断条件 (1.循环结束,2.if判断条件)
- int[] BubbleSort = {24,69,80,57,13};
- int num = 0;
- System.out.println(BubbleSort.length);
- for(int i = 0;i < BubbleSort.length-1; i++){ //次数 进行4次 只需要4次就可以
- int flag = 1;//每次循环重新初始化
- for(int j = 1; j < BubbleSort.length-i; j++){ // 小于(长度-i) 因为第一次就会筛出最大的一个
- //有问题肯定是判断出问题
- if(BubbleSort[j-1] > BubbleSort[j]){
- num = BubbleSort[j-1];
- BubbleSort[j-1] = BubbleSort[j];
- BubbleSort[j] = num;
- flag = 0;
- //标记发生了交换
- }
- }
- //运行完for第二个循环 就会进来判断 没有交换 就说明排序完成
- if(flag == 1){
- return;
- }
- }
- for(int i = 0; i < BubbleSort.length; i++){
- System.out.println(BubbleSort[i]);
- }
复制代码 3.toString方法
默认返回的是全类名 就是包名加类名 + @ + 哈希值 16进制
子类都会重写 也有使用Alt + Ins快捷键 进行重写。
<img alt="1666627720351" loading="lazy">
toString源码- //冒泡排序 需要交换,就需要一个中介.
- //需要注意的就是 判断条件 (1.循环结束,2.if判断条件)
- int[] BubbleSort = {24,69,80,57,13};
- int num = 0;
- int tempPostion = 0;
- int len = BubbleSort.length-1;//记录内循环条件
- for(int i = 0;i < BubbleSort.length-1; i++){ //次数 进行4次 只需要4次就可以
- int flag = 1;//每次循环重新初始化
- for(int j = 0; j < len-i ; j++){ // 小于(长度-i) 因为第一次就会筛出最大的一个
- //有问题肯定是判断出问题
- if(BubbleSort[j] > BubbleSort[j+1]){
- num = BubbleSort[j];
- BubbleSort[j] = BubbleSort[j+1];
- BubbleSort[j+1] = num;
- flag = 0;
- //标记发生了交换
- tempPostion = j;
- }
- }
- //运行完for第二个循环 就会进来判断 没有交换 就说明排序完成
- len = tempPostion;
- if(flag == 1){
- return;
- }
- }
- for(int i = 0; i < BubbleSort.length; i++){
- System.out.println(BubbleSort[i]);
- }
复制代码 4.finalize方法
finalize fin- 尖 最终方案
实例中, 是几乎不会用, 因为要尽量避免
当对象被回收时,系统自动调用该对象的finalize方法, 之类可以重写该方法,做一些释放资源(内存、数据库链接、打卡的文件等)的操作。 (因为都继承了Object 所以默认调用Object的方法)
当垃圾回收器不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
什么时候对象会被回收: 当某个对象没有任何引用时,则jvm就认为这个对象是一个垃圾对象, 就会使用垃圾回收机制来销毁该对象, 在销毁该对象前,会先调用finalize方法. (来判定?)
垃圾回收机制的调用, 由系统来决定, 也可以通过System.gc() 主动出发垃圾回收机制,
finalize方法Object源码- package Array;
- /**
- * @Auther: qianl
- * @Date: 2022/10/18 01:18
- * @Description:
- */
- public class MyTools {
- public static void main(String[] args) {
- int[] arr = {1,2,41,43,213,45,312,451,225,3};
- int temp = 0;
- for (int i = 0; i < arr.length - 1; i++) {
- for (int j = 0; j < arr.length - 1 - i; j++) {
- if(arr[j] > arr[j + 1]){
- temp = arr[j];
- arr[j] = arr[j + 1];
- arr[j + 1] = temp;
- }
- }
- }
- for (int k:arr
- ) {
- System.out.println(k);
- }
- }
- }
复制代码 案例:
注意,System.gc 不会造成阻塞,而是两个线程, 会接着往下走 而调用的重写的finalize 在被调用就顺延了
程序退出..
使用了重写的finalize- String[] names = {"山顶巨人","雪山狮王","种花家传人"};
-
- Scanner stdIn = new Scanner(System.in);
- System.out.println("请输入你要寻找的名字");
- String findName = stdIn.next();
- int index = -1;
- for (int i = 0; i < names.length; i++ ) {
- if(findName.equals(names[i])) {
- System.out.println("找到了"+names[i]+"下标是"+i);
- index = i;
- break;
- }
- }
- if(index == -1){
- System.out.println("寻找失败");
- }
复制代码 5.debug 断点调试
使用断点调试,可以一步一步看程序的执行过程,
注意: 在断点调试过程中, 是处于运行状态的, 是以对象的运行类型来执行的.
1.在某一行设置断点,调试时,程序运行到这一行会停下, 任何可以一步步往下调试,可以看到各变量当前值, 出错时, 调试到出错代码行便会停止,进行分析从而找到该bug.
2.断点调试是必备技能
3,也能帮助学习java底层代码的执行过程.
注意 f7 (跳入) f8 (跳出) f9 (resume 执行到下一个断点)
以下三个属于方法的
f7 跳入方法内
f8 逐行执行代码
shift+f8 跳出方法
<img alt="1666785299754" loading="lazy">
可以通过Console 进行控制台的切换
<img alt="1666785740700" loading="lazy">
也可以查看越界等bug问题
设置勾选掉这两个 就能进入源码了 或者使用强制进入 alt+ shift+f7
<img alt="1666795197419" loading="lazy">
查看sort等方法的源码:- int[] arr = {10,12,45,90};
- int[] arrNew = new int[arr.length + 1];
- int number = 111;
- for (int i=0; i < arr.length ; i++ ) {
- if(arr[i] > number){ //判断开始进行替换
- for (int j=i+1;j<arrNew.length;j++ ) {
- arrNew[j] = arr[j-1]; //将i下标以后的数进行替换
- }
- arrNew[i] = number; //替换那个要插入的元素.
- break; //跳出大循环.
- }else{
- arrNew[i] = arr[i]; //要替换的值前面的 都替换了,后面的交给后面的人.
- }
- arrNew[arrNew.length-1] = number;
- }
- arr = arrNew;
- for(int element:arr){
- System.out.println(element);
- }
复制代码 到下一个断点 可以动态的下断点 , 也就是debug过程中可以动态下下一个断点.
也支持源码中下断点.
如果上一个是源码 下一个断点在main方法中 也能直接到下一个断点. 这样不限制于一个类. 或者一个断点.
创建对象的过程,- //标记的方法
- int[] arr = {10,12,45,90};
- int[] arrNew = new int[arr.length + 1];
- int index = -1;
- int number = 23;
- for (int i = 0; i < arr.length ; i++ ) {
- if(arr[i] >= number){ //判断开始进行替换
- index = i;
- break;
- }
- }
- ////最后一种情况
- if(index == -1){
- index = arr.length;
- }
- for (int i = 0,j = 0; i < arrNew.length ; i++ ) {
- if(i != index){
- arrNew[i] = arr[j]; //只要没有index 就没事发生, 不然就j会比i少1 就能使得arrNew多一个下标
- j++;
- } else {
- arrNew[i] = number;
- }
- }
- arr = arrNew;
- for(int element:arr){
- System.out.println(element);
- }
复制代码 零钱通项目:
模拟微信的零钱通
目的: 消费入账 , 消费, 查看明细 ,退出系统等;
化繁为简:
1.先完成显示菜单.
2.实现明细
3.实现入账\消费
4.实现退出的再判断
5.实现入账和消费合理化.
面向过程的方法:
[code]package SmallChanageSys;import java.beans.SimpleBeanInfo;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Scanner;/** * @Auther: qianl * @Date: 2022/10/27 22:43 * @Description: */public class SmallChangeSys { //先完成显示菜单 public static void main(String[] args) { //菜单 必须进入 所以必须进入 boolean loop = true; //控制 Scanner scanner = new Scanner(System.in); String key = ""; //零钱通明细 1. 直接输出字符串 2. 数组 3. 对象MM String details = "======零钱通明细======"; //完成收益入账 输入金额 并添加总金额 时间 double addMoney = 0; double sum = 0; Date date = null; //日期格式化文本 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");//日期格式化. String consume = ""; double reduceMoney = 0; String exit = ""; do { System.out.println("\n======零钱通菜单======"); System.out.println("\t\t\t1 零钱通明细\t\t\t"); System.out.println("\t\t\t2 收益入账\t\t\t"); System.out.println("\t\t\t3 消费\t\t\t"); System.out.println("\t\t\t4 退出系统\t\t\t"); System.out.println("\t\t\t请做出你的选择"); //注意进来以后才开始接受输入 key = scanner.next(); switch (key) { case "1": //零钱通明细方法; System.out.println("1 零钱通明细"); System.out.println(details); break; case "2": //收益; System.out.println("2 收益入账"); System.out.println("请输入总金额:"); addMoney = scanner.nextDouble(); //应该校验范围 只能增 之类的 //收益入账 找到正确和不正确的 选少的 再有不正确的进行增if //过关斩将,过不了就不能走. if(addMoney |