重学java第一阶段(上)

day1

1.了解Java

2.掌握JDK安装和环境变量的配置

3.理解Java代码的执行流程

4.使用notepad++书写第一个Java代码

1.什么是Java

Java是一门编程语言

思考问题:

​ 人和人沟通?

​ 中文 英文

​ 人和计算机沟通?

​ 计算机语言: C C++ C# php python

2. Java诞生

前身叫Oak(橡树)

目前最流行的版本还是JDK8

3.Java三大平台体系

JavaSE(J2SE):

​ 标准版:各个应用平台的基础

JavaEE(J2EE):

​ 企业版:为企业的环境进行开发的

JavaME(J2ME):

​ 微型版:致力于嵌入式开发

4.Java是跨平台的

Java源代码(你写的这个代码)-》编译-》字节码文件的-》运行(JDK中执行的)-》安装在不同的系统中

5.JDK开发环境的搭建和配置【重点】

5.1几个概念

JVM: Java虚拟机

jre:Java运行环境

jdk:Java开发工具

jdk里面包含了jvm和jre

5.2jdk的安装0

打开JDK安装包直接下一步下一步即可,关闭一下即可

5.3配置jdk的环境变量

为啥要配置环境变量?

1

2

3

4

5

6

一直确定下去即可

开始配置jre环境变量

8

9

10

11

一直确定下去即可

1
2
3
4
5
6
7
8
9
配置好以后开始验证:
打开黑屏终端: wind + r 输入 cmd 点击确定
输入第一个命令:
java -version
输入第二个命令:
java
输入第三个命令:
javac

回顾

1
jdk安装和环境变量的配置

6.Dos命令

依靠cmd打开窗口

wind + R

输入命令即可

6.1dir

展示当前目录下面的所有的文件和文件夹

12

6.2cd 路径

目录的切换

cd ../ 切换到上一级目录

cd 路径 切换这个路径

13

6.3mkdir

在指定的文件夹下面创建文件夹

14

6.4切换盘符

直接命令行中写盘符即可

15

6.5rd

删除指定的目录(文件夹)

16

6.6del

删除指定的文件

17

注意:是直接删除的,不是放到回收站

6.7cls

清屏

7.使用notepad++编写第一个Java代码

7.1打开文件的后缀(文件的扩展名)

wind11: 随便打开一个文件夹 查看-》显示-》文件扩展名 勾选即可

wind10:先打开一个文件夹 查看-》文件扩展名 勾选即可

wind7: 先打开一个文件夹,组织-》文件夹及搜索选项-》查看-》隐藏已知的扩展名 不勾选

7.2编写第一个Java代码,使用工具notepad++

步骤:

1.在某一个文件夹下面新建了一个叫Hello.java的文件

2.使用工具 notepad++打开当前的Java文件

3.书写一个关键字class 关键字以后跟着的是类名,类名和文件名字要保持一致的

类名的后面跟一个大括号 是成对的

4.在 大括号里面写main主函数,这个很重要 是程序的入口,没有他代码是不能执行的。

1
2
3
public static void main (String[] args) {

}

5.在main主函数中大括号中写一个输出语句即可

1
System.out.println("hello Java");

6.开始使用dos命令进行编译运行

1
2
3
首先得找到文件所在的目录
然后使用javac Java文件 -》进行编译
再然后使用 java 类名 -》运行Java类
1
2
3
4
5
class Hello {
public static void main (String[] args) {
System.out.println("hello Java");
}
}

7.3对第一个Java代码的简单介绍

1
2
3
4
5
class Hello {
public static void main (String[] args) {
System.out.println("hello Java");
}
}

class: 类

public: 公开的 公共的

static: 静态的

void: 空的

main:主要的 重要的 没有这个就无法执行下面的代码

String:字符串 就是用双引号 引起来的 就叫字符串 “abcdef”

[]:数组

args:参数

System:系统的

out:输出的意思

println:换行打印

print:打印

写的案例是不换行打印

1
2
3
4
5
6
7
class First {
public static void main (String args[]) {
System.out.print("abcd");
System.out.print("abcd");
System.out.print("abcd");
}
}

7.4针对于中文乱码的解决方案

18

打开notepad++,找到编码,点击编码,找到转为ANSI编码即可,然后保存

重新编译,重新运行即可

总结:

1
2
3
4
5
1.你写的Java文件在哪,你自己要清楚在哪?为啥?找到
2.class后面跟的是类名, 类名和文件名字要保持一致。
3.一定要注意大小写 String System
4.大括号 小括号 中括号 都是成双成对的
5.都是英文半角符号

7.5Java中的注释

注释:注释的目的是为了解释一段代码的,不运行

一个成熟的程序员,注释肯定比你代码写的多

1.单行注释: // 注释的内容

2.多行注释 / * 注释的内容 */

3.文档注释:

1
2
3
4
/**
*注释的内容
*注释的内容
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
*这个是文档注释
这个是一个类
*
*/
class Third {
public static void main (String[] args) {
//这个是单行注释
/*
DSN
DJSJD
DJHSJK
DJSJJK
*/
System.out.println("ashjasj");
}
}

day2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1.dos命令
dir 显示当前文件夹下面的所有的文件和文件夹
cd 切换目录的
mkdir 创建文件夹的
rd 删除文件夹的
del 删除文件
D: 切换盘符
cls 清屏

2.书写Java代码换行打印《静夜诗》这首古诗
class Demo1 {
public static void main (String[] args) {
System.out.println("");
}
}
3.Java中的注释
三个:
单行注释 //
多行注释
文档注释
4.使用notepad++打印中文乱码怎么解决
找到notepad++编码按钮 点击转为ANSI编码

今天的内容

1.安装eclipse

2.数据存储的方式【了解】

3.常量【了解】

4.变量【重点】

5.运算符【重点】

1.eclipse的安装

Java的开发工具

将我发给大家的eclipse的安装包解压以后放到任意盘符下面,找到eclipse.exe文件双击运行即可

1

新建项目

File->new->project->java project->next

设置eclipse的字体的大小

1

eclipse设置自动补全

4

练习:

1
使用eclipse创建Java工程,并打印一个古诗词望庐山瀑布

2.数据存储的方式【了解】

2.1数据的存储的基本单位【了解】

计算机存储的最小的单位 是字节(byte)

1024 byte = 1KB

1024 KB = 1MB

1024MB = 1GB

1024GB = 1TB

1024TB = 1PB

1024PB = 1EB

2.2常见的进制单位【了解】

进制单位 基数范围 规则
二进制 0-1 逢2进1
八进制 0-7 逢8进1
十进制 0-9 逢10进1
十六进制 0-9 a-f 逢16进1
1
2
3
4
5
6
7
8
9
10
11
12
13
二进制:
0(0) 1(1) 2(10) 3(11) 4 (100) 5(101)...
八进制:
0 (0) 1(1)....7(7) 8(10) 9 (11) 10 (12) ...
十进制:
生活中都是十进制的 数学中都是十进制的
十六进制:
0(0) ....9(9) 10(a) 11(b)12 (c) ...15(f) 16(10)
进制之间的转换千万不要自己算:
1.使用计算器
2.Jav代码中封装的有方法来进行进制的转换
3.在线进制转换网站
很少使用,学会使用计算器

3.常量【了解】

生活中不可改变的叫常量

pi e 一天24小时 给大家说一下常量目的是为了印出来变量

按照生活习惯来说:

​ 常量可以分为哪些种类:

​ 整数: 7天 24小数

​ 小数: pi g e

​ 字符: ‘男’ ‘女’

​ 字符串: “那就回家睡觉”

​ 真假关系: true false

4.变量【重点】

必须会写变量,并且知道变量的一些细节

4.1生活中的变量

体重

工资

温度

x + y = 10

4.2java代码中的变量

定义:在程序运行过程中,可以改变的量叫变量。主要的目的是为了存储数据的

定义语法格式:

​ 数据类型 变量的名字 = 初始化的值;

​ 数据类型:其实就是对数据的分类

​ 变量的名字:自己定义的命名的

​ =:赋值号

​ 初始化的值:就是咱们存储的数据

​ Java中声明变量的时候,从右往左看。

​ int a = 10; 将10 赋值给变量a

​ 宾馆的房间-》变量

​ 房间的名字 -》变量名字

​ 入住的房间-》值

​ 房间的类型-》数据类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.qfedu.a_test;

public class Demo2 {
public static void main(String[] args) {
//数据类型 变量的名字 = 初始化的值;
int a = 10;//将10赋值给变量a了
//拿a去进行操作
System.out.println(a);//10
a = 20;//将20赋值给了 a
System.out.println(a);//20
//其他的声明方式,了解层次的
int b;//将变量的名字先定义出来。,然后再赋值
b = 20;
int c,d;//一次性定义两个变量

}

}

4.3数据类型【重点】

Java有八大基本数据类型:

整型: 4个 byte short int long

小数(浮点数): 2个 float double

字符: 1个 char

布尔类型: 1个 boolean

熟悉八大基本数据类型的关键字。!!!

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
package com.qfedu.a_test;

//类的首字母大写的
public class Demo3 {

public static void main(String[] args) {
//声明一个整型的变量 byte类型的数据
//数据类型 变量名字 = 初始化的值;
byte b = 12;
System.out.println(b);
//声明一个整型的变量 short 类型的数据
short s = 67;
System.out.println(s);
//声明一个整型的变量 int 类型的数据
int i = 89;
System.out.println(i);
//声明一个整型的变量 long 类型的数据
long l = 89;
System.out.println(l);
//声明一个浮点(小数)类型的数据 float类型
float f1 = 89.9f;
System.out.println(f1);
//声明一个字符类型的数据,使用的单引号,而且单引号里面只能有一个元素

char c1 = '狗';
System.out.println(c1);
//声明一个布尔类型的数据,只有两个值 true false

boolean b1 = true;
System.out.println(b1);

}
}

4.4整型类型的数据

整型 数据范围 占用内存的字节
byte -128~127 1字节
short -32768~32767 2字节
int【Java中默认的整型的数据类型】 -2^31~2^31-1 4字节
long -2^63~2^63-1 8字节

注意事项:

1
声明long类型数据的时候,后面需要加L或者l

总结:

1
开发中只用int,  byte 和long 用的不多。  short  压根就不用

4.5浮点类型的数据

数据类型 数据范围 占用的字节数
float -3.4* 10^38~ 3.4*10^38 4字节
double(Java默认的是double类型的数据) -1.79*10^308 ~ 1.79 * 10^308 8字节

注意事项:

1
2
3
1.声明float类型的数据的时候加f或者F
2.double类型的数据的有效位数 15~16
3.float类型的数据有效位数是 6~7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.qfedu.a_test;

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

//double类型的数据
double d1 = 3.4;
System.out.println(d1);
//在声明float类型的数据的时候一定加f或者F
float f1 = 4.5f;
//double类型的数据 有效位数 是15-16位
double d2 = 82.121212121212122622;
System.out.println(d2);
double d3 = 4.352356789213451212;
System.out.println(d3);
//float类型的有效的位数6-7位
float f2 = 8.272802111238383f;
System.out.println(f2);
}

}

4.6字符类型

数据类型 数据范围 占用的字节数
char 除了\ 都可以当成一个字符 不定的

注意事项:

声明char类型的数据的时候,使用单引号声明。并且单引号里面只能放一个元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.qfedu.a_test;

public class Demo6 {
public static void main(String[] args) {
char c1 = 'a';
System.out.println(c1);
char c2 = '3';
char c3 = '中';
char c4 = '&';
//\是转义字符 不能当成一个字符来看
//char c5 = '\';
}

}

4.7布尔类型

数据类型 数据范围 占用字节数
boolean true或者false 1字节
1
2
3
4
5
//声明一个布尔类型的数据
boolean b1 = true;
System.out.println(b1);//true
boolean b2 = false;
System.out.println(b2);//false

总结:

1
2
3
4
5
6
int类型
char类型
boolean类型
double 类型
会声明这四种数据类型,就证明你今天已经学会了
数据类型 变量名字 = 初始化的值;

4.8变量的名字命名规范【默写的】

命名规范:

​ 在真实的开发中,对接口,抽象类,类,变量,方法等会有一定命名规范

4.8.1类名的命名规范

1.首字母要大写

2.以数字,字母,_,等命名,但是数字不能开头

3.采用大驼峰的命名规则,当一个类由两个单词组成的这两个单词的首字母要大写的

​ HelloWorld

4.8.2变量的命名规范

1.首字母小写

2.以数字,字母,_,等组成,但是数字不能开头

3.采用小驼峰命名规则,当一个变量由两个单词组成的时候,后面的单词要大写

​ 或者采用多个单词中间使用下划线进行拼接的一种写法

​ int userAge = 23;

4.命名见名知意

​ product_id product_name productName

5.已经被Java使用的关键字不能再作为变量的名字了

5.转义字符【重点】

目的:将无意义的字符转为有意义的字符或者将有意义的字符转为无意义的字符

语法格式:

​ \字符

​ 几个特殊的符号:(只能在字符串中使用)

​ \n:回车换行

​ \t:制表符 空格

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

public class Demo7 {
public static void main(String[] args) {
//打印一个字符类型的数据 '
//\'将'转为一个无意义的字符
System.out.println('\'');
//打印一个字符类型的\
System.out.println('\\');
//打印一个字符串 "
System.out.println("\"");
//打印一个字符串 \
System.out.println("\\");
//打印一个字符串 \\
System.out.println("\\\\");
//\n
System.out.println("巴萨不仅仅\n是今年是解决");
System.out.println("是南京南京\t叫撒解决");

}

}

6.运算符【重点】

1.算术运算符

2.关系运算符

3.逻辑运算符

6.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
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.qfedu.a_test;

public class Demo9 {
public static void main(String[] args) {
//加
int num1 = 20; //20赋值给num1
int num2 = 10;//将10 赋值给num2
//num1 = 20 + 10;
//num1是变量 可以变化的量

num1 = num1 + num2;
System.out.println(num1);//30
//减
int num3 = num1 - num2;
System.out.println(num3);//20
int a = 5;
int b = 3;
a = a * b;
System.out.println(b);//3
System.out.println(a);//15
//除
//注意 在Java中除法不能有小数点 取商整数
int c = 2;
c = b / c;//3/2
System.out.println(c);//1
//取余
int d = 6;
d = a % d;//15 % 6
System.out.println(d);//3
//先乘除后加减
//1 + 3 * 3
int e = c + d * b;
System.out.println(e);//10
//先算小括号里面的
int f = (c + d) * b;
System.out.println(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
package com.qfedu.a_test;

public class Demo10 {
public static void main(String[] args) {
int num1 = 10;
int num2 = 20;
//=要先看右边 将右边值赋值给左边
//num1 = num1 + num2;
//简写的情况
//num1 + num2 然后 在= 赋值 给谁啊 =左边的
//
num1 += num2;
System.out.println(num1);//30
int c;
c = num1 + num2;//不能简写
//以此类推 -= *= /= %= 都有
//num1 = num1 % num2;
num1 %= num2;
System.out.println(num1);//10

}

}

自增和自减

目的:一个变量自身加1或者减1

语法格式:

1
2
3
4
变量++; 先执行当前的操作,再自身加1
++变量;先自身加1,然后再执行当前的操作
变量--;先执行当前的操作,再自身减1
--变量;先减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 com.qfedu.a_test;

public class Demo11 {
public static void main(String[] args) {
int num1 = 10;
//num1++ 先执行当前的操作,再自身加1
System.out.println(num1++);//10
System.out.println(num1);//11
int num2 = 5;
//++num2 先自身加1 ,然后执行其他的操作
System.out.println(++num2);//6
System.out.println(num2);//6

int num4 = 3;
int ret = num4++ * num4;
System.out.println(ret);//12
System.out.println(num4);//4

int num5 = 2;
int ret1 = num5 * ++num5;
System.out.println(ret1);//6
System.out.println(num5);//3

}


}

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
作业1
int i = 3;
int a = -(i++);
sout(a);
sout(i);


int i = 5;
int a;
a = i++ + i++ + i++;
sout(a);
sout(i);

int a;
int i = 5;
a = ++i + (++i) + (i++) + (i++);
sout(a);
sout(i);

作业2:
从变量开始
你自己列一个纲要,看着纲要 然后自己去笔记补充完整, 不要看我的 笔记和代码,脑子里里面要装自己的东西
作业3:
预习视频第三天的东西

扩展:

声明一个字符串类型的数据

String不是基本数据类型, 是引用数据类型

语法格式:

1
String 变量名字 = "内容";
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.qfedu.a_test;

public class Demo8 {
public static void main(String[] args) {
//数据类型 变量名字 = 初始化的值;
String str = "一行白鹭上青天";
System.out.println(str);

//字符串拼接
String name1 = "老邢";
String name2 = "骚磊";
System.out.println(name1 + "爱" + name2);
int age = 89;
System.out.println(name1 + age);//老邢89
boolean b1 = true;
System.out.println(name2 + b1);//骚磊true
//一个字符串可以和任意的基本数据类型进行拼接
}

}

作业

1.变量的声明

​ 变量是用来临时保存数据的,该数据是可以变化的数据。

2.八大基本数据类型

​ 整形: byte, int, short, long

​ 布尔: boolean true, false

​ 字符型: char

​ 浮点数: double, float

3.变量的命名规范

​ 全部大写: 常量 如 PI

​ 大驼峰法 AaaBbbCcc 类和接口

​ 小驼峰法 aaaBbbCcc 变量

4.转义字符

​ \

5.运算符

​ 先乘除后加减

​ %是取余

​ 除法是取整

​ 自增自减 加(减)号在前,先自增后运算 否之相反

day3

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
1.八大基本数据类型
整型: byte short int long
浮点: float double
字符: char
布尔: boolean

2.声明整型和浮点和布尔类型的数据 一个变量
数据类型 变量名字 = 初始化的值;
int a = 234;
float f1 = 34.5f;
double d1 = 782.9;
boolean b1 = true;



3.变量名字的命名规范
1.首字母要小写
2.一般数字,字母,_组成的,但是数字不能开头
3.小驼峰的命名规则,或者使用_连接多个单词
4.见名知意
5.不能使用Java的关键字
4.++ 在变量的前面和后面有什么区别
++:在变量的后面,先执行当前的操作,然后再自身加1
++:在变量前面,先自身加1,然后再执行其他操作
5.算术运算符有哪些
+ - * / % += -= *= /= %= ++ --
6.转义字符
\字符: 将有意义的字符转为无意义的字符或者将无意义的字符转为有意义的字符

今天的内容

1.运算符

2.分支结构

1.运算符

1.算术运算符

2.关系运算符

3.逻辑运算符

1.1关系运算符

1
2
> (大于)  < (小于)   >= (大于等于)  <=(小于等于)  == (是否等于) !=(是否不等于)
使用关系运算符的结果是一个布尔类型的数据 boolean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.qfedu.a_test;

public class Demo1 {
//类体
public static void main(String[] args) {
boolean ret = 3 > 4;
System.out.println(ret);//false
boolean ret1 = (4 > 2);
System.out.println(ret1);//true
boolean ret2 = 4 >= 4;
System.out.println(ret2);//true
boolean ret3 = 5 != 8;
System.out.println(ret3);//true
boolean ret4 = 4 == 5;
System.out.println(ret4);//false

}
}

1.2逻辑运算符

返回值的结果也是一个布尔类型的数据

与 或 非

与:

​ &&

语法格式:

1
条件1 && 条件2  .....

条件就是咱们刚才讲的关系运算符的表达式

条件1 和条件2 都为true的时候,整体的结果就为true。

条件1和条件2只要有一个为false ,整体结果就为false。

逻辑与:

​ 取钱: 卡 和 密码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.qfedu.a_test;

public class Demo2 {

public static void main(String[] args) {
boolean ret1 = 3 > 4 && 5 < 6;
System.out.println(ret1);//false

boolean ret2 = (4 > 3) && (3 > 2);
System.out.println(ret2);//true

boolean ret3 = (7 > 4) && (5 > 2) && (7 >1);
System.out.println(ret3);//true

}
}

或:

​ ||

语法格式:

1
条件1 || 条件2 || .....

条件1和条件2 都为false的时候,才为false。如果一个条件为true,整体结果的就为true。

生活中的案例:

​ 你有一把钥匙 你媳妇一把钥匙。 你的一把丢了 还可以开门 因为你媳妇是true

​ 两个都丢了 两个都是false 整体就为false

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.qfedu.a_test;

public class Demo3 {
public static void main(String[] args) {
//false || true 整体的结果就为true
boolean ret1 = 3 > 4 || 5 > 3;
System.out.println(ret1);//true

boolean ret2 = 5 > 2 || 4 > 1 || 6 > 7;
System.out.println(ret2);//true

}

}

非:

​ !

语法格式:

1
!条件

条件是true,那么整体结果就为false。 条件为false ,整体结果就是true。、

犟 反着来

1
2
boolean ret3 = !(3 > 4);
System.out.println(ret3);//true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.qfedu.a_test;

public class Demo4 {
public static void main(String[] args) {
// true && (false || true)
boolean ret = (3 > 2) && ((4 > 5) || (5 > 2));
System.out.println(ret);//true
//false || true && false || false && false
//true && false|| false && false
//false || false && false
//false && false
//false
//!false
boolean ret1 = !((8 > 9) || (7 > 2) && (8 < 4) || (6 > 7) && (8 < 1));
System.out.println(ret1);//true

boolean ret2 = (8 > 9) || !((7 > 2) && (8 > 4)) && (10 > 1) || (9 < 4);
System.out.println(ret2);//false
}

}

1.3逻辑运算符的短路原则

逻辑与的短路原则:

​ 条件1 && 条件2 && 条件3……

​ 逻辑与只要一个为false整体就为false了。

​ 短路原则:只要碰到条件为false的话,后面的条件就不再执行了。

​ 比如 条件1为false了,那么条件2和条件3就不执行了。想通一个问题,条件1为false的话,整体结果已经确定下了,咱们的jvm会有自动的识别能力,为了提高代码的运行的效率

逻辑或的短路原则:

​ 条件1 || 条件2 || 条件3 ….

​ 逻辑与只要一个为true 就整体为true

​ 短路原则:只要条件为true的话,后面的条件就不再执行了。

​ 比如条件1为true,那么条件2和条件3就不执行了。

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
package com.qfedu.a_test;

public class Demo5 {
public static void main(String[] args) {
//逻辑与短路原则
int num = 10;
//false &&
boolean ret = (3 < 2) && (++num > 15) ;
System.out.println(ret);//false
System.out.println(num);//10

//逻辑或的短路原则
int num1 = 10;
boolean ret1 = (3 > 2) || (++num1 > 10);
System.out.println(ret1);//true
System.out.println(num1);//10

//
int num2 = 10;
//逻辑或在第一个的时候,如果条件1为true的话,后面的全部不执行了
//一般开发中要么单独使用逻辑与要么单独使用逻辑或,不然太复杂了
boolean ret2 = (3 > 2) || (++num2 > 15) && (3 > 2) && (++num2 > 20);
System.out.println(ret2);//true
System.out.println(num2);//10

}

}

可以自己百度一下Java位运算符

总结:

1
2
3
算术运算符
关系运算符
逻辑运算符

2.分支结构【重点】

先学习语法格式和执行流程

生活中的分支:就是一种选择

程序中的分支:也是一种选择

2.1if分支

语法格式:

1
2
3
if (表达式) {
语句体;
}

表达式:这个表达式的结果必须是一个布尔类型的数据

执行流程:

​ 如果代码走到if的时候,会先判断小括号里面表达式的结果。如果表达式的结果为true的话,就会执行大括号里面的语句体,如果表达式结果为false的话,就不执行大括号里面的语句体。代码往下继续执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.qfedu.a_test;

public class Demo6 {
public static void main(String[] args) {
int money = 10;
//只有通过关系运算符和逻辑运算符得到的结果才能是一个布尔类型的数据

if (money > 11) {
System.out.println("你是一个富豪,要请吃饭的。");
}
System.out.println("代码快结束了哦");
}

}

练习:用户名 111 密码 111 (int类型的数据) 使用if语句如果用户名和密码都对的话,打印一句话,登陆成功。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.qfedu.a_test;

public class Demo7 {
public static void main(String[] args) {
// int user = 111;
// int password = 111;
// if (user == 111 && password == 111) {
// System.out.println("登陆成功");
// }
String user = "admin";
String password = "123456";
if (user == "admin" && password == "123456") {
System.out.println("登陆成功");
}
System.out.println("执行代码");
}

}

2.2if-else分支

语法格式:

1
2
3
4
5
if (表达式) {
语句体1
} else {
语句体2
}

执行流程:首先判断b表达式,如果表达式为true的话,执行语句体1,如果为false的话,执行语句体2.两者不可兼得

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.qfedu.a_test;

public class Demo8 {
public static void main(String[] args) {
int money = 20;
if (money > 15) {
System.out.println("中午吃大盘鸡拌面");
} else {
System.out.println("中午吃泡面");
}
}

}

案例:判断一个年份是否是闰年。

注意:能被4整除,并且不能被100整除,或者能被400整除的年份

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.qfedu.a_test;

public class Demo9 {
public static void main(String[] args) {
//> 案例:判断一个年份是否是闰年。
//>
//> 注意:能被4整除,并且不能被100整除,或者能被400整除的年份
int year = 2100;
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
System.out.println("是闰年");
} else {
System.out.println("不是闰年");
}

}

}

2.3if-else的嵌套写法

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

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

int num = 10;
int num1 = 12;
//if之间相互嵌套
//10 > 8
if (num > 8) {
if (num1 > 20) {
System.out.println("num1 大于了20");
} else {
System.out.println("num1小于20");
}
} else {
System.out.println("num小于8");
}
}

}

今天上午

1
2
3
4
5
6
7
8
9
10
11
12
13
1.关系运算符
2.逻辑运算符
3.分支结构
if分支
if (表达式) {
语句体
}
if-else 分支
if (表达式) {
语句体1
} else {
语句体2
}

2.4if-else if 分支结构

语法格式:

1
2
3
4
5
6
7
8
9
10
11
if (表达式1) {
语句体1
} else if (表达式2) {
语句体2;
} else if (表达式3) {
语句体3
} else if (表达式4) {
语句体4
}else {
语句体n
}

执行流程:

​ 首先判断if后面的表达式1,如果表达式1为true,就执行当前大括号里面的语句体1,后面的代码就直接跳过了。如果表达式1为false,不执行语句体1,接着判断表达式2,如果为true,执行语句体2,以此类推。

总结:就是在判断表达式,一旦表达式为true的话,就执行当前的语句体,为false,就不执行的

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
package com.qfedu.a_test;

