JavaSE
常用连接
https://www.oracle.com/java/technologies/downloads/ JDK下载地址
https://www.injdk.cn/ 常见的JDK的下载地址
https://www.mrhelloworld.com/ 哈喽沃德先生
第一章:Java基础知识
1.1 Java基础概念
6个单词
- Java的产品方向
JAVASE
Java基础版本JAVAEE
后期Java方向工作是EE
的内容 主要是Web企业开发JAVAME
主要做客户端程序或者时桌面应用 目前市场占有率比较低
- Java的体系结构
- JDK
java development kit
Java开发工具包 它包含了JRE+工具套件 开发人员必备 - JRE
java runtime environment
Java运行时环境 它包含了JVM+类库信息 如果只是单纯的跑Java程序的话只需要安装JRE即可;类库信息:Java已经写好的一些功能组件、我们可以直接使用不需要重复编写; - JVM
java virtual machine
Java虚拟机, 专门用来执行bytecode
字节码文件的,也是Java这么语言跨平台的基础;
- JDK
问题1: 请说一下Java的产品线有哪些?
1.2 下载安装JDK
下载地址: https://www.oracle.com/java/technologies/downloads/
目前市面上使用的LTS
(long time support)包含JDK8、JDK11、JDK17
;
傻瓜式安装即可。目前使用推荐的版本时安装JDK8(方便后期看原码)
1.3 编写第一个程序
1.3.1 下载开发工具
subline
、或者是editorplus
http://www.sublimetext.com/ subline 下载地址
https://www.editplus.com/download.html 下载地址
网上找破解文档
1.3.2 编写第一个程序
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PoqGJsjW-1670331743839)(C:\Users\ZXL\Desktop \1659336525491.png)]
public class HelloWorld{
public static void main(String[] args){
System.out.println("hello world");
}
}
1.3.3 运行程序
I、如何能让程序找到java
和javac
#通过cd命令 来切换盘符 让当前路径到 JDK的安装目录下的bin目录中
C:\Users\wawjy>cd C:\Program Files\Java\jdk1.8.0_131\bin
#通过java -version 查看解释器的版本
C:\Program Files\Java\jdk1.8.0_131\bin>java -version
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)
#通过javac -version 查看编译器的版本
C:\Program Files\Java\jdk1.8.0_131\bin>javac -version
javac 1.8.0_131
C:\Program Files\Java\jdk1.8.0_131\bin>
II、编译以及执行当前HelloWorld.java
文件
# javac 编译当前.java文件 由于文件不在bin目录下 所以编译的时候会报错 找不到文件
C:\Program Files\Java\jdk1.8.0_131\bin>javac HelloWorld.java
javac: 找不到文件: HelloWorld.java
用法: javac <options> <source files>
-help 用于列出可能的选项
# javac 当前要编译文件的全路径 然后进行编译 会产生一个.class文件
C:\Program Files\Java\jdk1.8.0_131\bin>javac C:\Users\wawjy\Desktop\优极限61期\001_code\001_helloworld\HelloWorld.java
# java命令解释执行的时候 由于HelloWorld这个类不在当前路径下 所以报错 找不到当前类
C:\Program Files\Java\jdk1.8.0_131\bin>java HelloWorld
错误: 找不到或无法加载主类 HelloWorld
# 通过java -cp 当前类所在的路径 类名称
C:\Program Files\Java\jdk1.8.0_131\bin>java -cp C:\Users\wawjy\Desktop\优极限61期\001_code\001_helloworld HelloWorld
# 第一个程序的结果 打印输出hello world
hello world
C:\Program Files\Java\jdk1.8.0_131\bin>
1.3.4 DOS命令
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q4ca81MF-1670331743840)(C:\Users\ZXL\Desktop \1659336850165.png)]
I、DOS命令:
DOS命令就是在windows操作系统下通过命令的方式来操作我们的计算机。打开方式win+r
输入cmd
进入到对应的终端:
C:\Users\wawjy>大dsadasdas
'大dsadasdas' 不是内部或外部命令,也不是可运行的程序
或批处理文件。
- 我们在DOS下的任何输入操作 都会被理解为是命令,所以此时会查找电脑中是否存在该命令,如果存在则执行反之则报错:
II、分类
-
内部命令
- 操作系统内置的一些命令
# 查看内置命令 > help # HELP 命令名 查看cd命令的使用方法 > help cd # 命令 [选项] [参数] > rd /s a # 级联删除当前目录下a的所有的子目录以及自身 ## 第一步通过help 查找文档中要做的操作 ## help m命令 查看命令的使用方式 ## 使用命令 写demo
-
外部命令
- 通过在线安装等方式安装的程序,基本上都会在自己的系统中存在一个对应的外部命令;
-
批处理命令
- 执行批量脚本,定时脚本
.bat
,.sh
很多都可能是脚本
- 执行批量脚本,定时脚本
1.4 环境变量配置
1.4.1 为什么配置
配置环境变量的目的就是为了能简化在CMD
中的一些代码。
- 希望
java\javac
这些命令不需要每次都进入到bin目录下才能执行,我们希望在任意目录下都可以执行对应的可执行命令; - 在编译和执行的过程中,减少一些对于路径的指定;
1.4.2 环境变量在哪里
右击计算机->点击属性->高级系统设置->环境变量->选择系统变量->修改path
,在path
中增加JDK的安装目录;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nlZL96SG-1670331743840)(C:\Users\ZXL\Desktop \1659342340062.png)]
1.4.3 环境变量配置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2UPyN2Dm-1670331743841)(C:\Users\ZXL\Desktop \1659342492810.png)]
注意:如果重写对于环境变量进行了配置,千万记得重写DOS命令,不然配置是无法生效的;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n3hk6wAJ-1670331743841)(C:\Users\ZXL\Desktop \1659343746995.png)]
注意:这里的配置核心目的是为了切换版本;必配项
1.5 深入研究第一个程序
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z4bb9r9o-1670331743842)(C:\Users\ZXL\Desktop \1659408231215.png)]
1.5.1 常见错误
-
编译错误 (
javac
编译过程中程序无法正常通过编译)- 一个类如果是被
public
修饰的,那么这个类称之为主类,主类的类名要和.java文件的文件名保持一致; - 一个.java文件中不一定非得要存在主类,因为编译器编译的文件,解释器解释执行的是类
- 单词问题:拼写问题、大小写问题、漏写
- 统一英文符号
- 常见的不报错的错误:
- 格式问题:所有缩进全部使用
tab
键 - 所有的符号都是成对出现 能够很好的描述包含关系
- 格式问题:所有缩进全部使用
- 一个类如果是被
-
执行错误
- main方法一定写对了,main方法是程序的入口点 ,程序进入main方法之后依次执行里面的代码;
-
常见结论
- 一个.java文件中可以存在多个class类,这些类在编译文件的时候,会全部生成对应的字节码文件;
- 一个.java文件中可以存在多个类,但是有且只能有一个类时被public修饰,主类只能有一个;
- 一个文件中的多个类都可以编写对应的main方法,然后去解释执行;
1.6 注释
解释说明的文字,编写完成程序之后,对于服务器而言,我们只需要将.class
文件部署到服务器上即可,.java
文件是不需要部署的;所以我们需要在我们编写好的源程序.java
文件中编写必要的注释信息,来让其他程序员看懂我们的程序;
注释是源码期的行为,编译之后就不存在了;
如果出现报错信息,字符集和不统一,就进行如下设置;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jJOMakjs-1670331743842)(C:\Users\ZXL\Desktop \1659409835618.png)]
// 测试注释信息 单行注释 只能注释一行
public class Annotation{
/*
多行注释
main方法 程序的入口点
*/
public static void main(String[] args){
System.out.println(" 测试多行注释 ");
}
}
注释分类 | 书写格式 | 注意事项 |
---|---|---|
单行注释 | // 注释信息 | 只能注释一行 |
多行注释 | /* 注释信息 */ | 可以注释多行 |
1.7 标识符
是Java中用来起名字的。我们可以给类、变量、常量、接口、枚举。。。。。
- 3个规则
- 用字母 下划线 美元符号开头 后跟字母下划线 美元符号或者是数字结尾[不能以数字开头]
- 不能Java中的关键词
- 严格区分大小写 Java是对大小写敏感
- 2个标准 (约束 不能打破)
- 见名知意 (看见名字知道意思) 不能使用拼音
ceshizhushi
Test - 驼峰原则 (必须要大小写)
- 类:
UpperCamelCase
首字母大写 每个单词首字母大写 剩余全部小写UserDao
- 变量: 首字母小写 每个单词首字母大写 剩余全部小写
userDao
- 常量:所有字母均大写,单词之间通过
_
分割USER_DAO
- 方法: 首字母小写 每个单词首字母大写 剩余全部小写
userDao
- 类:
- 见名知意 (看见名字知道意思) 不能使用拼音
- 1个注意事项
- Java采用的字符集和时Unicode(万国码), 所有国家的通用字符都是支持的。练习 (不建议使用)
一下哪些内容不符合标识符的定义 (类):
A:练习 B:Class C:_$ D:hehe(不满足驼峰)
1.8 关键词
摘录自:https://baike.baidu.com/item/java%E5%85%B3%E9%94%AE%E5%AD%97/5808816
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y4yxs48r-1670331743842)(C:\Users\ZXL\Desktop \1659422627182.png)]
1.9 字符集和
一张表。一张用来存储所有常用字符信息的表。这张表中囊括了字符和数字的转换信息;
单位换算:
1b = 1位 1个bit 表示两种状态 0和1
1B = 8b 1个字节
1KB = 1024B 1个千字节
1MB = 1024KB 1个兆字节
1GB 1TB 1PB 1EP
16GB
的文本数据 通过一个2G
内存的物理机如何快速计算想要的结果?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iCuuqrjN-1670331743842)(C:\Users\ZXL\Desktop \1659423631191.png)]
- 计算机不能存储字符信息,字符信息的存储都是需要进行字符和数字的转换;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YEPgUJ3d-1670331743842)(C:\Users\ZXL\Desktop \1659424306329.png)]
// 测试字符集合
public class Encoding{
public static void main(String[] args) {
System.out.println("测试字符集合");
}
}
乱码解决的方式:保证字符集合统一即可。
1.9 变量
在程序执行的过程当中,我们需要一个存储数据的容器,这个容量就被称之为变量。这个容器在程序运行期间,容器中的值时可以随时发生改变的。
Java是一门强类型的语言,所有的变量以及数据都会存在类型,不同的类型存储的数据是不一样的,不同的类型存储的数据的大小是不一样的。
目前现阶段:我们需要确定的事情是: 所有的整数的类型暂时先使用 int
变量的三要素:数据类型 变量名 作用域
1.9.1 变量的声明和使用
/*
测试使用变量
1: 声明变量:
data_type name ; 声明了一个data_type这样类型的变量 名字叫name
*/
public class VariableTest01{
public static void main(String[] args){
//1声明一个int类型的变量
int num;
//2: 给变量初始化
num = 10; // 将字面值10赋值给int类型的变量num存储
//3:使用
System.out.println(num);
// 声明和初始化会放在一起
int sum = 10; // 将一个整数字面值10赋值给int类型的变量 sum存储
System.out.println(sum);
// 变量在程序运行期间其值可以发生改变
sum = 20;
System.out.println(sum);
}
}
-
重点
-
变量要先声明在初始化 然后才能使用 一般我们的声明和初始化时放在一起的 一行;
-
变量在程序运行期间 其值可以发生改变
-
变量在声明的时候必须要满足:
// data_type name = value int num = 10; // 这个行代码是自右向左进行运算的
-
1.9.2 数据类型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kDhvHsqI-1670331743843)(C:\Users\ZXL\Desktop \1659430051782.png)]
I、byte 字节型
// 测试使用byte数据类型
public class ByteTest{
public static void main(String[] args){
//1:声明byte类型的变量
byte b = 10;
//2: 输出一下b这个变量的值
System.out.println(b);
// 修改byte变量b的值
/*
ByteTest.java:13: 错误: 不兼容的类型: 从int转换到byte可能会有损失
b = 130
*/
b = 130;
System.out.println(b);
}
}
取值范围
数据类型 | 表数范围 | 所占空间 |
---|---|---|
字节型 byte | [-128,127] -2^7 - 2^7-1 | 1个字节 |
注意事项
对于byte这种数据类型而言,大家在赋值的时候要注意取值,不要超过byte的取值范围,一般我们可以使用byte去做类型的值判定。表述状态。
II、short 短整型
// 测试使用short数据类型
public class ShortTest{
public static void main(String[] args){
//1:声明short类型的变量
short b = 130;
//2: 输出一下b这个变量的值
System.out.println(b);
// 修改short变量b的值
/*
ShortTest.java:13: 错误: 不兼容的类型: 从int转换到short可能会有损失
b = 130000;
^
1 个错误
*/
b = 130000;
System.out.println(b);
}
}
取值范围
数据类型 | 表数范围 | 所占空间 |
---|---|---|
短整型 short | [-32768,32767] -2^15 - 2^15-1 +-3W | 2个字节 65536 |
注意事项
对于short这种数据类型而言,大家在赋值的时候要注意取值,不要超过short的取值范围,一般我们可以使用short存储大多数的值,但是一般不这么干;
III、int 整型
// 测试使用int数据类型
public class IntTest{
public static void main(String[] args){
//1:声明int类型的变量
int b = 130000;
//2: 输出一下b这个变量的值
System.out.println(b);
// 修改int变量b的值
/*
IntTest.java:16: 错误: 过大的整数: 2147483648
b = 2147483648;
^
1 个错误
*/
b = 2147483648;
System.out.println(b);
}
}
取值范围
数据类型 | 表数范围 | 所占空间 |
---|---|---|
整型 int | -2^31 - 2^31-1 +-21亿 | 4个字节 |
注意事项
对于int这种数据类型而言,大家在赋值的时候不需要特别注意,因为一般我们都直接使用int进行存储;Java所有字面整数值的默认类型时int类型;
IV、long 长整型
// 测试使用LongTest数据类型
public class LongTest{
public static void main(String[] args){
//1:声明long类型的变量
long b = 2147483647;
//2: 输出一下b这个变量的值
System.out.println(b);
// 修改long变量b的值
/*
LongTest.java:16: 错误: 过大的整数: 2147483648
b = 2147483648;
^
1 个错误
*/
b = 2147483648L;
System.out.println(b);
}
}
取值范围
数据类型 | 表数范围 | 所占空间 |
---|---|---|
长整型 long | -2^63 - 2^63-1 | 8个字节 |
注意事项
- 如果给一个long类型变量赋值的时候,当前这个字面值超过了int的取值范围,此时需要在字面值后面加
L
或者时l
。保证编译器可以识别当前字面值是long类型; - 在java中所有的字面整数都是int类型;
- 对于byte和short这两种数据类型而言,只要字面值没有超过对用的数据类型的取值范围,那么编译器是不会报错的;
V、关于整数的存储方式
VI、关于整数的赋值方式
// 测试整数的赋值方式
public class IntInitValue{
public static void main(String[] args){
//1: 二进制赋值
int n = 0b1101; //JDK1.7之后的特性 0b 0B开头 后跟二进制数字
System.out.println(n);
//2:八进制赋值
n = 027; //以0开头 后跟8进制数字
System.out.println(n);
//3:十进制赋值
n = 123;
System.out.println(n);
//4:十六进制赋值
n = 0x3F;//以0x 0X开头 后跟16进制数字 A:10 B:11 C:12 D:13 E:14 F:15
System.out.println(n);
//5:会计计数法
long num = 123_456_789_999L;
System.out.println(num);
}
}
VII、float 单精度
// 测试float变量
public class FloatTest{
public static void main(String[] args){
//1: 声明一个float类型的变量
/*
FloatTest.java:6: 错误: 不兼容的类型: 从double转换到float可能会有损失
float f = 3.14;
*/
float f = 3.14F; //告知编译器 我这个字面值时float类型 不是double
System.out.println(f);
}
}
取值范围
数据类型 | 精度 | 所占空间 |
---|---|---|
float 单精度 | 6-7位 | 4个字节 |
注意事项
- 如果给一个float类型变量赋值的时候,因为所有的字面小数都是double类型,所以需要在小数字面值后面加
F
\f
; - 在java中所有的字面小数都是double类型;
VIII、double 双精度
// 测试double变量
public class DoubleTest{
public static void main(String[] args){
//1: 声明一个double类型的变量
/*
FloatTest.java:6: 错误: 不兼容的类型: 从double转换到float可能会有损失
float f = 3.14;
*/
double d = 3.14;
System.out.println(d);
System.out.println(1/0.3);
System.out.println(1/0.3F);
// 小数运算时存在精度的问题 所以一般不要使用小数运算
// 解决问题的办法:扩大或者时缩小倍数
// java BigDecimal完成精度取值
System.out.println((0.6*10-0.5*10)/10);
}
}
取值范围
数据类型 | 精度 | 所占空间 |
---|---|---|
double 单精度 | 15~16位 | 8个字节 |
注意事项
- 如果给一个float类型变量赋值的时候,因为所有的字面小数都是double类型,所以需要在小数字面值后面加
F
\f
; - 在java中所有的字面小数都是double类型;
VIIII、小数的存储方式
X、小数的赋值方式
// 测试小数的赋值方式
public class DoubleInitValue{
public static void main(String[] args){
// 正常赋值
double d = 3.14;
// 省略0赋值
d = .5;
System.out.println(d);
// 科学计数法
d = 0.000134;
System.out.println(d);
d = 1.34E-4;
System.out.println(d);
}
}
XI、 boolean 布尔类型
// 测试boolean类型
public class BooleanTest{
public static void main(String[] args){
boolean flag = true;
System.out.println(flag);
flag = false;
System.out.println(flag);
}
}
取值范围
数据类型 | 取值 | 所占空间 |
---|---|---|
boolean 布尔类型 | true \ false | 实际占用空间1位 虚拟开空间的时候可能会当他当成byte或者是int去开空间; |
注意事项
- 有且只有两个值 分别是true 和false
- 并且不能赋值0和1
XII、char 字符型
摘录自:https://baike.baidu.com/pic/ASCII/309296/1/e850352ac65c103880a07b53bc119313b17e8941?fr=lemma&ct=single#aid=1&pic=e850352ac65c103880a07b53bc119313b17e8941
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yTANIPL3-1670331743843)(C:\Users\ZXL\Desktop \1659595075474.png)]
Tips: 48—>0 65---->A 97---->a
// 测试使用char数据类型
public class CharTest{
public static void main(String[] args){
//1:声明char类型的变量
char ch = 'a'; // 字符都是一个个数字
System.out.println(ch);
// 当声明char类型的变量的时候直接赋值数字会怎么样?
ch = 23345;
System.out.println(ch);
// 第三种赋值方式:通过一个个的unicode代码点去赋值
// 斜杠\+u 后跟一个4位的16进制数字
ch = '\u5B31';
System.out.println(ch);
System.out.println('c'+3);
}
}
取值范围
数据类型 | 赋值方式 | 所占空间 |
---|---|---|
char 字符型 | 通过单引号引起来的单个字符 通过[0,65535]之间的正整数 通过\u开头 后跟一个4位的16进制数字 | 2个字节 |
注意事项
- char类型是可以赋值为一个数字的,所以char类型是可以参与四则运算的;
1.9.3 常量
常量程序运行期间不可以发生改变的。
// 测试常量
public class FinalTest{
public static void main(String[] args) {
//1: 字面常量: 写什么就是什么
int num = 10; // 10是字面常量
char ch = 'A';
double d = 3.14;
//2: 符号常量
// 声明一个变量 半径是5
int r = 5;
//声明一个变量 存储pi的值
final double pi = 3.1415;
// 计算当前半径是5的圆的面积
double area = pi*r*r;
System.out.println(area);
}
}
- 通过final关键词修饰的变量称之为常量,常量是在程序运行期间其值不能发生改变的;
- final修饰的常量,在一定程度上是能够提升程序的编译以及执行的效能的,因为它存储的值时不变的;
1.9.4 类型转换
我们在学习类型转换的时候,基本数据类型的类型转换不重要,引用类型的类型转换。
类型转化的意思:一个类型变为另外一个类型。
I、自动类型转换
// 测试基本数据类型的自动转换
public class Convert01{
public static void main(String[] args) {
//1:声明一个变量 byte类型
byte b = 10;
System.out.println(b);
//2: 转换
int n = b;
System.out.println(n);
//3:四则运算会触发自动类型转换
char m = 10+'A'; // 编译的时候就10+'A'=>常量折叠 已经做完了 执行的时候 char m = 75;
System.out.println(m);
char ch = 'A';
int result = 10+ch; // 类型转换 编译期间做的 char = int 检查的时候报错了
System.out.println(result);
// boolean是不可以参与运算的
boolean flag = true;
n = flag+1;
System.out.println(n);
}
}
- 四则运算都会触发类型转换,自动向上提升(小变大)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vqpjg4TU-1670331743843)(C:\Users\ZXL\Desktop \1659603357084.png)]
II、强制类型转换
// 测试基本数据类型的强制转换
public class Convert02{
public static void main(String[] args) {
char ch = 'A';
char result = (char)(10+ch); // char+char不是char 是int
System.out.println(result);
ch = 'A';
result = (char)(65535+ch); // char+char不是char 是int
System.out.println(result);
byte b = (byte)135;
System.out.println(b);
}
}
强转有风险、转换需谨慎;但是实际上是不需要谨慎的(你能够确定是否会出现数据问题)。
1.9.5 变量的分类以及变量的作用域
变量分为两种:一种称之为成员变量,还有一种叫做局部变量;
I、局部变量
声明在方法中或者是代码块中的变量称之为局部变量; 局部变量的特点就是局部有效:
从声明位置开始到方法或者是代码块的}
结束而结束;
* 局部变量必须要先声明 在初始化 再使用
II、成员变量
声明在类中,方法外的变量称之为成员变量
/**
* 变量的声明周期
*/
public class VariableLifeCircle {
// 声明一个变量
static int num;
boolean gender;
static byte b;
static short s;
static long l;
static float f;
static double d;
static char ch;
static String str;
public static void main(String[] args) {
System.out.println(num);
// 创建对象
VariableLifeCircle c = new VariableLifeCircle();
//boolean flag = c.gender;
System.out.println(c.gender);
System.out.println("测试不同类型的默认值");
System.out.println(b);
System.out.println(s);
System.out.println(l);
System.out.println(f);
System.out.println(d);
System.out.println("==="+ch+"===");
System.out.println(str);
}
}
-
成员变量具备默认值;在整个类中都有效
-
成员变量如果想要被
static
修饰的方法使用-
把当前成员变量声明为
static
; -
创建当前成员变量所属的类的对象,然后通过对象.属性名称调用
// 创建对象 VariableLifeCircle c = new VariableLifeCircle(); //boolean flag = c.gender; System.out.println(c.gender);
-
III、代码块
java中代码块就是通过一组{}
括起来的称之为代码块;
A、局部代码块
声明在方法中的代码块称之为局部代码块:
/*
测试局部代码块
*/
public class BlockTest {
public static void main(String[] args) {
// 这个位置声明一个变量num
int num = 10;
//局部代码块 以后看不见了
{
//int num = 19;
System.out.println(num);
}
//System.out.println(num);
}
}
节省内存,但是一般已经不需要通过这样的方式节省内存开销;
B、初始化块
C、静态块
1.10 转义字符
能够转变含义的字符,称之为转义字符;java中的转义字符
\
//测试转义字符
public class TransferMeaning{
public static void main(String[] args){
System.out.println("aaaabbbbccccdddd");
// 制表符位 8个空格位
System.out.println("aaaa\tbbbbccccdddd");
System.out.println("aaaabb\tbbccccdddd");
System.out.println("\taaaabbbb\tccccdddd");
System.out.println("==========================");
System.out.println("aaaabbbbccccdddd");
System.out.println("aaaa\bbbbbccccdddd");
System.out.println("==========================");
System.out.println("aaaabbbbccccdddd");
System.out.println("aaaa\rbb");
System.out.println("==========================");
System.out.println("aaaabbbbccccdddd");
System.out.println("aaaabbbb\nccccdddd");
System.out.println("==========================");
System.out.prini("aaaabbbbccccdddd");
}
}
1.11 运算符
1.11.1 运算符的基本概念
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bzY26nYE-1670331743843)(C:\Users\ZXL\Desktop \1659666457851.png)]
1.11.2 赋值运算符
int num = 10; // = 就是赋值符号 自右向左进行运算的 唯一的一个
1.11.3 算数运算符
I、+号
- 当
+
左右两边的操作数有一个是字符串类型(String “”),此时作为连接符号,连接符号的计算方式是将左右两边的操作数拼接成为一个新的字符串。
1+“+”+1+“=”+1+1
=> 1+“+” ==> "1+"
=> "1+"+1+“=”+1+1 => "1+1"+“=”+1+1 => "1+1"+“=”+1+1 => "1+1=”+1+1 => "1+1=11"
// 算数运算符
public class ArithmeticOperator{
public static void main(String[] args) {
// +号
int num = +5; //正号
System.out.println(num);
// 加法运算符
num = 4 + 5;
System.out.println(num);
// 连接符号 输出内容的时候我们希望输出更多的信息
// 计算结束之后的num的值是9
System.out.println("计算结束之后的num的值是" + num);
//System.out.println("hello world"); // "" 多个字符 组成的 串 ---> 字符串 String
// 希望打印出来 1+1=1+1 => 1+1=2
System.out.println(1+"+"+1+"="+(1+1)); //"1+1="
}
}
II、自增 自减
// ++ 和 --
int j = 5;
j--; // 自增1 自减1 没有区别 单独一条语句
System.out.println("j++之后的结果是:"+j);
// 重新给j赋值
j = 5;
int result = ++j;
// int result = j++; j=6 r=5
// int result = ++j; j=6 r=6
System.out.println("当不是单独一条语句的时候:j=["+j+"] 和 result=["+result+"]");
- 单独一条语句,前加 和 后加;前减和后减没有区别;
- 如果不是单独语句
- 前加 前减–> 先自增 自减 再运算
- 后加 后减–> 先运算 再自增 自减
1.11.4 扩展运算符
算数+赋值 位+赋值
+= -= *= /= %=
// 扩展运算符
public class ExtendsOperator{
public static void main(String[] args) {
// 计算全班所有同学的分数之和
//1:声明同学分数
int zhangScore = 199;
int liScore = 89;
//2:声明一个变量求和
int sumScore = 0;
//3:将一个学生的分数累加到求和变量中
sumScore = sumScore+zhangScore;// sumScore += zhangScore;
sumScore = sumScore+liScore;
System.out.println("累加分数之和是:"+sumScore);
int n = 10;
byte m = 0;
m += n; // => m = m+n
System.out.println("m的结果时:"+m);
}
}
- 优势
- 提升开发效率+提升编译效率
- 自动帮助我们做强制类型转换
- 缺点
- 不利于阅读
- 什么情况下可以使用扩展运算符
- 赋值符号左右两边有同名变量
1.11.5 关系运算符
>
<
>=
<=
==
!=
instanceof
// 关系运算符
public class RelationOperator{
public static void main(String[] args) {
//1: 关系运算符最后的结果是boolean值
int n = 10;
int m = 20;
boolean flag = n>m;
System.out.println(flag);
System.out.println(n>m);
// > < >= <= 无法比较boolean的值
//System.out.println(true > false);
// 两个引用类型 : 复合类型
/*String str1 = "abc";
String str2 = "abd";
System.out.println(str1 > str2);*/
//2: == !=
flag = n != m;
System.out.println(flag);
System.out.println(true == false);
// 两个引用类型 : 复合类型
String str1 = "abc";
String str2 = "abd";
System.out.println(str1 != str2);
//3: instanceof 不能比较基本数据类型 只能比引用类型
// 判定一个变量、值是否属于某个指定的类型
System.out.println(str1 instanceof String);
System.out.println("apple" instanceof String);
//System.out.println(1 instanceof String);
}
}
- 关系运算符最后的结果是boolean值
< >= <=
无法比较boolean的值- == != 所有类型都可以比较
instanceof
不能比较基本数据类型 只能比引用类型,判定一个变量、值是否属于某个指定的类型
1.11.6 逻辑运算符
逻辑运算符的操作数和结果都是一个boolean值
// 逻辑运算符
public class LogicOperator{
public static void main(String[] args) {
// 1: 左右变量的操作数都是boolean类型的值 &有两种身份 一种是逻辑 一种是位
//boolean flag = true & false;
//System.out.println("逻辑&之后的结果是:"+flag);
//System.out.println(1 & 2);
System.out.println("逻辑&运算符的结果结果如下:");
System.out.println(true & true);
System.out.println(true & false);
System.out.println(false & false);
System.out.println(false & true);
System.out.println("逻辑&& 短路与 运算符的结果结果如下:");
System.out.println(true && true);
System.out.println(true && false);
System.out.println(false && false);
System.out.println(false && true);
System.out.println("逻辑|运算符的结果结果如下:");
System.out.println(true | true);
System.out.println(true | false);
System.out.println(false | false);
System.out.println(false | true);
System.out.println("逻辑|| 短路|| 运算符的结果结果如下:");
System.out.println(true | true);
System.out.println(true | false);
System.out.println(false | false);
System.out.println(false | true);
System.out.println("逻辑^ 异或 运算符的结果结果如下:");
System.out.println(true ^ true);
System.out.println(true ^ false);
System.out.println(false ^ false);
System.out.println(false ^ true);
System.out.println("逻辑! 取反 运算符的结果结果如下:");
System.out.println(!true);
System.out.println(!false);
}
}
- &和&& &&的效率高,第一个操作数为false,第二个操作数不参与运算;
- |和|| ||的效率高,第一个操作数为true,第二个操作数不参与运算;
1.11.7 位运算符
//位运算符
public class BitOperator{
public static void main(String[] args) {
// 位运算符是直接基于二进制运算的 所以它的效率高
// 按位&
/*
0011
0100
————————
0000
每位上的值都是1其结果是1 剩余都是0
*/
int ans = 3&4;
System.out.println(ans);
// 按位|
/*
0011
0100
————————
0111
每位上的值只要有1其结果是1 剩余都是0
*/
ans = 3|4;
System.out.println(ans);
// 按位^
/*
0011
0100
————————
0111
相同为0 不同为1
*/
ans = 3^4;
System.out.println(ans);
// 按位~
/*
0 0100
————————
1 1011
符号位一起取反
*/
ans = ~4;
System.out.println(ans);
// 按位>>
/*
N>>M = N/2^M
*/
ans = -16>>2;
System.out.println(ans);
// 按位<<
/*
N<<M = N*2^M
*/
ans = 2<<4;
System.out.println(ans);
// 按位>>> 无符号 基本不用
/*
N<<M = N*2^M
*/
ans = -32>>>3;
System.out.println(ans);
}
}
1.11.8 条件运算符
三目运算符 它可以跟三个操作数,具体格式如下:
表达式1?表达式2:表达式3
- 先计算表达式1的值 如果表达式1的值时true 则整个结果时表达式2的值 反之则是表达式3的值;
// 表达式1?表达式2:表达式3 三目运算符
// 声明两个变量 计算两个数的最大值
int num1 = 20;
int num2 = 30;
// 将num1和num2 中最大的那个数赋值给max变量
//int max = num1>num2?num1:num2;
//System.out.println(max);
// 再声明一个变量 计算三个数的最大值
int num3 = 44;
//max = num3>max?num3:max;
//max = num3>num1>num2?num1:num2?num3:num1>num2?num1:num2;
System.out.println(num3>(num1>num2?num1:num2)?num3:(num1>num2?num1:num2));
// 笔试题
int result = 90>100?90.0:100;
System.out.println(result);
/*int result = 90>100?90:100.0;
System.out.println(result);*/
/*double ans = 90>100?90:100.0;
System.out.println(ans);
double ans = 90>100?90.0:100;
System.out.println(ans);*/
Tips:一定要注意,使用三目运算符的时候第一点:要么接收这个结果的值要么打印结果的值; 第二点:三目运算符的最后两个表达式的类型一定要保证一致,省的出现类型自动转换
1.11.9 优先级
摘录自:https://blog.csdn.net/qq_41306849/article/details/119729810
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MRGoSM58-1670331743844)(C:\Users\ZXL\Desktop \1659685132192.png)]
- 不要试图通过优先级来确定程序的执行顺序 (不要相信自己)
- 你希望先要运算的 通过括号括起来 ()
- 单目>双目>三目>赋值
- 算数 > 关系 > 逻辑 > 赋值
第二章:Java语言基础
2.1 流程控制
指挥程序的执行流程,执行顺序;
2.1.1 流程控制分类
I、顺序流程
程序逐行执行;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PFBDnA0i-1670331743844)(C:\Users\ZXL\Desktop \1659686056960.png)]
II、分支流程
程序在执行的过程中,可能根据业务不同的情况要采取不同的策略。执行不同的代码流程;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YMr0z8FW-1670331743844)(C:\Users\ZXL\Desktop \1659686304586.png)]
III、循环流程
希望通过一种流程能够往复的执行某些代码,而不需要重复编写这些代码;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-78AD5s9H-1670331743844)(C:\Users\ZXL\Desktop \1659686533855.png)]
2.2 分支流程
2.2.1 switch分支
https://zhuanlan.zhihu.com/p/408799706 JDK17switch
的用法
switch(month){
case 12,1,2->System.out.println("你就像那冬天里的一把火");
case 3,4,5->System.out.println("春天在哪里呀!春天在哪里~");
case 6,7,8->System.out.println("夏天夏天悄悄过去 留下小秘密");
case 9,10,11->System.out.println("就让秋风带走我的思念 ");
}
//测试switch语法结构
public class SwitchTest{
public static void main(String[] args) {
//声明一个变量 这个变量存储月份1-12, 通过存储的变量的值判定当前月份所属的季节
//1:声明变量存储月份
char month = 5;
//2:通过switch去完成
switch(month){
case 12:
case 1:
case 2:
System.out.println("你就像那冬天里的一把火"); break;
case 3:
case 4:
case 5:
System.out.println("春天在哪里呀!春天在哪里~");break;
case 6:
case 7:
case 8:
System.out.println("夏天夏天悄悄过去 留下小秘密");break;
case 9:
case 10:
case 11:
System.out.println("就让秋风带走我的思念 ");break;
default:
System.out.println("您的输入有误。。。");break;
}
System.out.println("GAME OVER");
}
}
I、语法结构
switch(expression){
case value1:
statement1;break;
case value2:
statement2;break;
case value3:
statement3;break;
.............
default:
statement3;[break;]
}
II、执行顺序
- 计算表达式的值
- 依次匹配对应的case 如果匹配成功执行对应的执行语句;
- 一定要保证后面break,跳出整个switch结构;
- 所有的case都不满足,执行default,如果存在的话;
III、注意事项
- 表达式的结果可以通过自动类型转换转换为int,基本数据类型中只有byte、short、int、char 4种类型可以使用;
JDK1.5
之后支持枚举类型Enum
,JDK1.7
之后支持String字符串;
2.2.2 if分支结构
// Math.random() 指定区间的随机数(整数) [1,8] [min,max]
// (int)(Math.random()*(max-min+1)+min)
I、单分支结构
//测试if单分支
public class IfTest01{
public static void main(String[] args) {
// 生成一个随机数 查看随机数是否大于50 大于则显示随机数的结果反之则结束
double random = Math.random(); //[0-1)随机小数
System.out.println(random);
// Math.random() 指定区间的随机数(整数) [1,8] [min,max]
// (int)(Math.random()*(max-min+1)+min)
// 产生一个[45,80]
int num = (int)(Math.random()*36+45);
System.out.println(num);
//判定
if(num>50){
System.out.println("产生的数字大于50,数字是:"+num);
}
System.out.println("GAME OVER");
}
}
A、语法结构
if(expression){
statement;
}
B、执行顺序
- 判定expression的结果 如果结果时true 则执行对应的执行语句;结束整个if单分支
- 如果表达式的结果时false,则跳过if单分支,执行后续代码
C、注意事项
- 分支比较简单 可能不能完全使用情况比较复杂的业务;
// 声明一个变量
boolean flag = true;
if(flag=false){
System.out.println("aa");
}
System.out.println("bb");
讨论题目:
1: 请说明各个运算的注意事项;
2:++ 和 – 的区别?
3: 说明一下&& 和& ||和|的区别于联系?
4: 说一下运算符的优先级别?
5: 请描述流程控制有哪些?
6:请说明switch的执行过程和注意事项?
7: 请说明if单分支的执行过程和注意事项?
II、双分支结构
//测试if双分支
public class IfTest02{
public static void main(String[] args) {
// 判定某个数字的奇偶性
// 1: 随机生成一个数字 [20,56]
int random = (int)(Math.random()*37+20);
System.out.println("产生的随机数是:"+random);
//2: 判定奇偶性
//boolean flag = (random%2)==0;
/*if((random%2)==0){
System.out.println("产生的随机数是:"+random+",它是一个偶数");
}else{ //flag = false
System.out.println("产生的随机数是:"+random+",它是一个奇数");
}*/
String msg = (random&1)==1?"奇数":"偶数";
//System.out.println(msg);
System.out.println("产生的随机数是:"+random+",它是一个"+msg);
System.out.println("GAME OVER");
}
}
A、语法结构
if(expression){
statement1;
}else{
statement2;
}
B、执行顺序
- 判定expression的结果 如果结果时true 则执行对应的执行语句
statement1
;结束整个if双分支 - 如果表达式的结果时false,则执行
statement
2, 则跳过if双分支,执行后续代码
C、注意事项
- 分支比较简单 可能不能完全使用情况比较复杂的业务;
- 双分支中的if-else一定会被执行一个;
III、多分支结构
//测试if多分支
// 分别使用if和switch 来完成方向控制
// 45上 46右 47下 48左
public class IfTest03{
public static void main(String[] args) {
// 随机生成一个分数 判定分数的等级
// 100 NB [90-100) 优秀 [80-90) 良好 [70-80) 还行 [60-70) 勉强
//1:生成一个随机数
int score = (int)(Math.random()*92+9);
System.out.println("生成的分数是:"+score);
if(score==100){
System.out.println("NB");
}else if(score>=90 && score<100){
System.out.println("优秀");
}else if(score>=80 && score<90){
System.out.println("良好");
}else if(score>=70 && score<80){
System.out.println("还行");
}else if(score>=60 && score<70){
System.out.println("勉强");
}else{
System.out.println("男女混合双打");
}
System.out.println("GAME OVER");
}
}
A、语法结构
if(expression1){
statement1;
}else if(expression2){
statement2;
}else if(expression3){
statement3;
}..........{
}[else{
statementN;
}]
B、执行顺序
- 判定
expression1
的结果 如果结果时true 则执行对应的执行语句statement1
;结束整个if多分支 - 如果表达式的结果时false,判定
expression2
的结果,如果结果时true,则执行statement
2, 则跳过if多分支,执行后续代码 - 以此类推
- 直到所有的结果结果都不满足的情况下,如果代码中存在else 则执行else的内容
C、注意事项
- 多分支可能会导致代码过于臃肿,所以一般不建议分支出现3条以上;
- 编写条件的时候,可以适当的增加整个分支的判定效率;
- if做的事区间判定,switch是等值判定,他们是可以互通的;
2.3 循环结构
2.3.1 while循环
//测试while循环
import java.util.Scanner;
public class WhileTest{
public static void main(String[] args) {
//用户输入一个数字 判定这个数字的长度 123 --> 3
/*
1: 在当前类的头顶上编写如下代码:
import java.util.Scanner;
2: 使用
Scanner input = new Scanner(System.in);
3: 获取用户输入的值
int num = input.nextInt();
*/
Scanner input = new Scanner(System.in); // int num = 10;
System.out.println("请输入一个数字>>>>>>>");
int num = input.nextInt(); //Math.random();
System.out.println("用户输入的值是:"+num);
// 计算当前用户输入数字的长度
//a:声明一个变量存储 长度
int length = 0;
while(num!=0){
num = num / 10;
length++;
}
System.out.println("您输入的数值的长度是"+length+"位数");
}
}
I、语法结构
while(expression){
//loop-statement;
}
II、执行流程
- 判定表达式的结果 如果结果时true则执行循环体一次 ,继续判定 直到循环条件(表达式)的结果时false,则终止整个while循环
- 最开始表达式的结果就是false 则直接跳过;
III、注意事项
- 需要在循环体中存在一些代码能够改变循环条件的结果,这样该循环才不会变为死循环(死循环不一定是坏的);
- 知道循环终止条件,但是不确定循环次数;
// 一下代码没有问题 编译器只管类型ok
boolean flag = true;
while(flag){
}
System.out.println("excute.....");
// 一下代码有问题 编译的时候确定了表达式的值 所以可以肯定后面的excute是不可达的
while(true){
}
System.out.println("excute.....");
// 一下代码有问题 final之后相当于flag会被替换为字面值
final boolean flag = true;
while(flag){
}
System.out.println("excute.....");
2.3.2 do-while循环
//测试do-while循环
import java.util.Scanner;
public class DoWhileTest{
public static void main(String[] args) {
//用户输入一个数字 判定这个数字的长度 123 --> 3
Scanner input = new Scanner(System.in); // int num = 10;
System.out.println("请输入一个数字>>>>>>>");
int num = input.nextInt(); //Math.random();
System.out.println("用户输入的值是:"+num);
// 计算当前用户输入数字的长度
//a:声明一个变量存储 长度
int length = 0;
do{
num = num / 10;
length++;
}while(num!=0);
System.out.println("您输入的数值的长度是"+length+"位数");
}
}
I、语法结构
do{
//loop-statement
}while(expression);
II、执行流程
- 不管三七二十一,先做一次循环体;
- 然后判定表达式的结果 如果结果时true则再执行循环体一次 ,继续判定 直到循环条件(表达式)的结果时false,则终止整个do-while循环
III、注意事项
- 知道循环终止条件,但是不确定循环次数;
- do-while的使用场景比较少,适用于循环条件的判定依赖于循环体的执行;
2.3.3 for循环
//测试for循环
public class ForTest{
public static void main(String[] args) {
// 1: 计算1-100累加求和
//int num = 1; // 这个变量存储 1- 100之间的值
int sum = 0; // 累加求和
//1:声明循环变量
//2:判定循环条件 //5:继续判定循环条件
for(int num = 1;num<=100;num++){//4:改变循环变量的值
//3:执行循环体1次
sum = sum+num;
}
System.out.println("1累加到100之间的和是:"+sum);
}
}
I、语法结构
for(;;){
// 循环体
}
for(;循环条件;){
// 循环体
}
for(声明循环变量;循环条件;改变循环变量的表达式){
// 循环体
}
II、执行流程
- 声明循环变量;
- 判定循环条件 如果条件位true 执行循环体一次
- 如果条件位false 则跳过for循环执行后续代码
- 如果条件位true 执行循环体之后,执行改变循环变量的表达式 ,继续判定循环条件以此类推;
III、注意事项
- for循环是所有循环里面格式最灵活的;
- 循环变量声明在for中,会在一定程度上降低内存消耗;
- 改变循环变量的值的表达式,这是执行完循环体之后要做的,不能因为写在了同一行,所以认为它的执行顺序和循环变量声明,循环条件判定是在一起执行的;
- for循环能够确定循环次数,while确定的循环的终止条件;
2.4 流程中断
2.4.1 continue
一定要知道我们的程序的执行流程是严格按照顺序流程执行的,在执行的过程中会嵌套各种分支以及循环;
continue:跳出循环 只跳出当前循环一次;
//测试continue
public class ContinueTest{
public static void main(String[] args) {
// 使用生成1-100之间的数字 然后判定这些数字中是否存在
// 偶数,只打印偶数 如果是奇数 则跳过
for (int i=1;i<=100 ;i++ ) {
// i就是1-100之间的数值
// 判定i的值是奇数还是偶数
if(i%2==1){ //i是奇数
continue;
}else{//i是偶数
System.out.print(i+" ");
}
System.out.println("我是换行");
}
}
}
2.4.2 break
打断case穿透,跳出当前循环
// 测试break
public class BreakTest{
public static void main(String[] args) {
// 需求:计算1-100累加求和 然后计算累加值超过3000之后的累计的值是几
//声明变量存储累加的值
int sum = 0;
//1:计算累加求和 1-100
for(int i = 1;i<=100;i++){
sum = sum+i; //sum+=i
// 判定累加的值是否超过3000了
if(sum>=3000){
System.out.println("累加的和超过了3000,目前累加到"+i+",累加的和是"+sum);
// 跳出循环
break;
}
}
System.out.println("game over");
}
}
2.4.3 return
跳出方法
// 测试break
public class BreakTest{
public static void main(String[] args) {
// 需求:计算1-100累加求和 然后计算累加值超过3000之后的累计的值是几
//声明变量存储累加的值
int sum = 0;
//1:计算累加求和 1-100
for(int i = 1;i<=100;i++){
sum = sum+i; //sum+=i
// 判定累加的值是否超过3000了
if(sum>=3000){
System.out.println("累加的和超过了3000,目前累加到"+i+",累加的和是"+sum);
// 跳出循环
return;
}
}
System.out.println("game over");
}
}
从跳出的程度而言,continue<break<return
**作业: idea的安装和使用 建议使用idea2020
版本 以及破解方式 **
一下代码是为了更好的认识continue、break和return;
public class Test02 {
public static void main(String[] args) {
/*out:*/for (int j=1;j<=9;j++){ //行
for (int i=1;i<=j;i++){//列
if (i==4){
//continue;
//break;
//return;
//break out;
}
System.out.print(i+"*"+j+"="+(i*j)+"\t");
}
System.out.println();
}
System.out.println("game over");
}
}
- 用户输入一个数字,将当前该数字倒叙输出:
12345----》54321
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nYWu9aRW-1670331743845)(C:\Users\ZXL\Desktop \1659925580140.png)]
/**
* 12345 ---> 54321
*/
import java.util.Scanner;
public class Test03 {
public static void main(String[] args) {
//1: 获取用户输入的值
System.out.println("请输入要计算的值>>>>>>>");
//1-1 固定代码套路
Scanner input = new Scanner(System.in);
int num = input.nextInt();
//2:计算当前数字时几位数
//2-1: 声明一个变量存储当前数字时几位数
int length = 0;
//2-2: 声明一个变量 暂时存储num的值 防止后续对于num的改变导致后续的程序出现问题
int temp = num;
while(temp!=0){
temp = temp/10;//1234 / 10 = 123
length++; //每除一次 偷偷递增1
}
// System.out.println("当前用户输入的值时:"+num+",该数字是个"+length+"位数");
//i:声明一个变量 存储 每一位乘完的结果
int ans = 0;
//3:分离当前的每一位
temp = num; // 让num重新赋值给temp 针对temp做操作
while(temp!=0){
//3-1:对10求余 求最低位 123%10=3
int bit = temp%10;
//System.out.println("分离当前数字,分离的值时:"+bit);
//3-2 准备针对于bit做操作即可
//3-2-1 : 求bit*10^length-1次方
//ii:使用for循环计算
for (int i = 1;i<length;i++){
bit = bit*10;
}
// 累加求和
ans = ans+bit;
//3-3:改变当前temp的值 123->12 123/10
temp = temp/10;
// 递减length的长度
length--;
}
System.out.println("您输入的值时:"+num+",倒叙输出的结果时"+ans);
// 另外一种方式
String str = "";
/*
while(num!=0){
int bit = num%10;
str = str+bit;
num = num/10;
}
System.out.println(str);
*/
System.out.println(Integer.valueOf(new StringBuilder(String.valueOf(num)).reverse().toString()));
}
}
- 用户输入一个数字,判定该数字是否时水仙花数?
用户可以输入一个任意长度的数字
假设有一个N位数,这个N位数的每个数字的N次方等于当前数字本身,那么该数字就是水仙花数,比如:
153 = 3位数
1^3+5^3+3^3 = 153 153是一个水仙花数
12345 = 5位数
1^5+2^5+3^5+4^5+5^5 = 12345 12345是一个水仙花数
1位数和2位数的数字时不包含水仙花的 1 一定不是 99 一定不是
2.5 方法
就是一个功能,为了能让职责单一的具体体现,目的是为了方便后期维护、代码复用、职责单一;
方法的定义就是通过一个{}将多行语句分离出来,形成一个整体;
2.5.1 方法定义
方法声明按照如下的模板进行即可,方法中能编写的代码:main方法中可以写啥 ,你方法中就可以写啥;方法调用:在main方法里面调用;
// 功能 多行语句
修饰符 [static] {void|数据类型} 方法名([参数列表]) {
}
public static void 方法名(){
执行语句;
}
/**
* 测试定义方法 以及使用方法
*/
public class Method01 {
// 程序的入口
public static void main(String[] args) {
// 调用add方法
add();
System.out.println("hello main method");
}
// 定义一个方法
public static void add(){
System.out.println("hello method");
}
}
2.5.2 方法的使用
-
在需要调用的位置通过方法名称调用
-
调用的时候,不光需要指定名称,还需要保障参数列表存在,如果被调用的方法存在参数列表的话
public static void main(String[] args) { add(5); // 实参 } public static void add(int num){ // 形参 num = 5 System.out.println("带参数的add方法"); System.out.println(num); }
-
保证实际参数和形式参数的个数、顺序、类型保持一致
public static void main(String[] args) {
// 调用
shopSmoke("大前门",10);
}
public static void shopSmoke(int money,String type){
System.out.println("我去买烟了。。。。");
}
2.5.3 参数问题
方法中的参数就是一根天线,需要接收外部调用时传入的值:方法根据传入的值进行运算。
方法的参数不需要初始化,因为在程序调用的时候,能够确定赋值,所以不初始化也可以使用
public static void main(String[] args) {
add(5); // 实参
}
public static void add(int num){ // 形参 num = 5
System.out.println("带参数的add方法");
System.out.println(num);
}
这两个num
有什么区别和联系?
public static void main(String[] args){
int num = 10;
add(num);
}
public static void add(int num){
System.out.println(num);
}
2.5.4 返回值
一个方法执行结束之后,调用者需要使用被调用的计算的结果,此时通过return语句在被调用方法中将结果返回;
注意的是:
public static 数据类型 方法名(){
// 语句
return 返回结果; // 返回结果的类型和方法声明的数据类型要保持一致
}
/*
计算一个数字时几位数
*/
public class Method04 {
public static void main(String[] args) {
int num = 12345;
int len = getLength(num); // 计算了num是5位数 5
// 想要计算 倒叙输出
System.out.println("main:"+len);
}
/**
* 计算num的长度
* @param num
*/
public static int getLength(int num){
// 声明变量存储长度
int length = 0;
while(num!=0){
num /= 10; //num = num/10
length++;
}
System.out.println("当前数字时一个"+length+"位数");
return length;
}
}
栈内存的执行过程:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-InXPo6Ks-1670331743845)(C:\Users\ZXL\Desktop \1659942437274.png)]
2.5.5 如何编写方法
// 因人而异
// 套路
// 读十遍需求
// 计算一个数字是否是水仙花?
// 返回值的重点在于 调用者是否需要
public static boolean isFlower(int num){
sout("是");
return true;
}
// 计算一个数字时几位数
// 计算两个数字之和
public static void add(){
System.out.println(10+10);
}
public static void add(int num){
System.out.println(10+num);
}
public static void add(int num1,int num2){
System.out.println(num1+num2);
}
public static int add(int num1,int num2){
System.out.println(num1+num2);
return num1+num2;
}
2.5.6 方法的优势
- 简化代码开发 复用代码逻辑
- 优化开发复杂度,程序员关系核心业务,具体的细节编写成一个个的方法,按部就班的去调用即可;
- 学习方法不需要调入底层实现细节,关心方法能做什么? 具体关系方法需要哪些参数?是否存在返回值即可;
2.5.7 方法重载
两同三不同:
两同: 同类、同名;
三不同: 参数列表不同:参数个数、参数的顺序、参数的类型;
重载的调用顺序: 1:精确匹配 完全一致 实际参数的类型和形式参数的类型一致 2: 最近最优 自动类型转换
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8VM7roWm-1670331743845)(C:\Users\ZXL\Desktop \1659603357084.png)]
public class Method07 {
public static void main(String[] args) {
// add(1,2);
}
public static void add(){
System.out.println(10+10);
}
public static void add(int num){
System.out.println(10+num);
}
public static void add(int num1,int num2){
System.out.println(num1+num2);
}
public static void add(float num1,int num2){
System.out.println(num1+num2);
}
public static void add(int num1,float num2){
System.out.println(num1+num2);
}
}
// 笔试题
public class Method08 {
public static void main(String[] args) {
// 先找完全匹配的,按照自动类型转换查找
m('a',123);
}
/* public static void m(char ch,int num){
System.out.println("char int");
}*/
/* public static void m(int ch,int num){
System.out.println("int int");
}*/
public static void m(int ch,long num){
System.out.println("int long");
}
public static void m(int ch,double num){
System.out.println("int double");
}
/* public static void m(long ch,int num){
System.out.println("int double");
}*/
}
题目讨论:
-
两道题目的逻辑流程;
-
为什么使用方法?
3)参数和返回值的区别?
- 如何定义方法?
5)什么是重载? 重载有哪些问题?
2.5.8 递归
递归不重要:
重点: 文件存储、数据结构(树、堆、图)
递归是一种编程技巧: 方法内部调用自身编程技巧称之为递归。
递归 : 找已知条件、找规律;套模板
//测试使用递归
/**
* 递归程序:
* 递归头 当前递归程序的终止条件
* 递归体 当前递归程序执行的流程 核心业务
* 递归:
* 1: 找规律
*
* a: 计算阶乘:
*
* 1!= 1 已知条件 头
* 2!= 2*1 = 2*1!
* 3!=3*2*1 = 3*2!
* f(n) = n*(n-1)! 规律就是体
*
* 计算斐波那契数列:
*
* 1 1 2 3 5 8 13 21 34 55 。。。。。
* 求第n项的值
*
* f(1) = 1
* f(2) = 1
* f(3) = 2 = 1+1 = f(1)+f(2);
* f(4) = 1+2 = f(2)+f(3)
*
* f(n) = f(n-1)+f(n-2);
*
*
*
*
*
*/
public class Method09 {
public static void main(String[] args) {
//fun();
//int result = getNum(5);
System.out.println(getNum(5));
System.out.println(feiBo(10));
}
// 让自己调自己
// StackOverflowError : SOFE 栈内存溢出
public static void fun(){
fun();
}
//计算阶乘 计算那个数字
public static int getNum(int num){
if (num==1){
return 1;
}
return num*getNum(num-1);
}
public static int feiBo(int num){
if (num==1||num==2){
return 1;
}
return feiBo(num-1)+feiBo(num-2);
}
}
递归程序最大问题:第一个问题是吃内存,第二个问题是效率差;
// 获取当前系统时间
long startTime = System.currentTimeMillis();
System.out.println(feiBo(50));
long endTime = System.currentTimeMillis();
拓展练习:查看一下尾递归 复用栈帧;
第三章 面向对象(最重要)
思路、思想、东西多;
3.1 面向对象和面向过程的区别和联系
最开始的时候,我们编写业务的方式是过程式:
- 谭凯去开门
- 过程式
- 起立->向右转->走两步->向右转->走20步->推门
- 所有步骤按部就班完成
- 对象式
- 我喊谭凯去开门
- 过程式
面向对象:现实生活中最常见的处理事情的解决办法; 有钱人的解决办法; 不去管对象如何做事的,只需要对象是否能完成这个功能;在面向对象过程中,找对对象很重要
。
演变过程:之前的业务简单、业务抽象程度低,我们很容易通过过程式方式方式解决问题,后面随着互联网爆发,我们发现业务变得越来越复杂,应对复杂的业务,面向过程已经力不从心了。
我们通过面向对象去处理整个业务的走向和控制业务流程,确定当前业务需要哪些对象,然后开始通过面向过程的方式编写每个对象完成这些功能需要做的细节,这些细节都是要程序员自己写的。
请说明面向对象和面向过程的区别和联系?
3.2 面向对象概述
3.2.1 如何编写面向对象的代码
思考问题? 作为一个对象而言我们需要它做什么?
1: 它应该具备一定的功能,这些功能就是它完成的一些事,对于代码而言就是一个个的方法。
思考问题? 我们编写代码的时候,方法是放在哪里的?
2: 方法是放在类里的。
思考问题? 对象能够发生关系的地方是什么?
3: 只能是类。
3.2.2 类和对象的关系
-
类
- 现实生活的维度
类: 类型、类别、人类、鸟类
说说人类: 一种高级动物,有独立的思维,有特定的沟通方式,存在社会关系,会使用工具;
人类这个词、类别、鸟类这些词是抽象的,不好落地,空泛的概念就是类。 人类等等这些使用类去组的词语:目的是为了让子孙后代能够更好的认识这个世界所描述一些概念;
这些人类、鸟类如何起名字的? 为什么要这样做?
鸟类: 把一些具备相同特性或者时行为的动物归为一类;
- 编写代码的维度
类: 类型; 引用类型就是复合类型; 人类:<— 将一个个活生生人的相同的特质抽取出来,归为一类;
-
对象:
-
现实生活的维度
可以和你通过生活的一个生物; 女朋友 、男朋友
可以帮助我们去处理生活中其他事情,她们本身具备一定的能力,和你共同营造美好生活;
-
代码维度
对象可以能够做事的个体,实体。它很具体;
-
类和对象的关系?
类是一个抽象的概念,对象是对于某个类的一个具体实现;
类: 是对于对象的抽象,抽取象的部分;
对象: 是对于类的具象化的表现形式;
请描述一下先有类 还是先有对象?
- 构建的角度说: 先有对象 再有类
- 编写代码的角度说:先有类 再有对象;
3.3 类和对象的使用
3.3.1 类的声明
将从属于这个类的所有的实例对象的共性抽取出来,抽取两部分:
第一部分是:属性 类似姓名、年龄、性别、身高
第二部分是:方法 类似 吃饭 睡觉
public class 类名{
/*属性*/
类型 变量名;
。。。。。。
/*方法*/
public {void|数据类型} 方法名([参数列表]){
// 语句
}
。。。。。。。
}
3.3.2 对象的创建
// 类名 变量名 = new 类名();
Person p = new Person();
// 使用person对象的属性或者时方法
p.属性;
p.方法;
3.3.3 题目分析
要编写一个订单类,订单类中商品名称、商品价格、商品类型(饮料、坚果、零食)、商品数量; 创建一个商品对象,然后依次填写订单对象中的各个属性,随后计算当前订单的金额是多少?
public class Order{
String goodsName;
double goodsPrice;
byte goodsType; // 1:饮料 2:坚果 3:零食
int goodsCount;
public double getPrice(){
double price = goodsPrice*goodsCount;
return price;
}
}
public static void main(String[] args) {
//1:创建订单对象
Order order = new Order();
//2:给订单的每个属性进行赋值操作
order.goodsName = "旺仔牛奶";
order.goodsPrice = 6;
order.goodsType = 1;
order.goodsCount = 10;
//3:计算当前订单的价格
double price = order.getPrice();
System.out.println("该订单总金额是:"+price);
}
}
3.3.4 new关键词
成员变量–>属性–>字段–>域 Filed
以后但凡只要看见new
,保证在内存中做三件事
- 开空间 在堆内存中开辟存储空间
- 初始化 在堆中给成员变量初始化 属性初始化
- 指向引用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3eXFj3XI-1670331743845)(C:\Users\ZXL\Desktop \1660036685469.png)]
3.4 构造器
创建对象的方法称之为构造方法也叫构造函数也叫构造器;通过new关键词去调用;
/*
测试使用构造器
*/
public class Constrictor01 {
public static void main(String[] args) {
//1:创建一个婴儿对象
Baby b = new Baby();
}
}
// 声明一个婴儿类
// 性别 姓名 体重 身高
// 哭
class Baby{
/* 属性 */
String name;
boolean gender;
double weight;
double height;
/* 构造器 特殊方法 */
/* public Baby(){
System.out.println("我被执行了");
}*/
/* 方法 */
public void cry(){
System.out.println("嚎啕大哭~~~~~");
}
}
- 构造器时一个特殊的方法
- 方法名和类同名
- 构造器声明位置不需要编写返回值
- 构造器内部不需要显式编写return语句
- 一个类中默认会存在一个空参数的构造器,你不写也存在;
- 构造器时支持重载的
- 一个类中默认存在一个空构造器,但是如果你在这个类中声明可其它构造器,那么空构造器就不存在了;
3.5 this关键词
this. 还有一种 this()
3.5.1 this.
this. ----> 当前对象的
this. 可省略:大多数情况下都可以省略
this.不可省略:出现同名变量 局部变量和成员变量同名;
public class Student {
/* 属性 */
String name;
int age;
boolean gender;
int score;
/* 构造器 */
public Student(){
}
public Student(String name){
this.name = name;
}
/* 方法 */
public void study(){
System.out.println("在学习。。。。");
}
public void program(){
System.out.println(this.name+"敲代码");
}
public static void main(String[] args) {
// 创建学生对象 去敲代码
Student stu = new Student();
stu.program();
// 直接打印当前stu对象的姓名
System.out.println(stu.name);
// 希望创建出来的学生对象已经包含名字
Student stu1 = new Student("张三");
System.out.println(stu1.name);
// 创建出来的stu1 调用敲代码功能
stu1.program();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IPVpPS94-1670331743845)(C:\Users\ZXL\Desktop \1660185551979.png)]
// 可以通过javap指令反编译class文件查看this是否存在
>javap -v Student.class
public Student();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1 // 空参构造器 里面参数时1个 这一个就是this
}
3.5.2 this()
用来做构造器调用,复用构造器的逻辑;
必须要在构造器的首行
/* 构造器 特殊方法 */
public Baby(){
this("100");
System.out.println("我被执行了");
//this.name = "100"; // UUID.randomUUID().toString();
}
// 创建对象的时候可以传入值 将值赋值给成员变量 对象创建之后就存在属性值
public Baby(String name){
this.name = name;
}
3.6 面向对象的三大特性
3.6.1 继承
I、继承
子承父业
-
A extends B A继承了B
-
在Java中只支持单继承,不支持多继承,导致继承所带来的的代码复用性是比较有限的,另外单继承导致我们编写代码的时候尽量不要使用继承,因为机会只有一次;
-
如果使用继承,后续出现业务扩展,解决方案A->B,A->B->C,但是这样会导致继承链边长,后期不利于维护;
class Animal{
String nickName;
String color;
String type;
public Animal(){}
public void shout(){
System.out.println("叫");
}
public void info(){
System.out.println("["+nickName+"],["+color+"],["+type+"]");
}
}
// 编写一个小狗类
class Dog extends Animal{
public Dog(){}
public void lookDoor(){
System.out.println("看门");
}
}
II、super关键词
它的用法和this一模一样,唯一区别是,this代指的是当前对象,当前对象的父类对象;
A、super()
调用父类构造器的;在子类的每个构造器中都存在一个super()
指向,用来调用父类的空构造器; 调用构造器的目的是:可以保证父类被加载到内存,子类如果创建对象,那么子类一定在内存中,而子类在内存,父类必须要在内存中;
public Dog(String color){
super();
this.color = color;
}
如果构造器中包含了this()和super(),那么省略super(),super()在每个构造器中都有一个:
public Dog(){
this("白色"); //super()
// 调用父类的构造器
System.out.println("Dog 构造器");
}
public Dog(String color){
//super(); 可以写 可以不写
this.color = color;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X59NW6vo-1670331743846)(C:\Users\ZXL\Desktop \1660199750381.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SZPds9Zg-1670331743846)(C:\Users\ZXL\Desktop \1660199768716.png)]
B、super.
指向当前对象的父类对象;
public Dog(String color){
super();
this.color = color;// ==> super.color = color;
}
如果出现了父类成员变量和局部变量同名,此时super和this是可以互相代替的,但是一般我们为了规格化编写代码,统一使用,实际上这里使用super更加何时,因为是父类对象的属性而不是当前对象的属性;
- super.
super.不能省略的情况是 子类中的方法和子类中的属性和父类的方法和父类的属性同名了,但是还想要调用父类的同名的方法或者是属性此时super不能省略;[但是一旦真的出现了子类和父类不论方法还是属性同名,可以理解为子类将其覆盖掉了,所以是不会主动调用父类中的同名变量或者时方法的,除非笔试题]
// 测试继承
public class Test02 {
public static void main(String[] args) {
// 创建一个dog对象
Dog d = new Dog();
}
}
class Animal{
String nickName;
String color;
String type;
public Animal(){
System.out.println("animal 构造器");
}
public Animal(String nickName){
this.nickName = nickName;
System.out.println("animal 构造器");
}
public void shout(){
System.out.println("叫");
}
public void info(){
System.out.println("["+nickName+"],["+type+"]");
}
}
// 编写一个小狗类
class Dog extends Animal{
String color; // 不可能写这样的代码
public Dog(){
this("白色"); //super()
// 调用父类的构造器
System.out.println("Dog 构造器");
}
public Dog(String color){
super();
super.color = color;
// 调用一下父类中的方法 info
info();
}
public void shout(){
System.out.println("汪汪");
}
public void lookDoor(){
System.out.println("看门");
super.shout();
}
}
III、Object
当一个类中没有显示的继承关系情况下,默认会继承Object
。所以Object
称之为所有类的父类、也叫超类、基类、根基类;
public class Test03 extends Object{
public static void main(String[] args) {
Test03 t = new Test03();
}
}
getClass(); // 反射 获取某个对象的Class对象
hashCode(); // 集合 生成一个对象的唯一值
clone(); // 配合克隆模式一起使用 专门用来创建对象的
notify();
notifyAll();
wait();
wait(timeout);
wait(long timeout, int nanos); // 多线程的时候
equals(Object obj) ;
toString() ;
A、toString
通过输出语句输出对象的时候,会默认调用当前对象的
toString
方法,如果当前类没有,没有关系,因为Object中有,那么如果一个类中没有toString
方法,打印输出当前对象是会默认调用Object中的toString
,Object中的toString
会打印输出当前对象所属的类名称+@+hash值转换为的16进制字符串,因为hash值时唯一的所以近似看做是当前对象的地址;
System.out.println(teacher); //Teacher@1540e19d
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4zZo47FA-1670331743846)(C:\Users\ZXL\Desktop \1660206303669.png)]
IV、重写
父类中定义的功能不满足子类的需要,子类会重新定义;覆盖;
现阶段的重写方法满足2个条件:
- 一定要发生继承关系
- 方法同名,返回值一致、参数列表一致,修饰符一致
- 判定方法是否重写,在当前方法头顶上写一个
@Override
// 定义一个Teacher类
class Teacher extends Object{
/*属性*/
String name;
int age;
boolean gender;
/*构造器*/
public Teacher(){}
public Teacher(String name,int age,boolean gender){
this.name = name;
this.age = age;
this.gender = gender;
}
/*方法*/
public void coding(){
System.out.println("敲代码");
}
/*
public void info(){
System.out.println("["+name+"],["+age+"],["+(gender?"男":"女")+"]");
}
*/
@Override
public String toString() {
return "["+name+"],["+age+"],["+(gender?"男":"女")+"]";
}
}
请说明重载和重写的区别和联系?
3.6.2 封装
权限修饰符。4种;
权限修饰符可以修饰:(public、默认的)类、方法、成员变量、构造器
修饰符 | 本类 | 同包下的子类 | 同包下的异类 | 异包下的子类 | 异包下的异类 |
---|---|---|---|---|---|
public | √ | √ | √ | √ | √ |
protected | √ | √ | √ | √ | × |
默认的 不写 | √ | √ | √ | × | × |
private | √ | × | × | × | × |
题目:
1: 请说明this和super的区别和联系?
区别:this是对当前类的调用。super是对父类的调用。
this.是对当前对象的引用,谁来调用我我就就代表数;
super.是当前对象对父类的引用
this()调用和访问当前类的构造器
super()是用来确定访问父类中的哪一个构造器
联系
- 都是java中的关键字
- this()和super()在使用时必须放在构造器内的首行,并且不能同时出现
2: 请说明继承的优缺点分析?
优点
- 减少重复代码
- 提高代码复用性
- 提高开发效率
缺点
- 不支持多继承,所以会导致继承之后的代码复用性有限
- 继承之后当业务出现扩展的时候可能会导致继承链变长,不利于后期维护
3: 谈谈你对Object的理解
-
Object是java中所有方法的父类
-
当一个类中没有显示继承关系的时候,默认为继承Object
-
public class Test{ .......... } public class Tese extends Object{ .......... }
4:请说明重载和重写的区别和联系?
-
重写就是子类吧父类中原有的东西重新写一遍
-
子类继承父类原有的方法,但是有的时候子类并不想完全继承,所以就在方法名,参数列表,返回值相同的情况下对方法体进行修改或者重写
-
重载在一个类中方法名参数列表不同的就可以叫做重载,重载对返回值没有要求。返回值可以相同也可以不相同。
5:请谈谈你对于权限修饰符的理解?
作业;
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
/*
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
1*1=1 1*2=2 1*3=3 .....
2*2=4 2*3=6 .....
3*3=9 3*4=12
4*4=16 4*5=20
.........
9*9=81
8*9=72 8*8=64
7*9=63 7*8=56 7*7=49
..............................
*/
public void info(){
System.out.println(“[”+name+“],[”+age+“],[”+(gender?“男”:“女”)+“]”);
}
*/
@Override
public String toString() {
return "["+name+"],["+age+"],["+(gender?"男":"女")+"]";
}
}
> 请说明重载和重写的区别和联系?
#### 3.6.2 封装
权限修饰符。4种;
权限修饰符可以修饰:(public、默认的)类、方法、成员变量、构造器
| 修饰符 | 本类 | 同包下的子类 | 同包下的异类 | 异包下的子类 | 异包下的异类 |
| ----------- | ---- | ------------ | ------------ | ------------ | ------------ |
| public | √ | √ | √ | √ | √ |
| protected | √ | √ | √ | √ | × |
| 默认的 不写 | √ | √ | √ | × | × |
| private | √ | × | × | × | × |
题目:
1: 请说明this和super的区别和联系?
区别:this是对当前类的调用。super是对父类的调用。
this.是对当前对象的引用,谁来调用我我就就代表数;
super.是当前对象对父类的引用
this()调用和访问当前类的构造器
super()是用来确定访问父类中的哪一个构造器
联系
- 都是java中的关键字
- this()和super()在使用时必须放在构造器内的首行,并且不能同时出现
-
2: 请说明继承的优缺点分析?
优点
- 减少重复代码
- 提高代码复用性
- 提高开发效率
缺点
- 不支持多继承,所以会导致继承之后的代码复用性有限
- 继承之后当业务出现扩展的时候可能会导致继承链变长,不利于后期维护
3: 谈谈你对Object的理解
- Object是java中所有方法的父类
- 当一个类中没有显示继承关系的时候,默认为继承Object
- ```java
public class Test{
..........
}
public class Tese extends Object{
..........
}
4:请说明重载和重写的区别和联系?
-
重写就是子类吧父类中原有的东西重新写一遍
-
子类继承父类原有的方法,但是有的时候子类并不想完全继承,所以就在方法名,参数列表,返回值相同的情况下对方法体进行修改或者重写
-
重载在一个类中方法名参数列表不同的就可以叫做重载,重载对返回值没有要求。返回值可以相同也可以不相同。
5:请谈谈你对于权限修饰符的理解?
作业;
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
/*
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
1*1=1 1*2=2 1*3=3 .....
2*2=4 2*3=6 .....
3*3=9 3*4=12
4*4=16 4*5=20
.........
9*9=81
8*9=72 8*8=64
7*9=63 7*8=56 7*7=49
..............................
*/