前言

碎碎念

java这门语言,我已经记不清开了多少课,敲了多少代码了。但是现在因为生活和学习上的需要,重新开课重新学习,颇有一种朝花夕拾的感觉。代码是以前敲过的代码,知识点是以前学过的知识点,现在只是重走西游路,在复习以前知识的同时找到自己。

关于笔记记录过程

按照本人复习过程来,力求逻辑上的完整性,重点放在逻辑上的连贯性,所以不会把理论和实践完全拆分开,在理论和实践的过程中推进。但是本质上还是为了期末的考试,所以会在最后加上一个做题和解析的模块。记录题目的同时方便自己查漏补缺。
本套笔记按照优先建立知识体系学习法,知识点的细节在学习和实战中慢慢完善。

JAVA的知识背景

java的诞生

JAVA由美国的SUN公司发明,诞生于1991年。
设计初衷是给机顶盒这类电子产品,这类产品的特点就是不同厂家生产的型号拥有不同的CPU不同的操作系统。(为后续跨平台性埋下伏笔)
因此要求JAVA产生的程序是中立的(既跨平台)
可是命运总是爱跟人开玩笑,java发明之后这类产品直接褒姒,所以java失去了用武之地。
直到90年代中期互联网爆发,各式各样不同的电脑都连接到了互联网上(不同u不同系统)
此时急需一个跨平台语言,所以java堂堂崛起!

JAVA的主要应用范围

服务器端软件开发:各类网站系统和管理系统

移动端开发:安卓系统、鸿蒙

科学研究、云计算、大数据

JAVA的版本选择

目前企业中应用最广的还是java8.0,占据了最大的份额。

image-20241003082723831

JVM、JRE、JDK

JVM:Java Virtual Machine虚拟计算机,主要负责Java程序的运行
JAVA程序是在JAVA虚拟机上直接运行,而不是运行在操作系统上(有别于C++)
Java的跨平台就是基于不同版本的JVM实现。
举例:我用mac系统写了一个JAVA程序,首先我MAC系统上需要有对应的MAC版JVM,所以程序在MAC上可以跑,然后我又把程序发给Linux系统,Linux系统上安装的Linux版JVM负责运行发送过去的程序

JRE :Java Runtime Environment, java运行时环境。
一张图解释
image-20241003083520608

JRE包含了JVM,JRE是java运行环境,从字面上理解,java运行的时候JVM是必须的,因为Java的run就是run在JVM上。 加上核心的库类和文件,就组成了完整的运行环境。

JDK:Java Development kit ,Java 开发工具包。提供给java开发人员使用
再用一张图解释
image-20241003084432765

JRE构成了运行JAVA的所有条件,JDK在此基础上加入了开发工具。

写出第一个JAVA程序。

JAVA的组织结构

image-20241003090408814

关于java的组织结构和缩进
两个花括号一对,最外层下面的花括号对应上面的p,表示中间的部分是class类的类体
对于main方法来说,同理下面的花括号和上面的p对齐,两个花括号中间的部分是方法的方法体。

实际上java开发的步骤

image-20241003090554702

从上图可以知道,虚拟机运行的程序都是.class文件,编写的程序是.java文件

简单的程序bug调试以及发散出的思维

关于bug:

1、bug说明程序有部分有错,也可以说明你离成功不远了,遇到bug是非常正常的事情
2、bug越多程序越复杂,程序越复杂bug越多
3、程序员的能力可以简单由调试bug的数量来判断,调试解决的bug越多,程序员的段位越高。
4、写不出bug的程序员是没有写代码的程序员,多写多错才会有所成长。

由bug发散的思维:

以下是刚才这个简单的bug我认为新手可能出现的错误以及原因
1、类名写错了 public class 后面的类名一定要和建的.java文件前面的名字相同,并且区分大小写
2、System的S打成小写,System.out.print 中的 System 是指 Java 的 java.lang.System 类。这个类是 Java 自带的,不需要额外导入,因为 java.lang 包是自动导入的。其中System是一个类,out是一个静态字段,print是一个方法(包括println)

标识符、关键字、变量本质、注释

标识符命名规则及使用规范

标识符命名规则

image-20241003155147873

注:图中一个没有说到的细节就是可以以人民币符号¥开头,在我上课的PPT里面确实显示是可以的
我已经测试过了,确实是可以的。但是原理和图中说的有些出入
所以用一句话概括

开头字母钱标下划线,大小写敏感,区别关键字。

关于人民币符号¥

¥符号也是作为”字母“被识别的,和中文和字母一样,因为Java用的是unicode字符集,¥和中文都满足,所以都可以作为”字母“被识别。而不是这个符号本身被识别。

标识符使用规范

image-20241003155953266

主要是引入了驼峰原则,实际情况可能乱起名的人才是占了大多数

测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package Y24M10D4;

public class Test002 {
public static void main(String[] args) {
int age = 1;
int _age = 2;
int $age = 3;
int ¥age = 4;
int age123 = 5;
// int 123age = 6; 数字在前无法作为标识符,直接报错
// int age# = 7; 标识符只能是字母数字下划线$
int 年龄 = 8; //java使用的是unicode字符集,中文也被识别成字符集中的 ”字母“
// int class = 9; class 是java中的关键字,同样无法作为标识符,所以错误
int _class = 10; //用下划线等符号标识一下就不是关键字了。
}
}

关键字

JAVA关键字是JAVA语言保留给内部使用的。所以关键字也叫保留字。
关键字都有特殊的含义,我们不能使用关键字作为标识符。
下面放一下java中的50个关键字,但是背是不可能背的,这辈子不可能背的。

image-20241003163132626

变量

变量的本质

可操作的存储空间

image-20241003163334181

用商场停车位来举例
商场有停车位,每个停车位有独一无二的编号,这个编号就是变量名
假设停车位编号A1,你停车之前A1就是一个空值,但是还是存在A1停车位
去停车的时候,你把车”小黑“停到一个A1,A1就有了自己的”值“ 小黑
所以A1 = 小黑 ,实际上是把小黑赋值给了A1。

测试代码

1
2
3
4
5
6
int monthlySalary = 3000;
int annualSalary = monthlySalary*12;
System.out.println(annualSalary);
double bonus = 150.123;
double sum = annualSalary+bonus;
System.out.println(sum);

注释

重点

注释不会出现在字节码文件中(.class文件)。
java编译器编译的时候会跳过注释语句
同样的程序不管写多少注释写没写注释,编译之后的大小都是一样的。

分类

image-20241003164311620

变量

八种基本数据类型

image-20241003200200688

继续用上文是商场停车位来解释
高速休息站里的车位有不同的类型,SUV和越野车的车位大,卡车和客车的车位更大,卡车和客车的停车位可以停下小轿车和越野车,但是卡车和客车没办法停在小轿车和越野车的停车位里。
由此可知 :定义数据类型就是定义停车位的大小和类型
JAVA是一种 强类型语言每个变量都必须声明数据类型