public class Demo11 {
public static void main(String[] args) {
/**
* 学生的成绩:
* 90-100:打印优秀
* 80-90:打印良好
* 70-80:打印一般
* 60-70:打印及格
* 60分以下:叫家长
*/
//if-else if
int score = 180;//声明了一个成绩变量
if (score > 100 || score < 0) {
System.out.println("您书写的成绩有误!!!");
//退出当前程序
System.exit(0);
}
if (score >= 90 && score <= 100) {
System.out.println("优秀");
} else if (score >= 80 ) {
System.out.println("良好");
} else if (score >= 70 ) {
System.out.println("一般");
} else if (score >= 60 ) {
System.out.println("及格");
} else {
System.out.println("叫家长");
}
}

}

案例:

​ 手机按键

如果你按的是1 打印给爸爸打电话

如果你按的是2 打印给妈妈打电话

如果你按的是3 打印给爷爷打电话

如果你按的是4 打印给奶奶打电话

如果你按的是其他的 报警

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

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

// ctrl + shift + ? 多行注释的快捷键
int num = 3;
if (num == 1) {
System.out.println("给爸爸打电话");
} else if (num == 2) {
System.out.println("给妈妈打电话");
} else if (num == 3) {
System.out.println("给爷爷打电话");
} else if (num == 4) {
System.out.println("给奶奶打电话");
} else {
System.out.println("报警");
}
}

}

2.5swicth-case结构

也是一种分支结构,只有满足条件的时候才会执行的

语法格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
switch (表达式) {
case 常量1:
语句体1;
break;
case 常量2:
语句体2;
break;
case 常量3:
语句体3;
break;
....
default:
语句体n;
break;
}

执行流程:switc后面的小括号里面的表达式的值,去匹配case后面的常量,如果匹配到就执行:后面的语句体。下面就不执行了。

手机按键

如果你按的是1 打印给爸爸打电话

如果你按的是2 打印给妈妈打电话

如果你按的是3 打印给爷爷打电话

如果你按的是4 打印给奶奶打电话

如果你按的是其他的 报警

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
package com.qfedu.a_test;

public class Demo15 {
public static void main(String[] args) {
int num = 1;
//主要是去看switch 后面小括号里面的值,这个值相当重要
//因为要去匹配下 面的case 后面的常量
switch (num) {
case 1:
System.out.println("给爸爸打电话");
break;//终止打断的意思
case 2:
System.out.println("给妈妈打电话");
break;//终止打断的意思
case 3:
System.out.println("给爷爷打电话");
break;//终止打断的意思
case 4:
System.out.println("给奶奶打电话");
break;//终止打断的意思
default:
System.out.println("报警");
break;
}
}
}

案例:

/**
* 学生的成绩:
* 90-100:打印优秀

    * 80-90:打印良好

     * 70-80:打印一般

     * 60-70:打印及格

     * 60分以下:叫家长
     */

     由于是swicth 表达式是一个值,所以得找规律

     90~100 规律    int score  = 98;  
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
package com.qfedu.a_test;

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

int score = 78;
switch (score / 10) {
case 10:
System.out.println("优秀");
break;
case 9:
System.out.println("优秀");
break;
case 8:
System.out.println("良好");
break;
case 7:
System.out.println("一般");
break;
case 6:
System.out.println("及格");
break;
default:
System.out.println("叫家长");
break;
}
}

}

重点:

1
2
3
4
5
swicth (表达式) {

}
表达式的值可以是什么数据类型的
int short byte char String 枚举
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 com.qfedu.a_test;

public class Demo17 {
public static void main(String[] args) {
//switch小括号里面是一个表达式
//这个表达式是一个具体的一个值
//那么就应该有对应的数据类型
//那么这个表达式的数据类型应该是啥?
//int short byte char
//String jdk1.8及以后的版本的
//枚举
//Cannot switch on a value of type long.
//Only convertible int values,
//strings or enum variables are permitted
//long num = 7;
char c = 'b';
String str = "中国";
switch (str) {
case "小日本":
System.out.println("细细打");
break;
case "漂亮国":
System.out.println("呵呵哒");
break;
case "中国":
System.out.println("哈哈哒");
break;
case "泡菜国":
System.out.println("今年夏季那是你");
break;
default:
break;
}
}

}

总结:

1
2
3
4
1.if
2.if- else
3.if-else if
4.swicth-case

作业:

1
2
3
4
1.将今天至少三遍  写注释写上自己的见解
2.向昨天一样,写一个大纲
3.等我给大家发一个文档 作业文档
明天抽查

扩展知识点

咱们现在声明变量的时候是如何声明的?

​ int a = 20;

直接对a进行赋值。

咱们还有一种方式对变量进行赋值。

通过控制台输入,然后交给代码中的某一个变量

1.导包

​ import java.util.Scanner;

2.创建Scanner对象

​ Scanner sc = new Scanner(System.in);
3.获取控制台中的数据

//3.将控制台的输入的数据 赋值给咱们代码的一个变量
    int a = sc.nextInt();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.qfedu.a_test;

//1.导包
import java.util.Scanner;

public class Demo13 {
public static void main(String[] args) {
//String str = "";
//2.获取Scanner对象
Scanner sc = new Scanner(System.in);
//3.将控制台的输入的数据 赋值给咱们代码的一个变量
int a = sc.nextInt();
System.out.println("您输入的是:" + a);
}

}

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 com.qfedu.a_test;

import java.util.Scanner;

public class Demo14 {

public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//获取控制台里面的int类型的数据
// int a = scanner.nextInt();
// System.out.println("输入的是:" + a);
//获取控制台里面float类型的数据
// float f1 = scanner.nextFloat();
// System.out.println("输入的是:" + f1);
//获取控制台里面double类型的数据
// double d1 = scanner.nextDouble();
// System.out.println("输入的是:" + d1);
//获取控制台里面boolean类型的数据
// boolean b1 = scanner.nextBoolean();
// System.out.println("输入的是:" + b1);
//);
//获取控制台里面String类型的数据
//String str = scanner.next();
// String str = scanner.nextLine();
// System.out.println(str);
//获取控制台里面char类型的数据
//字符是在字符串的基础之上再取单个的字符
char c1 = scanner.nextLine().charAt(2);
System.out.println(c1);
}
}

day4

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
1.jdk安装和环境变量地配置
2.使用notepad++书写第一个Java代码
class HelloWorld {
public static void main (String[] args) {

}
}
3.会使用eclipse新建咱们第一个Java工程
4.变量的语法格式
数据类型 变量名字 = c初始化的值;
int a = 20;
5.数据类型
八大基本数据类型
整型: byte short int long
开发使用int
浮点: float double
字符: char '\'
布尔: boolean

引用数据类型:
String 声明字符串类型的类型数据的 使用双引号
变量的命名规范:
1,首字母是要小写的
2.一般由数字,字母,_,$等组成的,但是不能以数字开头
3.一般使用小驼峰的命名规则,或者使用单词拼接下划线组成的
4.见名知意(英文)
5.不能使用Java的关键字

6.运算符
1.算术运算符
+ - * / % += -= *= /= %= ++ --
2.关系运算符
> < >= <= != ==
3.逻辑运算符
&& || !

逻辑运算符的短路原则

7.分支结构
if () {

}
if () {

} else {

}

if () {

} else if () {

} else if () {

} else {

}
switch () {
case 常量:
break;
default:

}
8.控制台输入
1.导包
improt java.util.Scanner;
2.创建Scanner对象
Scanner sc = new Scanner(System.in);
3.从控制台获取任意类型的数据
nextInt()
nextFloat()
nextDouble()
nextBoolean()
next() 字符串
nextLine()字符串
next().charAt(int index)

今天的内容

1.三目运算符

2.循环结构

1.三目运算符

开发用的很多。

语法格式:

1
数据类型  x = (表达式) ? value1 :  value2;

执行流程: 当表达式 为true的时候,将value1赋值给x。 当表达式为false的时候,将value2赋值给x

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

public class Demo1 {
public static void main(String[] args) {
int a = 30;
int c;
//如果a> 30的话, true,将250 赋值给c这个变量
//如果a > 30为false的话,将360赋值给c这个变量
c = a > 30 ? 250 : 360;
System.out.println(c);
if (a > 30) {
c = 250;
System.out.println(c);
} else {
c = 360;
System.out.println(c);
}

}

}

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
package com.qfedu.a_test;

import java.util.Scanner;

//输入一个整数,判断这个整数是大于0,还是小于0,还是等于0。
public class Demo2 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个整数:");
int a = scanner.nextInt();
// if (a > 0) {
// System.out.println("这个整数大于0");
// } else if (a < 0) {
// System.out.println("这个整数小于0");
// } else {
// System.out.println("这个整数等于0");
// }
//a > 0 是true的时候 直接将"这个整数大于0" 赋值给str
//a > 0是false的时候 又执行 a < 0 ? "这个整数小于0" : "这个整数等于0"; 又是一个三目运算符
//a < 0 是true的话,"这个整数小于0" 赋值给str 不然则
String str = a > 0 ? "这个整数大于0" : a < 0 ? "这个整数小于0" : "这个整数等于0";
System.out.println(str);
}

}

2.循环结构

2.1为啥会有循环结构

如果代码中出现了大量的重复的或者有规律的代码的话,使用cv大法

1.代码臃肿

2.阅读性差

3.维护性特别差

循环可以解决以上的问题:

​ 循环的三个条件:1.初始化条件 2.循环条件 3.终止条件

会讲三个循环: while 循环 do-while循环 for循环

2.2while循环

语法格式:

1
2
3
while (布尔表达式) {
循环体;
}

执行流程:当代码执行到while以后,会去判断while后面的布尔表达式,如果布尔表达式为true的话,会执行大括号后面的循环体这个代码。执行完以后,再次回到while关键,再去判断布尔表达式,如果布尔表达式为true的话,再次执行循环体。执行完以后,再次回到while关键,再次判断布尔表达式,直到布尔表达式为false的话,就结束循环,就不再执行循环体,也不会回到while关键字

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

public class Demo4 {
public static void main(String[] args) {
//打印3遍的hello
/**
* i = 0 0 < 3 true sout("hello") 打印第一个hello i++
* 1< 3 true sout("hello") 打印第二遍的hello i++
* 2< 3 true sout("hello") 打印第三遍的hello i++
* 3< 3 false 大括号里面的代码是不执行的,并且循环结束
* 所谓的循环结束就是不再执行while关键字
*/
int i = 0;//1.初始话的条件
while (i < 3) {//3.循环的终止条件i < 3
System.out.println("hello");
i++;//2.循环条件
}
System.out.println("嘻嘻哒");
}

}

案例:利用循环打印1 2 3 4 5

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

public class Demo5 {
public static void main(String[] args) {
//打印 1 2 3 4 5
int i = 1;
/**
* i=1 1<6 true sout(1) i++
* 2<6 true sout(2) i++
* 3<6 true sout(3) i++
* 4<6 true sout(4) i++
* 5<6 true sout(5) i++
* 6<6 false 循环结束
*/
while (i < 6) {
//刚好借助于变量i的值
System.out.println(i);
i++;
}
}

}

案例:输出100 99 98

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.qfedu.a_test;

public class Demo6 {
public static void main(String[] args) {
int num = 100;
/**
* num =100 100>97 true sout(100) num--
* 99>97 true sout(99) num--
* 98>97 true sout(98) num--
* 97>97 fasle循环终止
*/
while (num > 97) {
System.out.println(num);
num--;
}
}

}

案例:打印 1 3 5 7 9

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
package com.qfedu.a_test;

public class Demo7 {
public static void main(String[] args) {
//打印1 3 5 7
//思路:能不能先找到 1 2 3 4 5 6 7
//之后能不能在循环中写if语句进行哦判断输出
/**
* i = 1 1<8 true 1%2!=0 true sout(1) i++
* i=2 2<8 true 2%2!=0 false i++
* i=3 3<8 true 3%2!=0 true sout(3) i++
* i=4 4<8 true 4%2!=0 false i++
* i=5 5<8 true 5%2 !=0 true sout(5) i++
* i=6 6<8 ...... i++
* i=7 7< 8 true 7%2!=0 true sout(7)
*
*/
// int i = 1;
// while (i < 8) {
// if (i % 2 != 0) {
// System.out.println(i);
// }
// i++;
// }

/**
* i = 1 1< 8 true sout(1) i= i+ 2 i=1+2
* i=3 3<8 true sout(3) i=i+2 i=3+2
* i=5 5<8 true sout(5) i= i+2 i=5+2
* i=7 7<8 true sout(7) i=i+2 i=7+2
* i=9 9<8 false
*/
int i = 1;
while (i < 8) {
System.out.println(i);
//i = i + 2;//循环条件
i += 2;
}
}

}

案例:打印1-100以内的能被7整除的数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.qfedu.a_test;

public class Demo8 {
public static void main(String[] args) {
int i = 1;
while (i < 101) {
if (i % 7 == 0) {
System.out.println(i);
}
i++;
}
}

}

回顾上午的内容

1
2
3
4
5
6
7
1.三目运算符
数据类型 x = 表达式 ? value1 : value2;
2.while循环
while (布尔表达式) {
循环体
}

2.3do-while【几乎不用】

语法格式:

1
2
3
do {
语句体
} while (布尔表达式);

执行流程:代码 执行到do的时候,就会执行语句体,然后再判断while后面的布尔表达式。如果布尔表达式为false的话,循环结束了。如果布尔表达式为true的话,再次回到do去执行语句体。

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 com.qfedu.a_test;

public class Demo9 {

public static void main(String[] args) {
//打印3遍的晚上加班

/**
* i = 0 第一个打印sout("晚上加班") i++ 1<2 true
* 打印第二个sout("晚上加班") i++ 2<2 false
* 循环结束
*
*/
int i = 0;
do {
System.out.println("晚上加班");
//i++放在了 布尔表达式的前面
i++;
} while (i < 3);


}
}

while循环和do-while区别:

1
2
while循环先判断,如果为false,循环体不执行
do-while 循环 先执行一次,然后再判断表达式

2.4for循环【重点】

语法格式:

1
2
3
for (表达式1; 表达式2; 表达式3) {
循环体;
}

表达式1:初始化的条件

表达式2:终止条件

表达式3:循环条件

执行流程: 先执行表达式1,在去判断表达式2 是否为true,如果为true执行循环体。然后再执行表达式3。再次回到表达式2进行判断,如果为true,再执行循环体,然后再执行表达式3。再回到表达式2,如果为false。就直接结束循环。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.qfedu.a_test;

public class Demo10 {
public static void main(String[] args) {
//打印3遍的 云想衣裳花想容
/**
* i=0 0<3 true 就去执行大括号里面的代码 sout("云想衣裳花想容") i++
* i=1 1<3 true 打印第二遍的sout("云想衣裳花想容") i++
* i=2 2<3 true 打印第三遍的sout("云想衣裳花想容") i++
* i=3 3<3 false循环结束
*/
for (int i = 0; i < 3; i++) {
System.out.println("云想衣裳花想容");
}
}

}

案例1:打印1-10以内的奇数

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
package com.qfedu.a_test;

public class Demo12 {
public static void main(String[] args) {
//打印1-10之间的奇数
/**
* i=1 1<11 true 1%2==1 true sout(1) i++
* i=2 2<11 true 2%2==1 false i++
* i=3 3<11 true 3%2==1 true sout(3) i++
* i=4 4<11 true 4%2==1 false i++
* ......
*/
// for (int i = 1; i < 11; i++) {
// if (i % 2 == 1) {
// System.out.println(i);
// }
//
// }
/**
* i=1 1<11 sout(1) i=i+2
* i=3 3<11 sout(3) i=i+2
* i=5 5<11 sout(5) i=i+2
* ...
*/
for (int i = 1; i < 11; i+=2) {
System.out.println(i);
}
}

}

案例:

打印100以内的偶数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.qfedu.a_test;

public class Demo13 {

public static void main(String[] args) {
//打印1-100以内的偶数
for (int i = 1; i < 101; i++) {
if (i % 2 == 0) {
System.out.println(i);
}
}

}
}

案例:

​ 100以内的逢7过

​ 凡是7的倍数和带7 的都要给我打印”过”

​ 其他都是打印数字

​ 分为两种情况:

​ 1. 七的倍数

​ i % 7 ==0

​ 2.带7的

​ 分为两种情况:

​ 个位带7的: i % 10 == 7

​ 十位带7的: i / 10 ==7

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.qfedu.a_test;

public class Demo14 {
public static void main(String[] args) {
/**
* i=6 6<101 true sout(6) i++
* i=7 7<101 true sout("过") i++
* ......
*/
for (int i = 1; i < 101; i++) {
if (i % 7 == 0 || i % 10 == 7 || i / 10 == 7) {
System.out.println("过");
} else {
System.out.println(i);
}
}
}

}

案例:求1-100数的和 1 +2 + 3+ ….+ 99 + 100

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 com.qfedu.a_test;

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

//求1-100数的和
//要一个具体的数
/**
* i=0 0<101 true sum = sum + i=>sum=0+0 i++
* i=1 1<101 true sum=sum+i=>sum=0 + 1 i++
* i=2 2<101 true sum=sum+i=>sum=0+1 +2 i++
* i=3 3<101 true sum=sum+i =>sum=0+1+2+3 i++
* i=4 4<101 ......=>sum = 0+1+2+3+4
* i=100 100<101..... sum=0+1+2+3+4+.... + 100
*/
int sum = 0;//初始化的值,是一个变量
for (int i = 0; i < 101; i++) {
//sum = sum + i;
sum += i;
}
System.out.println(sum);
}

}

2.5循环的嵌套

一个循环里面再套另外一个循环

秉承着一点: 外部循环进入倒内存循环以后先把内部循环结束以后再进入倒外部的循环

需求:

1
2
3
*****
*****
*****
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
package com.qfedu.a_test;

public class Demo16 {

public static void main(String[] args) {
//System.out.println("*****");
/**
* i=0 0<5 true 打印* i++
* i=1 1<5 true 打印** i++
* i=2 2>5 true 打印*** i++
* ...
* 打印*****
*/
// for (int i = 0; i < 5; i++) {
// System.out.print("*");
// }
// System.out.println("*****");
// System.out.println("*****");
// System.out.println("*****");
/**
* 一定要把执行流程弄清楚
* i=0 0<3 true 执行外层循环后面大括号的代码
* 进入到了内层循环了
* j=0 0<5 true 打印* j++
* j=1 1<5 true 打印** j++
* j=2 2<5 true 打印*** j++
* j=3 3<5 true 打印**** j++
* j=4 4<5 true 打印***** j++
* j=5 5<5 false 内层的循环结束 换行 i++
* i=1 1<3 true 进入到内层for循环了
* j=0 0<5 true 打印* j++ 在第二行打印的
* j=1 1<5 true 打印** j++
* j=2 2<5 true打印*** j++
* j=3 3<5 true 打印**** j++
* j=4 4<5 true 打印***** j++
* j=5 5<5 false 内层循环结束 换行 i++
*
* i=2 2<3 true 进入内层循环
* j=0
* 告知我一个规律:最外层的循环控制的是行
* 最内层循环控制的是列
* id name age info
* 1 狗蛋 67 像老邢
* 2 老邢 89 像狗蛋
* 3 骚磊 78 臀大
*/
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; j++) {
System.out.print("*");
}
System.out.println();//换行
}
}
}

需求:

1
2
3
4
*            第一行  1个*    (2 * i) - 1
*** 第二行 3个*
***** 第三行 5个*
******* 第四行 7个*

注意事项:这种情况,列和你的行是有关系的

i =>1 2 3 4

j=> (2 * i) - 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
29
30
31
32
33
package com.qfedu.a_test;

public class Demo17 {
public static void main(String[] args) {
//打印一个直角三角形
/**
* i=1 1<=4 true 进入到内层的循环
* j=1 1<=1 true 打印* j++
* j=2 2<=1 false 换行 i++
* i=2 2<4 true 进入到内层的循环
* j=1 1<=3 true 打印* j++
* j=2 2<=3 true 大印** j++
* j=3 3<=3 true 打印*** j++
* j=4 4<=3false 换行 i++
* i=3 3<=4 true 进入到内层循环
* j=1 1<=5 true 打印* j++
* j=2 2<=5 true 打印** j++
* j=3 3<=5 true 打印*** j++
* j=4 4<=5 true 打印**** j++
* j=5 5<=5 true 打印***** j++
* j=6 6<=5 false 换行 i++
*
*/
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= (2 * i - 1); j++) {
System.out.print("*");
}
System.out.println();
}
}

}

需求:

1
2
3
4
5
6
打印九九乘法表
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.qfedu.a_test;

public class Demo18 {
public static void main(String[] args) {
//留给你们分析执行流程!!!!
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
System.out.print(j + "*" + i + "=" + j*i + "\t");
}
System.out.println();//换行
}
}

}

day5

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
1.switch后面的小括号里面的  数据类型是那种数据类型
int byte short String char enum
2.if-else的语法格式
if (布尔表达式) {
语句体1
} else {
语句体2
}
3.switch-case的语法格式
switch () {
case 常量1:
语句体1;
break;
case 常量2:
语句体2;
break;
defautl:
语句体n;

}

4.逻辑的短路原则
逻辑与的短路原则:当条件为false的时候,后面条件就不再执行了
逻辑或的短路原则:当条件为true的时候,后面条件就不再执行了
5.while循环的语法格式及执行流程
while (布尔表达式) {
循环体;
}
执行流程: 当布尔表达式为true的时候,执行循环体,再次回到while关键字,再次判断布尔表达式。如果表达式为false的话,循环结束
6.while和do-while的循环的区别
while先判断表达式是否为true或者false,再决定是否执行循环体。但是do-while先执行一次循环体。
7.for循环的语法格式和执行流程
for (表达式1; 表达式2; 表达式3) {
循环体
}
执行流程: 先执行表达式1然后再判断表达式2,如果表达式2为true,就会执行循环体,执行表达式3,再次回到表达式2进行判断.....
8.使用for循环打印99乘法表
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; ) {
System.out.print(j + "*" + i + "=" + i*j);
}
System.out.println();
}



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
循环体
1.
* 第一行 3个空格 1个* 2* i-1
*** 第二行 2个空格 3个*
***** 第三行 1个空格 5个*
******* 第四行 0个空格 7个*

2.
*******
*****
***
*
3.
*
**
***
****
*****
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
package com.qfed.a_for;

public class Demo1 {

public static void main(String[] args) {
/**
* i=1 1<5 true
* 进入到内层第一个for循环
* j=1 1<=3 true 打印第一个空格 j++
* j=2 2<=3 true 打印第二个空格 j++
* j=3 3<=3 true 打印第3个空格 j++
* j=4 4<=3 false 循环结束
* 进入倒内层的第二个for循环
* k=1 1<=1 打印第一个* k++
* k=2 2<=1 false 循环 结束 换行 i++
* i=2...
*
*
*
*/
for (int i = 1; i < 5; i++) {//控制是行数

for (int j = 1; j <= 4 - i; j++) {//打印的空格的列
System.out.print(" ");
}
for (int k = 1; k <= (2 * i - 1); k++) {//打印*这个列
System.out.print("*");

}
System.out.println();//换行
}
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.qfed.a_for;

public class Demo2 {
public static void main(String[] args) {
//打印倒的直角三角形
//学会自习分析
for (int i = 4; i > 0; i--) {
for (int j =1; j <= (2 * i - 1); j++) {
System.out.print("*");
}
System.out.println();
}
}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.qfed.a_for;

public class Demo3 {
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {//控制行数
for (int j = 5 - i; j > 0; j--) {
System.out.print(" ");
}
for (int j = 1; j <= i; j++) {
System.out.print("*");
}
System.out.println();
}
}

}

今天的内容

方法

方法会贯穿咱们整个职业生涯

1.方法【重点】

1.1为什么要有方法

开发中如果出现了大量的重复的代码,或者是重复的功能,循环满足不了咱们的需求了。

可以使用方法

1.代码臃肿

2.可读性差

3.维护性差

建议用方法即可

1.2其实已经见过方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static void main (String args) {
方法体
}
这个方法是Java给咱们提供好的
方法的名字叫main
public static : 不要问
void :返回值 空的 没有返回值的
main: 就是方法的名字
方法的名字的命名和变量的命名一样。
1.首字母小写
2.使用数字,字母,下划线 ,$等组成的,但是数字不能开头
3.使用小驼峰,命名规则,或者使用下划线进行拼接
4.见名知意
5.不能使用Java的关键字
main的后面跟了一个小括号
小括号中可以带参数
小括号后面跟着的是一个大括号

学会抄

1.3定义方法的语法格式

无参无返回值的方法

有参无返回值的方法

无参有返回值的方法

有参有返回值的方法

1.3.1无参无返回值的方法

语法格式:

1
2
3
public  static void 方法的名字 () {
方法体;
}

注意事项:

​ 1.方法的声明必须在类中,在main主函数外面。

​ 2.方法的调用必须在主函数中,使用的是方法的名字来调用的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.qfed.b_method;

public class Demo2 {

public static void main(String[] args) {
//在main主函数调用方法
//
printEat();
printEat();
}
//在main方法的外部声明一个新的方法
//无参 无返回值的方法
public static void printEat () {
for (int i = 0; i < 10; i++) {
System.out.println("中午吃梅菜扣肉");
}
}


}

练习:写一个方法,打印出来99乘法表,使用无参无返回值的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.qfed.b_method;

public class Demo3 {
public static void main(String[] args) {
printNineNineTable();
printNineNineTable();
}
public static void printNineNineTable () {
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
System.out.print(j + "*" + i + "=" + j * i);
}
System.out.println();
}
}

}

练习:逢7过,使用方法的写法

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
package com.qfed.b_method;

public class Demo3 {
public static void main(String[] args) {
printNineNineTable();
//printNineNineTable();
printPassSeven();
}
public static void printNineNineTable () {
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
System.out.print(j + "*" + i + "=" + j * i);
}
System.out.println();
}
}
//逢7过
public static void printPassSeven () {
for (int i = 1; i < 101; i++) {
if (i % 7 == 0 || i % 10 == 7 || i / 10 == 7) {
System.out.println("过");
} else {
System.out.println(i);
}
}
}

}

总结:

1
2
3
4
1.新建一个类
2.在类中书写main主函数
3.在main主函数的外面写一个方法
4.在main主函数调用方法
1.3.2有参无返回值的方法

语法格式:

1
2
3
public static void 方法的名字 (数据类型 参数名字, 数据类型 参数名字, ...) {
方法体;
}

注意事项:

​ 1.方法的声明处的参数是形参。方法的调用处是实参

​ 实参赋值给形参

​ 2.方法在调用的时候一定要注意方法声明处形参的数据类型,是一一对应的关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.qfed.b_method;

public class Demo4 {
public static void main(String[] args) {
printHello(8);
//在方法额调用处 18啥意思?
//18是实际参数 又叫实参 会讲实参赋值给形参,让形参具备真实的意义

//将18赋值给方法的声明处的那个变量 num
}
//打印4遍的hello
//此时方法的声明处 int num 是形式参数 又叫形参
//只是一个形式而已
public static void printHello (int a) {
for (int i = 0; i < a; i++) {
System.out.println("hello");
}
}

}

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 com.qfed.b_method;

