Java基础复习篇
1.Java的特性和优势
- 简单性
- 面向对象
- 可移植性
- 高性能
- 分布式
- 动态性
- 多线程
- 安全性
- 健壮性
2.JDK、JRE、JVM
3.IDEA优化
4.Java基础语法
4.1.注释
- // 单行注释
- /* */ 多行注释
- /** */ 文档注释
4.2.数据类型
- 强类型语言 :要求变量的使用要严格符合规定,所有变量都必须先定义后才能使用
- 弱类型语言:跟强类型相反,比较随意
Java的数据类型分为两大类
- 基本类型
- 基本类型包括数值类型和boolean类型
- 数值类型又包括整数类型、浮点类型和字符类型
- 整数类型又包括以下几个
- byte –占1个字节 范围(-128~127)
- short –占2个字节 范围(-32768~32767)
- int –占4个字节 范围(-2147483648~2147483647)
- long –占8个字节 范围(-9223372036854775808~9223372036854775807)
- 浮点类型包括
- float –占4个字节
- double –占8个字节
- 字符类型有char –占2个字节
- 而boolean类型只有true和false两个,各占一个字节
- 引用类型
- 类
- 接口
- 数组
- 基本类型
最好避免使用浮点数进行比较,因为浮点数的精度会丢失,如果有这个场景,使用BigDecimal工具类来比较
所有的字符本质还是数字(97 = a,65 = A)
1
2
3
4
5
6
7
8
9
10
11
12
13public class Project {
public static void main(String[] args) {
//字符类型
char a = 'a';
char b = '张';
System.out.println(a);
System.out.println("a转为int:"+(int)a);
System.out.println(b);
System.out.println("张转为int:"+(int)b);
}
}布尔值知识扩展
1
2
3
4boolean flag = true;
if(flag==true){} //新手
if(flag){} //老手
//less is More! 代码要精简易读
4.3.类型转换
强制转换 (类型)变量名 高–低
1
2
3
4
5
6
7
8
9public class project1 {
public static void main(String[] args) {
int i = 150;
byte b = (byte) i; //内存溢出
System.out.println(i);
System.out.println(b);
}
}ps:我们可以看到byte b打印的值为-106这是为什么呢?
答:我们从底层源码可以看到byte最大值为127,我们的int i 为150,超出了byte的最大内存,造成内存溢出,byte值就会重新循环
Byte的底层源码:
1
2
3
4
5
6
7
8
9
10
11/**
* A constant holding the minimum value a {@code byte} can
* have, -2<sup>7</sup>.
*/
public static final byte MIN_VALUE = -128;
/**
* A constant holding the maximum value a {@code byte} can
* have, 2<sup>7</sup>-1.
*/
public static final byte MAX_VALUE = 127;自动转换 低–高
1
2
3
4
5
6
7
8
9
10public class project1 {
public static void main(String[] args) {
int i = 150;
byte b = (byte) i;
//我们可以看到int i转为double类型不需要加(类型)变量名也不会报错,这就是低到高的自动转换
double d = i;
System.out.println(i);
System.out.println(b);
}
}
注意点:
不能对布尔值进行转换
不能把对象类型转换为不相干的类型
在把高容量转换到低容量的时候,强制转换
转换的时候可能存在内存溢出,或者精度问题
1
2System.out.println((int)27.96); //27
System.out.println((int)56.48f); //56ps:我们的double类型和浮点类型转成int并不会四舍五入,而会丢失精度,直接舍弃小数点后面的值
char 跟 int 之间的转换
1
2
3
4char c = 97;
int x = c+1;
System.out.println(x);
System.out.println((char)x);ps:我们可以看到char转换成int是可以做运算的,但是当我们把运算后的x值强转为char的时候x的值就变成了b,这是因为在char字符中97对应的a,加一之后就会变成b,字符的本质就是数字,字符和数字的对应也是有顺序的。
操作比较大的数的时候,注意溢出问题
1
2
3
4
5
6
7
8
9
10
11
12
13public class project2 {
public static void main(String[] args) {
//jdk7的新特性,数字之间可以用下划线分割
int money = 10_0000_0000;
int years = 30;
int total = money*years; //-64771072,计算的时候超出了int的最大内存,导致内存溢出
long total1 = money*years; //-64771072,计算后默认是int类型,在转换之前就已经溢出了
long total2 = money*(long)years; //30000000000,先将一个值转换,计算后会将值转换为long类型
System.out.println(total);
System.out.println(total1);
System.out.println(total2);
}
}
4.4.变量和常量
变量:就是可以变化的值
1 |
|
变量的命名规范:
- 所有变量,方法,类名:都要求见名知意
- 类成员变量:首字母小写和驼峰原则:monthSalary,除了第一个单词以外,后面的单词首字母大写
- 局部变量:首字母小写和驼峰原则
- 类名:首字母大写和驼峰原则:Man,GoodMan
- 方法名:首字母小写和驼峰原则:run(),runRun()
常量:初始化后不能再改变值!不会动的值,常量名一般使用大写字符和下划线:MAX_VALUE
1 |
|
ps:常量不能被修改,初始化之后值就给定死了
4.5.运算符
- 算术运算符:+,-,*,/,%,++,–
- 赋值运算符:=
- 关系运算符:>,<,>=,<=,==,!=,instanceof
- 逻辑运算符:&&,||,!
- 位运算符:&,|,^,~,>>,<<,>>>(了解)
- 条件运算符:?,:
- 扩展赋值运算符:+=,-=,*=,/=
一元运算符:
1 |
|
短路运算:
&&:如果前面一个为假就不会再往后面执行
1
2
3
4
5
6
7
8
9public class Project6 {
public static void main(String[] args) {
int a = 4;
boolean b = (a<4) && (a++<4);
System.out.println(a);
System.out.println(b);
}
}ps:我们可以看到a打印的还是4,如果往&&后面去执行了a++就会是5
三元运算符:
1 |
|
4.5.JavaDoc生成文档
5.Java流程控制
5.1.Scanner的使用
5.2.顺序结构
- Java的基本结构就是顺序结构,除非特别指明,否则按照顺序一句一句执行。
- 顺序结构是最简单的算法结构,他是任何一个算法都离不开的一种基本算法结构
5.3.选择结构
- if单选择结构
- if双选择结构
- if多选择结构
- 嵌套的if结构
- switch多选择结构
- 从JavaSE 7开始 switch就支持字符串类型了
- case穿透 ,为了防止case穿透,尽量在每个case后面都加上break;
拓展:反编译 java — class(字节码文件) —反编译(IDEA)
ps:哈希通过特定算法,给每个对象一个唯一的值
5.4.循环结构
while循环:
只要布尔表达式为true,循环就会一直执行下去
我们大部分情况是会让循环停止下来的,我们需要一个让表达式失效的方式来结束循环
少部分情况需要循环一直执行,比如服务器的请求响应监听等。
循环条件一直为true就会造成无限循环【死循环】,我们正常的业务编程中应该尽量避免死循环。会影响程序性能或者造成程序卡死崩溃!
实例:计算1+2+3+……+100=?
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Project8 {
public static void main(String[] args) {
int i = 1;
int sum = 0;
while (i<=100){
sum+=i;
i++;
}
System.out.println(sum);
}
}
do while循环:
和while循环的区别:
- while是先判断后执行,do while是先执行后判断
- do while 总是保证循环体至少会被执行一次!这是他们的主要差别
for循环:
for循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环结构
实例1:计算0到100之间的奇数和偶数和
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public class Project9 {
public static void main(String[] args) {
int oddSum = 0;
int evenSum = 0;
for (int i = 0; i <=100; i++) {
if(i%2!=0){
evenSum+=i;
}else{
oddSum+=i;
}
}
System.out.println("奇数和:"+evenSum);
System.out.println("偶数和:"+oddSum);
}
}
结果:
实例2:用for循环输出1-1000之间能被5整除的数,并且每行输出3个
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18package demo2;
public class Demo1 {
public static void main(String[] args) {
int l = 0;
for (int i = 1; i <= 1000; i++) {
if (i % 5 == 0) {
System.out.print(i + "\t");
l++;
}
if (l == 3) {
System.out.println();
l=0;
}
}
}
}实例3:打印九九乘法表
1
2
3
4
5
6
7
8
9
10
11
12package demo2;
public class Demo2 {
public static void main(String[] args) {
for (int i = 1; i <=9; i++) {
for (int j = 1; j <=i; j++) {
System.out.print(i+"*"+j+"="+(i*j)+"\t");
}
System.out.println();
}
}
}
增强for循环:
Java5引入了一种主要用于数组或集合的增强型for循环
实例:
1
2
3
4
5
6
7
8
9
10package demo2;
public class Demo3 {
public static void main(String[] args) {
int[] a = {1,2,3,4,5};
for (int i : a) {
System.out.println(i);
}
}
}
break continue goto关键字(了解):
break在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句。(break也可以在switch语句中使用)
continue语句用在循环句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定
总结:实例:打印三角形
1 |
|
6.Java方法
何为方法:
- Java方法是语句的集合,他们在一起执行一个功能
- 方法就是解决一类问题的步骤的有序组合
- 方法包含于类或对象中
- 方法在程序中被创建,在其他地方被引用
- 设计方法的原则:方法的本意是功能块,就是实现某个功能的语句块的集合,我们设计方法的时候,最好保持方法的原子性,就是一个方法只实现1个功能,这样利于我们后期的扩展。
方法的定义:
Java的方法类似于其它语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含以下语法:
方法包含一个方法头和一个方法体。下面是一个方法的所有部分:
- 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。
- 返回值类型︰方法可能会返回值。returnValueType是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType是关键字void。
- 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
- 参数类型:参数像是一气占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
- 形式参数:在方法被调用时用于接收外界输入的数据。
- 实参:调用方法时实际传给方法的数据。
- 方法体:方法体包含具体的语句,定义该方法的功能。
语法:
1 |
|
方法的重载:
重载就是在一个类中,有相同的函数名称,但形参不同的函数
方法的重载规则:
- 方法名称必须相同
- 参数列表不许不同(个数不同,类型不同,参数排列顺序不同)
- 方法的返回类型可以相同也可以不同
- 仅仅返回类型不同不足以成为方法的重载
实现理论:方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,已选择对应的方法,如果匹配失败,则编译器报错。
命令行传参:
可变参数:
- JDK1.5开始,Java支持传递同类型的可变参数给一个方法
- 在方法声明中,在指定参数类型后面加一个省略号(…)
- 一个方法中只能定义一个可变参数,他必须是方法的最后一个参数。任何普通的参数必须在它之前声明
1 |
|
ps:可变参数的本质上就是数组
递归:
递归就是A方法调用A方法,就是自己调自己
递归结构包括两个部分
- 递归头:什么时候不调用自身方法,如果没有头,将陷入死循环,就是结束递归的方法
- 递归体:什么时候需要调用自身方法
实例:阶乘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18package demo2;
public class Demo6 {
public static void main(String[] args) {
Demo6 demo6 = new Demo6();
System.out.println(demo6.f(5));
}
public int f(int num){
if(num == 1){
return 1;
}
if(num>1){
num = num*f(num -1);
}
return num;
}
}ps:不要用递归做大的运算,不然很容易就内存溢出了
实例:编写一个计算器
1 |
|
7.数组
数组的定义:
- 数组是相同类型数据的有序集合
- 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成
- 其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问他们,数组的下标是从0开始的
数组声明创建的几种方式:
1 |
|
数组的四个特点:
- 数组的长度是确定的,数组一旦被创建,它的大小就是不可改变的。
- 数组的元素必须是相同类型,不允许出现混合类型
- 数组中的元素可以是任何数据类型,包括基本类型和引用类型
- 数组变量属引用类型,数组也可以看出是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的
总结:
- 数组是相同数据类型(数据类型可以为任意类型)的有序集合
- 数组也是对象。数组元素相当于对象的成员变量
- 数组长度是确定的,不可变的。如果越界,则报:ArrayIndexOutoBounds
实例:
计算所有元素的和 和 查找最大的元素
1
2
3
4
5
6
7
8
9
10
11
12
13int maxNum = 0;
int sum = 0;
for (int i = 0; i < a.length; i++) {
sum+=a[i]; //计算所有元素的和
//查找最大的元素
if(a[i]>maxNum){
maxNum=a[i];
}
}
System.out.println(sum);
System.out.println(maxNum);
}数组入参
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15package demo2;
public class Demo9 {
public static void main(String[] args) {
int[] array = {1,2,3,4,5};
Demo9 demo9 = new Demo9();
demo9.test(array);
}
public void test(int[] array){
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
}反转数组
1
2
3
4
5public void test1(int[] arrays){
for (int i = arrays.length-1; i>=0; i--) {
System.out.println(arrays[i]);
}
}
多维数组:
多维数组可以看出是数组的数组,比如二维数组就是一个特殊的一维数组,其每个元素都是一个一维数组。
二维数组的两种创建方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17package demo3;
public class Demo1 {
public static void main(String[] args) {
int[][] array = new int[3][5];
array[0][1] = 1;
array[0][4] = 5;
System.out.println(array[0][4]);
System.out.println("=========================");
int[][] array1 = {{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15}};
for (int i = 0; i < array1.length; i++) {
for (int j = 0; j < array1[i].length; j++) {
System.out.println(array1[i][j]);
}
}
}
}
Array类的常用方法:(详情查看jdk帮助文档)
1 |
|
冒泡排序法:
1 |
|
ps:排序后的结果
稀疏数组:
8.面向对象编程
面向过程思想:
- 步骤清晰简单,面对过程适合处理一些较为简单的问题,面向过程是具体的
面向对象思想:
- 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。
- 面向对象适合处理复杂的问题,适合处理需要多人协作的问题。
总结:对于描述复杂的事物,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理
什么是面向对象:
- 面向对象编程的本质就是:以类的方式组织代码,以对象的方式封装数据
- 三大特性:封装,继承,多态
- 从认识论角度考虑是先有对象后有类。对象,是具体的事物,类是抽象的,是对对象的抽象
- 从代码运行角度考虑是先有类后有对象。类是对象的模板
构造方法:
和类命相同
没有返回值
作用:
- new 的本质是在调用构造器
- 初始化对象的值
注意:定义有参构造之后,如果想使用无参构造,显示的定义一个无参构造
创建对象内存分析:
图片引用狂神说Java
封装:
该露的露,该藏得藏,我们程序设计要追求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉,低耦合:仅暴露少量的方法给外部使用
封装(数据的隐藏):通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏
属性私有,提供一些可操作属性的get/set方法,set方法中还能做一些判断
封装的好处:
- 提高程序的安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 可维护性
继承:
- Java中只有单继承,没有多继承
- 继承是类和类之间的一种关系,除此之外,类和类之间的关系还有依赖、组合、聚合等。
- 继承关系的两个类,一个为子类,一个为父类。子类继承父类,使用关键字extends来表示,子类继承父类,就会拥有父类的全部方法,子类可以调用父类的方法
- 所有的类,都默认直接或间接继承Object类
super注意点:
super调用父类的构造方法,必须在构造方法的第一个
super必须只能出现在子类的方法或构造方法中
super和this不能同上调用方法
vs this
代表的对象不同
- this : 本身调用者这个对象
- super : 代表父类对象的应用
前提
- this: 没有继承也可以使用
- super:只能在继承条件才可以使用
构造方法 :
- this():本类的构造
- super():父类的构造
方法重写:
- 需要有继承关系,子类重写父类的方法
- 方法名必须相同,参数列表也必须相同
- 修饰符:范围可以扩大,但不能缩小:public>Protected>Default>private
- 抛出的异常:范围可以缩小,但不能扩大
- 重写,子类的方法和父类必须一致,方法体不同
- 为什么需要重写:
- 父类的功能,子类不一定需要,或者不一定满足!
多态:
即同一方法可以根据发送对象的不同而采用多种不同的行为方式
多态存在的条件
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
注意:
- 多态是方法的多态,属性没有多态性
- 要有继承关系才能类型转换
- static方法:属于类,它不属于实例,不能重写,也就没有多态
- final修饰的方法不能被修改,所有无法重写,所有也没有多态
- private方法修饰的方法也不能重写,没有多态
static关键字详解:
静态变量和静态方法都可以直接调用
静态代码块:类加载的时候就会执行,只执行一次
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24package demo3;
public class Demo4 {
//2
{
System.out.println("匿名代码块");
}
//类加载的时候就会执行,只会执行一次
//1
static {
System.out.println("静态代码块");
}
//3
public Demo4(){
System.out.println("构造方法");
}
public static void main(String[] args) {
Demo4 demo4 = new Demo4();
System.out.println("=====================");
Demo4 demo41 = new Demo4();
}
}
![image-20210401155655719](image-20210401155655719.png)ps:执行顺序:静态>匿名>构造 但是static只会执行一次
静态导入包
1
2
3
4
5
6
7
8
9
10package demo3;
import static java.lang.Math.random;
import static java.lang.Math.PI;
public class Demo5 {
public static void main(String[] args) {
System.out.println(random());
System.out.println(PI);
}
}
抽象类:
类添加abstract关键字,就变成了抽象类
方法加abstract关键字,就变成了抽象方法
抽象方法只有方法名字 没有方法的实现,让继承抽象类的类去帮我们实现
1
2
3
4
5
6package demo3;
//抽象类
public abstract class Demo6 {
//抽象方法,继承抽象类的必须重写这个方法,我们不需要写具体实现,交给继承的类去帮我们实现
public abstract void add();
}1
2
3
4
5
6
7
8
9
10
11
12
13
14package demo3;
//继承抽象类
public class Demo7 extends Demo6{
//重写抽象方法,并添加具体实现
@Override
public void add() {
System.out.println("继承抽象类的抽象方法");
}
public static void main(String[] args) {
Demo7 demo7 = new Demo7();
demo7.add();
}
}总结:
- 不能new这个抽象类,只能靠子类去实现它
- 抽象类中可以写普通的方法
- 抽象方法必须在抽象类中
接口:
- 接口可以定义一些方法,让不同的类去实现
- 接口不能被实例化,接口中没有构造方法
- 使用implements可以实现多个接口,实现接口必须要重写接口中的方法
内部类:
异常机制:
- 五个关键字:
- try:监控异常
- catch:捕获异常
- finally:处理善后工作,总会执行
- throw:主动抛出异常,一般在方法中使用
- throws:主动抛出异常,一般在方法上使用
- Post title:java基础复习篇
- Post author:周瑜
- Create time:2021-04-01 17:20:04
- Post link:https://xinblog.github.io/2021/04/01/java-md/
- Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.