整型数据类型

image-20241003200350108

image-20241003200414469

派生知识点:

image-20241003200502344

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package Y24M10D4;

public class Test003 {
public static void main(String[] args) {
byte age = 18; //默认是int类型,转换成byte没有损失,所以正常转换了
short salary = 25000;
int salary2 = 50000;
int pekingPopulation = 30000000;
// int globalPopulation = 700000000; 表示过大是数会报错
//以上就是整形常量 ,默认的类型是int ,改成long类型需要后面加L/l
// int globalPopulation = 7000000000L;
//还是报错,因为是把70亿 赋值给int,int 最大只能接受21亿的数

//关于进制,可以定义不同的进制
int t1 = 65; //十进制
int t2 = 065; //八进制 0开头
int t3 = 0x65; //十六进制 0x开头
int t4 = 0b01000001; //二进制 0b开头
System.out.println(t1+"\n"+t2+"\n"+t3+"\n"+t4);

}
}

浮点型数据类型

image-20241004083854873

可以看到浮点数的表数范围非常大,这是因为浮点数是不精确

image-20241004084218697

需要注意:
指定范围内的整数是有限的,比如0-10,但是0-10之间的小数是无限的。
因此,有限的空间存储无限的数据,必然存在误差,所以浮点数不能精确表示。
如果需要进行不产生舍入误差的精确计算,就需要引入BigDecimal类。后续再说。

实操代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

//测试浮点数
double d1 = 3.14;
/* float f1 = 3.14;
报错java: incompatible types:
possible lossy conversion from double to float
说明浮点常量默认是double*/
float f1 = 3.14F;//后面加大写的F,通过编译
double d2 = 314E-2;//科学计数法 xEn= x * 10^n
System.out.println(d1+"\n"+f1+"\n"+d2);
//浮点数是精确的,用于比较要小心。
float f3 = 0.1F;
double d3 = 0.1;
System.out.println(f3 == d3);
//输出false 说明不相等

Char字符集

说到char字符,首先要注意String类型
String是字符串不是基本数据类型!是一个类!包含在Java.lang包里面,自动引入
本质上是一个字符的数组

ASCII字符集

ASCII字符集由美国国家标准协会指定,由一个字节的后7位来表示一个字符。(所以一共有2^7 128字符)
剩下的最高位一般为0
例 字母A在计算机中就是01000001 也就是65
ASCII字符非常简单,就是一个简单的查表的过程(如下图)
image-20241005121503946

image-20241005121533973

字符集的发展过程

image-20241005121604545

ISO GB BIG5,都是不同地区自己制定的标准,由于不互通,经常造成乱码问题
所以有了Unicode字符集,每个字符都基于了全球独一无二的编码

Unicode原理

unicode采用了字符集和编码分开的策略。
image-20241005121931383

unicode统一采用了两个字节表示一个字符,包括英文字母
但是因为英文占据了互联网信息的绝大部分,所以在传输过程中会造成极大的浪费
所以现在主流的UTF-8

UTF-8

用1-6个字节来编码表示Unicode字符,西欧字符仍然是一个字节,汉字是三个字节

转义字符

对照表格
image-20241005122714547

布尔类型

布尔类型由两个常量,一个true 一个false组成
在内存中占1或4个字节。
和C的区别:不可以使用0或非0的整数来代替t或者f
常用来坐判断逻辑的条件。

练习代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package Y24M10D4;

public class Test004 {
public static void main(String[] args) {
//测试char
char c1 = 'A';
char c2 = '薯';

System.out.print(c1);
System.out.print(c2);

char c3 = '\n';
char c4 = '片';
System.out.print(c2);
System.out.println(c3);
System.out.println(c4);

//字符串不是基本数据类型,是类!
String str = "\n薯片";
//字符串用双引号,本质上就是一个字符数组
String str2 = "\n\n\"床前\"\t明\'月光\'";
System.out.println(str2);
//布尔类型
boolean flag = true;
if (flag){
System.out.println("我在写代码");
}


}
}

基本运算符

运算符分类

image-20241005130928325

算术运算符

image-20241005131146127

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
System.out.println("==========算术运算符=========");

int a = 3;
int b = 4;
int c = a + b * 4;
int c1 = (a + b) * 4;
System.out.println("c=" + c);
System.out.println("c1="+ c1);
int d1 = 15/4;
int d2 = 15%4;
System.out.println("d1="+d1 +"\n"+"d2="+d2);

a = 10;
b = a ++; //先赋值后自增,代码从左往右执行,先把a赋值给a然后a再打印
System.out.println("b="+b +"\n"+"a="+a);
a = 10;
b = ++a; //先自增后赋值,--和++同理
System.out.println("b="+b +"\n"+"a="+a);

扩展运算符

image-20241005132427532

运算符和表达式完全等效 没有过多的说明,用的情况也少
代码示例

1
2
3
4
5
6
System.out.println("==========拓展运算符=========");

a = 20;
b = 30;
a += b;
System.out.println("a="+a + "\n"+"b="+b);

关系运算符

image-20241005153134726

关系运算符的计算结果为布尔值
代码示例

1
2
3
4
5
System.out.println("==========关系运算符=========");
a = 20;
b = 30;
boolean result = a<b;
System.out.println(result);

逻辑运算符

这一块基本上用图片来说明

image-20241005153620084

image-20241005153743620image-20241005153828335

短路与、或可以节省计算量,提前返回ture或false
image-20241005153957310

image-20241005154031303

关于异或
个人理解就是简单的 “不同”
A和B不同 结果就是true
A和B相同 结果就是false 因为不是 “不同”
注意异或的符号是^,幂运算的符号,但是表示的不是幂运算
java中幂运算(科学计数法)要用E来表示 比如 xEy 就是x乘10的y次方
示例代码

1
2
3
4
5
6
7
8
9
10
11
System.out.println("==========逻辑运算符=========");
boolean b1 = true & false;
boolean b2 = true | false;
boolean b3 = !b2;
boolean b4 = true^true;
System.out.println("b1="+ b1 +"\n"+"b2="+ b2 +"\n"+"b3="+ b3 +"\n"+"b4="+ b4 );
//短路与、短路或
int w =3/0;
boolean b5 = 3<4 || (4<4/0); //这里如果是普通的或的话就会报错,使用了短路就没问题
System.out.println(b5);

位运算符

image-20241005182815752

例如“3”的二进制:00000000 00000000 00000000 00000011
取反就是: 11111111 11111111 11111111 11111100
示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
        System.out.println("==========位运算符=========");