public class Demo5 {
public static void main(String[] args) {
add(5, 6);
//将5赋值给a 将6 赋值给 b
addDouble(45.3, 566.9, 89.3);
printStr("大漠孤烟直");
concate("落霞与孤鹜齐飞,", "秋水共长天一色");
print1(1, "狗蛋", 2.3, 'a');
}
//打印两个int类型数据的和
//a 和 b 是形式参数,是占着位置的变量
public static void add (int a, int b) {
System.out.println(a + b);
}
//打印3个doule数据类型的和
public static void addDouble (double d1, double d2, double d3) {
System.out.println(d1 + d2 + d3);
}
//打印一个字符串
public static void printStr (String str) {
System.out.println(str);
}
//字符串拼接
public static void concate (String str1, String str2) {
System.out.println(str1 + str2);
}
//参数类型是不一致的情况
public static void print1 (int i1, String str1,double d1, char c1) {
System.out.println(i1 + str1 + d1 + c1 );

}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.qfed.b_method;

public class Demo6 {
public static void main(String[] args) {
printChengFaBiao(100);
}
public static void printChengFaBiao (int num) {
for (int i = 1; i <= num; i++) {
for (int j = 1; j <= i; j++) {
System.out.print(j + "*" + i + "=" + j * i);
}
System.out.println();
}
}

}

上午回顾

1
2
3
4
5
6
7
8
9
1.无参无返回值的方法
public static void 方法的名字() {
方法体
}
2.有参无返回值的方法
public static void 方法的名字 (数据类型 形参, 数据类型 形参, ....) {

}
调用的时候在main主函数中 使用方法名字来调用即可。
1.3.3无参有返回值的方法

语法格式:

1
2
3
public static 数据类型 方法的名字 () {
return 返回值;//这个返回值的数据类型必须和方法的声明的地方的数据类型保持一致
}

注意事项:

​ 1.使用关键自 return

​ 2.return的后面不能再写代码了

​ 3.有返回值的方法在调用的时候,要将返回值的值是可以给一个变量的

​ 4.无返回值的方法,只是打印一下而已。 是不能给一个变量的

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
package com.qfed.b_method;

public class Demo7 {
public static void main(String[] args) {
printNum();//这个只是单纯的打印显示而已
int i1 = giveNum();//可以获取出来进行下一步的操作
System.out.println(i1);
//拿到值以后做下一步的操作
System.out.println(i1 + 15);//20
String string = giveString();
System.out.println(string);

}
//定义一个方法,带有返回值的方法
public static int giveNum () {
//This method must return a result of type int
return 5;


}
public static void printNum () {
System.out.println(5);
}
//返回值是字符串类型的数据
public static String giveString () {
String str = "你才觉得时间空间";
return str;
}

}

1.3.4有参有返回值的方法

语法格式:

1
2
3
public static 数据类型 方法的名字 (数据类型 形参, 数据类型 形参,...) {
return 返回值;
}
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
package com.qfed.b_method;

public class Demo8 {
public static void main(String[] args) {
int sum = add(3, 4, 5);
System.out.println(sum);
add1(3, 4, 5);
System.out.println(judge(67.6, 89.8));//false
}
//求三个int类型数据的和 带有返回值的方法
public static int add (int a, int b , int c) {
return a + b + c;
}
public static void add1 (int a, int b, int c) {
System.out.println(a + b + c);
}
//我现在脑海中有一个问题?这个形参和返回值类型有关系吗?
//没有任何关系的
//我想判断两个double类型的数据 如果 a 比 b大返回值一个true
//反之返回false
public static boolean judge (double a, double b) {
if (a > b) {
return true;
} else {
return false;
}
}


}

练习:

无参无返回值的方法:

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 com.qfed.b_method;

import java.util.Scanner;

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

String str = isOddOrEven1();
System.out.println(str);
}
//判断一个数是否是偶数和奇数,不带参数的
//无参无返回值的方法
public static void isOddOrEven () {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个整数:");
int i = scanner.nextInt();
if (i % 2 == 0) {
System.out.println("该数是偶数!!!");
} else if (i % 2 == 1) {
System.out.println("该数是奇数!!!");
}
}
//无参有返回值的方法
public static String isOddOrEven1 () {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个整数:");
int i = scanner.nextInt();
if (i % 2 == 0) {
return "该数是偶数!!!";
} else {
return "该数是奇数!!!";
}
}

}

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

import java.util.Scanner;

public class Demo10 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个整数:");
int i = scanner.nextInt();
isOddOrEven(i);
}
//有参无返回值的方法
public static void isOddOrEven (int a) {
if (a % 2 == 0) {
System.out.println("该数是偶数!!!");
} else if (a % 2 == 1) {
System.out.println("该数是奇数!!!");
}
}

}

总结:

1
2
3
4
5
6
7
1.无参数无返回值的方法
脑海里面必须有无参无返回值方法的语法格式
2.有参无返回值的方法
3.无参有返回值的方法
4.有参有返回值的方法

以后方法天天写!!!你现在不会,慢慢就带着会了

2.break和continue关键字

字面意思:

​ break: 终止 打断

​ continue: 继续

2.1break;

语法格式:

1
break;

注意事项:

​ break关键字 只能在switch-case中或者循环中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.qfed.c_breakandcontinue;

public class Demo1 {
public static void main(String[] args) {
//break; 终止打断的意思
for (int i = 0; i < 5; i++) {
System.out.println("嘻嘻哒");
break;//终止 打断的意思
}
System.out.println("呵呵哒");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.qfed.c_breakandcontinue;

public class Demo2 {
public static void main(String[] args) {
for (int i = 1; i < 100; i++) {
if (i % 5 == 0) {
System.out.println(i);//5
break;
}
System.out.println(i);//1 2 3 4
}
}
//今天你们试一下 for循环里面使用switch-case
//语法格式完全可以的,但是swicth-case里面的break;不会终止循环


}

2.2continue;

语法格式:

1
continue;

跳过本次循环,继续下一次的循环

只能在循环中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.qfed.c_breakandcontinue;

public class Demo4 {
public static void main(String[] args) {
/**
* i=4 4<8 true 4%5==0 false sout(4) i++
* i=5 5<8 true 5%5==0 true continue 结束了本次循环 i++
* i=6 6<8 true 6%5==0 falsesout(6) i++
* i=7 7<8 true 7%5==0false sout(7) i++
* i=8 8<8循环结束
*/
for (int i = 4; i < 8; i++) {
if (i % 5 == 0) {
continue;//结束本次循环执行下次的循环
}
System.out.println(i);
}
}

}

1-100带7 的不打印,使用continue

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.qfed.c_breakandcontinue;

public class Demo5 {
public static void main(String[] args) {
for (int i = 1; i < 101; i++) {
if (i % 7 == 0 || i % 10 == 7 || i / 10 == 7) {
continue;
}
System.out.println(i);
}
}
}

3.案例关于方法的练习

1.写一个方法,找出两个int类型最大值,并输出打印最大值

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
package com.qfed.d_method;

public class Demo1 {
public static void main(String[] args) {
//max();
//max1(89, 67);
//System.out.println(max2());
System.out.println(max3(150, 250));
}
//求两个int的最大值的
//无参无返回值的方法
public static void max () {
int a,b;
a = 45;
b = 69;
if (a >= b) {
System.out.println(a);
} else {
System.out.println(b);
}

}
//有参无返回值的方法
public static void max1(int a, int b) {
if (a >= b) {
System.out.println(a);
} else {
System.out.println(b);
}
}
//无参有返回值的方法
public static int max2 () {
int a,b;
a = 45;
b = 32;
if (a >= b) {
return a;
} else {
return b;
}
}
//有参有返回值的方法
public static int max3 (int a, int b) {
if (a >= b) {
return a;
} else {
return b;
}
}


}

案例2:控制台输入一个字符,判断这个字符是否是大写的英文字符,如果是打印是大写的,如果不是打印不是大写的英文字符

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 com.qfed.d_method;

import java.util.Scanner;

public class Demo2 {
public static void main(String[] args) {
//控制台输入
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个字符:");
char c1 = scanner.next().charAt(0);
System.out.println(isUpper(c1));
}
//判断一个字符是否是大写的字符
public static String isUpper (char c1) {
//if (c1 >= 'A' && c1 <= 'Z') {
if (c1 >= 65 && c1 <= 90) {
return "是大写的字母";
} else {
return "不是大写字母";
}
}

}

案例3:判断一个字符是否是数字字符

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

import java.util.Scanner;

public class Demo3 {
public static void main(String[] args) {
isNumber();
}
//判断一个字符是否是数字字符
public static void isNumber () {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个字符:");
char c1 = scanner.next().charAt(0);
if (c1 >= '0' && c1 <= '9') {
System.out.println("是数字字符");
} else {
System.out.println("不是数字字符");
}
}

}

day6

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
1.八大基本数据类型
整型: byte short int long
浮点: double float
字符: char
布尔: boolean

2.声明变量的语法格式
数据类型 变量名字 = 初始化的值;
3.使用for循环打印等腰三角形
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= 4 - i; j++) {
System.out.print(" ");
}
for (int k = 1; k <= (2 * i - 1); k++) {
System.out.print("*");
}
System.out.println();
}
4.break和continue关键字的简单介绍
break: swicth-case 和循环里面 终止 打断
continue: 循环 结束本次循环 执行下一次循环
5.四种方法的语法格式分别列出来
无参无返回值的方法: public static void 方法的名字 () {

}
public static void 方法名字(数据类型 形参,....) {

public static 数据类型 方法名字 () {
return 返回值
}
public static 数据类型 方法名字 (数据类型 形参) {
return 返回值
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1.写一个方法,判断一个字符是否是英文字符(大写和小写)

2.写一个方法将一个整数逆序换行打印

int a = 3456;

6

5

4

3

3.写一个方法,控制台输入哪一个年份,判断是否是闰年

4.写一个方法判断一个数字是否是正数
5.写一个方法输出1-100之间不能被5整除的数,每5个一行
6.写一个方法求出1-1/2+1/3-1/4……1/100
7.写一个方法 求1+(1+2)+(1+2+3)+(1+2+3+4)+……+(1+2+……+100)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.qfedu.b_homework;

import java.util.Scanner;

public class Demo1 {

public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("输入一个字符:");
char c = scanner.next().charAt(0);
isEnglish(c);
}
//判断是否是英文字符
public static void isEnglish (char c) {
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
System.out.println("是英文字符");
} else {
System.out.println("不是英文字符");
}
}
}

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 com.qfedu.b_homework;

public class Demo2 {
public static void main(String[] args) {
int i1 = 3456;
reverse(i1);
}
//对一个int类型的数据进行倒序的打印
public static void reverse (int a) {
/**
* i=3456 3456 != 0 true sout(3456%10) 6 i=i/10 345
* i=345 345 != 0 true sout(345%10) 5 i=i/10 34
* i=34 34!=0 true sout(34 %10) 4 i=i/10 3
* i=3 3!= 0 true sout(3%10) 3 i=i/10 0
* i=0 0!= 0 false 循环结束
*/
int i = a;
while (i != 0) {
System.out.println(i % 10);
i = i / 10;
}
}

}

今天的内容

数组

1.数组

1.1开发中为啥要有数组

如果开发中出现了大量的同一类型的数据的时候,如果按照现在所学,声明变量的话,进行数据的存储。

这样的话,变量很多。相当麻烦

使用数组:只需要声明一个变量,然后存储多个数据

把他们当成一个容器即可

1.2在Java中如何定义数组

变量:

​ 数据类型 变量名字 = 初始化的值;

数组定义的语法格式:

第一种定义方式:

1
2
3
数据类型[] 数组变量名字 = {值1, 值2, 值3,......};
或者
数据类型 数组变量名字 []= {值1, 值2, 值3,......};

第二种声明方式:

1
数据类型[]  数组变量名字 = new 数据类型[容量];

第三种声明方式:

1
2
数据类型[] 数组变量名字 = new 数据类型[]{值1, 值2, 值3,.....};
是第一种的简写情况
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
package com.qfedu.c_array;

public class Demo1 {
public static void main(String[] args) {
//使用第一种方式声明数组
//声明数组并赋值,这个数组里面存了三个值
int[] arr = {12, 56, 89};
float f1[] = {34.2f, 89.78f, 76.345f};
char[] ch1 = {'中', 'a', '2'};
boolean[] b1 = {false, true, false};
String[] strs = {"学虎", "腾飞", "狗蛋"};

//使用第二种声明方式
//声明的这个数组的容量是3,就意味着可以存放3个数据
//仅仅是声明了一个容器而已。里面还没有放值,但是会存放默认的值
//如果是int 默认值就是0 [0, 0, 0]
int[] arr1 = new int[3];
boolean[] b2 = new boolean[2];//[false,false]
String[] strs1 = new String[3];
//[null, null, null]
//第三种写法
int[] arr2 = new int[] {34, 56, 7,8};




}

}

脑海里面想到一个问题 第二种声明方式没有对数组进行赋值

1.3对第二种声明方式进行赋值

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 com.qfedu.c_array;

import java.util.Arrays;

public class Demo2 {

public static void main(String[] args) {
int[] arr = new int[3];//只能存3个元素
//[0, 0, 0]
//对空的容器进行赋值
arr[0] = 12;//[12, 0,0] 将12赋值给下标为0的位置
arr[1] = 13;//[12, 13, 0]
//arr[2] = 14;//[12, 13, 14]
//数组下标越界的
//arr[3] = 78;

//打印一下看看结果
System.out.println(arr);//打印的是一个内存地址
//内存地址对程序友好不?不优化,看不出来你的数据是个啥
//咋办?有一个超纲的东西可以将内存地址转为字符串
System.out.println(Arrays.toString(arr));

//对一个String类型的数组进行赋值
String[] strs1 = new String[4];
strs1[0] = "老邢";
strs1[1] = "骚磊";
strs1[3] = "老万";
System.out.println(strs1);
System.out.println(Arrays.toString(strs1));
//对一个char 类型数组进行赋值
//但是唯独char不需要toString
char[] ch1 = new char[4];
ch1[0] = 97;
ch1[1] = 'z';
ch1[3] = 'x';
System.out.println(ch1);

}
}

1.4对数组进行取值

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 com.qfedu.c_array;

public class Demo3 {
public static void main(String[] args) {
int[] arr = {12, 78, 13, 89, 100,200};
System.out.println(arr[0]);//下标为0的位置上的值
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[3]);
System.out.println("=========");
//发现一个特点,下标是有规律的,循环是专门出来重复或者有规律的
for (int i = 0; i < 4; i++) {
System.out.println(arr[i]);
}
System.out.println("-----------");
//arr.length arr的长度 【重点】

System.out.println(arr.length);//6
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}

}

练习: 字符数组 和字符串数组,遍历他们的打印出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.qfedu.c_array;

public class Demo4 {
public static void main(String[] args) {
String[] strs1 = {"唐三藏","孙悟空","猪八戒"};
for (int i = 0; i < strs1.length; i++) {
//遍历
System.out.println(strs1[i]);
}
System.out.println("=======");
char[] ch1 = {'中', '过', '系', '是'};
for (int i = 0; i < ch1.length; i++) {
System.out.println(ch1[i]);
}
}


}

回顾

1
2
3
4
5
6
7
8
9
10
11
1.声明数组
三种
int[] arr = {1,2,3,4};
int[] arr1 = new int[3];
int[] arr2 = new int[]{1,2,3,4};
2.对数组赋值
对第二种进行赋值
arr1[下标] = 32; 下标从0开始的
3.数组的取值遍历
可以使用for循环进行遍历
arr[下标]

1.5二维数组【了解】

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
package com.qfedu.c_array;

import java.util.Arrays;

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

//[1,2,3,4]
//二维数组 行 列
//[[1 , 2, 3],
// [2, 4 , 5]]
//int[] arr = new int[3];
int[][] arr = new int[2][3];//总共6个
arr[0][0] = 1;
arr[0][1] = 2;
arr[0][2] = 3;
arr[1][0] = 2;
arr[1][1] = 4;
arr[1][2] = 5;
System.out.println(arr);
System.out.println(Arrays.toString(arr));
//取值 使用循环
for (int i = 0; i < 2; i++) {//行
for (int j = 0; j < 3; j++) {
System.out.println(arr[i][j]);
}

}


}

}

1.6数组可以当成一个方法的参数【重点】

方法的参数可以是八大基本数据类型和String,数据也可以作为方法的参数

语法格式

1
2
3
public static void 方法名字(数据类型[] 形参) {

}
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 com.qfedu.c_array;

import java.util.Arrays;
import java.util.Scanner;

public class Demo6 {
public static void main(String[] args) {
// int[] arr = {1,2,3,4};
// printArr(arr);
//声明空的数组,然后向里面存值
int[] arr = new int[5];//1.声明了一个空的数组
add(arr);//2.对这个空的数组赋值
//代码走到这一步,arr这个数组有值了没?
System.out.println(Arrays.toString(arr));//3.打印这数组有哪些数据
}
//遍历一个数组 打印数据
public static void printArr (int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
//使用方法对一个空的数组进行赋值
/**
*
* @param arr 是一个空的数组, 对空的数组进行赋值
*/
public static void add (int[] arr) {
Scanner scanner = new Scanner(System.in);
for (int i = 0; i < arr.length; i++) {
System.out.println("请输入第" + (i + 1) + "数");
int i1 = scanner.nextInt();
arr[i] = i1;
}
}

}

1.7数组可以当成一个方法的返回值

1
2
3
public  static 数据类型 方法名字 () {

}

八大基本数据类型和String都可以当成一个方法的返回值

那么数组也是可以的

案例:

​ [1,2,3,4]=>[4,3,2,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
29
30
31
32
33
34
35
36
37
38
package com.qfedu.c_array;

import java.util.Arrays;

public class Demo7 {
public static void main(String[] args) {
int[] arr = reverse();
System.out.println(Arrays.toString(arr));
}
//需求:将一个数组[1,2,3,4]转为[4,3,2,1]
/**
*
*
* @return
*/
public static int[] reverse () {
int[] arr = {1,2,3,4};//原数组
//定义一个空的数组 用来接收反转以后的数据
int[] arr1 = new int[arr.length];

//表达式1 :int i = 0, j = 3
//初始话条件 有两个
//表达式2: i < arr1.length
//表达式3:i++, j-- 循环条件
for (int i = 0, j = arr.length - 1; i < arr1.length; i++, j--) {
arr1[j] = arr[i];
//arr=[1,2,3,4]
//arr1=[0,0,0,0]
// arr1[3] = arr[0];//arr1[0,0,0,1]
// arr1[2] = arr[1];//arr1[0,0,2,1]
// arr1[1] = arr[2];//arr1[0,3,2,1]
// arr1[0] = arr[3];//arr1[4,3,2,1]
}
return arr1;
}

}

1.8数组在内存中如何分配的【了解】

以后还会再讲

目前学到的知识点你只需要关注:栈内存 和堆内存

内存区域的名字 作用
寄存器 给CPU使用的,和开发没有关系
本地方法栈 JVM虚拟机操作咱们的电脑的系统的时候,才会使用
方法区 存储和运行的class文件
堆区 存储的是对象或者数组, 凡是new出来的都存在堆区
方法栈 方法运行的时候使用的内存,比如main方法会进入到方法栈区

栈:存储的是八大基本数据类型的数据

​ int a = 20; 这个存在了栈区

​ 存储的是对象的引用 scanner 就是一个对象的等号的左边的

​ Scanner scanner = new Scanner(System.in);

堆区:

​ 凡是new的 都存在堆区

​ int[] arr = new int[5];

​ arr存在了栈区 new int[5];存在了堆区

​ Scanner scanner = new Scanner(System.in);

​ scanner 存在了栈区, new Scanner(System.in); 在堆区

1

2.数组方法循环分支的练习题

需求:定义一个方法,找出一个int数组中的最大值的索引下标

[3,1,2,7,6]=> 最大值的索引下标是3

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
package com.qfedu.c_array;

public class Demo8 {
public static void main(String[] args) {
int[] arr = {3, 2, 6, 1, 7};
//找出一个int数组中最大值的索引下标
int maxIndex = 0;//用来接收最大值的下标的
/**
* i=0 0<4 true arr[0] <arr[0] false i++
* i=1 1<4 true arr[0] <arr[1] false i++ maxIndex=0
* i=2 2<4 true arr[0]<arr[2] true maxIndex=2 i+=
* i=3 3<4 true arr[2]<arr[3] false maxIndex=2 i++
* i=4 4<4 false 循环结束
*
*/
for (int i = 0; i < arr.length; i++) {
if (arr[maxIndex] < arr[i]) {
maxIndex = i;
}
}
System.out.println(maxIndex);

}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.qfedu.c_array;

public class Demo9 {
public static void main(String[] args) {
int[] arr = {3,4,2,6,8,7};
int max = maxIndexOfArray(arr);
System.out.println(max);
}
//求一个数组中的最大值的索引下标
public static int maxIndexOfArray (int[] arr) {
int maxIndex = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[maxIndex] < arr[i]) {
maxIndex = i;
}
}
return maxIndex;
}

}

day7

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
1.return关键字的用法
return 在有返回值的方法中使用
return 返回值;
return 关键字书写以后后面的代码就不能写了

2.声明方法的四种形式
无参无返回值的
语法格式
有参无返回值的
无参有返回值的
有参有返回值的


3.什么是形参,什么是实参
在方法的声明处,写的变量叫形参
在方法的调用处,书写的是实参
在方法的调用的时候,将实参赋值给形参
4.数组的三种声明方法
数据类型[] 数组名字 = {值1, 值2,...};
数据类型[] 数组名字 = new 数据类型[容量];
数据类型[] 数组名字 = new 数据类型[]{值1, 值2, ...};
5.对第二种数组进行声明的时候如何进行赋值
arr[0] = 12;
6.for循环的语法格式和执行流程
for () {

}

回顾

1
2
3
4
5
6
7
8
9
1.数组的声明
三种的声明
2.对数组如何进行赋值
通过下标来进行赋值
3.对数组进行取值
通过下标进行取值
4.数组可以作为方法的参数
5.数组可以作为方法的返回值
[1,2,3,4]=>[4,3,2,1]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1.需求:定义一个方法,找出int数组中,最大值的索引下标
[1,2,23,5,6,7,8] 打印出来2
2.需求:定义一个方法,找出int数组中,最小值的索引下标
3.需求:定义一个方法,在指定的int数组中找出指定的数据第一个的下标
8这个数的下标
[1,2,8,4,5,78,7,8,9]

4. 在一个数组中,找出所有的 指定数据的下标位置 【难】
找出所有的下标存倒数组中
8这个数的下标
[1,2,8,4,5,7,8,7,8,9]
5. 完成一个方法,替换掉数组中所有元素为0的元素,替换为指定元素 [1,2,3,0,0,0]
6. 完成一个方法,删除指定下标的元素,要求从删除位置开始,之后的元素整体前移。【难】
[1,2,3,4,5,6,7]=>[1,2,4,5,6,7,0]
7. 完成一个方法,添加指定元素到指定下标位置,要求从指定下标位置之后的元素,整体向后移动。【难】
[1,2,3,4,5,0]=>[1,2,250,3,4,5]

8. 找出数组中最大的元素,放到下标为0的位置

9. 在上一道题的基础上,不考虑下标为0的元素。
找出数组中最大的元素,放到下标为1的位置

1.方法循环数组的练习题

1.需求:定义一个方法,找出int数组中,最小值的索引标

[1,2,3,4,5]=>0

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 com.qfedu.a_test;

public class Demo1 {
public static void main(String[] args) {
//需求:定义一个方法,找出int数组中,最小值的索引下标
int[] arr = {3,2,1,4};//2
int minIndex = 0;//minIndex目的是用来存储最小值的下标的
for (int i = 0; i < arr.length; i++) {
/**
* i=0 0<4true arr[0]>arr[0] false minIndex=0 i++
* i=1 1<4 true arr[0]>arr[1] true minIndex=1 i++
* i=2 2<4 true arr[1]>arr[2] true minIndex=2 i++
* i=3 3<4 true arr[2]>arr[3] false i++
* i=4 4<4 false 循环结束
*/
if (arr[minIndex] > arr[i]) {
minIndex = i;
}

}
System.out.println(minIndex);
}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.qfedu.a_test;

public class Demo2 {

public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
System.out.println(minIndexInArray(arr));
}
public static int minIndexInArray (int[] arr) {
int minIndex = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[minIndex] > arr[i]) {
minIndex = i;
}
}
return minIndex;
}
}

2.需求:定义一个方法,在指定的int数组中找出指定的数据第一个的下标

    8这个数的下标

[1,2,8,4,5,7,8,7,8,9]
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
package com.qfedu.a_test;

public class Demo3 {

public static void main(String[] args) {
int[] arr = {1,2,8,3,4,8,9,8};
System.out.println(indexOf(arr, 100));
}
/**
*
* @param arr 是数组,原始数组 你要在整个数组中找出那个值
* @param find 要找的值
* @return 是返回的找到值的索引下标
*/
public static int indexOf (int[] arr, int find) {
int index = -1;
for (int i = 0; i < arr.length; i++) {
if (find == arr[i]) {
index = i;
break;//终止
}
}
return index;
}
}

3.在一个数组中,找出所有的 指定数据的下标位置 【难】

​ 找出所有的下标存倒数组中
​ 8这个数的下标
[1,2,8,4,5,7,8,7,8,9]===>[2,6,8]

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
package com.qfedu.a_test;

import java.util.Arrays;

public class Demo4 {
public static void main(String[] args) {
//在一个数组中,找出所有的 指定数据的下标位置 【难】
// 找出所有的下标存倒数组中
// 8这个数的下标
//[1,2,8,4,5,7,8,7,8,9]
//1.先声明一个数组
int[] arr = {8, 2, 8, 4, 8, 9,8,78,67,8};
int count = 0;//计数的
//就找8 8的下标 2,6,8 将他们存到一个新数组中
//2.新建一个空的数组,空的数组容量是上一个数组的大小
int[] indexes = new int[arr.length];//容器
//[0,0,0,0]
for (int i = 0; i < indexes.length; i++) {
indexes[i] = -1;
}
//代码走到这一步 indexes = {-1,-1,-1,-1};
/**
* {8, 2, 8, 4,};
* i=0 0<4 true 8 == arr[0] true indexes[0] = 0; count++ i++
* i=1 1<4 true 8==arr[1] false i++
* i=2 2<4 true 8==arr[2] true indexes[1]=2;count++ i++
* i=3 3<4 true 8==arr[3] false i++
* i=4 4<4 false 循环结束
*/
for (int i = 0; i < arr.length; i++) {
if (8 == arr[i]) {
//将i存到新数组中[0,2,-1,-1]
//根据索引下标进行存储的
indexes[count++] = i;

}
//此时新数组中indexes = {0,2,-1,-1};
//{0,2}
}
System.out.println(Arrays.toString(indexes));
//现在要求有几个索引就是几个不要-1
//借助于count这个变量
//重新弄一个数组
int[] newIndexes = new int[count];
for (int i = 0; i < newIndexes.length; i++) {
newIndexes[i] = indexes[i];
}
System.out.println(Arrays.toString(newIndexes));

}

}

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
package com.qfedu.a_test;

