前八天笔记
DAY 01
JAVA简述
Java是由SUN公司在1995年推出的一门高级编程语言,是现今服务器端的首选编程语言,是大数据的基础语言。Java的一个重要的特性是跨平台。
Java之所以能够跨平台是因为有JVM(Java Virtual Machine, Java虚拟机)。所有的Java程序并不是直接和操作系统交互而是先交由JVM进行翻译,然后JVM将程序翻译为当前操作系统能够理解的语言之后再交由操作系统执行。
注意:JAVA语言是跨平台的但是JVM不是跨平台的
技术结构
JAVASE --- Java Standard Edition --- Java标准版/基础版。是Java技术结构的基础
JAVAEE --- Java Enterprise Edition --- Java企业版,是在企业中进行团队开发的时候使用
JAVAME --- Java Micro Edition --- Java微型版,是为一些小型电子的嵌入来提供方案
JDK --- Java Development Kit --- Java开发工具包,为Java程序的开发来提供基本的工具 --- 包含了工具包+ JRE
JRE --- Java Runtime Environment --- Java运行时环境,为Java程序的运行来提供基本的环境 --- 包含了JVM + 核心类库
JVM --- Java Virtual Machine --- Java虚拟机,是Java程序能够跨平台的前提
Oak --- 橡树
JDK1.0 -> JDK1.1 -> JDK1.2 -> JDK1.3 -> JDK1.4 -> JDK1.5/JDK5.0 -> JDK1.6/JDK6 -> JDK1.7/JDK7.0 -> JDK1.8 -> JDK1.9/JDK17.9 -> JDK10/JDK18.3 -> JDK11/JDK18.9
扩展:LTS - long time service
www.oracle.com
注意:安装路径中不要出现空格和中文
将程序翻译成计算机所能理解的语言 --- 编译
Java文件在编译完成之后会产生一个class文件 --- 字节码文件(给计算机看的)
注意:
1. 程序要想运行需要一个入口 --- 主函数
2. class文件名和类名对应,在运行的时候要写的是class文件名
3. 用public限制的类称之为公共类,公共类要求类名和Java文件名必须一致。
4. 如果定义了包,在运行的时候需要添加包名(同一个盘符)
Java 包名.类名 java cn.tedu.de.Demo
5.如果想把Java文件编译到指定包中,需要在包中声明位置,然后使用下列命令编译,再使用第四个知识点运行包内文件。
环境变量:指给当前的操作系统来指定运行参数的值
JAVA_HOME变量值为JDK的安装路径。
Path=%JAVA_HOME%\bin;
PS:不同盘符下的编译和调用
编译: javac D:\\(java文件的位置)包名.java
例子:javac D:\\OperatorDemo.java
运行:java(空格)-cp(空格)D:\\(java文件的位置)(空格)包名
例子:java(空格)-cp(空格)D:\\(空格)OperatorDemo
关键字
在Java中有特殊的含义。
到目前为止一共是53个关键字 --- 2个关键字没有使用:const/goto --- 保留字
注意:关键字都是小写的
标识符
在程序自定义的名称
命名规则
由字母(常见语言的基本字符)、数字、_、$组成(但是减少使用$)
虽然java支持中文命名,但是减少使用
数字不能开头
不能使用关键字
区分大小写 Demo demo
见名知意
没有主函数,程序依然能够编译
DAY 02
复习:
1. Java跨平台:基于JVM。针对每一个操作系统都有不同的jvm与之对应,jvm在这个过程中屏蔽了各个操作系统之间的差异性。
2. Java的技术结构:JAVASE JAVAEE JAVAME
3. JDK、JRE、JVM:JRE包含了JVM+核心类库(Java程序运行所需要的基本的支持),为程序的运行提供环境。JDK包含了JRE+开发工具。
4. 入门程序:Java程序一定是写到Java文件(.java);程序运行需要入口---主函数;类编译完成之后会产生一个class文件。
5. javac -d 包的存放位置 要编译的Java文件
java包名.类名
java cn.tedu.de.Demo
6. 环境变量:JAVA_HOME=JDK的安装路径,Path = %JAVA_HOME%\bin;
7. 关键字:有特殊含义的单词 --- 53个关键字 --- 2个保留字:const/goto --- 所有的关键字都是小写
8. 标识符:程序自定义的名称。由字母、数字、_、$组成,支持中文命名。不能以数字开头,不能使用关键字,区分大小写。见名知意。
驼峰命名法
类名/接口名:如果由多个单词组成,那么每一个单词的首字母大写。 HelloWorld
变量名/方法名:如果由多个单词组成,那么第一个单词的首字母小写,其余单词的首字母大写 playGame main
包名:如果由多个单词组成,那么每一个单词之间用 . 隔开,所有字母都是小写 cn.tedu.de
常量名:如果由多个单词组成,那么每一个单词之间用_隔开,所有字母都是大写 PLAY_GAME
注释 单行注释之间可以嵌套 ,多行注释之间不能嵌套,文档注释不能嵌套多行注释。
用于解释说明的文字
// 注释文字 单行注释
/* 注释文字*/ 多行注释
/** 注释文字 */文档注释 --- 里面的注释内容可以利用javadoc命令提取出来形成文档(就是对程序的说明书)
代码内容: javadoc文件名.java
字面量
在计算机中不可改变的量
整数常量:所有的整数 7 15 186 -42
小数常量:所有的小数 3.12 8.005 6.0 9.00
字符常量:将一个字母、数字或者是符号用 ‘’ 标识起来 ‘a’ ‘+’ ‘5’ ‘小’ ‘ ’
字符串常量:将一个或者多个字符用 “” 标识起来 “abc” “+” “”
布尔常量:true/false --- 用于表示逻辑值
空常量:null
进制
计数方式
二进制:0-1,满2进1 1+1=10 11+1=100 111+1=1000。在程序中以0b/0B开头标记一个二进制数字(从JDK1.7开始) 0b1001 0b00101
八进制:0-7,满8进1 7+1=10 27+1=30 77+1=100要求以0开头标记一个八进制数字 045 053
十进制:0-9,满10进1 Java中数字默认就是十进制
十六进制:0-9,A-F,满16进1 9+1=a a+1=b f+1=10 39+1=3a 3f+1=40 99+1=9a 9f+1=a0 af+1=b0 ff+1=100要求以0x/0X作为开头标记 0xB3
进制的转换
十进制转换为二进制:将一个十进制数字不断的除以2,然后获取余数,将余数倒序排列,排列之后的结果就是对应的二进制
二进制转化为十进制:从这个二进制数字的最低位次开始,然后每一位乘以当前的2的位次次幂,最后求和。
十进制转化为其他进制:十进制数字向哪个进制转化那么久除以对应的进制,然后取余数,将余数倒排
其他进制转化为十进制:从这个进制的数字的低位次开始,然后按位次乘以当前的进制的位次次幂,最后求和
二进制转化为八进制:从二进制数字的低位次开始,每三位划分为一组产生一个八进制数字,最高位如果不足三位,补0。最后将产生的八进制数字排列 --- 三变一
八进制转化为二进制:每一位八进制数字产生3位二进制数字,如果不足三位,补0. --- 一变三
十六进制和二进制之间的转换类比八进制和二进制的转换
扩展:十进制小数转换为二进制
绝大部分的小数转化为二进制都是无限的 --- 所以计算机在存储小数的时候会产生舍入误差
变量
在程序中用于存储数据的容器。
变量不能重名。
变量必须先定义后使用
变量必须先给值后使用
变量必须在哪儿定义就在哪儿使用
扩展:计算机存储单位
每一个二进制数字称之为1位 --- bit - b
字节- Byte - B 1B = 8b
千字节 - kilobyte - KB 1KB = 210B = 1024B
兆字节 - MB -> GB -> TB -> PB
8Mb = 1MB
100Mb = 12.5MB
3GB = 3000MB --- 在通信领域是按照千进制计算
数据类型
基本数据类型
数值型
整数型
byte - 字节型- 1个字节 - -27~27-1 -> -128~127
byte b = 25; byte b2 = 127; byte b3 = -128;
short - 短整型 - 2个字节 - -215~215-1 -> -32768~32767
short s = 800; short s2 = 1500;
int - 整型 - 4个字节 - -231~231-1 -> -2.1*109~2.1*109 - Java中,整数默认为int类型
int i = 5;
long - 长整型 - 8个字节 - -263~263-1 -> -1018~1018 需要以L/l作为结尾标记
long l = 54L;
浮点型
float - 单精度 - 4个字节 -> -1038~1038 - 需要以f/F作为结尾
double - 双精度 - 8个字节 -> -10308~10308 Java中小数默认为double类型 - 小数结尾可以添加D/d作为标记
double d = 4.5; double d2 = 2.58; double d3 = 9.54D;
char - 字符型 - 2个字节 -> 0~65535 - 存储用的就是utf-16
char c = ‘a’; char c2 = '\ua4f3'; char c3 = ‘中’;
转义字符
\t-制表符 table \r-回车 return \n-换行next
\\-反斜杠\ \’-单引号 \”-双引号
扩展:将字符转换数字的过程称之为编码 --- 编码表
ISO-8859-1 - 西欧码表 - 1个字节表示1个字符 a
gb2312 - 国标码 - gbk - 2个字节表示1个字符 - 收录了常见的简体汉字以及一部分常见的繁体汉字
Unicode编码体系 - 收录了世界上常见语言的基本字符 - 规定了一系列的编码规则 - utf-8-> 3个字节表示一个字符 utf-16 -> 2个字节表示1个字符
注意:规定无论哪张码表兼容西欧码表
k 1 1 1 1
区 X 2 3 2
boolean - 布尔型 - true/false,用于表示逻辑值
boolean b = true; boolean b2 = false;
引用数据类型
数组[]
类 class
接口interface
数据类型的转换
自动类型转换/隐式转换
byte b = 125;
int i = b;
规律一:小的类型自动转化为大的类型
short s = 7;
long l = s;
long l = 500; // 500是一个整数,整数默认为int,int的范围比long小,所以可以自动转换
float f = 56.71F;
double d = f;
int i = 300;
double d = i;
规律二:整数类型可以自动转化为浮点类型,可能会产生舍入误差
int i = 500;
float f = i; // i是int类型,int的取值范围比float小,所以int可以自动转化为float
long l = 259L;
float f = l;
float f = -25; // -25是整数
char c = ‘a’;
int i = c;
规律三:字符可以自动提升为整数
强制类型转换/显式转换
int i = 35;
byte b = (byte)i;
规律一:当把大的类型转化为小的类型的时候,因为补码的换算问题,所以可能会产生一些想不到数据
double d = 6.4;
int i = (int)d;
规律二:小数在转化为整数的时候是舍弃小数位
扩展:数据的原反补三码
数据类型的最高位是符号位 --- 如果最高位是0,则表示一个正数;如果最高位是1,则表示一个负数。
计算机中存储的是数据的补码,计算的也是数据的补码
直接计算出来的二进制数字是数据的原码
如果是正数,那么原反补三码一致
int i = 7;
00000000 00000000 00000000 00000111 原码
00000000 00000000 00000000 00000111 反码
00000000 00000000 00000000 00000111 补码
如果是负数,那么反码是在原码的基础上,最高位不变,其余位0<->1;补码是在反码的基础上+1
int j = -9;
10000000 00000000 00000000 00001001 原码
11111111 11111111 11111111 11110110 反码
11111111 11111111 11111111 11110111 补码
注意:规定用-0表示当前类型的最小值
运算符
算术运算符
+ - * / % ++ --
注意:
1. byte/short/char在运算的时候自动提升为int
2. 整型在运算的时候保持类型不变
3. 小类型和大类型运算,结果一定是大类型
4. 任意整数/0 - ArithmeticException - 算术异常
任意非零数字/0.0 任意非零小数/0 - Infinity - 无穷大
0/0.0 0.0/0.0 0.0/0 - NaN - Not a Number - 非数字
DAY 03
复习:
1. 注释:是程序中用于解释说明的文字 - 文档注释中的文字可以利用javadoc命令进行提取
2. 字面量:整数、小数、字符、字符串、布尔、空
3. 进制:实际上是一种计数方式。
二进制:0-1,满2进1,需要以0b开头(从JDK1.7开始)
八进制:0-7,满8进1,需要以0开头
十进制:0-9,满十进1,程序中默认就是十进制
十六进制:0-9,a-f,满16进1,需要以0x开头
注意进制之间的转换规则
4. 变量:数据类型 变量名 = 数据; - 变量必须在定义的范围内使用;变量必须先定义后使用,也必须先给值后使用
5. 数据类型:
基本数据类型
byte short int long float double char boolean
byte的取值范围:-128~127
整数默认为int,小数默认为double
long类型需要以l/L作为结尾
float类型需要以F/f作为结尾
char类型的默认编码是utf-16 - 2个字节
boolean用于表示逻辑值
引用数据类型
数据[] 类class 接口interface
6. 数据类型的转换
隐式转换
小类型可以自动转化为大类型
整数可以自动转化为小数,可能会产生精度损失
字符可以自动转化为整数
显式转换
大类型转换为小类型,因为字节的损失可能导致数据不精确
小数转换为整数的时候需要舍弃小数位
运算符
算术运算符
+ - * / % ++ --
注意:
1. byte/short/char在运算的时候会自动提升为int
2. 整数的运算结果一定是整数
3. 小类型和大类型运算结果一定是大类型
4. 任意整数/0 - ArithmeticException
非零数字/0.0 非零小数/0 - Infinity
0.0/0.0 0.0/0 0/0.0 - NaN - 非数字
% 取模运算 - 取余运算
9%4=1 3%8=3
-9%4=-1 9%-4=1 -9%-4=-1
%的结果的正负看的是%左边数据的正负 -> 如果左边的数字是一个正数,那么结果就是正数;反之,那么结果就是负数
5%1.4=0.8 6.3%1.7=1.2
++/-- 自增/自减运算
++/--如果在变量之前,那么先自增/自减,然后参与后续运算
++/--如果在变量之后,那么先将值取出来参与运算,然后变量再自增/自减
int i = 6;
// int j = i++ + ++i; -> 14
int j = ++i + i++; -> 14
byte/short/char都可以参与自增运算
char c = ‘b’;
int i = c + 2; -> 100
‘a’ ~ ‘z’ -> 97~122 ‘A’ ~ ‘Z’ -> 65~90 ‘0’ ~ ‘9’ -> 48~57
char c = ‘0’;
int i = c + 3; -> 51
赋值运算符
= += -= *= /= %= &= |= ^= <<= >>= >>>=
byte/short/char可以参与赋值运算
除了=以外,其余的符号都要求这个变量得先有值
注意:在Java中不支持连等定义但是支持连等赋值
int i = 5;
i += i *= i -= 3; -> 15
i = 5 + (5 * (5 - 3));
int j = 7;
j -= j *= j++; -> -42
j = 7 - (7 * 7);
关系/比较运算符
==相等 !=不等 > < >= <=
注意:不支持连着的比较方式
逻辑运算符
注意:逻辑运算符算的是逻辑值
&与 |或 !非 ^异或 &&短路与 ||短路或
true&true=true true&false=false false&true=false
false&false=false
true|true=true true|false=true false|true=true
false|false=false
!true=false !false=true
true^true=false true^false=true false^true=true
false^false=false
&&:如果前边的表达式的结果为false,则后边的表达式不再运算,整个表达式的结果就确定为false
||:如果前边的表达式的结果为true,则后边的表达式就不再运算,整个表达式的结果就确定为true
注意:||如果在&&的前边可以把&&短路掉
位运算符
注意:位运算符针对整数的补码进行运算,所以运算结果也是补码
& | ^ << >> >>> ~取反
交换值的方式
方式一:异或法
int i = 5, j = 9;
i = i ^ j;
j = i ^ j; -> j = i ^ j ^ j; -> j = i;
i = i ^ j; -> i = i ^ j ^ i; -> i = j;
方式二:加减法
int i =5, j = 9;
i = i + j;
j = i - j; -> j = i + j - j; -> j = i;
i = i - j; -> i = i + j - i; -> i = j;
方式三:追尾法
int i = 5, j = 9;
int temp = i;
i = j;
j = temp;
总结:三种方式的比较
异或法的效率是最高的。只能针对整数进行交换,局限性太大
加减法的效率是低于异或但是高于追尾。理论上可以交换数值类型,但实际上很少用于交换小数
追尾法的效率是最低的。可以交换任意一个类型的值
三元运算符
格式:逻辑值 ? 表达式1 : 表达式2
执行顺序:先执行逻辑值,如果逻辑值为true,则执行表达式1;反之则执行表达式2
三元表达式本身是一个表达式,意味着这个表达式执行完成之后需要有一个结果 --- 这个结果必须能定义对应类型的变量来接住
a > b ? “abc” : true; -> 没有办法定义一个统一类型的结果来存储,这种写法就是错误的
double d = a > b ? 3 : 5.25;
float f = a > b ? ‘a’ : 3.5f;
练习: 输出分数对应的等级 >=90-A >=80-B >=70-C >=60-D <60-E
扩展:从控制台获取数据
import java.util.Scanner;
Scanner s = new Scanner(System.in);
int i = s.nextInt(); // 获取整数
double d = s.nextDouble(); // 获取小数
String str = s.next(); // 获取字符串
运算符的优先级
~ ! ++ -- * / % + - << >> >>> 关系 逻辑 & | ^ 三元 赋值
一元 > 二元 > 三元 > 赋值(程序的运行顺序是从上到下,从左到右,一定要注意运算符的优先级)
流程控制
顺序结构:指代码是从上到下从左到右来依次编译运行的
分支结构
判断结构
if(逻辑值){
代码块;
}
执行顺序:先执行逻辑值,如果逻辑值为true,则执行代码块;反之则不执行
注意:如果if中的代码块只有1句话,那么可以省略{}不写
if(逻辑值){
Code1;
} else {
Code2;
}
执行顺序:先执行逻辑值,如果逻辑值为true,那么执行Code1;反之执行Code2
练习:
1. 输入三个数字,获取三个数字中的最小值
2. 输入一个数字表示重量,如果重量<=20,则每千克收费0.35元;如果超过20千克不超过100千克的范围,则超过的部分按照每千克0.5元收费;如果超过100千克,则超过的范围按照每千克0.8元收费。计算输入的重量对应的总费用
if(逻辑值1){
Code1;
} else if(逻辑值2){]
Code2;
}
...
else {
Code;
}
执行顺序:先执行逻辑值1,如果逻辑值1为true,则执行Code1;反之则执行逻辑值2,如果逻辑值2为true,则执行Code2;反之则顺次继续往下执行
练习:
输入一个数字表示月份,然后输出这个月份所对应的季节。3-5-春 6-8-夏 9-11-秋 12、1、2-冬
Day04
复习:
1. 运算符
算术:
% - 取余 - 注意结果的正负号
++/--在变量之前需要先自增后运算;在变量之后先运算后自增;byte/short/char参与运算
赋值:
除了=,其他的符号都要求变量先有值才能使用
byte/short/char可以参与赋值运算
不允许连等定义但是允许连等赋值
比较:
不允许用比较运算符表示一个连续的范围 --- 3 < n < 5
逻辑:
^:相同为假不同为真
&&和||的短路特性
位:
针对整数的补码进行运算
交换值的方式:追尾法、加减法、异或法
三元:
执行顺序:先执行逻辑值,如果逻辑值为true则执行表达式1;反之执行表达式2
三元表达式中的两个式子的结果类型必须能够转化
流程控制
顺序结构:指代码从上到下从左到右依次编译运行
分支结构
判断结构
if(){}
if(){}else {}
if(){}else if(){}
练习:输入一个数字,然后输出这个数字表示星期几
3 -> 星期三
选择结构
switch(选择){
case 选项1:Code1;break;
case 选项2:Code2;break;
...
}
switch()中需要一个选项,选项只能是byte/short/char/int,从JDK1.7开始,允许使用String
如果每一个case之后都有break,case顺序不影响结果
如果有一个或者多个case之后没有break,那么这个时候case之间的顺序影响结果
练习:输入两个数字以及一个符号,输出这两个数字在这个符号下运算产生的结果
5 9 + -> 14
switch(){
case “+”:...
case “-”:...
}
练习:输入三个数字表示年月日,输出这一天在这一年是第几天
2012 3 5 ---> 65
2014 3 5 ---> 64
需要判断平年闰年:逢百整除400;不逢百整除4
2012 % 4 == 0 --- true
2100 % 400 == 0 --- false
循环结构
用于完成一些相同或者相似的重复的操作
while(逻辑值){
Code;
}
执行顺序:
练习:
1. 求1-100以内所有的奇数的和 --- i = 1; i += 2;
2. 打印100以内能被3整除而不能被7整除的数字 --- 先获取3的倍数 int i = 0; i += 3;
3. 输入一个数字,输出这个数字是一个几位数
4. 输入一个数字,输出这个数字的所有的因数 --- 从1开始,逐个数字取余这个输入的数字,看是否能够整除
20:1 2 4 5 10 20
定义一个循环,需要三个要素:定义一个变量来控制次数,利用判断条件决定循环结束;在循环过程中需要改变变量
do{
Code;
} while(逻辑值);
注意:无论条件是否满足,do-while的循环体必然至少执行一次。
for(定义循环变量; 控制条件; 改变循环变量){
Code;
}
习惯上如果变化不规律或者次数不确定一般使用while循环;如果变化规律或者是次数固定,一般是用for循环
求1-10的和 --- for循环
int sum = 0;
for(int i = 1; i <= 10; i++){
sum += i;
}
从控制台获取一个大于10的奇数
Scanner s = new Scanner(System.in);
int n = s.nextInt();
// 使用while循环
while(n < 10 || n % 2 == 0){
n = s.nextInt();
}
// 使用for循环
for(; n < 10 || n % 2 == 0; n = s.nextInt()){
}
练习:打印九九乘法表
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
。。。
练习:
百钱百鸡 --- 3文钱1只公鸡,2文钱1只母鸡,1文钱3只小鸡;100文钱如何买恰好100只鸡? --- 先定义一个循环表示公鸡,嵌套一个循环表示母鸡,计算小鸡的个数,根据各种鸡的个数来计算钱数是否为100
break和continue
break:用于选择结构和循环结构,表示结束当前的一层结构
continue:只能用于循环结构,表示跳过本次循环继续下次循环(只能跳过一层循环)
扩展作业:一个循环打印九九乘法表
数组
存储同一类型的多个数据的容器---大小是固定的
数组会对放入其中的数据(元素)进行编号,编号是从0开始的 - 下标
数组的容量 --- 长度
定义格式
数据类型[] 数组名 = new 数据类型[长度];
int[] arr = new int[5]; --- 表示定义一个能存储5个整型元素的数组
arr[3] = 10;
内存
Java将所占用的内存划分为了5块:栈内存、堆内存、方法区、本地方法栈、PC计数器(寄存器)
栈内存
用于存储变量的。变量在栈内存使用完成之后会立即移除出栈内存。
堆内存
用于存储对象(数组是一种特殊的对象)的。元素在存入堆内存中之后会自动的赋予默认值:byte/short/int-0 long-0L float-0.0f double-0.0 char-‘\u0000’ boolean-false,其他类型的默认值都是null。对象在用完之后是在不确定的某个时刻被回收。
logab = logcb/logca logabn = nlogab logab = loga + logb
DAY05
复习:
1. 流程控制
顺序结构
分支结构:
判断结构:if, if-else, if-else if
选择结构:switch-case --- 选项的类型可以是byte/ short/ char/ int, 从JDK1.7开始,允许使用String。case之后有无break,那么他的顺序将会影响结果
循环结构:while, do-while, for
do-while的循环体无论如何都会至少执行一次。
在次数固定或者是变化规律的前提下,建议使用for循环;在次数不固定或者变化不规律的情况下,建议使用while循环
循环嵌套
break和continue
break:用于选择和循环结构,表示终止当前的一层结构。
continue:用于循环结构,表示跳出当前的一次循环继续下次循环(也是只能跳一层)
数组
用于存储多个同一类型的数据的容器 --- 大小是固定的
下标是从0开始,所以最大下标是长度-1
定义格式
数据类型[] 数组名 = new 数据类型[长度];
数据类型[] 数组名 = new 数据类型[]{元素1, 元素2, ...};--- 这种方式在定义的时候给定了具体的元素同时也规定了数组的长度
int[] arr = new int[]{5,3,7,1,8,9,2}; 表示定义了一个元素类型为整型的数组,数组中的元素是5,3,7,1,8,9,2,意味着数组的长度是7
数组类型[] 数组名 = {元素1, 元素2, ...}; --- 不允许分开定义
数组的内存
数组存储在堆内存中,并且在堆内存中会自动赋予默认值:byte/short/int - 0, long - 0L, float - 0.0f, double - 0.0, char - ‘\u0000’, boolean - false,其他所有类型的默认值都是null
注意:数组在赋值的时候赋的实际上是地址
数组的应用
1. 操作指定位置上的元素:数组名[下标]
2. 获取数组的长度:数组名.length
3. 遍历数组
// 方式一:下标是从0->length - 1
for(int i = 0; i < arr.length; i++){
System.out.println(arr[i]);
}
// 方式二:直接获取每一个位置上的元素
// 增强for循环
// 只能遍历数组但是不能改变数组中的元素
for(int i : arr){
System.out.println(i);
}
// 方式三:将数组中的元素一个个的拿出来拼接成字符串
String str = Arrays.toString(arr);
System.out.println(str);
4. 获取数组中最值(最大值/最小值)
方式一:定义变量来记录数组中的最大值,然后遍历数组,让数组中的元素依次与最大值进行比较;如果大于最大值,则将用这个元素覆盖原来的最大值
方式二:定义变量来记录最大值的下标
5. 数组的排序
时间复杂度:在程序中找一段必然会执行的代码,将这段代码的执行时间认为是单位1,执行这个单位1需要的次数就是时间复杂度 - 时间复杂度不考虑系数,一般来说是找最高阶 -> O(nx), O((logn)x),O(nx(logn)y)
空间复杂度:这段程序执行所需要额外耗费的空间就是空间复杂度
扩展:冒泡排序和选择排序都是稳定的排序算法 --- 排序算法的稳定与否的依据是相等的元素在排序的时候是否需要交换
6. 反转数组:首尾互换 --- 时间复杂度O(n),空间复杂度o(1)
7. 数组元素的查找:
数组元素无序的前提下,获取一个元素的位置只能通过遍历的方式一一比较。
如果数组元素有序,使用二分查找 --- 空间复杂度o(1),时间复杂度O(logn)
2x = n -> x = log2n -> logn --- 默认以2为底数
8. 数组的复制
System.arraycopy(要复制的数组, 要复制的起始下标, 存放的数组, 要存放的起始下标, 个数);
二维数组
存储的元素是一维数组 --- 存储数组的数组
定义格式
数据类型[][] 数组名 = new 数据类型[包含的一维数组的个数][每一个一维数组的长度];
int[][] arr = new int[3][5]; 表示定义了一个能存储3个整型一维数组的二维数组,每一个一维数组能5个整型元素
数据类型[][] 数组名 = new 数据类型[包含的一维数组的个数][];
int[][] arr = new int[5][]; 定义了一个能存储5个整型一维数组的二维数组 --- 必须先保证这一位上的一维数组先给定大小,然后再给值
arr[0] = new int[3];
arr[1] = new int[7];
arr[2] = new int[2];
数据类型[][] 数组名 = {{数组1}, {数组2}, {数组3},...};
int[][] arr = {{2,4,1}, {4,7,2,9}, {3}, {5,0,6,7,4,3}}; --- 二维数组的大小为4
注意:[]如果在变量名之前那么紧跟数据类型,也就意味着后面定义的变量实际上都是数组;但如果[]在变量名之后,那么[]只管跟着的这个变量不会去影响其他的变量。
内存存储
练习:杨辉三角
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
特点:每一行的开始和结束都是1;其余位置的元素是计算:
arr[i][j] = arr[i - 1][j] + arr[i - 1][j - 1];
输入一个数字n表示行数,输出对应的前n行
DAY06
复习:
1. 数组
定义格式
内存存储:数组是存储在堆内存中,在栈内存中存储堆内存中对应的地址。数组在存入堆内存的时候需要自动赋予默认值。--- 数组在赋值的时候给的也是地址
int[] arr1 = new int[3];
int[] arr2 = arr1; // 指向同一个空间
数组应用:
数组的遍历:通过下标遍历,增强for循环
元素的排序:冒泡排序(相邻两个元素两两比较),选择排序(选定一个元素和其他元素来依次比较)--- 时间复杂度O(n2),空间复杂度o(1),是稳定的排序算法;Arrays.sort只能进行升序排序
数组的反转:首尾互换 - 时间复杂度O(n),空间复杂度o(1)
元素的查找:元素无序,循环遍历;元素有序,二分查找 - 时间复杂度O(logn),空间复杂度o(1)
数组的复制:System.arraycopy - Arrays.copyOf
2. 二维数组
用于存储一维数组
定义格式
内存存储:二维数组的每一个位置上存储的是对应的一维数组的地址;如果没有指定一维数组的大小,那么二维数组的位置上存储得是null
方法
当在程序中需要重复使用某段逻辑或者功能,将这段逻辑提取出来形成一种新的形式---方法,也叫函数
定义格式
修饰符 返回值类型 方法名(参数列表){
方法体;
return 返回值;
}
// 写一个方法求1-n的和
// 明确结果:求1-n的和,那么和是一个整数,意味着结果是int类型,所以返回值类型也就是int类型
// 明确未知量:求1-n的和,n在方法中不能自动产生,需要使用方法的人来传入一个值,这个时候需要以参数形式来体现
// 定义方法的时候在()中定义了参数 --- 形式参数 - 形参
public static int sum(int n){
int sum = 0;
for(int i = 1; i <= n; i++){
sum += i;
}
return sum;
}
练习:
1. 哥德巴赫猜想:任何一个大于等于6的偶数都可以分解成两个质数之和。
16 = 3 + 13
16 = 5 + 11
输入大于等于6的偶数,然后输出它所有的分解形式
思路:在这个过程中要重复执行的代码是判断质数
2. 亲密数:如果A的所有因子(含1而不含本身)之和等于B,而且B的所有因子(含1而不含本身)之和等于A,A和B就是一对亲密数
16:1+2+4+8 = 15
15:1+3+5 = 9
打印5000以内所有的亲密数
思路:需要重复执行的逻辑是获取一个数的所有因子之和
方法的重载
在同一个类中,存在了方法名一致而参数列表不同(参数个数不同或者是对应位置上的参数类型不同)的方法 --- 方法的重载 --- 依靠参数列表来区分调用的方法
方法在调用的时候会进行模糊匹配---参数类型在没有最符合的情况下会自动提升,就会导致提升之后可能会有多个匹配
方法的传值
注意:
1. 方法是在栈内存中执行
2. 方法在传值的时候,基本类型传递的实际值,数组传递的是地址。
3. 传递地址之后,如果地址没有发生改变,则代码执行影响原来的数组;如果地址发生了改变,则改变之后的代码不会影响原来的数组
方法的递归
展现形式:方法调用了自己本身
练习:输入一个数字n,求n! = n(n-1)(n-2)...1
6! = 6*5*4*3*2*1=720
注意:在递归的时候,当执行次数过多会产生StackOverflowError - 栈溢出错误
总结:在一些场景中,如果能确定这一项和前n项的关系,那么可以使用递归 ---> 逆推
IDE --- 智能开发工具
Eclipse(日食) --- 免费、基于插件、开源、绿色
Kepler(开普勒) -> Luna(月神) -> Mars(火星) -> Neon(霓虹灯) -> Oxygen(氧气)
面向对象
面向对象是一种思维方式,相对于面向过程而言的。
面向过程在流程中关注动作执行的每一个细节 --- 自己动手做
面向对象重点找这个对象,只要找到了对象,那么这个对象所具有的功能就能够被使用 --- 找别人做
面向对象一定比面向过程好吗?--- 不一定 ---相对简单的事务建议使用面向过程,相对复杂的事务建议使用面向对象
面向对象本身是基于面向过程的
类与对象的关系
根据一类对象进行抽取和总结,将这类对象的特征抽取成了属性,将这类对象的行为抽取成了方法,用类表示这一类对象 -> 类是对象的抽取和概括的过程
对象的内存存储
成员变量和局部变量
1. 定义位置:成员变量定义在类内方法外;局部变量是定义在方法或者是语句里面
2. 作用范围:成员变量作用在整个类内;局部变量是只能作用在定义它的方法或者语句中
3. 内存位置:成员变量随着对象的创建而存在了堆内存中并且在堆内存中赋予了默认值;局部变量在栈内存中存储
4. 生命周期:成员变量再对象创建的时候出现,在对象被回收的时候销毁;局部变量在方法或者语句执行的时候创建,方法或者语句执行完成之后就立即销毁
Eclipse - 日食
免费、开源、绿色、基于插件
Eclipse是由Java语言开发的
Kepter - Luna(JDK1.7) - Mars - Neon - Oxygen
Intelli J --- IDEA --- 收费
Ctrl + c 复制
Ctrl + v 粘贴
Ctrl + x 剪切
Ctrl + s 保存
Alt + / 快捷提示键
Ctrl + 1 错误提示键
Ctrl + Shift + o 导包
Alt + Shift + S source
Ctrl + Shift + f 调整格式 --- 不能在任何输入法下使用
Alt + ↑/↓ 整行上移/下移
Ctrl + F11 运行
Ctrl + F 搜索
Alt + Ctrl + ↑/↓ 整行向上/向下复制一行
Ctrl + D 删除一行
Ctrl + / 添加/取消单行注释
Ctrl + Shift + / 添加多行注释
Ctrl + Shift + \ 取消多行注释
Alt + ← 切换到上一个编辑的页面
Ctrl + N 新建
Ctrl + W 关闭当前的界面
Alt + F4 关闭当前的应用程序
DAY 07
复习:
1. 方法:需要重复使用某段逻辑的时候,就将这段逻辑提取成新的形式。
定义格式:修饰符 返回值类型 方法名(参数列表){方法体; return 返回值;} --- 形参,实参 --- 方法名+参数列表 -> 方法签名
public static int add(int i, int j){} --- add(int, int)
方法的重载:在同一个类中存在了方法名一致而参数列表不同(参数的个数/对应位置上的参数类型)的方法
方法的传值:基本类型传递的是实际值;对象传递的是地址,地址不变的前提下可以改变其中的属性或者元素。
方法的递归:在方法中调用了自己本身。当递归层次太深会出现StackOverflowError --- 栈溢出错误 --- 递归的思路往往是逆推的思维方式
2. 面向对象与面向过程的比较:都是思维方式。面向过程是注重流程中的每一个步骤,清楚每一个步骤中的细节(自己做);面向对象是注重对象,只要拥有了对象就能使用对象身上的功能(找别人做)。面向对象是基于面向过程的。相对简单的事务使用面向过程,相对复杂的事务使用面向对象。--- 面向对象更适合于团队的开发;面向过程一般而言比面向对象更适合于效率开发。
3. 类与对象的关系:类是对象的概括/抽取,对象是类的具体实现
4. 对象的内存存储:对象是存储在堆内存中,在栈内存中会存储对象的地址引用。对象在存储到内存中之后其中的属性会自动赋予默认值。--- 对象在使用完成之后不一定立即移出堆内存而是在不定的某个时刻被回收。
5. 成员变量和局部变量:定义位置、作用范围、内存位置、生命周期
构造方法
特点:与类同名而没有返回值类型的方法
作用:创建对象
this关键字
this关键字在类中调用本类里面的属性和方法,代表当前在活动的对象。
this语句 -> this(参数列表) - 表示在本类的构造方法中调用本类对应形式的其他的构造方法 - this语句必须放在构造方法的第一行
代码块
构造代码块:定义在类中用{}包起来的代码 --- 在创建对象的时候先于构造方法执行
局部代码块:定义在方法中用{}包起来的代码 --- 提高了栈内存的利用率
面向对象的特征
封装、继承、多态(抽象)
封装
将代码进行提取和总结,抽取成不同的形式 --- 封装
体现形式:方法、类(属性的私有化 - 将属性限制为私有的,然后提供对外的设置和获取的方法,然后在方法中进行限制使数据更加符合常理)
优势:提高了代码的复用性,保证了数据的合法性
权限修饰符
指在Java中用于限定使用范围的关键字
本类中 子类中 同包类中 其他类中
public 可以 可以 可以 可以
protected 可以 可以 可以 不可以
默认 可以 同包子类可以 可以 不可以
private 可以 不可以 不可以 不可以
练习:定义一个类表示矩形(长方形),提供获取周长和面积的方法
继承
如果一些类中含有相同的代码,那么可以将这些相同的代码提取到一个新的类中,然后通过extends关键字让原来的类和新的类产生关系 --- 继承。 通过继承,原来的类就称之为了子类(派生类),新的类就成了父类(超类/基类)。
子类通过继承父类可以使用父类中的一部分方法和属性
注意:子类继承了父类的全部的数据域(方法+属性),但是继承之后只有一部分数据域对子类可见
在Java中,支持的是类和类之间的单继承 -> 一个子类只能继承一个父类,但是一个父类可以有多个子类
单继承一定优于多继承吗? - 不对
多继承比单继承能够更好的提高代码的复用性
class A {
public int m(){return 9;}
}
class B {
public boolean m(){return false;}
}
class C extends A, B{}
C c = new C();
c.m(); // 返回值类型能确定吗?
多继承导致在调用方法的时候可能产生歧义
优势:提高代码的复用性,避免方法的调用产生歧义
super关键字
在子类中用于表示父类对象的引用,可以在子类中调用父类中的方法的属性。
super语句 --- 子类在继承父类之后,子类的构造方法中会含有一个super语句。如果没有手动指定super语句,那么默认使用super()调用父类无参的构造;如果父类只提供了含参构造,那么子类就必须手动提供对应形式的super语句 --- super语句必须在子类构造方法的首行
方法的重写/覆盖
在父子类中存在了方法签名相同的非静态方法。遵循 “两等两小一大”原则:
1. 方法签名相同
2. 如果父类中的方法的返回值类型是基本类型/void,那么子类重写的方法的返回值类型与父类一致
class A {
public void m(){}
}
class B extends A {
public void m(){}
}
3. 如果父类中的方法的返回值类型是引用类型,那么子类在重写方法的时候,返回值类型要么与父类一致,要么是父类方法返回值类型的子类
class A {}
class B extends A {}
class C {
public A m(){return null;}
}
class D extends C {
public B m(){return null;}
}
4. 子类重写的方法的权限修饰符的范围要大于等于父类中对应方法的权限修饰符的范围
class A {
public void m(){}
}
class B extends A {
public void m(){}
}
注意:如果父类中的方法用private修饰,那么这个方法对子类不可见,所以此时与子类中的方法构不成重写
多态
编译时多态:方法的重载
add(2, 4) -> add(int, int)
add(3, 1, 7) -> add(int, int, int)
运行时多态:向上造型和方法的重写 --- 基于继承的
注意:如果使用向上造型来创建对象,那么这个对象所能调用的方法看的是父类中的声明,方法如何执行看的是子类中的实现过程
重写的理解
1. 子类重写的方法的权限修饰符的范围要大于等于父类中对应方法的权限修饰符的范围
2. 如果父类中的方法的返回值类型是引用类型,那么子类在重写方法的时候,返回值类型要么与父类一致,要么是父类方法返回值类型的子类
注意:Java中所有的基本类型之间没有继承关系,之所以能够自动提升,是因为所表示的范围是否能够包含
DAY08
复习:
1. 构造方法:
特点:与类同名而没有返回值类型
作用:用于创建对象
当类中没有手动指定构造方法的时候在编译的时候自动添加一个无参构造
2. this关键字:代表本类的在活动的对象,用于在本类中调用本类的方法和属性 --- this语句,表示调用本类中其他的对应形式的构造方法,必须放在首行
3. 代码块:
构造代码块:在创建对象的时候先于构造方法执行一次 --- 用于完成一些初始化操作
局部代码块:提高栈内存的利用率
4. 封装:
体现形式:方法、类(属性的私有化 -> 将属性设置为private,对外提供对应的get/set的方法,在方法中可以进行限定使数据更加符合场景要求)
优势:提高复用性,保证数据的合法性
5. 继承 :用extends关键字来完成继承关系 --- 支持的类与类之间的单继承 --- 单继承和多继承的优劣性 --- 提高复用性,避免方法调用产生歧义 --- 子类可以继承父类全部的数据域,但是只有一部分可见
6. 多态:
编译时多态:方法的重载
运行时多态:
向上造型:用父类来声明用子类来创建 --- 对象能干什么看的是父类,对象如何执行方法看的是子类。
方法的重写(Override):父子类中存在了方法签名完全相同的非静态方法。--- 两等两小一大
7. 权限修饰符:public protected 默认 private --- protected在子类中使用的时候指的是在对应的子类中使用,不能跨子类使用
8. super关键字:在子类中表示父类对象的引用,用于调用父类中的方法和属性 --- super语句,表示在子类的构造方法中调用父类对应形式的构造方法。子类构造方法中如果没有手动指定super语句,那么默认调用父类无参构造(super());如果父类只提供了含参构造,那么子类的构造方法中必须手动提供对应形式的super语句
static - 静态
修饰符 - 用于修饰数据、方法、代码块以及内部类
静态变量
用static修饰变量,称之为静态变量,也叫类变量。在类加载的时候加载到了方法区,并且在方法区中被赋予了默认值。静态变量是先于对象出现的,所以习惯上是通过类名来调用静态变量。每一个对象存储的是这个静态变量在方法区中的地址,所以静态变量是被这个类的所有对象所共享的
静态变量能否定义到构造方法中?---不能。静态变量是在类加载的时候出现,先于对象出现。构造方法在创建对象的时候执行。
注意:
1. 类是加载到方法区中的
2. 类是在第一次使用的时候才加载,加载之后就不会移除
练习:定义一个类,统计这个类创建对象的个数
静态方法
用static修饰的方法,称之为静态方法。静态方法随着类的加载而加载到方法区中,但是在方法区中不执行只存储,在方法被调用的时候到栈内存执行。静态方法先于对象存在,所以习惯上是通过类名来调用静态方法。
main Arrays.sort() System.arraycopy()
静态方法中可以定义静态变量吗?--- 不能 --- 静态方法在调用的时候执行,静态方法执行的时候里面的变量才能初始化;静态变量是在类加载的时候初始化
静态方法中能否使用this/super?--- 不行 --- this代表当前在活动的对象,静态方法先于对象存在
能否在静态方法中直接使用本类中的非静态方法/非静态属性?--- 不行
public class A {
int i = 5;
public static void m(){
int j = (this.)i;
}
}
静态方法可以重载吗?---可以
静态方法可以被继承吗?---可以
静态方法可以重写吗?---不可以
静态方法虽然不能被重写,但是父子类中可以存在方法签名一致的静态方法 --- 静态方法的隐藏(hide)
注意:父子类中可以存在方法签名一致的方法,要么都是非静态(重写)要么都是静态(隐藏)
静态代码块
用static{}包起来的代码 --- 在类加载的时候执行一次
执行顺序:父类静态 -> 子类静态 -> 父类非静态 -> 父类的构造方法 -> 子类非静态 -> 子类的构造方法