int m = 3;
int n = 7;
int p1 = m&n;
System.out.println("p1="+p1);
/* 3 = 00000000 00000000 00000000 00000000 00000011
* 7 = 00000000 00000000 00000000 00000000 00000111
* 按为与 直观 的可以看到 上下的都是1的时候才是一所以答案为
* 00000000 00000000 00000000 00000011 = 3*/
int p2 = m | n ;
int p3 = m^n ;
int p4 = ~m;
System.out.println("p2="+p2);
System.out.println("p3="+p3);
System.out.println("p4="+p4);

int m2 = 3<<3;//左移3位 =3*2*2*2
int m3 = 12>>2;//右移2位 =12/2/2
System.out.println("m2="+m2);
System.out.println("m3="+m3);

字符串连接符

字符串连接符指的是+在连接字符时自动变为字符串连接符,会失去+原本的加的功能
代码示例:

1
2
3
4
5
System.out.println("==========字符串连接符=========");
int r1 = 3;
int r2 = 4;
System.out.println(r1 + r2);//正常显示
System.out.println("result is"+r1+r2);//这里+变成字符串连接符

条件运算符

image-20241005185520236
条件运算符可以很方便的替代if_else语句中的某些特殊情况

示例代码

1
2
3
4
System.out.println("==========条件运算符=========");
int y1 = 30;
int y2 = 40;
int minY = y1<y2?y1:y2;//返回y1y2中比较小的值

此致,java中所有的基本运算符都已经学完了

数据类型自动和强制转换

自动类型转换

image-20241008080327235

自动类型转换指容量小的数据类型可以自动转换为容量大的数据类型

注意:这里的容量大小,指的不是字节数,而是表数范围
例如八个字节的long可以自动转换为四个字节的float
image-20241008080511585

图中的实线表示的是无数据丢失的自动类型转换,虚线表示的是可能会有数据丢失的自动类型转换。

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package Y24M10D4;
/*测试基本数据类型的转换(自动转换,强制转换)
*
* */

public class Test006 {
public static void main(String[] args) {
//自动类型转换:表数范围小的可以自动转换为表数范围大的
long a1 = 3456;
float a2 = a1;
System.out.println("a1="+ a1 + "\n" + "a2="+ a2);
//整型常量自动赋值给byte/short/char等类型,只要不超表数范围,则可以自动转换
byte b1 = 121;//legal
// byte b2 = 200;//illegal 200超过了byte的表数范围,所以不合法
//算术运算符,两个操作数都是整形的时候,有一个是long,则结果为long,否则结果为int(即使是byte,结果也是int)
long c1 = 1234;
int c2 = 123;
long c3 = c1 + c2;//c1是long,所以整个结果全部变成long

//算术运算符有一个操作数是double,则结果是double
double d1 = 3.14;
int d2 = 3;
double d3 = d1+d2;

//强制类型转换
double m1 = 3.98;
int m2 = (int)m1;
System.out.println("m2=" + m2 );
//转型的时候直接把小数丢掉,不会做任何的四舍五入运算。

char m3 = 'C';
int m4 = m3 + 2;
char m5 = (char)m4;
System.out.println("m5="+ m5);
//这里体现的基本上就是ASCII编码,C往后两位是E
/*当将一种类型强制转换成另一种类型
* 而又超出了目标类型的表数范围
* 就会被截断成一个完全不同的值
* */
int n1 = 300;
byte n2 = (byte)n1;
System.out.println("n2="+n2);
//不要去纠结这个值的意义,这个值没有任何的意义,就是随机截的

//溢出错误,操作比较大的数,要留意是否溢出。
int salary = 1000000000;//10e
int years = 30;
// int total1 = salary*years; 出来了负数,说明发生了溢出。
//特别需要注意 溢出不会报异常,还是会正常显示。
/*修改方法1,把salary和year改成int类型
*/
//修改方法2
long total2 = 1L*salary*years;
System.out.println(total2);

}
}

通过键盘输入

流程控制语句

流程控制语句有两种结构
1、选择结构
2、循环结构
学会了程序控制语句,我们的一只脚就迈进了程序员的大门。

编程的本质

编程的本质就是用代码表达现实世界的逻辑。
而现实世界中的任何逻辑,最终都可以拆分成选择结构和循环结构。
image-20241008211552442

选择结构代表 如果…则… 这样的逻辑
例:如果看到红灯 则立即停车
循环结构就是选择结构的基础上加上重复执行。
任何的编程
本质上都是由“变量、选择语句、循环语句”组成

if语句

image-20241009081542457

语法结构

image-20241009081559194

流程图

image-20241009081328179

if else语句

image-20241009083036459

image-20241009083036459

多分支结构

image-20241009083313068

image-20241009083400325

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package Y24M10D4;
/*流程控制语句
* */
public class Test010 {
public static void main(String[] args) {
System.out.println(Math.random()/*这个方法返回一个0-1之间的随机数【0,1)*/);
//所以如果要返回一个0-10之间的随机数
int r = (int)(Math.random() * 10);
System.out.println(r);

//如果r小于5,则打印"数比较小"
if(r<5){
System.out.println("数比较小");
}//这里如果不加这个花括号其实也有效,但是限制很大,重点是只对第一句有效。
//所以为了更规范的写代码,最好还是加上。

if (r<5){
System.out.println("number is small");
}else {
System.out.println("number is big");
}

//年龄筛选器
int age = (int)(Math.random()*100);
if (age<15){
System.out.println("childhood");
} else if (age<25) {
System.out.println("teenage");
} else if (age<45) {
System.out.println("adult");
}else if (age<65){
System.out.println("old man");
}else if (age<85){
System.out.println("get rest");
} else {
System.out.println("die");
}
}
}

特殊练习,数字和字母的转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package Y24M10D4;

public class Test011 {
public static void main(String[] args) {
/*随机生成字母,aeiou输出元音,其他输出辅音*/
int num = (int)(Math.random()*26);
char alpha = 'a';
alpha = (char)(alpha + num);
if(alpha == 'a'|| alpha == 'e'||alpha == 'i'||alpha == 'o'||alpha == 'u'){
System.out.println("元音");
}else {
System.out.println("辅音");
}
}
}

Switch语句

switch语句特别适合做多值判断
代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package Y24M10D9;

public class Test001 {
public static void main(String[] args) {
/*以下是一个简单的判断语句
* 随机生成了一个值 判断大学几年级*/

int grade = (int)(Math.random()*4);

if (grade == 1){
System.out.println("grade 1");
} else if (grade ==2 ) {
System.out.println("grade 2");
} else if (grade == 3) {
System.out.println("grade 3");
}else {
System.out.println("grade 4");
}
/* 以下是上面代码的switch语句版本*/
switch (grade){
case 1:
System.out.println("grade 1");
break;//必须要每个case后面跟一个break
/*break是switch的跳出语句,没有break
* switch就会一直执行*/
case 2:
System.out.println("grade 2");
break;
case 3:
System.out.println("grade 3");
break;
case 4:
System.out.println("grade 4");
break;
}
int month = (int)(Math.random()*12);
if (month ==1 || month ==2 || month == 3){
System.out.println("spring");
} else if (month ==4 || month ==5 || month == 6) {
System.out.println("summer");
} else if (month ==7 || month ==8 || month == 9) {
System.out.println("autumn");
}else {
System.out.println("winter");
}

switch (month){
case 1:
case 2:
case 3:
System.out.println("spring");
break;
case 4:
case 5:
case 6:
System.out.println("summer");
break;
case 7:
case 8:
case 9:
System.out.println("autumn");
break;
// case 10:
// case 11:
// case 12:
// System.out.println("winter");
// break;
default:
System.out.println("winter");
break;
}
}
}