import java.util.Arrays;

public class Demo5 {
public static void main(String[] args) {
int[] arr = {2,3,8,7,8,2,8};
int[] arr1 = findAllIndexes(arr, 8);
System.out.println(Arrays.toString(arr1));

}
public static int[] findAllIndexes (int[] arr, int find) {
int count = 0;//计数器
//这个数组使用存放值的下标的
int[] indexes = new int[arr.length];//[0,0,0,0,0]
for (int i = 0; i < indexes.length; i++) {
indexes[i] = -1;
}
//[-1,-1,-1,-1,-1...]
for (int i = 0; i < arr.length; i++) {
if (find == arr[i]) {
indexes[count++] = i;
}
}
//[2,4,6,-1,-1,-1...]
//再弄一个新的数组 只要2 4 6
int[] newIndexes = new int[count];
for (int i = 0; i < newIndexes.length; i++) {
newIndexes[i] = indexes[i];
}
return newIndexes;
}
}

4. 完成一个方法,替换掉数组中所有元素为0的元素,替换为指定元素 [1,2,3,0,0,0]

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

import java.util.Arrays;

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

}
public static int[] replace (int[] arr, int find) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == 0) {
arr[i] = find;
}
}
return arr;
}


}

5.完成一个方法,删除指定下标的元素,要求从删除位置开始,之后的元素整体前移。【难】

​ [1,2,3,4,5,6,7]=>[1,2,4,5,6,7,0]

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

import java.util.Arrays;

public class Demo7 {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
//想删除下标为2的
/**
* i=2 2<4 arr[2]=arr[3] =>{1,2,4,4,5} i++
* i=3 3<4 arr[3]=arr[4]=>{1,2,4,5,5} i++
* i=4 4<4 false循环结束
* arr[4] = 0;
*/
for (int i = 2; i < arr.length - 1; i++) {
arr[i] = arr[i + 1];
}
arr[arr.length - 1] = 0;
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
package com.qfedu.a_test;

import java.util.Arrays;

public class Demo8 {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
System.out.println(Arrays.toString(remove(arr, 1)));
}
public static int[] remove (int[] arr, int find) {
if (find > arr.length - 1) {
System.out.println("删除的索引超出了数组的范围");
System.exit(0);
}
for (int i = find; i < arr.length - 1; i++) {
arr[i] = arr[i + 1];
}
arr[arr.length - 1] = 0;
return 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
package com.qfedu.a_test;

import java.util.Arrays;

public class Demo10 {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8,10,0};
System.out.println(Arrays.toString(add(arr, 3, 799)));
}
/**
*
* @param arr 被添加的数组
* @param index 添加到数组中下标值
* @param number 添加到数组中的值
* @return
*/
public static int[] add (int[] arr, int index, int number) {

for (int i = arr.length - 1; i > index; i--) {
arr[i] = arr[i - 1];
}
arr[index] = number;
return arr;
}

}

上午的东西是数组 循环 分支 方法 综合一起的案例

6. 找出数组中最大的元素,放到下标为0的位置

[3,2,4,5,1]=>[5,2,4,3,1]

把最大值放到下标为0的位置,原来下标为0的数据,放到之前最大值的下标位置

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 com.qfedu.a_test;

import java.util.Arrays;

public class Demo11 {
public static void main(String[] args) {
int[] arr = {3,2,4,5,1};
int maxIndex = 0;//接收最大值下标
for (int i = 0; i < arr.length; i++) {
if (arr[maxIndex] < arr[i]) {
maxIndex = i;
}
}
//代码走到这一步 其实就是之前讲过的最大值的下标
//最大值的下标是3 要把下标为3的数据放到下标为0的位置
//arr[0] = arr[maxIndex];//{5,2,4,5,1}这种方式不行啊
//咋办? 借助于中间变量
int temp = arr[maxIndex];//先将最大值赋值给temp
arr[maxIndex] = arr[0];//将第一个数据3 赋值给最大值{3,2,4,3,1}
arr[0] = temp;//{5,2,4,3,1}
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
package com.qfedu.a_test;

import java.util.Arrays;

public class Demo12 {
public static void main(String[] args) {
int[] arr = {89,67,34,90,98,98,34};
change(arr);
}
public static void change (int[] arr) {
int maxIndex = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[maxIndex] < arr[i]) {
maxIndex = i;
}
}
System.out.println(maxIndex);
//交换
int temp = arr[maxIndex];
arr[maxIndex] = arr[0];
arr[0] = temp;
System.out.println(Arrays.toString(arr));


}

}

7.在上一道题的基础上,不考虑下标为0的元素。找出数组中最大的元素,放到下标为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
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.qfedu.a_test;

import java.util.Arrays;

public class Demo13 {

public static void main(String[] args) {
int[] arr = {3, 2, 4, 5, 1 };
int maxIndex = 0;// 接收最大值下标
for (int i = 0; i < arr.length; i++) {
if (arr[maxIndex] < arr[i]) {
maxIndex = i;
}
}
// 代码走到这一步 其实就是之前讲过的最大值的下标
// 最大值的下标是3 要把下标为3的数据放到下标为0的位置
// arr[0] = arr[maxIndex];//{5,2,4,5,1}这种方式不行啊
// 咋办? 借助于中间变量
int temp = arr[maxIndex];// 先将最大值赋值给temp
arr[maxIndex] = arr[0];// 将第一个数据3 赋值给最大值{3,2,4,3,1}
arr[0] = temp;// {5,2,4,3,1}
System.out.println(Arrays.toString(arr));
//找2 4 3 1 中的最大值,然后把最大值放到下标为1的位置
//{5,4,2,3,1}
int maxIndex1 = 1;
for (int i = 1; i < arr.length; i++) {
if (arr[maxIndex1] < arr[i]) {
maxIndex1 = i;

}
}
//交换位置
int temp1 = arr[maxIndex1];
arr[maxIndex1] = arr[1];
arr[1] = temp1;
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
39
40
41
42
package com.qfedu.a_test;

import java.util.Arrays;

public class Demo14 {
public static void main(String[] args) {
int[] arr = {3, 2, 4, 5, 1 };
change1(arr);
}
public static void change1 (int[] arr) {
int maxIndex = 0;// 接收最大值下标
for (int i = 0; i < arr.length; i++) {
if (arr[maxIndex] < arr[i]) {
maxIndex = i;
}
}
// 代码走到这一步 其实就是之前讲过的最大值的下标
// 最大值的下标是3 要把下标为3的数据放到下标为0的位置
// arr[0] = arr[maxIndex];//{5,2,4,5,1}这种方式不行啊
// 咋办? 借助于中间变量
int temp = arr[maxIndex];// 先将最大值赋值给temp
arr[maxIndex] = arr[0];// 将第一个数据3 赋值给最大值{3,2,4,3,1}
arr[0] = temp;// {5,2,4,3,1}
System.out.println(Arrays.toString(arr));
//找2 4 3 1 中的最大值,然后把最大值放到下标为1的位置
//{5,4,2,3,1}
int maxIndex1 = 1;
for (int i = 1; i < arr.length; i++) {
if (arr[maxIndex1] < arr[i]) {
maxIndex1 = i;

}
}
//交换位置
int temp1 = arr[maxIndex1];
arr[maxIndex1] = arr[1];
arr[1] = temp1;
System.out.println(Arrays.toString(arr));
}

}

2.排序

[3,2,1,4,5]=>从小到大排序

2.1选择排序

原理:找到最小值的索引,然后和第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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.qfedu.b_sort;

import java.util.Arrays;

public class Demo1 {
public static void main(String[] args) {
//选择排序
int[] arr = {3,4,1,5,2};
/**
* i=0 0<4 true minIndex=0
* 进入内层的for循环
* j=0 0<5 true arr[0] >arr[0]false j++
* j=1 1<5 true arr[0] >arr[1] false j++
* j=2 2<5 true arr[0]>arr[2]true minIndex=2 j++
* j=3 3<5 true arr[2]>arr[3]fasle j++
* j=4 4<5 true arr[2]>arr[4] fasle j++
* j=5 5<5fasle循环结束
* 执行交换代码
* temp = arr[2]=1
* arr[2] = arr[0] {3,4,3,5,2}
* arr[0] = 1 {1,4,3,5,2} i++
* i=1 1<4 true minIndex =1
* ......
*
*/
for (int i = 0; i < arr.length - 1; i++) {//控制的是轮数
int minIndex = i;
for (int j = i; j < arr.length; j++) {//遍历咱们的数据找到最小值的索引的
if (arr[minIndex] > arr[j]) {
minIndex = j;
}

}
//交换位置
int temp = arr[minIndex];
arr[minIndex] = arr[i];
arr[i] = temp;
}
System.out.println(Arrays.toString(arr));
}

}

2.2冒泡排序

从小到大排序

原理:比较两个相邻的数据,如果左边比右边元素大就交换位置。如果左边比右边小,就不变

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
package com.qfedu.b_sort;

import java.util.Arrays;

public class Demo2 {

public static void main(String[] args) {
//冒泡 排序和索引没有关系
int[] arr = {1,5,2,3};
for (int i = 0; i < arr.length - 1; i++) {
//最内层的循环两两比较交换位置
//4-1-i=>i=0 第1轮 3次
//4-1-i=>i=1 第2轮 2次
//4-1-i=>i=2 第3轮 1次
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
//交换位置
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
}

day8

回顾

1
2
3
4
1.选择排序
原理: 找到最小值的下标,交换
2.冒泡排序
原理: 比较相邻的两个元素,把最小值放到左边。第一次比较的时候最大值放到最右边了,以此类推

今天的内容

1类和对象

2.类和对象内存

3.构造方法

1.从生活的角度区理解面向对象开发

有两种编程思想:

​ 面向过程:

​ 程序自上而下执行,不牵涉到类和对象的操作。本质是代码自己完成自己的功能

​ 冒泡排序是面向过程的

​ 亲力亲为 都是面向过程的00

​ 面向对象:

​ 程序是靠对象完成一定的功能

​ Arrays.sort(arr) 这个就是面向对象的

​ 借助于对象来实现功能的

2.面向对象两个重要概念

类: 是对一切相似事物的统称。是一个泛泛的概念。可以用来描述事物的特征和行为的

对象:是一个具体的实体。是这是真实存在的。在类的基础之上孵化出来的。

对象
我家里面的一个大黄狗
千锋Java教学部郑州校区的王博
桌子 学虎正在坐的桌子
1
2
3
4
5
6
7
8
特征:就是一类事物的属性,比如人的年龄  身高 体重  性别
在Java代码中使用变量来表示一个类的特征或者属性
int age;
double height;
是静的东西
行为:就是动作 吃饭 睡觉 敲代码
在Java中使用方法来描述一个类的行为
是动的东西

只要注意好特征和行为就可以写好一个类了。

1
2
3
4
5
人类:
特征,又叫属性:
名字 性别 身高 体重
行为,又叫方法:
吃饭 睡觉 敲代码

3.声明一个类

语法格式:

1
2
3
4
[public] class 类名 {
对于当前类的属性的描述
对于当前类的行为的描述
}
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 com.qfedu.a_class;

class Person {
//人类:
//属性: 姓名 年龄 性别 身高
//行为: 吃饭 睡觉
//类下面的属性: Java使用变量来描述
//在类中 变量最好不要赋值
String name; //名字 null
int age;//年龄 0
char sex;//性别
double height;//身高0.0
//在类中后书写行为 Java使用方法来描述行为
//public static void eat() {}
//今天学的内容,和之前方法的声明不一样,去掉static即可
public void eat () {

System.out.println("中午吃酸菜鱼");
}
public void sleep () {
System.out.println("中午不睡,下午崩溃");
}








}

案例:

​ 狗类:

​ 属性: 名字 毛色 品种 性别

​ 行为: 看家 打架

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.qfedu.a_class;

public class Dog {
String name;//声明的狗的名字
String color;//代表的是狗毛色
String kind;//代表狗的品种
boolean sex;//性别

//定义方法
public void lookHome () {
System.out.println("狗汪汪叫,在看家");
}
public void fight () {
System.out.println("狗咬狗,一嘴毛");
}

}

案例:

​ 猪类:

​ 属性和方法自己想

4.对象的创建

一个类声明好以后,不使用它,它是一直存在,咱们可以借助于对象衍生出一个实体。

类可以衍生出来一个对象。类相当于一个模子。可以造出来一个实体。

造出对象的目的是为了啥? 就是执行属性的复制和方法的调用的

先有类,再有对象

对象的创建在main主函数中。目的是为了执行这个对象代码

Java语法格式:

1
类名  对象的名字 = 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
33
34
35
package com.qfedu.a_class;

//Demo1叫测试类 里面有main主函数
public class Demo1 {
public static void main(String[] args) {
//类名 对象的名字 = new 类名();
//这个对象是由类衍生出来的,就意味着类下面的属性可以使用
//类下面的方法我可以调用
Person person = new Person();
//对属性进行赋值
//person的名字 为 狗蛋
person.name = "狗蛋";
person.age = 78;
person.sex = '男';
person.height = 98.7;
//以上是对对象的属性进行赋值
//将对象的属性值取出来
System.out.println(person.name + person.age + person.sex + person.height);
//方法的调用 对象.方法名字();
person.eat();
person.sleep();

Person person1 = new Person();
person1.name = "二狗";
person1.age = 12;
person1.sex = '男';
person1.height = 178;
System.out.println(person1.name + person1.age + person1.sex + person1.height);
person1.eat();
person1.sleep();

}

}

案例:

​ 之前写过一个Dog类。现在开始通过Dog类创建dog对象,可以创建多个的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.qfedu.a_class;

public class Demo2 {
public static void main(String[] args) {
Dog dog = new Dog();
dog.name = "";
dog.color = "花色";
dog.kind = "金毛";
dog.sex = true;
System.out.println(dog.name + dog.color + dog.sex + dog.kind);
dog.fight();
dog.lookHome();
}

}

咱们现在实体类和测试类写在了不同的Java文件中。

5.创建的实体类和测试类在同一个Java文件中

文件的名字以测试类来命名

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
package com.qfedu.a_class;

//注意事项:实体类和测试类写在同一个文件中的时候,实体类不能带public修饰符
class Pig {
String name;
double weight;//体重
char sex;//性别

public void eat () {
System.out.println("猪吃白菜!!!");
}
public void sleep () {
System.out.println("猪睡觉打呼噜");
}
}
class Demo3 {
public static void main(String[] args) {
//创建对象
Pig pig = new Pig();
pig.name = "大黄";
pig.weight = 100.1;
pig.sex = '公';
System.out.println(pig.name + pig.weight + pig.sex);
pig.eat();
pig.sleep();
}

}

练习 :

​ 羊类 龙类 老鼠 鸡

​ 属性和方法自己声明,创建对象对属性进行赋值和方法调用。

​ 写在同一个文件中!!!

上午的内容

1
2
3
1.会新建一个类
2.会通过类创建一个对象 并对对象的属性进行赋值 对象还可以调用类下面的方法

6.构造方法

构造方法的目的是为了初始化对象的,换句话说,可以对对象的属性进行赋值

对象创建其实是依据构造方法创建的!!!【重点】

6.1无参构造方法

构造方法必须写在实体类中

语法格式:

1
2
3
public 类名() {

}
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
package com.qfedu.b_constructor;

class Dog {
String name;
int age;
public Dog () {
System.out.println("嘻嘻哒");
name = "大黄";
age = 12;
}

}
public class Demo2 {
public static void main(String[] args) {
//当new Dog()的时候就会去自动调用无参构造方法去执行无参构造方法中的方法体
Dog dog = new Dog();
dog.name = "旺财";
dog.age = 3;
//打印的是旺财和3 为啥没有打印大黄和12 因为无参构造先执行了
//后面赋的值就会覆盖掉初始化的值
System.out.println(dog.name);
System.out.println(dog.age);

}

}

6.2有参构造

语法格式:

1
2
3
public 类名 (参数) {
初始化条件;
}
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
package com.qfedu.b_constructor;

class Cat {
String name;
String kind;
int age;

public Cat() {

}
//和下面的有参构造一模一样!!!
// public Cat (String kind) {
// this.kind = kind;
// }
//声明一个有参构造方法
public Cat (String name) {
this.name = name;
}
//带有三个参数 构造方法
public Cat (String name, String kind, int age) {
this.name = name;
this.age = age;
this.kind = kind;
}


}
public class Demo3 {

public static void main(String[] args) {
Cat cat = new Cat("狗蛋");

System.out.println(cat.name);
//new对象的时候依据构造方法来创建对象
Cat cat1 = new Cat("毛蛋", "波斯", 3);
System.out.println(cat1.name);
System.out.println(cat1.age);
System.out.println(cat1.kind);
//一旦写了有参构造方法以后,默认的无参构造方法就没有了
Cat cat2 = new Cat();
cat2.name = "Tom";
cat2.age = 4;
cat2.kind = "蓝猫";
}
}

案例:

猴子类:

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
package com.qfedu.b_constructor;

class Monkey {
String name;
int age;
double weight;

public Monkey (String name, int age, double weight) {
this.name = name;
this.age = age;
this.weight = weight;
}


}
public class Demo4 {
public static void main(String[] args) {
Monkey monkey = new Monkey("弼马温", 3, 98.7);
//不让你使用对象.变量 = 初始化的值; 这种方式对属性进行赋值了
//换一种方式赋值。叫有参构造
// monkey.name = "孙悟空";
// monkey.age = 500;
// monkey.weight = 89;
System.out.println(monkey.name);
System.out.println(monkey.age);
System.out.println(monkey.weight);
}

}

7.对象在内存中如何存储的

栈内存:

​ 存的是八大基本数据类型的数据

​ 对象的引用。 =左边

堆内存:

​ 对象的全部数据

1

8.构造代码块【了解】

开发中已经不用了

以后会讲静态代码块。

构造代码块的目的也可以对咱们的对象进行初始化的。功能和构造方法一样的

语法格式:

1
2
3
{
语句体
}

注意事项:

​ 1.构造代码块必须写在实体类中

​ 2.先执行的是构造代码块,再执行构造方法

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
package com.qfedu.b_constructor;

class Tiger {
String name;
int age;


//再声明一个构造方法
public Tiger () {
this.name = "haha";
System.out.println("我是无参构造方法");
}
//先写一个构造代码块
{
this.name = "嘻嘻";
System.out.println("我是构造代码块");
}
}
public class Demo5 {
public static void main(String[] args) {
//先执行实体类中构造代码块 然后再执行构造方法
Tiger tiger = new Tiger();
System.out.println(tiger.name);
}

}

9.局部变量和成员变量

9.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
29
30
package com.qfedu.c_var;

import org.omg.CORBA.PUBLIC_MEMBER;

public class Demo1 {

public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
//上面的i就是for循环的局部变量,出了for循环还能用吗?不能
//紧紧围绕着一个东西就是那个大括号
System.out.println(i);
}
//System.out.println(i);
if (3 < 4) {
int i = 98;

}

}
public static void test () {
int i = 20;
System.out.println(i);
}
public static void test1 () {
//System.out.println(i);
}
//总结一下: 一定要看清大括号里面的那个变量只能在大括号里面来使用的

}

9.2成员变量

定义在实体类中的大括号的后面,又叫属性

String name;

int age;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.qfedu.c_var;

class Person {
//name 和 age都是成员变量
String name;
int age;
//作用域 是作用再整个类中 的,只要在类中都可以使用当前的成员变量

public void eat () {
double weigt;//局部的变量
System.out.println(name + age);
}
}
public class Demo2 {
public static void main(String[] args) {

}

}

9.3局部和成员变量的区别

区别 成员变量 局部变量
定义的位置 类的大括号的后面(属性) 定义在方法体中
作用 用来描述对象的特征的 在方法体中只是用来存储数据的
初始化的值 默认值 在使用的时候必须赋值
内存 堆区 栈区
作用域 作用整个类 只能在当前的方法中使用

总结:

1
2
3
4
5
6
7
8
9
10
1.会声明一个类
2.会创建一个对象
3.会对对象的属性进行赋值
4.会对对象的方法进行调用
5.构造方法的声明
有一些细节一定要关注
构造方法是初始化对象的

6.构造代码块
7.局部变量和成员变量

day9

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
1.声明一个类的语法格式
实体类
class 类名 {
String name;
int age;
double weight;
char sex;

public void eat () {
sout("中午吃饭");
}
}
2.通过类创建一个对象
类名 对象名字 = new 类名();

3.无参数的构造方法语法格式
public 类名 () {}

4.有参数构造方法的语法格式
public 类名 (参数) {

}
5.构造方法的作用是啥
构造方法初始化对象的
6.在类中声明方法的语法格式是什么
public void 方法名字 () {}
7.冒泡排序

8.构造代码块执行 比构造方法先执行
9成员变量和局部变量

今天的内容

1.封装

2.this关键字

3.类对象可以作为一个方法的参数

4.多类合作

1.封装

Java 有三大特性: 封装 继承 多态

封装是面向对象的思想的特性

​ 对属性进行封装 对方法进行封装 对类进行封装 对项目进行封装

​ 今天主要讲属性的封装。

​ 写过类,类下m面的成员变量

​ String name;。只需要通过对象.属性 = 初始化值;进行赋值。这样存在一定的隐患

对属性进行封装:

​ 1.对成员变量加修饰符 private

​ 2.在类中书写 set和get方法进行对属性的赋值和取值

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
package com.qfedu.b_fengzhuang;

class Pig {
private String name;
private int age;

//依靠set方法进行赋值了 赋值是没有返回值的
public void setName (String name) {
this.name = name;
}
//有规律 在赋值的时候 set变量名字 小驼峰的命名规则
public void setAge (int age) {
//可以控制变量值的范围 大小
if (age < 0 || age > 100) {
this.age = 0;
} else {
this.age = age;
}

}
//书写get方法
public String getName() {
return name;
}
public int getAge () {
return age;
}
}
public class Demo3 {
public static void main(String[] args) {
Pig pig = new Pig();
pig.setName("猪刚鬣");
pig.setAge(-90);
System.out.println(pig.getName() + ":" + pig.getAge());

}

}

练习:

声明一个Cat类,属性 name age sex weight 必须是private修饰的

对属性进行赋值和取值

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
package com.qfedu.b_fengzhuang;

class Cat {
private String name;
private int age;
private char sex;
private double weight;

public Cat(String name, int age, char sex, double weight) {

this.name = name;
this.age = age;
this.sex = sex;
this.weight = weight;
}
public void setName (String name) {
this.name = name;
}
public String getName () {
return name;
}
public void setAge (int age) {
this.age = age;
}
public int getAge () {
return age;
}
public void setSex(char sex) {
this.sex = sex;
}
public char getSex() {
return sex;
}
public void setWeight (double weight) {
this.weight = weight;
}
public double getWeight () {
return weight;
}
}
public class Demo4 {
public static void main(String[] args) {
//要么使用set方法进行赋值,要么使用构造方法进行赋值。
//这两个选择一个即可
Cat cat1 = new Cat("Jerry", 7, '公', 9);

System.out.println(cat1.getName() + cat1.getSex() + cat1.getAge() + cat1.getWeight());


}

}

案例:

​ 一个Pandas类,属性 name age weight height 要求私有话成员变量 书写set方法

和get方法,对成员变量进行赋值和取值

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
package com.qfedu.b_fengzhuang;

class Pandas {
private String name;
private int age;
private double height;
private double weight;
//快捷键: 右键-》source-》generater getter and setter 全选属性即可
//就是取值
public String getName() {
return name;
}
//就是赋值的 对属性
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}


}
public class Demo5 {
public static void main(String[] args) {
Pandas pandas = new Pandas();
pandas.setName("圆圆");
pandas.setAge(8);
pandas.setHeight(1.2);
pandas.setWeight(100.3);
System.out.println(pandas.getName() + ":" + pandas.getAge() + ":" + pandas.getHeight() + ":" + pandas.getWeight()) ;

}

}

总结:

1
2
3
4
就是要对成员变量就赋值和取值的
1.对实体类中的成员变量进行加private修饰
2.在实体类中 set方法进行赋值 get方法进行取值!!!

20分钟 十二生肖 成员变量加private 修饰,快捷键。对属性进行赋值和取值。

个人能力强的,提前看一下this关键字

2.this关键字

字面意思:这个

​ 1.写在类中,代表当前对象

​ 可以使用this关键字调用属性和方法

​ this这个关键只能在方法(成员方法和构造方法)中使用。

​ 2.this可以调用当前的构造方法(很少用的)

​ 1.只能在构造方法中去调用构造方法

​ 2.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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package com.qfedu.b_fengzhuang;

class Rabbit {
String name;
int age;

public Rabbit(String name, int age) {
//this();//在调用无参构造
this.name = name;
this.age = age;
}
public Rabbit() {
//在Rabbit的无参构造方法中调用了有参的构造方法
this("狗狗", 12);
//这个this 就是rabbit1
System.out.println(this);//代表的当前的对象 打印的是一个内存地址

}
//写一个方法
//在main主函数中调用eat
//对象.eat(); 哪个对象调用 的eat方法 this就是那个对象
public void eat() {
//可以使用this调用属性
this.name = "狗蛋";
System.out.println(this.name);
//可以使用this调用方法
this.test();
}
public void test () {
System.out.println("这个是测试方法");
}

}
public class Demo6 {
public static void main(String[] args) {
Rabbit rabbit1 = new Rabbit();
System.out.println(rabbit1);
//rabbit1.eat();
System.out.println(rabbit1.name);
System.out.println(rabbit1.age);
/**
* com.qfedu.b_fengzhuang.Rabbit@15db9742 this
com.qfedu.b_fengzhuang.Rabbit@15db9742 rabbit1

*/
Rabbit rabbit2 = new Rabbit();
System.out.println(rabbit2);

/**
* com.qfedu.b_fengzhuang.Rabbit@6d06d69c this
com.qfedu.b_fengzhuang.Rabbit@6d06d69c rabbit2

*/

}

}

上午的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
1.封装
对属性的封装
1.对成员变量加修饰符 private JavaBean规范
2.在实体类中写set方法和get方法 为啥要写set方法和get方法
咱们要对属性进行赋值。加上private之后 对象.变量 不能这样来操作了
只能通过set方法进行赋值。通过get方法进行取值

有快捷键

2.this关键字
这个 代表的是当前对象
1.可以调用成员变量 可以调用成员方法
2.可以调用构造方法

关于this关键字注意事项:

​ 1.调用成员变量。在构造方法,在成员方法。

​ 2.调用成员方法。在构造方法,在成员方法。

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 com.qfedu.c_this;

class Person {
String name;
int age;

//验证第一个 this关键字可以在构造方法中调用成员变量
public Person () {
this.eat();
this.name = "狗蛋";
}
//验证第二个 this关键在成员方法中调用成员变量
public void eat () {
//在方法中可以使用this.变量
this.name = "老邢";
System.out.println(name + "在吃饭");
this.test();
}
public void test () {
System.out.println("细细打");
}

}
public class Demo1 {
public static void main(String[] args) {
Person person = new Person ();
System.out.println(person.name);
//person.eat();
}

}

注意事项:这个用的很少!!!

​ 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
package com.qfedu.c_this;

class Dog {
String name;
int age;
public Dog() {
System.out.println("123");
//this("styb", 8);
}
public Dog(String name, int age) {
this();
System.out.println("有参构造");
}



}
public class Demo2 {
public static void main(String[] args) {
//需求:实例化对象dog 要求将有参构造这四个字打印出来
Dog dog = new Dog("goudan", 12);
//Dog dog = new Dog();
}

}

3.类对象可以作为一个方法的参数

方法的参数可以是八大基本数据类型,String,数组

类对象也是可以的

老师来让学生敲代码

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
package com.qfedu.d_args;

class Teacher {
//command的参数是一个类对象
public void command (Student stu) {
stu.coding();
}
}
class Student {
String name;
public void coding () {
System.out.println(name + "敲代码");
}
}
public class Demo1 {
public static void main(String[] args) {
Student student = new Student();
student.name = "骚磊";
Teacher teacher = new Teacher();
//在teacher方法中去调用student对象的一个方法
//最终打印的结果是 student类下面的方法
teacher.command(student);
}

}

人喂狗,狗在吃

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.qfedu.d_args;

class Person {
public void feed (Dog dog) {
dog.eat();
}
}
class Dog {
public void eat () {
System.out.println("狗在吃饭");//牛彩云
}
}
public class Demo2 {
public static void main(String[] args) {
Dog dog = new Dog();
Person person = new Person();
person.feed(dog);
}

}

4.多类合作【重点】

一个类对象可以当成另外一个类的成员变量

人类

​ 属性: 姓名 性别 猫

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 com.qfedu.e_moreclass;

class Person1 {
private String name;
private Cat1 cat1;//一个类对象可以作为另外一个类的属性来使用
//碰到private修饰的属性有set和get的想法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Cat1 getCat1() {
return cat1;
}
public void setCat1(Cat1 cat1) {
this.cat1 = cat1;
}

}
class Cat1 {
private String name;
private char sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}


}
public class Demo2 {
public static void main(String[] args) {
//要对Person1对象的属性进行赋值
Person1 person1 = new Person1();
person1.setName("老万");
Cat1 cat1 = new Cat1();
cat1.setName("小万");
cat1.setSex('母');
person1.setCat1(cat1);
//取值
//通过 人取猫的值
System.out.println(person1.getName());//获取人的名字
System.out.println(person1.getCat1());//获取猫对象
System.out.println(person1.getCat1().getName());//获取猫的名字
System.out.println(person1.getCat1().getSex());
}

}

紧紧围绕者一个点:赋值和取值 只是针对于属性 的

day10

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
1.构造代码块和构造方法的区别

代码块

public 类名 () {

}
都是实例化一个对象的时候执行的
只不过构造代码块先于构造方法执行的
2.局部变量和成员变量区别
局部变量写在方法中,只能在方法体中使用,出了这个方法就不能再使用了
成员变量写在类中,整个类都可以使用的。
3.声明类的语法格式
class 类名 {
属性
构造方法
方法
}
4.一个类中属性的意义是啥
用来描述一个类的特征的,可以通过对象对这个特征进行赋值的
5.构造方法的语法格式
public 类名 () {

}
public 类名 (参数) {

}
6.逻辑运算符的简单介绍

7.封装
1.对成员变量加修饰符 private
2.一定要写setter和getter方法进行赋值和取值即可
8.this关键字
1.this关键字可以调用成员属性和方法
2.this还可以调用构造方法
9.一个类对象作为方法的参数
10.多类合作

今天的内容

1.多类合作几个全部讲

2.继承

3.继承的内存分析

4.重写和重载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1.
部门类
员工类
部门类下面有员工
2.
老师类
学生类
老师带了很多学生 把学生存倒数组中 STudent[] stus = new Student[6];
3.
成年人类
孩子类
玩具类
4.
需求:
两个宠物一个狗一个猫宠物饿了,需要主人给宠物喂食
1.不同的宠物吃的不同
2.不同的宠物吃完食体力值增加
3.主人和狗玩游戏 接飞盘的游戏。狗体力值减去10,但是会和主人的亲密度提升5
4.主人和猫玩游戏 滚毛球。猫体力值减去12 ,但是会和主人的亲密度提升7

人类
猫类
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
package com.qfedu.a_homework;

//部门类
class Department {
private String depId;//部门id
private String deptName;//部门的名字
private Employee employee;//部们下面的员工
public String getDepId() {
return depId;
}
public void setDepId(String depId) {
this.depId = depId;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}


}
//员工类
class Employee {
private String name;//员工的名字
private int age;//员工的年龄

private char sex;//员工的性别

public String getName() {
return name;
}

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

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public char getSex() {
return sex;
}

public void setSex(char sex) {
this.sex = sex;
}


}
public class Demo1 {
public static void main(String[] args) {
//创建Employee对象
Employee employee = new Employee();
employee.setName("张三");
employee.setAge(28);
employee.setSex('男');
//先创建部门对象
Department department = new Department();
//对department对象属性进行赋值
department.setDepId("0001");
department.setDeptName("研发部");
department.setEmployee(employee);
//以上是在赋值
//取值
//想要部门的id
System.out.println(department.getDepId());
//想要获取部门的名字
System.out.println(department.getDeptName());
//想要获取部门下面的员工对象,会打印的啥? 会打印的是地址!!!
System.out.println(department.getEmployee());
//能够获取出来employe对象了。
//能不能获取emplopyee对象的属性值呢?

System.out.println("员工的名字:" +department.getEmployee().getName());
System.out.println("员工的年龄:" + department.getEmployee().getAge());
System.out.println("员工的性别:" + department.getEmployee().getSex());
}

}

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
package com.qfedu.a_homework;

class Teacher {
private String name;//老师的姓名
private char sex;
private int age;
//老师下面有很多的学生 Student[] stus = new Student[3];
private Student[] student;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student[] getStudent() {
return student;
}
public void setStudent(Student[] student) {
this.student = student;
}


}
class Student {
private String name;

public String getName() {
return name;
}

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

}
public class Demo2 {
public static void main(String[] args) {
Student[] stus = new Student[2];//现在数组是一个空的
//对数组进行赋值
Student student = new Student();
student.setName("骚磊");
Student student2 = new Student();
student2.setName("老万");
stus[0] = student;
stus[1] = student2;
//脑海里面 想到stus是一个容器 数组, 里面已经放了两个值了
//两个对象

Teacher teacher = new Teacher();
teacher.setName("老邢");
teacher.setAge(89);
teacher.setSex('女');
//现在setStudent的参数是一个数组
//stus里面有值了 两个对象student
teacher.setStudent(stus);

//以上都是在赋值
//取值
Student[] students = teacher.getStudent();
for (int i = 0; i < students.length; i++) {
System.out.println(students[i].getName());
}

}

}

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
package com.qfedu.a_homework;

class Adult {
private String name;//成年人的名字
private Child child;//成年人下面的孩子对象
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Child getChild() {
return child;
}
public void setChild(Child child) {
this.child = child;
}

}
class Child {
private String name;
private int age;
private Toy toy;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Toy getToy() {
return toy;
}
public void setToy(Toy toy) {
this.toy = toy;
}

}
class Toy {
private String name;//玩具的名字
private double price;//玩具的价格
private String kind;//玩具的种类
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getKind() {
return kind;
}
public void setKind(String kind) {
this.kind = kind;
}

}
public class Demo3 {
public static void main(String[] args) {
Toy toy = new Toy();
toy.setName("骚奥特曼");
toy.setPrice(67.8);
toy.setKind("皮套");
Child child = new Child();
child.setName("小骚磊");
child.setAge(1);
child.setToy(toy);
Adult saolei = new Adult();
saolei.setName("骚磊");
saolei.setChild(child);
//以上都是在赋值
//取值
//需求
//通过成年人找到孩子的名字
//saolei.getChild()获取孩子对象 .getName
System.out.println(saolei.getChild().getName());//获取孩子的名字
System.out.println(saolei.getChild().getAge());//获取孩子的年龄
//通过成年人获取玩具的种类 名字 价格的
System.out.println(saolei.getChild().getToy().getName());
System.out.println(saolei.getChild().getToy().getKind());

}

}

1.继承

Java 有三大特性: 封装 继承 多态

1.1.生活中的继承

子承父业

龙生龙 凤生凤

老鼠生来会打洞

你长得真像你父亲

1.2.Java中继承

继承是类和类之间的关系

继承至少得两个类:

语法格式:

1
2
3
class B  extends A {

}

其中 B是一个类,A是一个类

B类继承了A类。 B叫A的子类。A是B的父类(超类,基类)

入门案例:

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
package com.qfedu.b_extends;

class Father {
String name;
int age;
//行为
public void eat () {
System.out.println("吃大盘鸡拌面");
}
}
//使用了extends以后 Son 类就继承了Father这个类
//就意味着我Son类可以使用Father类下面某些属性和某些方法
class Son extends Father{

}

public class Demo1 {
public static void main(String[] args) {
Son son = new Son();
//发现继承以后,可以使用父类一些属性
son.name = "小骚磊";
son.age = 1;
System.out.println(son.name);
System.out.println(son.age);
son.eat();

}

}

案例:

Animal 类 父类

Dog类 子类

Cat类 子类

继承的意思,就是将父类的属性和方法拿到子类中去使用

1.成员变量(属性)

​ 公开的和默认的属性,子类可以继承使用的

​ 私有的成员变量,子类无法使用的

2.成员方法

​ 公开的和默认的成员方法,子类可以继承使用

​ 私有的成员方法,子类无法使用的

总结:凡是私有的 无法继承。

3.构造方法

​ 先执行父类的构造,再执行子类的构造方法

​ 如果父类中有有参构造,但是没有无参构造。子类会报错

​ 关于构造方法:父类与子类的构造方法的形式保持一致。
​ 父类中有无参构造。子类也有无参构造。父类中没有无参构造,子类也没有无参构造方法

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
package com.qfedu.c_extends;

class Father {
//只要是公开的或者默认的属性,子类可以使用的
public String name;//公开的一个属性
int age;//就是默认的属性
private int id;//private修饰的 子类不能使用

public Father () {
System.out.println("父类的构造方法");
}
public Father (String name) {
this.name = name;
}
//eat方法 使用public修饰的 子类可以使用
public void eat () {
System.out.println("吃窝窝头");
}
//默认的方法 子类是可以使用的
void work () {
System.out.println("开拖拉机耕地");
}
// 使用private修饰的方法就是私有化的方法,子类能调用吗?不能
private void smoking () {
System.out.println("抽旱烟");
}
}
class Son extends Father {


//在子类写有参构造即可


}
public class Demo1 {
public static void main(String[] args) {
Son son = new Son();
//验证name age在子类中可以使用的
son.name = "狗蛋";
son.age = 12;
//son.id = 12;
son.eat();//可以使用父类的公开的方法
son.work();
//不可以使用父类私有化的方法
//.son.smoking();

}

}

刚才在写代码的时候,发现私有成员变量子类不能用。还有私有化的方法子类不能调用。咋办?

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 com.qfedu.c_extends;

class Father1 {
private String name;

public String getName() {
return name;
}

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

private void smoking () {
System.out.println("抽旱烟");
}
public void test () {
smoking();
}


}
class Son1 extends Father1 {

}
public class Demo2 {
public static void main(String[] args) {
Son1 son1 = new Son1();
//咋办? 可以使用setter和getter方法
//son1.name = "";
son1.setName("狗蛋");
System.out.println(son1.getName());
son1.test();
}

}

练习的案例:

​ Animal 类:

​ 属性 : name, age ,sex 私有化的

​ 方法: 吃 运动

​ 子类:Panda

​ 使用Panda继承Animal 并可以使用Animal下面的所有属性和方法,对属性进行赋值

​ 方法调用

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
package com.qfedu.c_extends;

class Animal {
private String name;
private int age;
private char sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
//方法
public void eat () {
System.out.println("吃饭");
}
public void sport () {
System.out.println("运动");
}

}
class Panda extends Animal {

}
//继承有啥好处呢?代码可以重复利用
class Cat extends Animal {

}
class Dog extends Animal {

}
public class Demo3 {
public static void main(String[] args) {
Panda panda = new Panda();
panda.setName("熊大");
panda.setAge(9);
panda.setSex('公');
panda.eat();
panda.sport();
}

}

继承:

​ Java中的继承都是单继承。只能有一个父类

​ Java中可以多重继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.qfedu.c_extends;

class A {

}
class B extends A{

}
class C extends B {

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

}

}

总结:

1
2
3
4
1.至少两个类,使用关键字extends
2.子类是否能使用父类的成员变量和成员方法
子类不能使用父类私有化的所有的东西

1.3关于父类子类的内存分析

1

1.4重写【重点】

Override

重写目的:子类可以继承父类的非私有化的方法,但是有的 时候父类的需求满足不了子类的需求了,这个时候需要重写父类非私有的方法

​ 重写要求:

1
2
3
4
1.必须有继承关系
2.父类的方法必须是非私有化的
3.在子类中重写父类的方法,这个方法除了方法体不一样其他都一样的。
4.必须再子类中去重写
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 com.qfedu.d_override;

class Father {
public void eat () {
System.out.println("吃粗粮。。。。。。");
}
public void driver () {
System.out.println("开拖拉机。。。。。");
}
}
//当父类不能满足子类的需求的话可以在子类中重写父类的方法
class Son extends Father {
//重写的时候在子类中 只需要打上方法的名字一敲回车即可
//重写的方法 和父类 的 返回值 参数 方法名字 一模一样,但是方法体不一样的
@Override//是重写的严格限定,只要有这个,就证明咱们下面的这个方法
//就是重写的方法,告知程序员 此时eat方法是重写的不是自己独有的
public void eat() {
System.out.println("吃白面馒头......");
}
@Override
public void driver() {
System.out.println("开小汽车");
}

}
public class Demo1 {
public static void main(String[] args) {
Son son = new Son();
son.eat();
son.driver();
//重写的话,是不影响父类的方法的
Father father = new Father();
father.eat();
father.driver();
}

}

案例:

1
2
3
4
5
6
7
8
9
10
父类:
交通工具:
方法 run();
两个子类:
飞机:
方法 run()
高铁:
方法 run()
公交车:
方法 run()
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 com.qfedu.d_override;

class Transportation {
public void run () {
System.out.println("可以跑......");
}

}
class Fly extends Transportation {
//是继承 我就u可以重写父类下面的方法了
@Override//开启重写的严格的限制,告知编译器,下面的方法必须是重写的
public void run () {
System.out.println("飞机跑的很快大概500km/h");
}

}
class Train extends Transportation {
@Override
public void run() {
System.out.println("在铁轨上跑的300km/h");
}
}
class Bus extends Transportation {
@Override
public void run() {
System.out.println("在公路上跑的60km/h");
}
}
public class Demo2 {
public static void main(String[] args) {
Train train = new Train();
train.run();
}


}

1.5重载【overload】

在Java中同一个类中可以有很多个方法。方法名字一样。但是参数类型不一样。这种叫重载

总结:

1
2
3
4
5
1.方法的重载必须在同一个类中
2.方法名字必须一致
3.方法的参数类型必须不一样
4.方法的返回值可以不一样
5.无参构造和有参构造 也是一种重载

面试题: 重写和重载的区别

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 com.qfedu.d_override;

class Person {
//在一个类中,方法法名字一样,但是参数一定不一样。这叫方法的重载
//返回值可以不一样
public void test () {
System.out.println("test");
}
public void test (String name) {
System.out.println(name);
}
public void test (int i) {
System.out.println(i);
}
void test (double d1) {

}
public String test(String str1, String str2) {
return str1 + str2;
}
}
public class Demo3 {
public static void main(String[] args) {

}

}

day11

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
1.成员变量和局部变量的区别
成员变量:
定义在类体中,整个类可以使用
局部变量:
定义在方法中,只能在方法使用
2.继承的语法格式
class B extends A {

}
3.关于属性和方法子类继承父类一些要求
不能使用父类的私有化的属性和方法
4.重写的目的
父类的需求不能满足子类的需求
5.重写和重载的区别
重写:
1.必须继承关系
2.在子类中去重写
3.除了方法体不一样其他都一样的
4.不能是私有化方法
重载:
1.必须再一类中,至少两个方法
2.方法名字必须一样,参数类型 一定不一样
3.返回值可以不一样
6.多类合作
成年人类
孩子类
玩具类
一个类中让另外一个类对象作为属性看待
7.一个类对象作为一个方法的参数的案例
人喂狗 狗吃饭
public void feed (Dog dog) {}

今天的内容

1.super关键字【鸡肋】

2.抽象类

3.final关键字

4.接口

1.super关键字

只能用于继承,并在子类中使用。代表的意思是父类对象

this:

​ 代表当前类对象。

​ 可以调用属性和方法

​ 可以调用构造方法

super:

​ 代表是父类的对象

​ 可以调用父类的成员变量和成员方法

​ 注意事项:当super调用属性的时候,就是内存里面那一个

​ 可以调用父类的构造方法

​ 真实开发的时候, super.父类的方法。证明在调用父类的方法

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
package com.qfedu.b_super;
class Father1 {
String name;
public Father1 () {
System.out.println("Father1的无参构造");
}
public Father1 (String name) {
System.out.println("Father1有参构造");
}
}
class Son1 extends Father1 {
//在子类中无论你写了有参构造和无参构造,都要去执行父类的无参构造
//除非你自己调用父类有参构造方法
public Son1(String name) {
//在调用父类的无参构造方法
//super();
super("狗蛋");
}
}
public class Demo2 {
public static void main(String[] args) {
Son1 son1 = new Son1("狗蛋");

}

}

2.抽象类【重要】

在面向对象中,所有的对象可以通过类来创建。反过来说,并不是所有的类都可以创建对象的。如果一个类中没有足够完整的信息来描述具体的对象的话,那么这个类叫抽象类。

在Java中使用关键字abstract修饰类,这个类叫抽象类。

2.1abstract关键字

abstract修饰的类叫抽象类

abstract修饰的方法叫抽象方法

总结:abstract 只能修饰类和方法

语法格式:

1
2
3
4
5
6
7
8
9
abstarct class 类名{
普通的方法;
public void eat () {


}
抽象方法;
public abstarct void sleep ();

入门案例:

先学会说声明出来一个抽象类

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 com.qfedu.c_abstract;

//声明一个抽象类
abstract class Person {

//在抽象类中可以写普通成员方法
public void eat () {
System.out.println("今天中午吃外卖。。。。。。");
}
//定义一个抽象方法 是不完整的方法 没有方法体的
abstract public void work();

}
//定义了咋用啊? 抽象类创建不了对象的 咋解决?
//解决方案: 再写一个普通类去继承抽象类即可
class Man extends Person {
//the type Man must implement the inherited
//abstract method Person.work()
@Override
public void work() {
// TODO Auto-generated method stub
System.out.println("劳动力");
}


}
public class Demo1 {
public static void main(String[] args) {
Man man = new Man();
man.eat();
man.work();
}

}

注意事项:

​ 1.如果一个类中用abstract修饰的话,那么这个类叫抽象类

​ 2.抽象类中可以有普通成员方法和抽象方法

​ 3.抽象方法没有方法体,是不完整的方法

​ 4.抽象类不能被实例化

​ 5.写一个普通的类去继承抽象类

​ 6.在子类中一定去实现(重写)抽象类中所有的抽象方法

​ 7.非抽象方法可以重写也可以不重写

​ 8.一个抽象类能不能去继承另外一个抽象类? 可以的!!!

​ 9.抽象类可以继承非抽象类

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
package com.qfedu.c_abstract;

class Cell {
public void add () {
System.out.println("分裂");
}
}
abstract class Animal extends Cell{
public abstract void run();
}
abstract class Monkey extends Animal{//抽象类
public void call () {//普通的成员方法
System.out.println("咿咿呀呀.......");
}
public abstract void eat();
public abstract void sleep();
}
class People extends Monkey {

@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("吃肉!!!");
}

@Override
public void sleep() {
// TODO Auto-generated method stub
System.out.println("躺着睡。。。");
}
@Override
public void call() {
System.out.println("嘻嘻哈哈说话");
}

@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("人站立奔跑。。。");
}

}
public class Demo2 {
public static void main(String[] args) {
People people = new People();
people.add();
}
}

练习:

​ 抽象类:

​ Animal:

​ play()方法 抽象方法

​ eat方法 抽象方法

​ sleep方法 普通方法

​ Panda类去继承ANimal

​ Cat类去继承ANimal

​ 实例化Panda Cat 调用 上面的几个方法。

上午讲的

1
2
3
4
5
6
1.super关键字
1.可以调用父类的成员变量和成员方法
2.可以父类的构造方法,在子类的构造方法中

2.抽象类语法格式

3.final关键字

final中文意思: 修饰符

​ 最终的,最后的

用法:

​ 1.final可以修饰成员变量

​ 使用final修饰的成员变量,一定要赋值(初始化)。而且不能修改。

​ 2.final可以修饰局部变量

​ 使用final修饰局部变量的时候,可以先对变量不赋值,使用之前进行赋值。

​ 但是一旦赋值以后就无法更改。

​ 3.final可以修饰成员方法

​ final修饰的成员方法不能被重写,牵涉到继承

​ 4.final可以修饰一个类

​ final修饰的类不能被继承

​ 5.final可以修饰对象的引用

​ 修饰对象引用 一旦被赋值 就无法改变

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 com.qfedu.d_final;

class Person {
final String name = "狗蛋";

public void test () {
final int i;
i = 30;
//i = 80;//一旦被赋值,就无法改变了
System.out.println(i);
}
public final void eat () {
System.out.println("吃饭");
}
}
//class Man extends Person {
// @Override
// public void eat() {
// System.out.println("吃的多");
// }
//}
public class Demo1 {
public static void main(String[] args) {
final Person person = new Person();
System.out.println("Person:" + person);
//一旦使用final修饰person 对象引用 是一个固定的内存地址
Person person1 = new Person();
System.out.println("Person1:"+ person1);
//person.name = "嘻嘻";
//person = person1;//将person1赋值给了person对象
System.out.println(person);
}

}

4.接口【重要】

4.1生活中的接口

USB

插座

起到一个扩展的功能

4.2Java中接口

语法格式:

1
2
3
4
interface  接口名字 {
成员变量
成员方法
}

实现接口使用关键字implements

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
package com.qfedu.e_interface;

interface A {
//接口下面的属性都是常量 常量是使用static 和final修饰的
//只不过在接口中把 static和fianls省去了 常量的名字都要大写
String NAME = "狗蛋";
//在接口一般不写属性的!!!
//成员方法 在接口中全部是抽象的方法
public void eat ();
public void sleep();

}
//无法实例化接口A ,咋办?新建一个类去实现(implements)接口
class TestA implements A {

@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("吃好饭");
}

@Override
public void sleep() {
// TODO Auto-generated method stub
System.out.println("睡好觉");
}

}
public class Demo1 {
public static void main(String[] args) {
TestA testA = new TestA();
testA.eat();
testA.sleep();

System.out.println(testA.NAME);
}

}

接口的注意事项:

​ 1.使用关键字 interface 声明出来一个接口

​ 2.接口面可以有属性,但是是static 和final修饰的属性。被称为常量。几乎不用

​ 3.接口下面全部抽象的方法,不带方法体的

​ 4.jdk1.8以后是可以有默认(default)的方法的,这个默认方法带有方法体【重点!!!】

​ 5.接口下面没有构造方法,不能被实例化

​ 6.去使用一个普通的类去实现这个接口,使用关键字implements

​ 7.一定要在实现类中去实现所有的抽象方法

​ 8.一个普通的类可以实现多个接口,弥补了单继承的局限性

​ 9.一个接口可以去继承另外一个接口

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
package com.qfedu.e_interface;

interface B2 {
public void work();
}
interface B1 extends B2{
public void smoking();
}

interface A1 {
String NAME = "狗蛋";


public void test();
public void eat();
public default void sleep () {
System.out.println("睡觉睡得啥也不知道");
}
}
class TestA1 implements A1, B1{

@Override
public void test() {
// TODO Auto-generated method stub
System.out.println("测试");
}

@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("吃东西");
}
@Override
public void sleep() {
System.out.println("睡得什么都不会了");
}

@Override
public void smoking() {
// TODO Auto-generated method stub
System.out.println("不要在整栋楼抽烟!!!");
}

@Override
public void work() {
// TODO Auto-generated method stub

}

}
public class Demo2 {
public static void main(String[] args) {
TestA1 testA1 = new TestA1();
testA1.eat();
testA1.test();
testA1.sleep();
}

}

4.3案例

电脑类去实现以下的三个接口。

​ 电源接口

​ 鼠标接口

​ 网络接口

比如上面有三个接口,电脑是一个类,让电脑本身不具备插电源 连网线连鼠标的

只有在电脑类基础之上 去实现三个接口之后,那么电脑就会拥有充电 联网连鼠标这些功能的

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
package com.qfedu.e_interface;


//电源接口
interface Adapter {
public void input();//充电
}
//USB 接口 连接鼠标
interface USB {
public void mouse();
}
//网络接口 可以联网
interface Net {
public void internet();
}
class Computer implements Adapter, USB, Net{

@Override
public void internet() {
// TODO Auto-generated method stub
System.out.println("联网");
}

@Override
public void mouse() {
// TODO Auto-generated method stub
System.out.println("连接鼠标");
}

@Override
public void input() {
// TODO Auto-generated method stub
System.out.println("充电!!!");
}

}
public class Demo3 {
public static void main(String[] args) {
Computer computer = new Computer();
computer.mouse();
computer.input();
computer.internet();
}

}

4.4案例

假如学校有接待处。接待不同的人,有不同的方式。

身份
学生 食堂 学生宿舍
老师 教师食堂 教师公寓
领导 招待所 招待所

理论上来讲,每个人都是以恶搞不同的额对象。实现各自的方法

咱们能归纳出来一个模板。让学生 老师 领导 都去实现这个模板。

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
package com.qfedu.e_interface;

interface Person {
void eat();
void sleep();

}
class Stdudent implements Person {

@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("在学生食堂......");
}

@Override
public void sleep() {
// TODO Auto-generated method stub
System.out.println("在宿舍睡觉");

}

}
class Teacher implements Person {

@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("在教师食堂。。。。。。");
}

@Override
public void sleep() {
// TODO Auto-generated method stub
System.out.println("在教师公寓。。。。。。");
}


}
class Leader implements Person {

@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("招待所吃。。。");
}