switch的表达式

image-20241009185237150

image-20241009185312810

switch语句练习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package Y24M10D9;

public class Test002 {
public static void main(String[] args) {
//阿拉伯数字转化成英语。1--》one
int num = (int)(Math.random()*10);
String Character = "";//逻辑上来讲没有问题 但是从编译器的角度考虑最好先设置一个空值
switch (num){
case 0:
Character = "zero";
break;
case 1:
Character = "one";
break;
case 2:
Character = "two";
break;
case 3:
Character = "three";
break;
case 4:
Character = "four";
break;
case 5:
Character = "five";
break;
case 6:
Character = "six";
break;
case 7:
Character = "seven";
break;
case 8:
Character = "eight";
break;
case 9:
Character = "nine";
break;
}
System.out.println(Character);
/*超市推出积分活动,积分7000以上奖励苹果,5000以上奖励香蕉,3000以上奖励牛奶*/
int score = (int)(Math.random()*10000);
System.out.println("用户积分:"+ score);
/*简单的做法, 用if判断 这里用switch练习*/
switch (score/1000){
case 9:
case 8:
case 7:
System.out.println("apple");
break;
case 6:
case 5:
System.out.println("banana");
break;
case 4:
case 3:
System.out.println("milk");
break;
default:
System.out.println("none");
break;
}


}
}

循环结构

image-20241010075241955

一切的事物,核心都是循环,操作系统的核心是一个接一个的循环
屏幕显示是一个循环,键盘监听、鼠标监听,都是循环
大到宇宙的运行,也是循环;微观粒子运行,还是循环。
人生,也是循环。
循环结构分为两个

while循环和for循环
image-20241010075523742

whlie的语法结构

image-20241010075852717

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package Y24M10D9;
/*用于测试while循环*/
public class Test003 {
public static void main(String[] args) {
/*打印1-100*/
int i = 1;
while (i<101){
System.out.println("i="+i);
i++;
}
//计算1+2+...+100

i =0;
int sum = 0;
while (i<101){
//sum = sum + i;
sum += i ;
i++;
}
System.out.println("和:"+sum);

}
}

for循环

image-20241010082020653

只不过for循环的语法做了一些调整
image-20241010082722211

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

//for循环
for(int i1 = 0 ;i1<10;i1++){
System.out.println("i1="+i1);
}

int sum02 = 0;
for (int m = 8;m<10;m++){
sum02 += m;
}
System.out.println("sum02="+ sum02);
}

}

嵌套循环

嵌套循环就是大循环里面套着小循环
image-20241010174619193

这样可以解决更加复杂的问题

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package Y24M10D9;
/*测试嵌套循环*/
public class Test004 {
public static void main(String[] args) {
/*打印输出十行,每行输出0-9*/

for (int l = 0; l <= 10; l++) {
for (int h = 0; h < 10; h++) {
System.out.print(h + "\t");
}
System.out.println();
}
/*for循环内部初始化的变量只再for循环内部使用
* 除了for循环就没有了*/

for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (j % 2 == 0) {
System.out.print("奇\t");
} else {
System.out.print("偶\t");
}
}
System.out.println();

}

/*输出一个矩形*/
for (int m = 0; m<6 ; m++){
for (int n =0; n<6;n++){
System.out.print("*\t");
}
System.out.println();
}

/*输出一个直角三角形*/
for (int m = 0; m<6 ; m++){
for (int n =0; n<m;n++){
System.out.print("*\t");
}
System.out.println();
}

System.out.println("========");
//输出一个倒直角三角形
for (int m = 0;m<6;m++){ // 12345
for (int n=5;n>5-m;n--){//54321
System.out.print("*\t");
}
System.out.println();
}

System.out.println("========");
//输出一个倒直角三角形
for (int m = 0;m<6;m++){ // 12345
for (int n=0;n<5-m;n++){//54321
System.out.print("*\t");
}
System.out.println();
}
/*输出一个等腰的三角形*/
int num = 4;
for (int i=0;i<5;i++){
for (int j=0;j<10;j++){
if (j>=num-i && j<=num+i){
System.out.print("*\t");
}else {
System.out.print("\t");
}
}
System.out.println();
}

}
}

break和continue语句

image-20241010194440523

这段多说无益,直接上代码,通过代码来了解

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package Y24M10D9;
/*break和continue*/
public class Test005 {
public static void main(String[] args) {
//产生100以内的随机数,知道随机数为88时终止循环
int count = 0;
while (true){
int m = (int)(Math.random()*100);
count +=1;
System.out.println(m);
if (m == 88){
break;
}

}
System.out.println("count:"+count);


/*测试continue*/
/*把100-150之间补不能被3整除的数输出,并且每行输出5个*/
int a = 0;
for (int i = 100;i<151;i++) {
if (i % 3 == 0) {
continue;
}else {
System.out.print(i+"\t");
a++;
}
if (a % 5 == 0) {
System.out.println();
}

}
/* int a = 0;
for (int i = 100;i<151;i++) {
if (i % 3 == 0) {
continue;
} else if (a %5 ==0) {
System.out.println();
} else {
System.out.print(i);
a++;
} 逻辑问题 */

}
}
package Y24M10D9;

public class Test006 {
public static void main(String[] args) {
/*
* 抓动物小游戏
* 随机出现一个动物
* 如果出现老虎,则游戏结束,如果出现老鹰,就躲起来等待下一个动物出现
* 如果出现小猫小狗小鸟小乌龟就可以抓住。记数抓住多少个动物
* 0老鼠1老鹰2小猫3小狗4小鸟*/
//while(true)
int count = 0;//抓住动物的数量
for(;;){//和while(true)等价
int num = (int)(Math.random()*5);
String animal = "";
switch (num){
case 0:
animal = "tiger";
break;
case 1:
animal = "eagel";
break;
case 2:
animal = "pussy";
break;
case 3:
animal = "doggy";
break;
case 4:
animal = "bird";
break;
default:
animal="unknow animal";
break;
}
if (animal =="tiger"){
System.out.println(animal);
break;
} else if (animal == "eagel") {
System.out.println(animal);
continue;
}else {
count++;
System.out.println(animal);
System.out.println(count);
}

}

}
}