@Override
public void sleep() {
// TODO Auto-generated method stub
System.out.println("在招待所。。。。");
}

}
public class Demo4 {
public static void main(String[] args) {
//实例化三个对象,调用方法即可
}

}

day12

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
1.抽象类的声明
abstract class 类名 {
普通的成员方法;
抽象方法;
}
2.关于声明和使用抽象类得注意事项(共9条)
1.使用abstarct修饰的类叫抽象类
2.抽象类下面有抽象方法和普通方法
3.抽象方法是没有方法体的
4.抽象累不能被实例化
5.写一个普通类去继承它
6.去实现所有抽象方法
7.非抽象方法也可以重写
8.一个抽象类可以继承另外一个抽象类的
9.抽象类可以继承非抽象类
3.final关键字(5tiao)
1.final修饰成员变量
2.final修饰局部变量
3.final修饰成员方法
4.final修饰类
5.final对象引用
4.接口得声明语法格式
5.关于声明和使用接口的注意事项(共9条)
6.super关键字得使用
super调用父类的属性和方法
super调用父类构造方法

回顾

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
掌握到什么程度:
1.抽象类
2.final
3.接口
1.抽象类
abstract class Person {
public abstract void eat ();
public abstract void sleep();
public void work() {
sout();
}
}
class Man extends Perso {
public void eat () {

}
public void sleep() {

}

}
main {
Man man = new Man ();
man.eat();
man.sleep();
man.work();
}

2.接口
interface A {
void eat();
void sleep();

}
class TestA implements A, B {
public void eat () {

}
public void sleep() {

}
}
main {

}

今天的内容

1.多态

1.Java中的多态

Java有三大特性:封装 继承 多态

多态: 多种形态。是面向对象的三大特性之一。多态是建立在封装和继承之上

1.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
package com.qfedu.a_fun;

class Person {
public void eat () {
System.out.println("吃饭");
}
public void eat (String food) {
System.out.println("吃" + food);
}
}
class Man extends Person {
@Override
public void eat() {
System.out.println("吃枸杞");
}
@Override
public void eat(String food) {
System.out.println("吃"+ food);
}
}
public class Demo1 {
public static void main(String[] args) {

}

}

1.2对象的多态【重点】

1
2
3
4
5
1.一个对象 的编译类型和运行类型是不一样
2.编译类型是在定义对象的时候,就已经确定好的
3.运行类型是可以改变的
4.编译类型看=的左边 运行类型看 =的右边
Person person = new Person();

多态: 父类引用指向子类的对象

Animal animal = new Dog();

Animal anima1 = new Cat();

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
package com.qfedu.b_duotai;

class Animal {
public void cry () {
System.out.println("动物在叫......");
}
}
class Dog extends Animal {
@Override
public void cry() {
System.out.println("汪汪汪......");
}
//自己独有的方法
public void eat () {
System.out.println("狗吃shit");
}
}
class Cat extends Animal {
@Override
public void cry() {
System.out.println("喵喵喵.....");
}
public void sleep () {
System.out.println("睡觉打呼噜");
}
}
public class Demo1 {
public static void main(String[] args) {
//多态 父类的引用指向子类的对象
Animal animal = new Dog();
animal.cry();
//父类的引用是指向不了子类独有的方法的,就意味着
//父类的引用不能调用子类独有的方法
//animal.eat();
Animal animal2 = new Cat();
animal2.cry();
//animal2.sleep();
}

}

注意事项:

​ 多态:

1.必须有继承

2.必须有重写

3.=左边是父类引用 =右边是子类的对象

1.3父类的引用指向子类的对象在开发中如何使用

之前有一个作业 : 人喂狗,狗吃饭。 人喂猫,猫吃饭

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
package com.qfedu.c_duotai;

class Person {
// public void feed (Dog dog) {
// dog.eat();
// }
// public void feed (Cat cat) {
// cat.eat();
// }
//在开发中,一个方法的参数是父类的引用。但是真正传的值是子类的对象

public void feed (Animal animal) {
animal.eat();
}
}
interface Animal {
public void eat ();
}
class Dog implements Animal{
@Override
public void eat () {
System.out.println("狗在吃骨头......");
}
}
class Cat implements Animal{
@Override
public void eat () {
System.out.println("猫吃鱼......");
}
}
public class Demo1 {
public static void main(String[] args) {

Person person = new Person();
/**
* Animal animal = new Cat();
* public void feed (Animal animal) {
animal.eat();
}
*/
person.feed(new Cat());
/**
* Animal animal = new Dog();
* public void feed (Animal animal) {
animal.eat();
}
*/
person.feed(new Dog());
}

}

1
2
3
4
5
6
7
8
9
10
Person类
Student类 千锋学员
方法 执行学生手册
Teacher类 千锋讲师
方法 执行讲师手册
Employee 千锋的员工
方法 执行员工手册
Manager 管理层
管理学生 讲师 员工
manage();
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 com.qfedu.c_duotai;

class Manager {//管理层 去管理学员 讲师 员工
public void manage (Person1 person1) {
person1.excute();
}
// public void manage (Teacher tea) {
// tea.excute();
// }
// public void manage (Employee emp) {
// emp.excute();
// }
}
interface Person1 {
void excute();
}
class Student implements Person1{
public void excute () {
System.out.println("执行学员手册。。。。");
}
}
class Teacher implements Person1{
public void excute () {
System.out.println("执行讲师手册。。。。。");
}
}
class Employee implements Person1{
public void excute () {
System.out.println("执行员工手册。。。。。");
}
}
public class Demo2 {
public static void main(String[] args) {
Person1 person1 = new Student();
Manager manager = new Manager();
manager.manage(person1);
}

}

案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
编写程序实现比萨制作。需求说明编写程序,可供选择的比萨有:培根比萨和海鲜比萨。

实现思路及关键代码

1) 分析培根比萨和海鲜比萨

2) 定义比萨类

3) 属性:名称、价格、大小

4) 方法:展示

5) 定义培根比萨和海鲜比萨继承自比萨类

6) 定义比萨工厂类,根据输入信息产生具体的比萨对象
PizzaFactory {
createPizza(Pizza);//如果传的参数培根披萨就是生产培根披萨 如果传的是海鲜披萨就是生产的海鲜披萨
}
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
package com.qfedu.c_duotai;

class Pizza {
private String name;//名字
private double price;//价格
private double size;//尺寸
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public double getSize() {
return size;
}
public void setSize(double size) {
this.size = size;
}

//展示方法
public void getInfo () {

}
}
class BaconPizza extends Pizza{
@Override
public void getInfo() {
System.out.println("披萨的名字为:" + getName() + ",披萨的价格:" + getPrice() + ",披萨的尺寸:" + getSize());
}
}
class SeaPizza extends Pizza {
@Override
public void getInfo() {
System.out.println("披萨的名字为:" + getName() + ",披萨的价格:" + getPrice() + ",披萨的尺寸:" + getSize());
}
}
//披萨的生产工厂
class PizzaFactory {
//生产披萨的方法
public void createPizza (Pizza pizza) {
pizza.getInfo();
}

}
public class Demo3 {
public static void main(String[] args) {
Pizza pizza = new SeaPizza();
pizza.setName("海鲜披萨");
pizza.setPrice(78.9);
pizza.setSize(6.7);
PizzaFactory pizzaFactory = new PizzaFactory();
pizzaFactory.createPizza(pizza);
//生产培根披萨
Pizza pizza2 = new BaconPizza();
pizza2.setName("培根披萨");
pizza2.setPrice(45.9);
pizza2.setSize(7.2);
pizzaFactory.createPizza(pizza2);
}

}

1.4多态的转型【重点】

1.4.1多态的向上转型

本质就是:父类的引用指向子类对象

语法格式:

​ 父类 父类引用 = 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
package com.qfedu.d_duotai;

class Person {
public void eat () {

}
}
class Student extends Person {
@Override
public void eat() {
System.out.println("学生吃饭,吃披萨");
}
public void sleep () {
System.out.println("中午不谁下午崩溃!!!");
}
}
public class Demo1 {
public static void main(String[] args) {
Person person = new Student();//向上转型
person.eat();
//person.sleep();
}

}

1.4.2多态向下转型

语法格式:

1
2
父类类型 父类引用 = 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
package com.qfedu.d_duotai;

class TestA {
//Object 是所有类的父类
public void test (Object obj ) {
//必须给我打印一个String类型的狗蛋,我不要Object类型的狗蛋
// String str = (String) obj;
// System.out.println(str);
int i1 = (int)obj;
System.out.println(i1);

}
}
public class Demo4 {
public static void main(String[] args) {
TestA testA = new TestA();
//testA.test("狗蛋");
Object object = "狗蛋";
testA.test(98);
testA.test('狗');
}

}

回顾上午的

1
2
3
4
5
6
7
8
9
10
11
1.多态
父类的引用指向子类的对象
父类引用 对象 = new 子类();

真实的开发的时候,一个方法的参数传的是一个类的父类对象形参。但是真正调用这个
方法的时候,传的是子类对象。实参
2.
向上转型=====》 父类引用指向了子类的对象 子类赋值给父类引用
向下转型=====》将父类的引用赋值给子类 父类赋值给子类引用
注意点:
先向上转型,再向下转型

1.5instanceof 关键字

比较操作符,返回值是布尔类型的数据

语法格式:

1
2
对象引用  instanceof  运行类型

用来判断对象的运行类型(=右边), 是否是xx类型或者xx类型的子类

目的是为了在强转的时候不出现问题

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
package com.qfedu.e_instanceof;

class AA {}
class BB extends AA {}
public class Demo1 {
public static void main(String[] args) {
BB bb = new BB();
BB bb1 = new BB();
AA aa = new AA();
//instanceof 的左边放的对象的引用,右边是类
System.out.println(bb instanceof BB);//true
System.out.println(bb1 instanceof BB);//true
//判断对象bb是否是AA的对象或者子类的对象
System.out.println(bb instanceof AA);//true
System.out.println(aa instanceof AA);//true
System.out.println(aa instanceof BB);//false
//总结: 左边 的辈分小(对象的引用) 右边辈分大(类) 屡试不爽
AA aa2 = new BB();
System.out.println(aa2 instanceof AA);//true
System.out.println(aa2 instanceof BB);//true

//
Object object = new Object();
System.out.println(object instanceof AA);//false
System.out.println(object instanceof Object);//true

String string = "qwer";
System.out.println(string instanceof Object);//true
}
}

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 com.qfedu.e_instanceof;

class Employee {}
class Monkey {
//这个方法的返回值是一个字符串
public String xixi(Object obj) {
//Object obj = new String("狗蛋");
//obj instanceof String
if (obj instanceof String) {
String string = (String)obj;
return "传给我的 参数是字符串类型的数据";
} else if (obj instanceof Integer) {
Integer i1 = (Integer)obj;
return "传给我的 参数是int类型的数据";
} else if (obj instanceof Employee) {
Employee employee = (Employee)obj;
return "传给我的参数是一个Employee对象";
}
else {
return "参数不合法";
}


}
}
public class Demo3 {
public static void main(String[] args) {
Monkey monkey = new Monkey();
//System.out.println(monkey.xixi("狗蛋"));

//System.out.println(monkey.xixi(89));
Employee employee = new Employee();
System.out.println(monkey.xixi(employee));
String string = new String();
}

}

day13

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
1.多态的向上转型和向下转型
向上转型: 父类的引用指向子类的对象
Person person = new Man();
向下转型: 将父类的引用强转为子类的对象
Man man = (Man) person;
2.instanceof关键字的用法
引用 intanceof 运行类型
3.抽象类声明方式
abstract class Person {

}
4.接口的声明方式
interface 接口名字 {

}
5.继承的语法格式
class B extends A {

}
6.重写与重载
重写:
必须是继承关系,在子类中将父类的方法给覆盖
重载:
在一个类中,方法名字一样,参数列表不一样
7.final关键字用法
1.修饰成员变量
2.修饰局部变量
3.修饰成员方法
4.修饰类
5.修饰对象引用

回顾

1
2
3
4
1.父类的引用指向子类的对象(向上转型的)
真实的开发的时候 方法的参数是父类的引用。但是调用方法的时候,传参传的是子类的对象
2.向下转型 需要强转的。先向上转型再向下转型。
3.instanceof

今天的内容

1.static

2.异常

1.static关键字【重点】

static中文意思:静态的

static是和对象无关的。

1.1生活的角度来理解静态的资源

公共的资源的都属于静态的东西

​ 对象可以使用静态的资源,但是和对象无关

​ 厕所里面直饮机 就是静态资源

​ 对象.name

1.2Java中的静态

1.修饰成员变量 静态属性

2.修饰成员方法 静态方法

3.修饰代码块 静态代码块

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 com.qfedu.a_static;

class Man {
static String name;//静态的属性 和对象无关的
//静态方法
public static void eat () {
System.out.println("吃饭喝酒");
}
//静态代码块
static {
System.out.println("嘻嘻");
}
}
public class Demo1 {
public static void main(String[] args) {
//咋使用 类.静态的属性
Man.name = "狗蛋";
System.out.println(Man.name);
//使用 类.静态方法名字()
Man.eat();

}

}

1.2.1static修饰成员变量

静态成员变量:

static String name;

语法格式:

1
static 数据类型  变量名;

注意事项:

​ 1.使用static修饰的变量叫静态变量

​ 2.代码中对象还没有创建的时候,如果加载了类,static修饰的属性已经存在了,和对象没有关系。

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

class Person {
String name;
int age;
static String country;
}
public class Demo2 {
public static void main(String[] args) {
Person sb = new Person();
sb.name = "张三";
sb.age = 23;
Person.country = "中国";
//The static field Person.country
//should be accessed in a static way
System.out.println(sb.country);//中国
System.out.println(Person.country);//in a static way
sb.country = "PRC";
System.out.println(Person.country);//PRC
}

}

1

总结:

1
2
以后记住:
类.静态属性即可
1.2.2static修饰成员方法

静态方法

语法格式:

1
public static 返回值 方法的名字 (参数列表) {}

调用静态方法:

1
类.方法名字();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.qfedu.a_static;

class Dog {
public void eat () {
System.out.println("普通的成员方法");
}
public static void sleep () {
System.out.println("睡吧不用看家了");
}
}
public class Demo3 {
public static void main(String[] args) {
Dog.sleep();
//Dog.eat();只能拿对象来调用这个方法eat
Demo3.test();
}
public static void test () {
System.out.println("嘻嘻");
}

}

1.2.3static修饰代码块

语法格式: 静态代码块

1
2
3
static {
语句体
}

只要这个类加载,那么静态代码块一定会执行

执行顺序: 静态代码块-》构造代码块-》构造方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.qfedu.a_static;

class Cat {
public Cat () {
System.out.println("无参构造方法");
}
{
System.out.println("构造代码块");
}
static {
System.out.println("静态的代码块");
}
}
public class Demo4 {
public static void main(String[] args) {
Cat cat = new Cat();
}

}

2.异常

今天就给记语法格式和意思

2.1生活中的异常

人的一生 会经历伤病

医生会问?咋啦?

你头疼

脑部ct

医生诊断

完以后。治好这个病。

2.2Java中的异常

程序在自上而下执行的时候,发生了不可预期的事件,这个事件阻止程序的运行。这就是异常。

数组下标越界 类转换异常

Java给咱们封装很多的异常类,并且提供很优秀的异常处理机制。

Java提供了一个类Throwable

新学一个类,咋学?靠我教你吗?对的 你学会看API文档

1
https://www.matools.com/api/java8

2.3Throwable类

构造方法:

Throwable()构造一个新的可抛出的 null作为其详细信息。
Throwable(String message)构造一个具有指定的详细消息的新的throwable。

方法:

String getMessage()返回此throwable的详细消息字符串。
void printStackTrace()将此throwable和其追溯打印到标准错误流。
String toString()返回此可抛出的简短描述。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.qfedu.b_trhowable;

public class Demo1 {
public static void main(String[] args) {
System.out.println("嘻嘻");
System.err.println("哈哈");
Throwable throwable = new Throwable();
System.out.println(throwable.getMessage());
Throwable throwable2 = new Throwable("哈哈,我傻逼了");
System.out.println(throwable2.getMessage());
/**
* java.lang.Throwable: 哈哈,我傻逼了
at com.qfedu.b_trhowable.Demo1.main(Demo1.java:7)

*/
throwable2.printStackTrace();
//java.lang.Throwable: 哈哈,我傻逼了
//告知了这个错误信息
System.out.println(throwable2.toString());
}

}

2.4错误和异常

Throwable 下面有两个子类 一个叫Error 一个叫Exception

Error:是代表JVM本身的错误,咱们程序员是通过代码解决不了的。

Exception: 异常,代表程序在运行过程中,发生了不可预期的事件。可以使用Java来出来,让他继续执行下去。

​ 异常分为两种:

​ 编译时异常:

​ FileNotFoundException

​ SQLException

​ ClassNotFoundException

​ InterruptException

​ 运行时异常:

​ 数组下标越界 ArrayIndexOutOfBoundException

​ 类转换异常 ClassCastException

​ 空指针异常 NullPointerException

2.5异常【重点】

代码有可能会出现异常。Java给咱们提供了两种解决方案

​ 1.异常的捕捉

​ 2.异常的抛出

2.5.1异常的捕捉

在程序运行过程中,代码难免有可能会遇到异常。如果没有异常,代码正常执行。

如果有异常,就捕捉异常

语法格式:

1
2
3
4
5
6
try {
有可能出现异常的代码
} catch (异常对象) {
//针对于面异常的处理方案
}

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

public class Demo2 {

public static void main(String[] args) {
test(3, 0);
}
public static void test (int a, int b) {
int ret = 0;
try {
//有可能个出现异常的代码
ret = a / b;
} catch (ArithmeticException e) {
System.out.println("123");
//打印错误信息
System.out.println(e.getMessage());
}
//即使代码有异常,通过捕捉以后。是不会影响程序的接着执行的代码的
System.out.println(ret);
System.out.println( 4 + 4);
}
}

回顾上午的内容

1
2
3
4
5
6
7
8
1.static
static修饰成员变量
static修饰成员方法
static修饰代码块
2.异常
Exception
编译时异常
运行时异常
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
package com.qfedu.c_Exception;


public class Demo3 {
public static void main(String[] args) {
int[] arr = new int[2];//数组的容量是2
test(1, 1, arr);
}
public static void test (int a, int b, int[] arr) {
int ret = 0;
try {
ret = a / b;//有可能出现的异常的代码

arr[2] = 89;//这个会有异常
//jvm造出来哪个异常对象,就去catch 到哪个异常然后去执行具体的catch

} catch (ArithmeticException e) {
System.out.println("123");
System.out.println(e.getMessage());
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("456");
System.out.println(e.getMessage());
}

System.out.println(4 + 8);
}

}

继续改进

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
package com.qfedu.c_Exception;


public class Demo4 {
public static void main(String[] args) {
int[] arr = new int[2];//数组的容量是2
test(1, 1, arr);
}
public static void test (int a, int b, int[] arr) {
int ret = 0;
try {
ret = a / b;//有可能出现的异常的代码

arr[2] = 89;//这个会有异常
//jvm造出来哪个异常对象,就去catch 到哪个异常然后去执行具体的catch

} catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {
System.out.println("123");
System.out.println(e.getMessage());
}

System.out.println(4 + 8);
}

}

改进的最终版本

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
package com.qfedu.c_Exception;


public class Demo5 {
public static void main(String[] args) {
int[] arr = new int[2];//数组的容量是2
test(1, 0, arr);
}
public static void test (int a, int b, int[] arr) {
int ret = 0;
try {
ret = a / b;//有可能出现的异常的代码

arr[2] = 89;//这个会有异常
//jvm造出来哪个异常对象,就去catch 到哪个异常然后去执行具体的catch

} catch (Exception e) {
System.out.println("123");
System.out.println(e.getMessage());
}

System.out.println(4 + 8);
}

}

try-catch-finally

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
package com.qfedu.c_Exception;


public class Demo5 {
public static void main(String[] args) {
int[] arr = new int[2];//数组的容量是2
test(1, 0, arr);

}
public static void test (int a, int b, int[] arr) {
int ret = 0;
try {
ret = a / b;//有可能出现的异常的代码

arr[2] = 89;//这个会有异常
//jvm造出来哪个异常对象,就去catch 到哪个异常然后去执行具体的catch

} catch (Exception e) {
System.out.println("123");
System.out.println(e.getMessage());
} finally {
//无论有没有异常,最终都要执行的
System.out.println(4 + 8);
}


}

}

2.5.2异常的抛出

在代码出现异常的地方进行异常的抛出

如果异常的抛出的话,一旦发生异常,从出现异常的地方会终止代码

使用两个关键字:

​ throw: 在方法中抛出一个异常。自己造一个错

​ throws: 在方法的声明处书写,告知当前调用者,此处有异常。要小心

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.qfedu.c_Exception;

import java.io.FileNotFoundException;

public class Demo8 {
public static void main(String[] args) throws Exception{
test(0);
Thread.sleep(1000);
}
public static void test (int a) throws FileNotFoundException{
if (a == 0) {
//编译时异常
throw new FileNotFoundException();
}
System.out.println("jvm xixi");
}

}

总结:

1
关于异常:一阶段和二阶段  只需要会咋抛的或者咋捕捉的即可   

2.6自定义异常

Java给咱们提供了很多的异常对象,但是有的时候还是满足不了现实生活的需求,我自己造异常对象。

继承Exception

需求:

​ 如果是单身 抛出一个异常 单身异常类

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 com.qfedu.c_Exception;

import java.util.Scanner;

public class Demo11 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个整数:");
int score = scanner.nextInt();
try {
test(score);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public static void test (int score) throws Exception {
if (score > 100 || score < 0) {
throw new Exception("输入的整数有误的。。。");
}
if (score >= 90 && score <= 100) {
System.out.println("优秀");
} else if (score >= 80) {
System.out.println("良好");
} else if (score >= 70) {
System.out.println("及格");
} else {
System.out.println("叫家长。。。");
}
}

}

3.String类

3.1String类型的两种的声明方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.qfedu.d_string;

public class Demo1 {
public static void main(String[] args) {
//声明字符串的两种方式
String str = "狗蛋";
String str2 = "狗蛋";
System.out.println(str);
String str1 = new String("狗蛋");
System.out.println(str1);
System.out.println(str == str2);//true
//== 比较的是内存地址
System.out.println(str == str1);//false
//equal比较的是地址,如果地址不一样 再去比较内容。如果内容一样就是true
//开发中字符串的比较使用的是equals
System.out.println(str.equals(str1));//true
}
}

2

day14

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
1.try-catch得语法格式
try {
可能出现异常的代码
} catch(Exception e) {
异常的处理的
}
代码还会继续向下走
2.final关键字使用

3.throw和throws的区别
throw 是抛出异常的动作,给jvm来一个异常对象
throws 在方法处的声明处书写的,告知调用者当前有异常的抛出
4.抽象类和接口的区别
抽象类 abstract 修饰 接口interface修饰
抽象类可以有抽象方法和普通的方法
接口有抽象的方法和默认的方法
继承抽象 extends
实现接口 implements
5.对属性的封装如何操作
1.对属性加private 关键字
2.setter很getter方法
6.static关键字的使用
1.static修饰成员变量 类名.属性
2.static修饰成员方法 类名.方法
3.static修饰代码块

回顾

1
2
3
1.异常
未处理的异常
有两种: 捕捉 抛出,但是尽可能不要有异常

1.String类方法

1.1String类下面的方法

看官方的API手册

学习方法:

​ 1.方法的功能,这个方法是干啥的

​ 2.方法的参数

​ 3.方法的返回值

boolean equals(Object obj); 判断字符串的内容是否相等。

int length(); 获取字符串长度

char charAt(int index); 通过索引下标 获取当前下标的字符

int indexOf (String str);获取指定的字符第一个出现索引下标

int lastIndexOf(int ch);获取指定的字符最后一次出现索引下标

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
package com.qfedu.a_string;


public class Demo1 {
public static void main(String[] args) {
//equals方法 判断字符串是否相等
String str1 = "abc";
String str2 = "abc";
/**
* str1==> char[] ch1 = ['a','b', 'c'];
* str2==> char[] ch2 = ['a', 'b', 'c']
* while循环 ch1[i] == ch2[i]
*/
System.out.println(str1.equals(str2));//true
System.out.println("abc".equals("ced"));//false

System.out.println("abcdef".length());//6
System.out.println("abcd".charAt(2));//c
System.out.println("bbccaa".indexOf("c"));//2
System.out.println("bbccaa".indexOf('c'));//2
System.out.println("abcdadf".lastIndexOf('a'));//4

}

}

返回值是布尔类型数据的方法

boolean endWith(String str);判断是否是以指定的字符或者字符串结尾的

boolean isEmpty(); 判断字符串是否为空

boolean contains(String str); 在一个字符串中是否包含另外一个字符串啊

boolean equalsIgnoreCase();忽略大小写比较字符串的是否相等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.qfedu.a_string;

public class Demo3 {
public static void main(String[] args) {
String str1 = "Demo1.java";
System.out.println(str1.endsWith(".java"));//true
System.out.println(str1.endsWith("av"));//false

System.out.println("".isEmpty());//true
System.out.println("ab".isEmpty());//false
System.out.println(" ".isEmpty());//false

System.out.println("不破楼兰终不还".contains("不还"));//true
System.out.println("不破楼兰终不还".contains("还不"));//false
System.out.println("abc".equals("Abc"));//false
System.out.println("abc".equalsIgnoreCase("ABc"));//true
}

}

以下的几个方法比较重要,开发是要用的

将字符数组转为字符串

直接使用String类的构造方法

String(char[] ch);

static String valueOf(char[] chs);将字符数组转为字符串。静态的方法【重点】

valueOf方法的重载很多。一定要记住将八大基本数据类型转为字符串

将字符串转为字符数组

char[] tocharArray();将字符串转为字符数组【重点】

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

public class Demo4 {
public static void main(String[] args) {
char[] chs = {'a','g', 'e'};
//转为字符串
String str = new String(chs);
System.out.println(str);
String str1 = String.valueOf(chs);
System.out.println(str1);
String str2 = String.valueOf(98.76);
System.out.println(str2);//字符串类型的98.76
//一个double类型的数据 98.7654。取小数点后面的数

char[] chs1 = "我是狗蛋我怕谁".toCharArray();
System.out.println(chs1);
for (int i = 0; i < chs1.length; i++) {
System.out.println(chs1[i]);
}
}

}

开发要用的方法

String replace(char oldChar, char newChar);在字符串中用新的字符替换老的字符

String[] split(String regex); 以指定的字符串进行切割

String subString(int beginIndex);从指定的位置开始截取字符串

String subString(int beginIndex, int endIndex);从指定的位置开始截取字符串到指定的位置结束

String toUpperCase();将小写字符转为大写的

String toLowerCase();将小写字符转为大写的

String trim();去掉首尾空格

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
package com.qfedu.a_string;

import java.util.Arrays;

public class Demo5 {
public static void main(String[] args) {
System.out.println("abcd".replace('a', '狗'));
System.out.println("abcd".replace("cd", "中国牛皮"));

//切割一个字符串
//["ab", "cd", "ef"]
//["a", ",cd,ef"]
String[] strs = "ab&cd&ef".split("&");
System.out.println(Arrays.toString(strs));

String str1 = "abcdef".substring(2);
System.out.println(str1);//cdef
//要头不要尾
String str2 = "abcdef".substring(2, 4);
System.out.println(str2);//cd

System.out.println("ava".toUpperCase());
System.out.println("ABDF".toLowerCase());
System.out.println(" gsi jsjj ");
System.out.println(" gsi jsjj ".trim());
}

}

day15

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
1.String类下面的讲的所有方法
equals
length
charAt
indexOf
lastIndexOf
endWidth
isEmpty
contains
equalsIgnoreCase
valueOf
toCharArray
replace
split
subString
toUpperCase
toLowerCase
trim
2.多态的简单理解
父类的引用指向子类的对象
一个方法的参数是父类,真实传参的时候子类的对象
3.重写和重载
重写:
继承,在子类中去重写
子类的方法和父类的方法除了方法体不一样其他都一样
重载:
在一个类中,方法名字一样,参数列表一定不一样的
4.final和finally关键字的区别
final 修饰变量 类 方法等,代表最终的
finally 在try-catch 无论有没有异常都要执行的
5.抽象类的语法格式
abstract class 类 {


6.接口的语法格式
interface 接口名字 {

}
7.成员方法的语法格式
权限修饰符 返回值 方法的名字 (参数列表) {

}
8.继承的语法格式
class B extends A {

}
9.对成员变量的封装,如何做
1.private
2.set get

今天的内容

1.泛型

2.权限修饰符

3.集合

1.泛型

1.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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.qfedu.b_fanxing;

import java.util.ArrayList;

public class Demo1 {
public static void main(String[] args) {
//声明一个int类型数组
int[] arr = {1, 2, 3, 4};
char[] chs = {'a', 'b', 'c'};
//在数组的容量中 数据类型的都是一致的,很好!!!
//数组中的存储的数据确实一致的,但是开发不用!!!为啥?
//咱们 使用的时候,容量先定好的,而且数组添加数据删除数据,太麻烦了
//实际开发中咱们需要后面即将学的集合
//集合就是用来存储的数据的!!!
ArrayList list = new ArrayList();//就把他当成一个容器即可
list.add("狗蛋");
list.add(250);
list.add('a');
list.add(false);
//啥类型的数据都可以存进来的
System.out.println(list);
//以上存储的数据好不好? 不好!!!
//对数据类型一致性要求是比较高的!!!
//取值,每次都需要强转 太不好了
String str = (String)list.get(0);
System.out.println(str);

//可以使用泛型 进行约束
ArrayList<String> list1 = new ArrayList<>();
//告知编译器 这个集合只能存String类型的数据
list1.add("狗蛋");
list1.add("老邢");
list1.add("骚磊");
System.out.println(list1);
//取值
String s = list1.get(0);
System.out.println(s);
// ArrayList人家底层是封装了好了泛型,人家已经做好的
//学习自己如何自己写带有泛型的类 泛型的方法 等

}
}

1.2带有泛型的方法

成员方法的语法格式:

1
2
public 返回值类型  方法名字 (参数列表) {

带有的泛型的方法语法格式:

1
2
3
public <无意义的占位符> 返回值类型   方法的名字 (参数列表) {

}

无意义的占位符: 可以是T 或者E 也可以是? 等 都可以

无参无返回值的方法

有参无返回值的方法

无参有返回值的方法

有参有返回值的方法

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 com.qfedu.b_fanxing;

public class Demo2 {
public static void main(String[] args) {
test(34);
test("狗");
test('蛋');
test1();
test3("老邢");
test3(89.7);
}
// public static void test (int a) {
// System.out.println(a);
// }
// public static void test (String a) {
// System.out.println(a);
// }
// public static void test (char a) {
// System.out.println(a);
// }
//使用泛型的写法
//这个T只是一个占位而已,如果你传了字符串 那么这个T就是String
//如果你传了一个整数 那么T 就是Integer
//具有广泛性和普适性
//其实方法的重载的升级版本
//无返回值有参数的
public static <T> void test (T t) {
System.out.println(t);
}
//无返回值 无参的方法,没有必要使用泛型 没有意义
public static <T> void test1 () {
T t = null;
//你这个结果和泛型有有啥关联?没有任何意义
System.out.println("嘻嘻哒");
}
//无参 有返回值的方法,有咩有必要使用泛型? 没有
public static <T> T test2() {

return null;
}
//有参 有返回值的方法,这个使用泛型有没有意义? 有!!!
public static <T> T test3 (T t) {
return t;
}
// public static <T> T test4 (T t, T t1) {
// return t + ":" + t1;
// }
//总结:
/**
* 泛型的方法一定是带有参数的才有意义!!!
* 无参的都是无意义的,而且一定要注意带有返回值的
* 这个返回值是和参数的T 数据类型要保持一致的
*/


}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.qfedu.b_fanxing;

class Dog {

public <T> void test (T t) {
System.out.println(t);
}
}
public class Demo3 {
public static void main(String[] args) {
Dog dog = new Dog();
dog.test("goudan");
dog.test(89);
dog.test(90.8);
}
}

总结:泛型方法一定要使用带有参数的方法才有意义

1.3带有泛型的类

语法格式:

1
2
class 类<无意义的占位符> {

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 com.qfedu.b_fanxing;

class Person<T> {

// T name;//所以成员变量最好不用
// T age;
// T sex;
//主要看成员方法
//带有泛型的方法,最起码得有参数
//注意: 如果再一个带有泛型的类,成员方法不要加<T> 了
public <T> void test (T t) {
System.out.println(t);
}
//想要一个方法中的泛型和类保持一致,一定在方法不要加<T>
public void test1 (T t) {
System.out.println(t);
}
//如果是静态方法呢?
//对象创建的时候才 确定E数据类型,静态的方法在创建对象之前
//这个E和上面 类的T无关的 自娱自乐
public static <E> void test2 (E e) {
System.out.println(e);
}

}
public class Demo4 {
public static void main(String[] args) {
//在声明对象的时候,指定好了咱们的T是啥数据类型
//那么 你的成员变量 T name T 就是那种数据类型
Person<String> stringPerson = new Person<>();
// stringPerson.name = "goudan";
// stringPerson 泛型 是String 就意味着test(T t)
//T 也应该是String
stringPerson.test(89);
stringPerson.test1("wuw");
Person<Integer> person1 = new Person<>();
//person1.name = 98;
person1.test1(56);
//调用静态方法
Person.test2("hjsj");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.qfedu.b_fanxing;

class Cat<E> {

//带有泛型的方法
public void eat (E e) {
System.out.println(e);
}
}
public class Demo5 {
public static void main(String[] args) {
Cat<String> cat = new Cat<>();
cat.eat("还是当今世界");
}
}

声明一个泛型类Animal,子类Panda Panda下面重写Animal类下面的泛型方法 play(T t)

实例化对象 调用play方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.qfedu.b_fanxing;

class Animal<T> {
public void play (T t) {
System.out.println(t);
}
}
class Panda<T> extends Animal<T> {
@Override
public void play(T t) {
System.out.println(t);
}
}
public class Demo6 {
public static void main(String[] args) {
Panda<String> panda = new Panda<>();
panda.play("玩狗");

}
}

总结:

1
2
3
4
1.泛型方法

2.泛型类
在泛型类中如果写泛型方法的时候,不需要加<T>

1.4带有泛型的抽象类

语法格式:

1
2
abstract class 类名<无意义的占位符> {

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
package com.qfedu.c_fanxing;

abstract class A<T> {
abstract void testA (T t);
}
//抽象类,暂时没有办法直接实例化,只能再写一个普通类去继承抽象类
//总结:继承了带有泛型的抽象类,那么继承类也需要有泛型!!!
class TestA<T> extends A<T> {

@Override
void testA(T t) {
System.out.println(t);
}
}
public class Demo1 {
public static void main(String[] args) {
/**
* int 的包装类 Integer
* byte 的包装类 Byte
* short 的包装类 Short
* long 的包装类 Long
* float 的包装类 Float
* double 的包装类 Double
* char 的包装类 Character
* boolean 的包装类 Boolean
*
*/
//是int的包装类 就是代表的是int类型的数据
TestA<Integer> testA = new TestA<>();
testA.testA(89);
}
}

1.5带有泛型的接口

语法格式:

1
2
3
interface 接口的名字<无意义的占位> {


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

//element 元素 Type 类型
interface B<T> {
//成员方法
void eat(T t);
}
class TestB<T> implements B<T> {

@Override
public void eat(T t) {
System.out.println(t);
}
}
public class Demo2 {
public static void main(String[] args) {
TestB<Character> testB = new TestB<>();
testB.eat('g');


}
}

案例明天来讲

总结:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
泛型方法:
public <T> void test (T t) {}
泛型类中的泛型方法,不要这个<T>
public void test (T t) {}
泛型类:
class Person <T> {

}
抽象类:
abstract class Person<T> {

}
接口:
interface Person<T> {

}

2.权限修饰符【简单】

其实咱们已经见过权限修饰符了

public private default(不写是叫default) 默认的, protected

权限修饰符 四个:

​ 权限修饰符去修饰 类, 成员变量 ,成员方法 等。赋予他们不同的权限

2.1private修饰符

private 修饰成员变量和成员方法。私有的

1.在本类中可以使用私有化的成员属性和成员方法

2.同一个包下面其他类不能使用私有化的成员属性和成员方法

3.其他的包的下面的其他类不能使用私有化的成员属性和成员方法

总结:private修饰的成员变量和成员方法只能在本类中使用

2.2不写(默认的)

修饰方法和属性

就是不写,默认的

1.在本类中默认的属性和方法是可以使用的

2.同一个包下面的其他类可以使用

3.其他包下面的其他类不能使用的

总结:默认的属性和方法只能在同一个包使用!!!

2.3protected

修饰方法和属性

1.同一个类中可以使用的

2.同一个包下面其他类可以使用

3.不同包下面,如果是子类可以使用但是其他类不能使用

总结:其他包下面其他类不能使用,但是继承的子类可以使用的

2.4public

修饰方法和属性

公开的,谁都可以

开发中最常用的是 private public

权限修饰符的名称 当前类 同一个包下面其他类 不同包下面子类 不同包下面的其他类
public 可以 可以 可以 可以
protected 可以 可以 可以 不可以的
不写(默认) 可以 可以 不可以 不可以
private 可以 不可以 不可以 不可以

这个几个修饰符会写一辈子带到坟墓中

3.集合【重点】

集合和数组一样,都是用来存储数据的

真实开发的时候咱们用集合,不用数组

数组存数据:

​ 1.容量是固定

​ 2.数组封装的方法是比较少的,集合封装的方法是比较多的!!!

Java给咱们封装了集合的类库,封装了很多!!!所以先学集合的架构

3.1集合的架构

1

看官方的API

interface Collection<E> java中集合的总接口

Collection下面有两个重要的子接口 List 和 Set

1
2
3
4
5
6
7
8
List 接口:
Collection下面的子接口,存储数据特征: 有序的,可重复的
有两个比较重要的实现类:
ArrayList LinkedList
Set 接口:
Collection下面的子接口,存储数据特征: 无序的,不可重复的
有两个比较重要的实现类:
HashSet TreeSet

3.2Collection接口

学习Collection这个接口,其实就是在学习这个接口下面的方法

这些方法咋调用啊?接口不能直实例化?咋办?

借助于ArrayList即可,用多态

day16

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
1.权限修饰符的介绍
private : 只能在本类使用
protected :在本类中, 同一个包可以 出了这个包的子类可以使用 其他类不能使用
不写 : 在本类中,同一个包下面
public: 都可以

2.循环语法格式和执行流程
while () {}
do{
}while ();
for() {}
3.Collection接口下面的方法

4.集合的架构
colletion
List
ArrayList LinkedList
Set
HashSet TreeSet
5.泛型方法语法格式
public <T> void test(T t) {}
6.泛型类的语法格式
class Person<T>{}
7.泛型抽象类的语法格式
abstract class Person<T>
8.泛型接口的语法格式
interface Person<T>

今天内容

1.Collection

2.List

3.ArrayList和LinkedList区别

4.Object类

1.Collection

Collection是一个接口,不能被实例化。但是Java封装了实现类。咱们可以借助于多态De形式来实例化出来父类引用【重点】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Collection接口下面的方法,子类或者子接口能不能使用?可以的
增:
boolean add(E e);添加一个数据到集合中
boolean addAll(Collection<? extends E> c); 将一个集合数据添加到另外一个集合中
Collection<? extends E>:元素 是E本类或者继承的E,才能添加到另外一个集合中
删:
boolean remove(Object obj);删除指定的元素
boolean removeAll(Collection<? extends E> c); 删除的是交集
[a,b,c] [b, c, d]
void clear();清空的
查:
int size(); 查看集合中元素的个数
Object[] toArray(); 将集合转为Object类型数组
boolean contains(Object obj); 集合中是否包含这个元素 如果包含返回true
boolean containsAll(Collection<? extends E> c);一个集合是否另外一个集合子集合
boolean isEmpty(); 判断集合是否为空
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 com.qfedu.a_collection;

import java.util.ArrayList;
import java.util.Collection;

public class Demo {
public static void main(String[] args) {
Collection<String> list = new ArrayList<String>();//容器已经创建好了
list.add("山山");
list.add("福豪");
list.add("忠达");
System.out.println(list);
Collection<String> list1 = new ArrayList<String>();
list1.add("昊冉");
list1.add("泽文");
list1.add("梓宇");
list.addAll(list1);
Collection<Integer> list2 = new ArrayList<Integer>();
list2.add(2);
list2.add(89);
//lst.addAll(list2);直接报错
System.out.println(list);//
//[山山, 福豪, 忠达, 昊冉, 泽文, 梓宇]
//删除 山山
System.out.println(list.remove("山山"));//true
System.out.println(list);//山山是否还在list集合中
//[福豪, 忠达, 昊冉, 泽文, 梓宇]
System.out.println(list.remove("老邢"));//fasle 删除一个不存在的数据的时候就是false
Collection<String> list3 = new ArrayList<String>();
list3.add("昊冉");
list3.add("泽文");
list3.add("山山");
//list3["昊冉", “泽文”, "山山"]
//list[福豪, 忠达, 昊冉, 泽文, 梓宇]
list.removeAll(list3);
System.out.println(list);//[福豪, 忠达, 梓宇]
// list.clear();
// System.out.println(list);//[]
//SIZE()
System.out.println(list.size());//3
//toArray();
Object[] objects = list.toArray();
System.out.println(objects);//地址
for (int i = 0; i < objects.length; i++) {
System.out.println(objects[i]);
}
System.out.println(list.contains("忠达"));//true
System.out.println(list.contains("山山"));//false
System.out.println(list.isEmpty());//false
Object obj = "嘻嘻";
System.out.println(obj);
}
}

咱们现在已经往集合里面存数据了,接下来要取数据。

2.遍历集合中的数据

1
2
3
4
3种:
1.使用for循环
2.增强for循环
3.迭代器

2.1for循环遍历

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 com.qfedu.a_collection;

import java.util.ArrayList;
import java.util.Collection;

public class Demo2 {
public static void main(String[] args) {
Collection<Integer> list = new ArrayList<>();
list.add(250);
list.add(360);
list.add(470);
list.add(404);
list.add(500);
System.out.println(list);
//可以将集合转为数组,然后再for循环遍历
//不用!!!
Object[] objects = list.toArray();

for (int i = 0; i < objects.length; i++) {
System.out.println(objects[i]);
}
}
}

2.2增强for循环【重点】

语法格式:

1
2
3
for (集合中元素的数据类型 临时变量 : 集合或者数组) {
sout(临时变量)
}

有快捷键 : iter

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

import java.util.ArrayList;
import java.util.Collection;

public class Demo3 {
public static void main(String[] args) {
Collection<String> list = new ArrayList<>();
list.add("毛泽东");
list.add("邓小平");
list.add("江泽民");
list.add("胡锦涛");
System.out.println(list);
//String s : list
//将list集合 进行迭代,每次取一个值然后赋值给 s
//将list集合中的数据挨个的赋值给s
for (String s : list) {
System.out.println(s);
}
}
}

2.3迭代器

也是对集合中数据进行遍历的

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 com.qfedu.a_collection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Demo4 {
public static void main(String[] args) {
Collection<String> list = new ArrayList<>();
list.add("毛泽东");
list.add("邓小平");
list.add("江泽民");
list.add("胡锦涛");

//接下来咱们是哟个迭代器进行数据的遍历
//1.通过集合对象创建迭代器对象 cursor 光标 指针
Iterator<String> iterator = list.iterator();
//2第一个方法 hasNext(); 判断一个集合中是否有下一个元素
// System.out.println(iterator.hasNext());//true

//3.next() 一个方法干了两件事情,
//会返回当前光标下面的元素。并把光标挪到下一元素的位置
// System.out.println(iterator.next());
// System.out.println(iterator.hasNext());//true
// System.out.println(iterator.next());
// System.out.println(iterator.hasNext());//true
// System.out.println(iterator.next());
// System.out.println(iterator.hasNext());//true
// System.out.println(iterator.next());
// System.out.println(iterator.hasNext());//false
// System.out.println(iterator.next());
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}

3.在集合中存的是自定义的对象【重点】

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 com.qfedu.a_collection;

public class Person {
private String name;
private int age;

//有参构造方法,对属性进行赋值

public Person(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

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

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
//在一个类中重写toString方法
//将内存地址转为程序员能看懂的字符串

// @Override
// public String toString() {
// return "Person{" +
// "name='" + name + '\'' +
// ", age=" + age +
// '}';
// }
}

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
package com.qfedu.a_collection;


import java.util.ArrayList;
import java.util.Collection;

public class Demo5 {
public static void main(String[] args) {
Person person = new Person("老邢", 78);
System.out.println(person);//
// 之前打印的person对象是内存地址,现在在类中重写了toString方法
//以后,输出一个对象的话,就会打印出来一个字符串
//在集合中添加person对象
Collection<Person> list = new ArrayList<>();
list.add(person);
list.add(new Person("骚磊", 45));
list.add(new Person("阳仔", 89));
list.add(new Person("源哥", 35));
System.out.println(list);
Object[] objects = list.toArray();
Person person1 = (Person)objects[1];
System.out.println(person1.getName());

}
}

上午回顾

1
2
3
1.collection方法
2.遍历集合中数据
3.集合中存对象【重点】

4.List接口

List是Collection的子接口

开发中用List而不用Collection。

因为List接口下面的方法比COllection多。List在Collection基础之上添加了很多的方法

有序的可以重复的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Collection下面的方法List肯定有的,因为是继承关系。上午讲了Collection下面的方法,在List中也可以用。接下来咱们讲List独有的方法。
List独有的方法:
增:
void add(int index, E e);在指定的位置上插入一个元素
boolean addAll(int index, Collection<? extends E> e);将一个集合插入到另外一个集合的指定的位置
删:
Collection删除的时候,通过元素来删除的。 remove(Object obj)
E remove(int index);通过索引来删除指定的元素。返回的是被删除的元素
改:
E set(int index, E e); 通过指定的索引修改数据元素,返回值是被修改的原数据
查:
E get(int index); 通过索引下标去获取指定元素
int indexOf(Object obj);通过元素获取指定的下标的
int lastIndexOf(object obj);通过元素获取最后一次出现的元素的下标
List<E> subList(int formIndex, int toIndex);截取一部分出来

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 com.qfedu.b_list;

import java.util.ArrayList;
import java.util.List;

public class Demo1 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("张三");
//有序的 可重复的
System.out.println(list);//[张三, 李四, 王五, 张三]
list.add(2, "狗蛋");
System.out.println(list);
List<String> list1 = new ArrayList<>();
list1.add("麻子");
list1.add("赵四");
list1.add("贝贝");
list.addAll(1, list1);
System.out.println(list);

System.out.println(list.remove(0));//在删除
System.out.println(list);//目的是删除以后的集合的数据展示一下
//[麻子, 赵四, 贝贝, 李四, 狗蛋, 王五, 张三]

System.out.println(list.set(2, "彩云"));//贝贝
System.out.println(list);//修改之后的集合
System.out.println(list.get(0));
System.out.println(list.get(1));
System.out.println(list.get(2));
System.out.println(list.get(3));
//System.out.println(list.get(89));
System.out.println(list.indexOf("麻子"));//0
list.add(2, "张三");
System.out.println(list.lastIndexOf("张三"));//7

System.out.println(list);
List<String> strings = list.subList(3, 5);
System.out.println(strings);

}
}

5.遍历List集合中的数据

1
2
3
1.for循环
2.增强for循环
3.迭代器

5.1for循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.qfedu.b_list;

import java.util.ArrayList;
import java.util.List;

public class Demo2 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("张三");
System.out.println(list);
for (int i = 0; i < list.size(); i++) {
//通过索引获取元素
System.out.println(list.get(i));
}
}
}

5.2增强for循环

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
package com.qfedu.b_list;

import java.util.ArrayList;
import java.util.List;

public class Demo2 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("张三");
System.out.println(list);
//for循环
// for (int i = 0; i < list.size(); i++) {
// //通过索引获取元素
// System.out.println(list.get(i));
// }
//增强for循环
// for (String s : list) {
// System.out.println(s);
// }
//迭代器

}
}

5.3迭代器

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
package com.qfedu.b_list;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class Demo3 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("张三");
System.out.println(list);
ListIterator<String> sli = list.listIterator();
while (sli.hasNext()) {
System.out.println(sli.next());
}
//此时光标已经在最下面了
while (sli.hasPrevious()) {
System.out.println(sli.previous());
}

}
}

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

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class Demo4 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("张三");
System.out.println(list);
//可以将指针(光标)放到指定的额位置上,然后移动光标对数据进行遍历
ListIterator<String> sli = list.listIterator(4);
while (sli.hasPrevious()) {
System.out.println(sli.previous());
}
}
}

6.集合中存对象

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
package com.qfedu.b_list;

import java.util.ArrayList;
import java.util.List;


class User {
private String name;
private String password;
private int age;

public User() {
}

public User(String name, String password, int age) {
this.name = name;
this.password = password;
this.age = age;
}

public String getName() {
return name;
}

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

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", password='" + password + '\'' +
", age=" + age +
'}';
}
}
public class Demo5 {
public static void main(String[] args) {
List<User> list = new ArrayList<>();
list.add(new User("张三", "222", 34));
list.add(new User("李四", "333", 24));
list.add(new User("老邢", "250", 89));
list.add(new User("骚磊", "251", 94));
System.out.println(list);
//[user, user, user, user]
//获取下标为1 的元素
User user = list.get(1);//最常用方法
System.out.println(user.getName());
}
}

7.ArrayList

ArrayList底层是数组,可以扩容的。默认的容量是10.,超过10以后会自动扩容,扩容1.5倍

特征:

​ 查询快,增删慢。

​ 为啥?

开发就用ArrayList 因为开发的时候,主要查询多!!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.qfedu.c_arraylist;

import java.util.ArrayList;

public class Demo1 {
public static void main(String[] args) {
//一般开发的时候写成 父类的引用指向子类的对象
//因为List接口下面的方法已经够用了
//ArrayList独有的方法很少,几乎不用 所以List
ArrayList<String> list = new ArrayList<>();
list.add("狗蛋");
list.add(1, "老邢");
list.add("老万");
for (String s : list) {
System.out.println(s);
}
}
}

8.LinkedList

也是List的实现类,双向链表

特征: 查询慢,增删快

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.qfedu.d_linkedList;

import java.util.LinkedList;

public class Demo1 {
public static void main(String[] args) {
LinkedList<String> list = new LinkedList<>();
list.add("狗蛋");
list.add("嘻嘻");
list.addLast("哈啊哈");
list.addFirst("呵呵");
System.out.println(list);
for (String s : list) {
System.out.println(s);
}
}
}

9.ArrayList和LinkedList和Vector的区别

1
2
3
4
5
6
7
8
9
10
11
12
13
ArrayList和Vector 底层是数组,但是Vector是线程安全的,所以效率底,开发中不用Vector
接下来介绍ArrayList和linkedListu区别:
1.ArrayList底层是数组
LinkedList底层是双向链表
2.ArrayList 的特征:
查询快: 底层是索引,有序的通过内存有序地址,直接找到 时间复杂度 o(1)
增删慢: 增加数据和删除数据有可能扩容。每次扩1.5倍。扩容的话,浪费内存浪费时间o(n)
3.LinkedList的特征:
查询慢:底层是二分法查找的算法 时间复杂度是log以2为底 n的对数
增删快:直接找前置结点 Node prev,后继结点 Node next
。时间复杂度是 o(1)
所以开发时候的用ArrayList
后续还要学习ArrayList的源码

day17

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
1.Collection 接口下面的方法
add()
addAll()
remove(Object obj);
removeAll();
clear();
size();
contains();
toArray();
conatinsAll();
isEmpty();
2.List接口的方法
add(int index, E e);
addAll(int index, Collection<? extends E>);
remove(int index);
set(int index, E e);
get(int index);
indexOf(E e);
lastIndexOf(E e);
subList(int fromIndex, int toIndex);

3.static关键字的使用
static 修饰成员变量
static修饰成员方法
static修饰代码块
4.throw和throws的区别
throw 抛出一个异常对象
throws 在方法的声明处使用,告知调用者此方法有异常
5.接口和抽象类的区别
接口声明interface
抽象类abstract

6.ArrayList和LinkedList的区别

回顾

1
2
3
4
5
6
7
8
1.Collection的方法
2.对集合遍历
1.for循环
2.增强for循环
3.迭代器
3.List接口下面的方法
4.ArrayList和LinkedList的区别
5.集合中存对象的

今天的内容

1.Object类

2.Set集合

3.匿名内部类

4.map集合

1.Object类

Object类是Java中所有类的基类

学习Object类就是在学习他的方法

构造方法:

可以直接实例化

1
Object()

只需要学习三个方法

String toString()返回对象的字符串表示形式
1
public String toString()

返回对象的字符串表示形式。 一般来说, toString方法返回一个“textually代表”这个对象的字符串。 结果应该是一个简明扼要的表达,容易让人阅读。 建议所有子类覆盖此方法。