控制语句综合练习

练习代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package Y24M10D9;

import java.util.Scanner;

public class Test007 {
public static void main(String[] args) {
/*使用for循环打印a-z的26个字母*/
char character = 'a';
for (int i =0;i<26;i++){
System.out.println(character);
character++;
}

/*打印九九乘法表*/
for (int m=1; m<10;m++){
for (int n =1;n<=m;n++){
int k = m*n;
System.out.print(m+"*"+n+"="+k+"\t");
}
System.out.println();
}
/*个人理解 这一类问题的关键
* 其实是找到m和n的关系 也就是行和列之间的关系
* 找到了之后就好说*/

/*薪水计算器
* 通过键盘输入月薪,每年是几个月的薪水
* 输出年薪
* 输出一行字“”如果每年粘性超过十万,恭喜你超过90%的国人
* 如果年薪超过20万,恭喜你超越98%的国人
* 知道键盘输入数字88,则退出程序 使用break退出循环
* 输入中途 键盘输入数字66,则这个用户退出计算不显示 恭喜
* 直接显示 重新开始计算,然后算下一个用户的年薪*/
Scanner scanner = new Scanner(System.in);
/*这是面向对象里面的内容,总之通过这个方式可以获得键盘的输入*/
System.out.println("annual salary calculator");
while (true){
System.out.println("enter your salary:");
int monthSalary = scanner.nextInt();
System.out.println("Enter the number of times you are paid in a year:");
int months = scanner.nextInt();
int yearSalary = monthSalary * months;

System.out.println("your annual salary:"+ yearSalary );
if (yearSalary>=200000){
System.out.println("king!");
}else if (yearSalary>=100000){
System.out.println("victory");
}

System.out.println("enter [88] to exit,enter [66] to continue");
int commandNum = scanner.nextInt();
if (88==commandNum){
System.out.println("exit");
break;
}else if (66 == commandNum){
System.out.println("please reenter");
continue;
}

}
}
}

方法的定义_内存结构

JAVA中的方法与函数的关系

在 Java 中只使用“方法”(method)这个术语,而没有“函数”(function)的概念。Java 的方法(method)与其他编程语言中的函数(function)非常相似,它们都执行特定的任务并可以返回一个值。但是由于 Java 是面向对象的语言,所有方法必须属于一个类,因此使用“方法”这个词来强调它们是类的成员。

方法的定义和调用

image-20241008085025541

方法的声明格式

1
2
3
*多个修饰符  返回值类型 方法名(形势参数列表){
多个java语句;
}

这里修饰符就是public static,对于现在来说不是很重要,只要记住就行
具体的情况之后再解释

image-20241008085259515

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package Y24M10D4;
/*测试方法的定义和调用
* */
public class Test007 {
//main方法,程序的入口
public static void main(String[] args) {
int a1 = add(100,200);
int a2 = add(200,300);
int a3 = add(300,500);

int num1 = 10;
int num2 = 20;
int sum = add(num1,num2);//调用时实际传递的参数,实参

System.out.println("两个数的和"+ sum);

printInfo();
printInfo();
printInfo();//可以多次调用
}

//两个数求和
public static int add(int n1,int n2/*形参*/){
//定义新的变量 计算
int sum = n1 + n2;
return sum;//返回sum
}

//打印公司信息
//这类情况比较特殊,没有形参,也没有返回值
public static void printInfo(){
System.out.println("玲珑山车神");
}
}

方法的修饰符

可见性修饰符:

public—在所有类中可见,在其他包中可以用import导入。
缺省—就是没有修饰符,在同一个包中的类中可见,在其他包中不能用import导入。

修饰符:

final—终态类,表示该类不能被继承
abstract—抽象类,不能新建对象

方法调用过程

首先我们有一个叫栈的空间

image-20241008091615217

最初始的情况他是空的
然后看上面的示例代码,当我们执行到main方法(main方法是程序的入口)的时候
栈空间内部出现一个关于main方法的栈帧。(stack frame)

image-20241008091705727

每一个栈帧里面都包含main方法相关的信息
生成一个局部变量表,把上文main方法中的局部变量都放到表内

image-20241008092330712

当程序执行到int sum的时候,这里就需要调用一个新的add方法
开辟一个新的栈帧

image-20241008092431525

然后生成新的局部变量表
image-20241008092505469

调用函数的时候,把需要的局部变量的值传递进来。

image-20241011093324455

当调用printInfo()的时候,也同样会生成printInfo()的栈帧。 image-20241011093820561

打印完了之后直接车从栈里面出去 出栈
同时main方法执行完毕,main方法也出栈
然后栈就空了,然后整个程序结束执行。

方法的重载

overload

方法的重载,指的是一个类中可以定义多个方法名相同,但参数不同的方法。调用时会根据不同的参数自动匹配对应的方法。

image-20241012075559653

image-20241012075633825

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package Y24M10D11;
/*测试方法的重载*/
public class Test004 {
public static void main(String[] args) {
System.out.println(add(100.25,100));
System.out.println(add(100,100));
System.out.println(add(100,100,100));
System.out.println(add(100,100.25));


}
public static int add(int n1 , int n2){
int sum = n1 + n2;
return sum;
}

//方法名相同,参数类型不同,构成重载。
public static double add(double n1,int n2){
double sum = n1+n2;
return sum;
}
public static int add(int n1 , int n2, int n3){
int sum = n1 + n2 + n3;
return sum;
}

//方法名相同,参数顺序不同,构成重载
public static double add(int n1 , double n2){
double sum = n1+n2;
return sum;
}

/*只有返回值不同不构成重载,会报编译错误*/
// public static void add(int n1 , double n2){
// double sum = n1+n2;
// return sum;
// }
/*只有形参名字不一样,同样不构成重载,因为不知道调用的是哪一个*/
// public static double add(int m1 , double m2){
// double sum = m1+m2;
// return sum;
// }

}

面向对象

类的基本元素

image-20241013202627105

属性

image-20241013203352570

初始化

初始化就是赋一个默认值给这个成员变量,详见下面的成员变量的默认值

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package Y24M10D13;
/*建立一个学生类用来表示学生的信息*/
public class Student {
/*静态特征(数据),作为学生需要拥有的一些元素*/
int id;
String name;
int score;
int age;

/*方法(动态行为)(对数据的操作)*/
public void study(){
System.out.println(name + "is Studying" );
}
/*面向对象编程的好处就是把相关的数据和对他的操作全部都放在一起
* 这样去调用和定义的时候会非常方便*/
}

成员变量的默认值

image-20241013203930595

规则:对于数字 可以是0的都赋值为0,对于字符 赋值\u0000 本质也是0
对于布尔默认是 false 占一个字节 实际上也是0
引用类型: 从现在面向对象开始讲解的新的类型 自定义的类型 都是引用类型。
比如上文定义的student 就是一个引用类型