toString类方法Object返回一个由其中的对象是一个实例,该符号字符的类的名称的字符串@` ”和对象的哈希码(内存地址)的无符号的十六进制表示。 换句话说,这个方法返回一个等于下列值的字符串:

1
getClass().getName() + '@' + Integer.toHexString(hashCode()) 
  • 结果

    对象的字符串表示形式。

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
package com.qfedu.a_object;
class Person {
String name;
int age;
//person类是Object类子类不? 是!!!


//
@Override
public String toString() {
System.out.println("123");
return
"name=\"" + name + '\"' +
", age=" + age
;
}
}
public class Demo1 {
public static void main(String[] args) {
Object obj = new Object();
Person person = new Person();
System.out.println(person);

}
}

boolean equals(Object obj)指示一些其他对象是否等于此。

boolean eaqual(Object obj);

1
2
3
public boolean equals(Object obj) {
return (this == obj);
}

Object 类下面的方法比较是两个对象的地址。不看内容的

为啥String类下面的equals方法比较的是内容呢?String类继承了Object

equals方法重写了Object类下面的。为啥重写?

当父类的需求,满足不了子类的需求的时候要重写父类的方法

需求:比较两个对象的内容是否一样? 如果两个对象的内容一样返回一个true。反之返回false

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 com.qfedu.a_object;

import java.util.Objects;

class Student {
String name;
int age;

public Student(String name, int age) {

this.name = name;
this.age = age;
}
//重写equlas,要求去比较内容,如果内容一样的额话,返回true


//stu1.equals(stu2)
//stu2赋值给了 o 向上转型 Object o =new Student();
@Override
public boolean equals(Object o) {
if (this == o) {//比较是地址
return true;
}
//如果地址不一样的话,再去比较内容,如果内容一样也返回true
if (o instanceof Student) {
//才去比较值 name age
Student stu = (Student)o;//向下转型
//stu1.equals(stu2) stu就是stu2 this 是stu1
return stu.age == this.age && stu.name.equals(this.name);

}
return false;
}


}
public class Demo2 {
public static void main(String[] args) {
Student stu1 = new Student("老邢", 89);
Student stu2 = new Student("老邢", 89);
//stu1是Object类子类,用的是object 类面的equals方法
//Object类下面的equals方法比较是 地址 this==obj
//System.out.println(stu1.equals(stu2));//false
//现在我的需求是当两个对象的内容一致的时候返回的额是true
//内容不一样的时候,返回是false
//就意味着Object类的equals方法已经满足不了Student类的需求了
//咋解决? 重写equals方法
System.out.println(stu1.equals(stu2));//true
}
}

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 com.qfedu.a_object;

import java.util.Objects;

class Student1 {
String name;
int age;

public Student1(String name, int age) {

this.name = name;
this.age = age;
}
//重写equlas,要求去比较内容,如果内容一样的额话,返回true


@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || this.getClass() != o.getClass()){
return false;
}
Student1 student1 = (Student1) o;
return age == student1.age && Objects.equals(name, student1.name);
}


}
public class Demo3 {
public static void main(String[] args) {
Student1 stu1 = new Student1("老邢", 89);
Student1 stu2 = new Student1("老邢", 89);
//stu1是Object类子类,用的是object 类面的equals方法
//Object类下面的equals方法比较是 地址 this==obj
//System.out.println(stu1.equals(stu2));//false
//现在我的需求是当两个对象的内容一致的时候返回的额是true
//内容不一样的时候,返回是false
//就意味着Object类的equals方法已经满足不了Student1类的需求了
//咋解决? 重写equals方法
System.out.println(stu1.equals(stu2));//true
}
}

int hashCode();

哈希码值:在Object类下面,将内存地址(十六进制的值)转为十进制的值,此时这个十进制的值就叫hash码。

返回对象的哈希码值。 支持这种方法是为了散列表,如HashMap提供的那样

hashCode的注意事项是:

  • 只要在执行Java应用程序时多次在同一个对象上调用该方法, hashCode方法必须始终返回相同的整数,前提是修改了对象中equals比较中的信息。 该整数不需要从一个应用程序的执行到相同应用程序的另一个执行保持一致。
  • 如果根据equals(Object)方法两个对象相等,则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果。
  • 要求如果两个对象根据equals(java.lang.Object)方法不相等,那么在两个对象中的每个对象上调用hashCode方法必须产生不同的整数结果。 但是,程序员应该意识到,为不等对象生成不同的整数结果可能会提高哈希表的性能。

尽可能多的合理实用,由类别Object定义的hashCode方法确实为不同对象返回不同的整数。 (hash码的值通常通过将对象的内部地址转换为整数来实现,但Java的编程语言不需要此实现技术。)

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
package com.qfedu.a_object;

class Cat {}
public class Demo4 {
public static void main(String[] args) {
Cat cat1 = new Cat();
Cat cat2 = new Cat();
System.out.println(cat1.hashCode());
System.out.println(cat2.hashCode());
String str = new String("a");
String str1 = new String("b");
String str2 = new String("a");
//现在真他娘的尴尬,Object类的hash值是内存地址十进制的转换
//只要你内U存地址不一样,hash值一定不一样
//但是你看看str和str2 ,内存地址不一样,但是
//hash值是一样的?咋回事?在String类中重写了hashCode
//方法
System.out.println(str.hashCode());//97
System.out.println(str1.hashCode());//98
System.out.println(str2.hashCode());//97



}

}

请注意,无论何时重写equals方法,通常需要重写hashCode方法,以便维护hashCode方法的通用合同,该方法规定相等的对象必须具有相等的哈希码

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
package com.qfedu.a_object;

import java.util.Objects;

class Dog {
int id;
String name;

public Dog(int id, String name) {
this.id = id;
this.name = name;
}
public boolean equals (Object o) {
if (this == o) {
return true;
}
if (o instanceof Dog) {
Dog dog = (Dog)o;
return this.id == dog.id && dog.name.equals(this.name);
}
return false;
}

@Override
public int hashCode() {
return name.hashCode() + id;
}
}
public class Demo5 {
public static void main(String[] args) {
Dog dog1 = new Dog( 3, "a");
Dog dog2 = new Dog( 2, "b");
//现在关注的是内容,如果内容一样 调用equals方法的时候
//必须返回一个true
System.out.println(dog1.equals(dog2));//true
//此时这个两个对象的hash值一样不一样?因为内存地址不一样的
System.out.println(dog1.hashCode());
System.out.println(dog2.hashCode());
//现在hashCode不一样咋办? 重写hashCode即可
//如果根据equals(Object)方法两个对象相等,
// 则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果。
//如果两个对象的hash值一样,对象是不一定一样的。但是如果两个对象相等
//那么hash值一定相等
}
}

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
package com.qfedu.a_object;

import java.util.Objects;

class Panda {
int id;
String name;

public Panda(int id, String name) {
this.id = id;
this.name = name;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Panda panda = (Panda) o;
return id == panda.id && Objects.equals(name, panda.name);
}

@Override
public int hashCode() {
return id;
}
}
public class Demo6 {
public static void main(String[] args) {
String str1 = new String("ab");
String str2 = new String("a");
System.out.println(str1.equals(str2));//true
//31 * 97+ 98
System.out.println(str1.hashCode());//3105
System.out.println(str2.hashCode());
//STring类下面的hashCode重写的Object类下面的

Integer i1 = new Integer(45);
Integer i2 = new Integer(45);
System.out.println(i1 == i2);//false
System.out.println(i1.equals(i2));//true
//大胆猜测一下 hash值是啥?
System.out.println(i1.hashCode());
System.out.println(i2.hashCode());

Panda panda1 = new Panda(67, "狗蛋");
Panda panda2 = new Panda(67, "狗蛋");
System.out.println(panda2.equals(panda1));
System.out.println(panda1.hashCode());
System.out.println(panda2.hashCode());
}
}

回顾一下

1
2
3
4
1.toString方法
2.equals方法
3.hashCode方法
这个三个方法都可以有快捷键

2.Set集合

Set集合也是用来存储数据的

Set也是一个接口

父接口是Collection

存储数据的特征: 无序的 不可重复的

Set接口有两个实现类:

​ HashSet:

​ 依靠hash值进行存储的,如果两个元素hash值一样的话,就不再存储了

​ TreeSet:

​ 底层是二叉树,对存储数据进行自然排序

2.1hashSet类

HashSet这个类的方法和Collection接口和Set接口下面一样的

也有自己独有的方法,和ArrayList特别象

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 com.qfedu.b_hashSet;

import java.util.HashSet;
import java.util.Set;

public class Demo1 {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
//set集合存储的无序的 不可重复的
set.add("b");
set.add("a");
set.add("d");
set.add("c");
set.add("a");
set.add("ad");
System.out.println(set);

Set<Integer> set1 = new HashSet<>();
set1.add(78);
set1.add(23);
set1.add(100);
set1.add(56);
System.out.println(set1);
set1.remove(23);
//循环
for (Integer integer : set1) {
System.out.println(integer);
}

}
}

2.2HashSet集合存对象

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
package com.qfedu.b_hashSet;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

class Person {
int id;
String name;

public Person(int id, String name) {
this.id = id;
this.name = name;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return id == person.id && Objects.equals(name, person.name);
}

@Override
public int hashCode() {
return Objects.hash(id, name);
}

@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
public class Demo2 {
public static void main(String[] args) {
Person person1 = new Person(1, "zhangsan");
Person person2 = new Person(1, "李四");
Person person3 = new Person(1, "李四");
Person person4 = new Person(1, "李四");
Set<Person> set = new HashSet<>();
//在调用add方法的时候 底层在调用hashCode方法和equals
set.add(person1);
set.add(person2);
set.add(person3);
set.add(person4);
System.out.println(set);
//感觉不太合适,发现存的两个对象的内容是一样。真实开发的时候
//只关注内容的,如果内容一样,我也让你存不进去。!!!
//咋办

//总结:以后set集合中如果想存对象的时候,要求对象的内容如果一样的
//话,不能存到set集合中,咋办?重写equals方法和hahsCode方法


//hash值不一样,对象一定不一样。
//对象一样的话,hash只能一定一样
}
}

2.3TreeSet集合

也是实现了Set集合,可以保证数据 唯一性,存储也是无序的

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 com.qfedu.c_treeSet;

import java.util.Set;
import java.util.TreeSet;

public class Demo1 {
public static void main(String[] args) {
//TreeSet在存储的数据的时候 会排序
Set<Integer> set = new TreeSet<>();
set.add(89);
set.add(79);
set.add(69);
set.add(109);
set.add(39);
System.out.println(set);

Set<String> set1 = new TreeSet<>();
set1.add("d");
set1.add("w");
set1.add("a");
set1.add("c");
System.out.println(set1);
}
}

2.4TreeSet集合中存的是对象

如果想要在TreeSet集合中添加对象的话

要去实现Comparable这个接口

抽象方法:

int compareTo(T o)将此对象与指定的对象进行比较以进行排序。

将此对象与指定的对象进行比较以进行排序。 返回一个负整数,零或正整数,因为该对象小于,等于或大于指定对象。

stu1.comparetTo(stu2)

得有一个int类数据

好好思考一个问题:你得给我返回一个int类型的数据

​ stu1有age变量 stu1的年龄 减去 stu2的年领

如果年龄返回值是一个负数的话: stu1的年领小与 stu 2

如果年龄返回值是一个0的话,stu1的年龄和stu2年龄相等

如果年龄返回值是一个正整数的话: stu1的年领大于 stu 2

stu1 45

stu2 35

stu3 25

compareTo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
set.add(stu1);  第一次调用compareTo
stu1和stu1在比较 45-45 =0 只保留 stu1

set.add(stu2)的时候
又调用compareTo() 第二次调用compareTo
o:stu1
this: stu2 35 - 45 = -10 负数 stu2 比stu1小 咋排 [stu2, stu1]

set.add(stu3)的时候 第三次调用compareTo
this: stu3
o: stu1
[stu3, stu1]

第四次调用compareTo
this:stu3
o:stu2 [stu3 stu2]
[stu3 stu2 stu1]


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
package com.qfedu.c_treeSet;

import java.util.Set;
import java.util.TreeSet;

class Student implements Comparable<Student>{
String name;
int age;

public Student(String name, int age) {
this.name = name;
this.age = age;
}

@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}

@Override
public int compareTo(Student o) {
System.out.println("123");
int num = this.age - o.age;
return num;
}
}
public class Demo2 {
public static void main(String[] args) {
Student stu1 = new Student("老邢", 45);
Student stu2 = new Student("老邢", 35);
Student stu3 = new Student("saolei", 25);
Student stu4 = new Student("老万", 87);
//按照年龄进行排序 存到TreeSet集合中
Set<Student> set = new TreeSet<>();
set.add(stu1);
set.add(stu2);
set.add(stu3);
set.add(stu4);
System.out.println(set);

// Exception in thread "main" java.lang.ClassCastException:
// com.qfedu.c_treeSet.Student cannot be cast to java.lang.Comparable
// at java.util.TreeMap.compare(TreeMap.java:1294)
//类转换异常的错误,Student转换不了Comparable
//y因为底层在进行排序的时候,实现了Comparable这个接口
//为啥泛型String没有报错 Integer也没有报错
}
}

总结:

1
2
3
4
1.Object类  都有快捷键
2.HashSet存对象的时候,一定在类中重写equals和hashCode方法
3.TreeSet存对象的时候,一定要实现一个接口Comparable,重写compareTo方法
比较两个对象某个属性的int类型差值

数据结构简单的介绍

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
通过查阅API我们得知TreeSet集合是基于TreeMap的实现,而TreeMap是基于二叉树(红黑树)结构,也就是说TreeSet集合的底层使用的二叉树(红黑树)结构。

树结构:它也是数据结构中的一种。在计算机领域中树结构指的是倒立的树。

树结构存储的数据,每个数据也需要节点来保存。

而TreeSet集合底层是二叉树的数据结构,什么是二叉树呢?

二叉树:每个节点的下面最多只能有2个子节点。

说明:最多表示一个节点下面可以有两个子节点或者一个子节点或者没有子节点。

在二叉树的根节点左侧的节点称为左子树,在根节点的右侧的节点称为右子树。

既然已经得知TreeSet集合底层是二叉树,那么二叉树是怎样存储数据的呢?是怎样保证存储的数据唯一并有序的呢?

二叉树的存储流程:

当存储一个元素的时候,如果是树的第一个元素,这个元素就作为根节点。

如果不是第一个元素,那么就拿要存储的元素与根节点进行比较大小:

大于根元素:就将要存储的元素放到根节点的右侧,作为右叶子节点。

等于根元素:丢弃。

小于根元素:就将要存储的元素放到根节点的左侧,作为左叶子节点。

总结:二叉树是通过比较大小来保证元素唯一和排序的。
20 10 31 5 13 23 51

当日回顾

1.Object类

Object是Java中所有类的基类

主要是学习Object类的方法

构造方法:

Object下面有构造方法(无参构造)可以直接实例化

1.1.toString方法
1
2
public String toString()
其实就是把程序员看不懂的内存哈希码换成了程序员能看懂的字符串

官方介绍:

返回对象的字符串表示形式。 一般来说, toString方法返回一个“textually代表”这个对象的字符串。 结果应该是一个简明扼要的表达,容易让人阅读。 建议所有子类覆盖此方法。

toString类方法Object返回一个由其中的对象是一个实例,该符号字符的类的名称的字符串@` ”和对象的哈希码的无符号的十六进制表示。 换句话说,这个方法返回一个等于下列值的字符串:

1
getClass().getName() + '@' + Integer.toHexString(hashCode()) 
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 com.ccx.Set_;

public class Test1 {
public static void main(String[] args) {
Aaa aaa = new Aaa("张三",18);
System.out.println(aaa);//没有重写父类的toString时候打印的是一个地址@1b6d3586
//重写了toString后打印的是Aaa{名字是'张三', 年龄是18}

}
}
class Aaa{
private String name;
private int age;

public Aaa(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

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

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Aaa{" +
"名字是'" + name + '\'' +
", 年龄是" + age +
'}';
}//可以更改其打印的内容修饰

}
1.2.equals方法
1
2
3
4
5
public boolean equals(Object obj)
判断一个对象是否和这个对象相等
而Object下面的equals方法是比较的这两个的地址
在实际开发使用中一般会用来对比数据内容是否相同,所以需要重写这个方法
有快捷键,并且在使用中一般都要和hashCode一起重写。

官方介绍:

指示一些其他对象是否等于此。

equals方法在非空对象引用上实现等价关系:

  • 自反性 :对于任何非空的参考值xx.equals(x)应该返回true
  • 它是对称的 :对于任何非空引用值xyx.equals(y)应该返回true当且仅当y.equals(x)回报true
  • 传递性 :对于任何非空引用值xyz ,如果x.equals(y)回报truey.equals(z)回报true ,然后x.equals(z)应该返回true
  • 它是一致的 :对于任何非空引用值xy ,多次调用x.equals(y)始终返回true或始终返回false ,没有设置中使用的信息equals比较上的对象被修改。
  • 对于任何非空的参考值xx.equals(null)应该返回false

equals类方法Object实现对象上差别可能性最大的相等关系; 也就是说,对于任何非空的参考值xy ,当且仅当xy引用相同的对象( x == y具有值true )时,该方法返回true

请注意,无论何时覆盖该方法,通常需要覆盖hashCode方法,以便维护hashCode方法的通用合同,该方法规定相等的对象必须具有相等的哈希码。

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 com.ccx.Set_;

import java.util.Objects;

public class Test1 {
public static void main(String[] args) {
Aaa aaa1 = new Aaa("张三",18);
Aaa aaa2 = new Aaa("张三",18);
System.out.println(aaa1.equals(aaa2));
//没有重写equals这个方法前打印的是false,因为aaa1和aaa2的地址不同,对比的是地址
//重写了equals方法让其实现了内容相等也相等,所以现在结果为true
}
}
class Aaa{
private String name;
private int age;

public Aaa(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

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

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Aaa{" +
"名字是'" + name + '\'' +
", 年龄是" + age +
'}';
}//可以更改其打印的内容修饰

@Override
public boolean equals(Object o) {//重写这个equals的原因是为了让再对比时候两个对象的内容一样也相等
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Aaa aaa = (Aaa) o;
return age == aaa.age && Objects.equals(name, aaa.name);
}

}
1.3.hashCode方法
1
2
public int hashCode()
注意:无论何时重写equals方法,通常需要重写`hashCode`方法,以便维护`hashCode`方法的通用合同,该方法规定相等的对象必须具有相等的哈希码

官方介绍:

返回对象的哈希码值。 支持这种方法是为了散列表,如HashMap提供的那样

hashCode的总合同是:

  • 只要在执行Java应用程序时多次在同一个对象上调用该方法, hashCode方法必须始终返回相同的整数,前提是修改了对象中equals比较中的信息。 该整数不需要从一个应用程序的执行到相同应用程序的另一个执行保持一致。
  • 如果根据equals(Object)方法两个对象相等,则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果。
  • 要求如果两个对象根据equals(java.lang.Object)方法不相等,那么在两个对象中的每个对象上调用hashCode方法必须产生不同的整数结果。 但是,程序员应该意识到,为不等对象生成不同的整数结果可能会提高哈希表的性能。

尽可能多的合理实用,由类别Object定义的hashCode方法确实为不同对象返回不同的整数。 (这通常通过将对象的内部地址转换为整数来实现,但Java的编程语言不需要此实现技术。)

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
package com.ccx.Set_;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

public class Test1 {
public static void main(String[] args) {
Aaa aaa1 = new Aaa("张三",18);
Aaa aaa2 = new Aaa("张三",18);
System.out.println(aaa1.equals(aaa2));
//没有重写equals这个方法前打印的是false,因为aaa1和aaa2的地址不同,对比的是地址
//重写了equals方法让其实现了内容相等也相等,所以现在结果为true
System.out.println(aaa1.hashCode());//哈希码460141958
System.out.println(aaa2.hashCode());//哈希码1163157884
//现在这两个一样内容的对象的哈希码是不一样的
//如果根据`equals(Object)`方法两个对象相等,则在两个对象中的每个对象上调用`hashCode`方法必须产生相同的整数结果。
//所以必须要实现equals方法的结果为true时这个hashCode的结果也要为true
//那么就需要重写hashCode方法
System.out.println(aaa1.hashCode());//哈希码24022538
System.out.println(aaa2.hashCode());//哈希码24022538

}
}
class Aaa{
private String name;
private int age;

public Aaa(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

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

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Aaa{" +
"名字是'" + name + '\'' +
", 年龄是" + age +
'}';
}//可以更改其打印的内容修饰

@Override
public boolean equals(Object o) {//重写这个equals的原因是为了让再对比时候两个对象的内容一样也相等
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Aaa aaa = (Aaa) o;
return age == aaa.age && Objects.equals(name, aaa.name);
}

@Override
public int hashCode() {
return Objects.hash(name, age);
}

}
1.4.总结

1.在实际开发中,这几个方法都需要重写

2.equals和hashCode需要同时实现

2.Set集合

Set集合也是Collection的子接口

也是用来储存数据的

特点:储存数据是无序且不可重复的

Set下面的的两个主要的实现类:

​ HashSet:

​ 是靠Hash值进行储存的,特点是无序且不可重复,如果两个数据的Hash值一样就不会继续储存

​ TreeSet:

​ 底层是二叉数,是按照Hash值进行从小到大的顺序给元素自然排序的,存储是无序的

2.1HashSet类

HashSet下面的方法和Collection 还有Set的方法是一样的

它也有自己的一些独有的方法

但是总体和ArrayList差不多

但是需要注意HashSet集合里储存的数据是无序的,没有规则的存入的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Demo1 {
public static void main(String[] args) {
Set <String> set = new HashSet<>();
set.add("a");
set.add("b");
set.add("c");
set.add("m");
set.add("ab");
set.add("bc");
set.add("ca");
set.add("abccd");
System.out.println(set);

}
}
2.2HashSet存储对象
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
package com.ccx.Set_;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

public class Test1 {
public static void main(String[] args) {
Aaa aaa1 = new Aaa("张三",18);
Aaa aaa2 = new Aaa("张三",18);
Aaa aaa5 = new Aaa("李四",40);
Aaa aaa3 = new Aaa("王五",35);
Aaa aaa4 = new Aaa("麻九",22);

Set <Aaa> set = new HashSet<>();
set.add(aaa1);
set.add(aaa2);
set.add(aaa3);
set.add(aaa4);
set.add(aaa5);
System.out.println(set);
//打印结果:[Aaa{名字是'王五', 年龄是35}, Aaa{名字是'李四', 年龄是40},
//Aaa{名字是'张三', 年龄是18}, Aaa{名字是'麻九', 年龄是22}]
//是无序的,且不能重复

}
}
class Aaa{
private String name;
private int age;

public Aaa(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

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

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Aaa{" +
"名字是'" + name + '\'' +
", 年龄是" + age +
'}';
}//可以更改其打印的内容修饰

@Override
public boolean equals(Object o) {//重写这个equals的原因是为了让再对比时候两个对象的内容一样也相等
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Aaa aaa = (Aaa) o;
return age == aaa.age && Objects.equals(name, aaa.name);
}

@Override
public int hashCode() {
return Objects.hash(name, age);
}

}
2.3TreeSet集合

TreeSet集合也是实现了Set集合,也是无序且不可重复的

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
package com.ccx.Set_;

//import java.util.HashSet;
//import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;

public class Demo1 {
public static void main(String[] args) {
Set <String> set = new TreeSet<>();
set.add("a");
set.add("b");
set.add("c");
set.add("m");
set.add("ab");
set.add("bc");
set.add("ca");
set.add("abccd");
System.out.println(set);
//TreeSet在储存的时候是会自动排序,因为它实现了Comparator接口
//但是和储存的顺序毫无关系
}
}
class Person {
private String name;
private int age;
private char sex;

public Person(String name, int age, char sex) {
this.name = name;
this.age = age;
this.sex = sex;
}

public String getName() {
return name;
}

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

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public char getSex() {
return sex;
}

public void setSex(char sex) {
this.sex = sex;
}

@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
'}';
}



}
2.4TreeSet里存对象
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
package com.ccx.Set_;


import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;

public class Demo1 {
public static void main(String[] args) {
Set <Person> treeSet = new TreeSet<>();
treeSet.add(new Person("张三",18,'男'));
treeSet.add(new Person("李四",20,'男'));
treeSet.add(new Person("王五",16,'男'));
System.out.println(treeSet);
//如果想要在TreeSet集合中存入对象,那么需要这个对象实现Comparable<>这个接口
//并且要去重写它的compareTo方法,而且需要返回一个int类型的数据
//他是按照这个int类型的数据进行排序,
// 如果返回的是个负整数那么就等于当前的数小于对比的数,会把这个数放在前面
//如果返回的是个正整数那么就等于当前的数大于对比的数,会把这个数放在前面
// 如果返回0就等于相等,就不会储存
//如果没有实现Comparable这个接口的话就会出现类转换异常

}
}
class Person implements Comparable<Person>{//这个泛型必须要填你要存入对比的类型
private String name;
private int age;
private char sex;

public Person(String name, int age, char sex) {
this.name = name;
this.age = age;
this.sex = sex;
}

public String getName() {
return name;
}

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

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public char getSex() {
return sex;
}

public void setSex(char sex) {
this.sex = sex;
}

@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
'}';
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && sex == person.sex && Objects.equals(name, person.name);
}

@Override
public int hashCode() {
return Objects.hash(name, age, sex);
}

@Override
public int compareTo(Person o) {//重写Comparable的方法
return this.age - o.age;//返回一个int类型的值用来排序
}
}

总结:

1.Object类 下面需要被写的方法都有快捷键
2.HashSet存对象的时候,一定在类中重写equals和hashCode方法
3.TreeSet存对象的时候,一定要实现一个接口Comparable,重写compareTo方法
比较两个对象某个属性的int类型差值

扩展:

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
通过查阅API我们得知TreeSet集合是基于TreeMap的实现,而TreeMap是基于二叉树(红黑树)结构,也就是说TreeSet集合的底层使用的二叉树(红黑树)结构。

树结构:它也是数据结构中的一种。在计算机领域中树结构指的是倒立的树。

树结构存储的数据,每个数据也需要节点来保存。

而TreeSet集合底层是二叉树的数据结构,什么是二叉树呢?

二叉树:每个节点的下面最多只能有2个子节点。

说明:最多表示一个节点下面可以有两个子节点或者一个子节点或者没有子节点。

在二叉树的根节点左侧的节点称为左子树,在根节点的右侧的节点称为右子树。

既然已经得知TreeSet集合底层是二叉树,那么二叉树是怎样存储数据的呢?是怎样保证存储的数据唯一并有序的呢?

二叉树的存储流程:

当存储一个元素的时候,如果是树的第一个元素,这个元素就作为根节点。

如果不是第一个元素,那么就拿要存储的元素与根节点进行比较大小:

大于根元素:就将要存储的元素放到根节点的右侧,作为右叶子节点。

等于根元素:丢弃。

小于根元素:就将要存储的元素放到根节点的左侧,作为左叶子节点。

总结:二叉树是通过比较大小来保证元素唯一和排序的。
20 10 31 5 13 23 51