类和对象的关系

什么是对象?万物皆对象,在JAVA中,对象就是一类数据的实例化,他们有着一种或几种的相同特征。

image-20241013204949141

个人理解:用之前使用的过的写过的代码举例就是,比如说定义了 一个int类型的数据a1
那么就是存在一个a1,这个a1就是对象,属于的类是int类
比如说上文建立了一个student 的类之后,我再输入下面的语句

1
2
3
4
public static void main(String[] args) {
/*在main方里面去使用上面的内容*/
Student stu1 = new Student();
}

就是创建了一个新的对象 这个对象的名字叫stu1 属于student的类
同时他也是所谓的引用类型变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package Y24M10D13;
/**/
public class BaizhanStudent {
/*定义一个练习用的student类*/
int id;
String sname;
int age;
/*假设每个学生都需要一台电脑,
所以这里给每个学生加了一个电脑属性*/
Computer computer;

void study(){/*这里定义方法没有写修饰符,默认是公共抽象的,具体后面展开*/
System.out.println("我正在使用:"+ computer.brand+"学习");
}
/*关于修饰符*/


public static void main(String[] args) {
Computer c1 = new Computer();//这些new的本质是构造方法,这个后期再讲。
c1.brand = "lenovo";
c1.price = 6000;
Computer c2 = new Computer();
c2.brand = "Republic of Gamers";
c2.price = 9000;
Computer c3 = new Computer();
c3.brand = "alienware";
c3.price = 10000;
/*定义computer*/

/*定义baizhanstudent*/
BaizhanStudent stu01 = new BaizhanStudent();
stu01.id = 1001;
stu01.sname = "疯狂小扬哥";
stu01.age = 18;
stu01.computer = c1;

stu01.study();
}
}
package Y24M10D13;
/*这是对于computer整个类的定义*/
public class Computer {
/*定义电脑类的两个属性,品牌和价格*/
String brand;
int price;




}

以上是这段的示例代码,以下来讲述底层内存中的变化
首先内存中有栈和堆
image-20241014072610824

当我们启动哦那这个类进行运算的时候。 内存中首先会做类的加载动作。
双引号中的内容,会被优先做处理,在堆中生成。
image-20241014072706630

然后开始执行main方法,生成栈帧和局部变量表,其中c1 c2 stu1这些都是引用类型(四字节)
image-20241014072844614image-20241014072954550

然后创建一个computer对象,并给他的两个属性赋默认值。

image-20241014073750285

然后这个对象会有一个地址 例0x11(0x代表16进制)这个数我随便写的,无特殊含义
也可以用十进制写个2345 反正就是一个标记,告诉我们这个对象的地址是多少。
然后这里对象就建立完成了,建立完成了之后会把这个值个给c1,也就是那个0x11
image-20241014074129456

同时这也就意味着,c1这个变量指向了这个对象。
这个时候就可以通过c1找到这个对象。
这时候就可以通过C1找到这个对象。
因为他引用了这个对象的地址。
然后再看下一步c1.brand = 联想
假设这里给联想一个虚拟的值0x88
然后堆中相当于c1.brand = 0x88
image-20241014074730375

也就是c1.brand引用了0x88,然后c1.price 重新赋值=6000
因为c1.price是基本数据类型,基本数据类型是直接赋值给他,引用数据类型才是给地址。

image-20241014074826036

c2h和stu1的定义过程也是同理,这里就不赘述了,直接上结果

image-20241014075459180

注意 堆内存中的数据不会清除。因为不确定之后是否还会要被调用

构造方法constructor

image-20241015084635560

构造器的定义

image-20241015085112631

构造器 的四个要点

image-20241017193612797

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package Y24M10D17;
/*
* 描述二维空间中的一个点
* */
public class Point {
double x;
double y;
//构造器一定返回point对象所以没必要再声明返回值类型
public Point(double _x,double _y){//这个就是构造器
x = _x;
y = _y;
}
public static void main(String[] args) {
Point p1 = new Point(3.0,4);/*这个后面的括号没东西因为是无参的构造器
当构造器里面加入了参数之后,就变成了有参的构造器,这里就会报错*/
/*在之前还没有学习构造器的时候,baizhanstudent的时候
* 也可以自动newStudent类,是因为java的编译器
* 自动帮助我们添加了 无参构造器。*/
System.out.println(p1.x);

}
/*构造方法的核心作用:初始化对象*/

}

创建对象的步骤

image-20241017212316194

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package Y24M10D17;
/*模拟网站的账户(用于测试构造方法发的重载*/
public class User {
int id;
String uname;
String pwd;
/*以上是用户名和密码*/
User(){
}
public User(int _id){//这里定义了一个构造器 _id是里面的形参
id = _id;//这里给id赋值_id
}
/*同名的构造器方法,但是参数不一样*/
public User(int _id,String _uname, String _pwd){
id = _id;
uname = _uname;
pwd = _pwd;
}
public static void main(String[] args) {
User u1 = new User();
User u2 = new User(1001);
User u3 = new User(1001,"13"123456);
}
}

构造方法的重载

image-20241017212316194

内存 栈 和 堆

java虚拟机完整的内存模型

image-20241017214816354

简化模型

image-20241017214937026

栈的特点

1、栈描述的是方法执行的内部模型。每个方法被调用都会船舰一个栈帧(存储局部变量、操作数、方法出口等)
2、栈的存储特性是“线进后出,后进先出”
3、栈是由系统自动分配,速度快!栈是一个联系的内存空间!
其他特性:
4、JVM为每个线程出啊昂建一个栈,用于存放改线程执行方法的信息(实际参数、局部变量等)
5、栈属于线程私有,不能实现线程之间的共享

image-20241018195717248

如同上面的方法,假设main方法中调用了另一个A方法,那么在mian方法上面加入那个调用的A方法的栈帧A
然后假设A方法又调用了一个B方法,那么在A方法的上面再加入一个B方法的栈帧B
然后最后加入的栈帧B方法执行完了之后最先离开栈帧,然后A方法执行完了之后再离开栈帧,最后是main方法
也就是说越早调用的越晚离开。

堆的特点

1、堆用于存储创建好的对象和数组(数组也是对象)
2、堆是一个不连续的内存空间,分配灵活,速度慢!
3、JVM只有一个堆,被所有线程共享。

image-20241018200537074

方法区

1、方法区是JAVA虚拟机规范,可以有不同的实现。(比如JDK8是“元数据空间”和堆结合起来
2、方法区实际上也是堆,只是用于存储类、常量相关的信息!
3、用来存放程序中永远是不变或者唯一的内容。(类信息【class对象,放射机制中会重点讲授】、静态变量、字符串常量等)
4、JVM只有一个方法区,被所有线程共享!

image-20241017221125546

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package Y24M10D17;
public class Person {
String name;
int age;
//这是定义类里面的元素
public void show(){
System.out.println("姓名:"+ name + "\t年龄:"+age);
}
Person(String _name,int _age){
name = _name;
age = _age;
}
Person(){
}
public static void main(String[] args){
Person p1 = new Person();
p1.age = 24;
p1.name = "张三";
p1.show();

Person p2 = new Person("李四",30);
p2.show();
}
}

当执行这段代码的时候
首先 在堆内存中的方法区生成这个person 类
然后固定的字符串也一起存储在方法区

image-20241018204603943

然后在栈中生成main方法的栈帧
然后执行person p1的时候,现在栈帧中生成p1,但是此时p1的值为null,
然后执行后半句的时候

image-20241018204918572

执行后半句的时候,调用构造器,在堆中创建person的对象,然后把地址返回给p1(假设地址为0x23)

image-20241018205832177

此时栈帧中储存的p1 也就有了值(地址)
image-20241018205953095

然后执行接下来的语句,把堆内存中的p1对象(0x23对象)中的age赋值24,在吧name的值改为张三的地址

image-20241018210111493

然后再往下调用show方法打印
image-20241018210440169

执行完了show方法之后直接出栈
P2的过程也是同理

this 的本质

this的本质就是”当前对象的地址!”
普通方法中,this总是指向调用该方法的对象
构造方法中,this总是只想正要初始化的对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package Y24M10D19;
/*this 关键字的本质
* this的用法测试*/
public class User {
int id;
String name;
String pwd;

public User(){
}

public User(int id,String name){
System.out.println("正在要初始化的对象:"+ this);//这里实际输出的就是地址
this.id = id;
// 将形参 id 的值赋给实例变量 id
/*所以这个代码里面this的意思就是形参的值
* 具体意思就是形参的值=什么*/
this.name =name;
}
public User(int id,String name,String pwd){
this(id, name);//调用重载的构造器,这种调用必须位于构造方法的第一行
this.pwd = pwd;
System.out.println("正在要初始化的对象:"+ this);//这里实际输出的就是地址

}
public void login(){
System.out.println("要登陆:"+this.name+",密码:"+this.pwd);
}

public static void main(String[] args) {
User u1 = new User(101,"薯片");
u1.login();
User u2 = new User(102,"薯条","123");
u2.login();
}
}

static的本质

static关键字核心用法:
用static声明的变量为静态成员变量,也成为类变量
1、重属于类,只有一份,在类被载入时被显式初始化。
2、一般用“类名.属性/方法”来调用
3、在static方法中不可直接访问非static的成员

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package Y24M10D19;
/*测试static的用法*/
public class TestStatic {
int id;
static String company = "薯片责任有限公司";
static int companyId = 0;

static {
System.out.println("类被初始化的调用");
companyId = 111222;
}
/*类型: 这不是方法,也不是构造器,而是 静态初始化块(Static Initialization Block)。
作用: 在类被加载到 JVM 时执行。它可以用于初始化静态变量或执行一些一次性的操作。在这个例子中,它打印一条消息并将 companyId 设置为 111222。
特点:
只会在类加载时执行一次,适合进行静态变量的初始化。
可以包含多个静态初始化块,它们的执行顺序是从上到下的。*/
static void printCompany(){
System.out.println("公司信息"+company);
}
/*在static里面不能使用非static的成员*/
void login(){
System.out.println("登录");
}

public static void main(String[] args) {
TestStatic.printCompany();


TestStatic t1 = new TestStatic();
t1.login();
TestStatic t2 = new TestStatic();
t2.login();

}

}

继承

image-20241231203130532

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package Y24M12D31;


class Person
{
String name = "A";
int height;

public void rest()
{
System.out.println("rest");
}
}

class Student extends Person
{


String major;

public void study()
{
System.out.println(this.name+" is study");
}
public Student(String name,int height,String major)
{
this.name = name;
this.height =height;
this.major = major;
}
}

public class Test001 {
public static void main(String[] args) {
Student s1 = new Student("jack",180,"math");
s1.study();
s1.rest();
}
}

image-20241231203837050

重写

image-20241231203955030

image-20241231204101634

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package Y24M12D31;

class Vehicle
{
public void run()
{
System.out.println("run");
}
public void stop()
{
System.out.println("stop");
}
}

class Horse extends Vehicle
{
@Override
public void run()
{
System.out.println("马在跑");
}
@Override
public void stop()
{
System.out.println("马停了");
}

}

class aircraft extends Vehicle
{
@Override
public void run()
{
System.out.println("飞机在飞");
}
@Override
public void stop()
{
System.out.println("降落了");
}
}

public class Test002 {
public static void main(String[] args) {
Horse h1 = new Horse();
h1.run();
h1.stop();

aircraft a1 = new aircraft();
a1.run();
a1.stop();

}
}

final关键字

image-20241231204454150

类似c++中的const

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package Y24M12D31;

/*final用法*/

class Base
{
public void func()
{
System.out.println("Base func()");
}

public final void func2()
{
System.out.println( "base func02()");
}
}

class Son extends Base
{
/*正常继承*/
@Override
public void func()
{
System.out.println("sons base func");
}/*正常重写*/
// @Override
// public void func2()
// {
// System.out.println("son base func2");
// }
/*报错 final修饰无法重写
* 整个概念类似常函数*/

}


final class Base02
{

}
/*下面的语句报错 说明用final修饰的class 不能被继承*/
//class Son02 extends Base02
//{}


public class Test003 {
public static void main(String[] args) {

final int maxSpeed = 120;
/*maxSpeed = 100;
* 报错 final修饰之后变成常量 只能赋值一次*/
}


}

封装

image-20241231205821634

image-20241231205853835

image-20241231205910445

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package Y24M12D31.a;
/*同一个包中的*/
public class BYD extends Car{

void test()
{
// super.check();
/*编译不通过 无法调用私有的*/
super.addOil();/*同一个包中可以访问default*/
super.autoLighten();/*子类不管怎么样都可以访问父类的*/
super.run();/*任何类都能访问public*/
}


}
package Y24M12D31.a;

public class Car {
int id;
String brand;

private void check()
{
System.out.println("Car_check");
}

void addOil()
{
System.out.println("car.addoil");
}
protected void autoLighten()
{
System.out.println("car.autoLighten");
}

public void run()
{
System.out.println( "car.run");
}
}
package Y24M12D31.b;

import Y24M12D31.a.Car;

public class Testla extends Car {
void test()
{
//super.addoil();/*不同的包不可以访问default*/
super.autoLighten();
super.run();/*任何类都能访问public*/

}
}

image-20241231211205096

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package Y24M12D31;

public class User {
private int id;
private String name;
private String pwd;
private boolean admin;

public boolean isAdmin()
{
return admin;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getPwd() {
return pwd;
}

public void setPwd(String pwd) {
this.pwd = pwd;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}



public void login()
{
System.out.println("Userlogin");
}
}



package Y24M12D31;

public class Test004 {
public static void main(String[] args) {
User u1 = new User();
u1.setId(100);
System.out.println(u1.getId());
}
}

多态

image-20241231212028332

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package Y24M12D30;


public class Test001 {
public static void main(String[] args) {
Dog d1 = new Dog();
AnimalCry(d1);

}
static void AnimalCry(Animal a1)
{
a1.shout();
}

}

package Y24M12D30;
import Y24M12D30.Animal;

public class Animal
{
public void shout()
{
System.out.println("动物叫");
}
}

class Dog extends Animal {
@Override
public void shout()
{
System.out.println("汪汪汪");
}
}

class Cat extends Animal
{
@Override
public void shout()
{
System.out.println("喵喵");
}
}

抽象方法和抽象类

image-20241231220838611

在类中的方法前面加上abstract变成抽象方法,只要有了一个抽象方法这个类必须定义成抽象类
类定义的前面也要加上abstract,这个类中还可以有其他不抽象的方法,然后在他的子类中
必须要实现他的抽象方法,否则编译不通过,或者也会当成抽象类。
抽象类无法实例化对象,也就是说new不出来新的这个类的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package Y24M12D30;
import Y24M12D30.Animal;

/*抽象类*/
public abstract class Animal
{
/*抽象方法*/
public abstract void shout()

public void sleep()
{
System.out.println("sleep");
}

}

class Dog extends Animal {
@Override
public void shout()
{
System.out.println("汪汪汪");
}
}

class Cat extends Animal
{
@Override
public void shout()
{
System.out.println("喵喵");
}
}

image-20241231221742904

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package Y24M12D31;
/*接口*/
public class Test007 {
public static void main(String[] args) {
Angel a1 = new Angel();
/*这里可以用接口类型 但是用接口类型就调用不了剩下的一个方法*/
a1.fly();
a1.helpOthers();
}
}


/*飞行接口*/
interface Volant
{
int h = 100;
/*public static final*/

/*public abstract void fly()*/
void fly();
}
interface Honest
{
void helpOthers();
}

class Angel implements Volant,Honest
{

@Override
public void helpOthers() {
System.out.println("帮助他人");
}

@Override
public void fly() {
System.out.println("起飞");
}
}

数组和算法

一维数组

image-20241017181748938

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package Y24M10D19;
/*测试static的用法*/
public class TestStatic {
int id;
static String company = "薯片责任有限公司";
static int companyId = 0;

static {
System.out.println("类被初始化的调用");
companyId = 111222;
}
/*类型: 这不是方法,也不是构造器,而是 静态初始化块(Static Initialization Block)。
作用: 在类被加载到 JVM 时执行。它可以用于初始化静态变量或执行一些一次性的操作。在这个例子中,它打印一条消息并将 companyId 设置为 111222。
特点:
只会在类加载时执行一次,适合进行静态变量的初始化。
可以包含多个静态初始化块,它们的执行顺序是从上到下的。*/
static void printCompany(){
System.out.println("公司信息"+company);
}
/*在static里面不能使用非static的成员*/
void login(){
System.out.println("登录");
}

public static void main(String[] args) {
TestStatic.printCompany();


TestStatic t1 = new TestStatic();
t1.login();
TestStatic t2 = new TestStatic();
t2.login();

}

}

二维数组

image-20241231225912123

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package Y24M12D31;

import java.util.Arrays;

public class Test009 {
public static void main(String[] args) {
int[] [] a = new int[3][];
a[0] = new int[2];
a[1] = new int[4];
a[2] = new int[3];

a[0][0] = 10;
a[0][1] = 20;
a[1] = new int[]{10,20,30,40};
a[2] = new int[]{10,20,30};

int[][] b = {
{10,20,30},
{10,20},
{100,200,300,400}
};

for(int i = 0;i<b.length;i++)
{
for (int m=0;m<b[i].length;m++)
{
System.out.print(b[i][m]+"\t");
}
System.out.println();
}
for (int i=0;i<b.length;i++)
{
System.out.println(Arrays.toString(b[i]));
}
}
}

package和import

image-20241020225023951

排序算法

冒泡排序

不断做两两比较,可以从前往后,也可以从后往前,如果从前往后,那就是不断两两比较,如果大的就放到后面,第一轮结束之后可以找出最大的。
image-20241018085343879

第一轮开始之前是这样

image-20241018085353904

第一轮结束之后就是这样

image-20241018085432409

最后的结果

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package Y24M12D31;

/*测试冒泡排序*/

public class Test010 {
public static void main(String[] args) {
int[] values = {3,1,2,7,6,5,0,9,4,8};
for (int tempo:values)
{
System.out.print(tempo);
}
System.out.println();

for (int i = 0; i<values.length;i++)
{
for (int j = 0; j<values.length-i-1;j++)
{
int tempo = 0;
if (values[j]>values[j+1])
{
tempo = values[j];
values[j] = values[j+1];
values[j+1] = tempo;
}
}
}
for (int tempo:values)
{
System.out.print(tempo);
}
System.out.println();


}
}

选择排序

原理:每轮选择当前位置,开始找出后面的较小值与该位置交换
当前位置以此跟后面的比较,只要比他小的就交换

image-20241231233009550

总共需要确定的轮数:数组长度-1
每一轮确定一个元素,下一轮减少一个个元素参与

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package Y24M12D31;

import java.util.Arrays;

public class Test011 {
public static void main(String[] args) {
int[] arr = {5,1,3,2};
System.out.println(Arrays.toString(arr));

/*选择排序*/
for(int i = 0;i<arr.length;i++)/*比较的轮数*/
{/*当前元素之后的所有元素索引*/
for (int j=i+1;j<arr.length;j++)
{/*arr[i]是当前需要比的元素 找的位置*/
if (arr[i] >arr[j])
{
int temp= arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}

System.out.println(Arrays.toString(arr));

}
}

二分查找

前提条件:数组中的数据必须是有序的
核心思想:每次排除一半的数据,查询数据的性能明显提高极多

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package Y24M12D31;

public class Test012 {
public static void main(String[] args) {

int[]arr = {1,2,3,4,5,6,7,8,9,10,100,200,300,400};
System.out.println(arr[binSearch(arr,6)]);


}
/*接受数组和要查找的数据,返回的是索引*/
public static int binSearch(int[] arr,int number)
{/*查找范围,起始索引*/
int left = 0;
/*查找范围,结束索引*/
int right = arr.length-1;

while(left <= right)
{/*判断条件 元素存在 可以查找*/
int mid = (left+right)/2;

if (arr[mid]==number)
{
return mid;
}else if(arr[mid]>number)
{
right = mid -1;
} else if (arr[mid]<number) {
left = mid +1;
}
}

/*代码走到此处 说明查找元素不存在*/
return -1;

}
}

课堂题目