最后
一次偶然,从朋友那里得到一份“java高分面试指南”,里面涵盖了25个分类的面试题以及详细的解析:JavaOOP、Java集合/泛型、Java中的IO与NIO、Java反射、Java序列化、Java注解、多线程&并发、JVM、Mysql、Redis、Memcached、MongoDB、Spring、Spring Boot、Spring Cloud、RabbitMQ、Dubbo 、MyBatis 、ZooKeeper 、数据结构、算法、Elasticsearch 、Kafka 、微服务、Linux。
这不,马上就要到招聘季了,很多朋友又开始准备“金三银四”的春招啦,那我想这份“java高分面试指南”应该起到不小的作用,所以今天想给大家分享一下。
请注意:关于这份“java高分面试指南”,每一个方向专题(25个)的题目这里几乎都会列举,在不看答案的情况下,大家可以自行测试一下水平 且由于篇幅原因,这边无法展示所有完整的答案解析
| — | — | — |
| && | 短路与 | 作用与&相同,但是有短路效果 |
| ||
| 短路或 | 作用与竖线相同,但是有短路效果 |
- 范例:
public class Demo {
public static void main(String[] args) {
int i = 10;
int j = 20;
//&& :具有短路效果,符号左边为false的时候,右边就不执行
//如果符号左边为true,右边要继续执行
System.out.println((i++>100) && (j++>100)); //false & false,
System.out.println(“i=”+i); //11
System.out.println(“j=”+j); //20
}
}
注意事项
:
1、逻辑与 &:无论左边真假,右边都要执行
2、短路与 &&:如果左边为真,右边执行;如果左边为假,右边不执行
3、逻辑或 | : 无论左边真假,右边都要执行
4、短语或 ||:如果左边为假,右边执行;如果左边为真,右边不执行
3.7 三元运算符
-
格式:关系表达式 ? 表达式1 :表达式2;
-
范例:a > b ? a : b;
-
计算规则:
首先计算关系表达式的值
如果值为true,表达式1的值就是运算结果;
如果值为false,表达式2的值就是运算结果。
- 范例:
public class Demo {
public static void main(String[] args) {
int i = 10;
int j = 20;
//输出两个数据中的较大值
int max = i > j ? i : j;
System.out.println(“max=” + max); //20
}
}
3.8 Scanner使用的基本步骤
-
导包的三种方式:
-
1、手动导包:
import java.util.Scanner
; -
2、快捷键导包:创建好Scanner对象后,鼠标放在Scanner上按Alt+Enter
-
3、自动导包:写Scanner单词创对象时,按tab补全导包
-
导包的步骤:
-
1.导包
import java.util.Scanner; //导包必须在定义类上面
- 2.创建对象
Scanner sc = new Scanner(System.in); //只有sc是变量名可以变,其他都不可以变
- 3.接收数据
int i = sc.nextInt(); //i是变量名可以变,其他都不能变
sc.nextInt(); //Ctrl+alt+v:补全生成左边的内容
3.9 案例:三个和尚
import java.util.Scanner;
public class Demo {
public static void main(String[] args) {
//从键盘输出三个身高求出最高值
Scanner sc = new Scanner(System.in);
//键盘输入三个数值
int height1 = sc.nextInt();
int height2 = sc.nextInt();
int height3 = sc.nextInt();
int temp = (height1>height2) ? height1:height2;
int max = (temp>height3) ? temp:height3;
System.out.println(max);
}
}
4.1 流程控制语句分类
-
顺序结构
-
分支结构(if、switch)
-
循环结构(for、while、do…while)
4.2 if语句
4.2.1 if语句格式1
- 格式:
if(关系表达式) {
语句体;
}
- 执行流程:
1、首先计算关系表达式的值
2、如果关系表达式的值为true就执行语句体
3、如果关系表达式的值为false就不执行语句体
4、继续执行后面的语句内容
4.2.2 if语句格式2
- 格式:
if(关系表达式) {
语句体1;
}else {
语句体2;
}
- 执行流程:
1、首先计算关系表达式的值
2、如果关系表达式的值为true就执行语句体1
3、如果关系表达式的值为false就执行语句体2
4、继续执行后面的语句内容
4.2.3 if语句格式3
- 格式:
if(关系表达式1) {
语句体1;
}else if(关系表达式2){
语句体2;
}
…
else {
语句体n+1;
}
- 执行流程:
1、首先计算关系表达式1的值
2、如果值为true就执行语句体1;如果值为false就计算关系表达式2的值
3、如果值为true就执行语句体2;如果值为false就计算关系表达式3的值
…
4、如果没有任何关系表达式值为true就执行语句体n+1
- 范例:
import java.util.Scanner;
public class Demo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println(“请输入你的成绩”);
int score = sc.nextInt();
if(score == 100){
System.out.println(“满分”);
}else if(score >= 90) {
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(“不及格”);
}
}
}
4.3 switch语句
- 格式:
switch(表达式) {
case 值1:
语句体1;
break;
case 值2:
语句体2;
break;
…
default:
语句体n+1;
break; //最后一个可以省略
-
格式说明
-
表达式:取值为byte、short、int、char,JDK5以后可以是枚举,JDK7以后可以是String
-
case:后面跟的是要跟表达式比较的值
-
break:表示中断结束的意思,用来结束switch语句
-
default:表示所有情况都不匹配的时候,就执行该处内容,和if语句中的else相似
-
执行流程:
1、首先计算表达式的值
2、以此和case后面的值进行比较,如果有对应值,就会执行相应语句,在执行过程中,遇到break就会结束
3、如果所有的case的值和表达式的值都不匹配,就会执行default里面的语句体,然后程序结束
-
注意事项:在switch语句中,如果case控制的语句后面不写break,将会出现穿透现象,在不判断下一个case的情况下,向下运行,直到遇到break,或者整体程序结束
-
案例:初夏秋冬(case穿透)
import java.util.Scanner;
public class Demo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println(“请输入一个月份”);
int month = sc.nextInt();
switch(month) {
//case穿透
case 1:
case 2:
case 12:
System.out.println(“冬季”);
break;
case 3:
case 4:
case 5:
System.out.println(“春季”);
break;
case 6:
case 7:
case 8:
System.out.println(“夏季”);
break;
case 9:
case 10:
case 11:
System.out.println(“秋季”);
break;
default:
System.out.println(“你输入的月份有误”);
}
}
}
4.4 for循环语句
- 格式:
for(初始化语句;条件判断语句;条件控制语句){
循环体语句;
}
- 流程图
- 执行流程
1、执行初始化语句
2、执行条件判断语句,且看结果是true还是false
如果是false,循环结束;如果是true,继续执行
3、执行循环体语句
4、执行条件控制语句
5、返回到2继续
4.4.1 案例1: 输出数据
public class Demo {
public static void main(String[] args) {
// 输出1-5
for(int i=1;i<=5;i++) {
System.out.print(i+" "); //1 2 3 4 5
}
// 输出5-1
for(int i=5;i>0;i–) {
System.out.print(i + " "); //5 4 3 2 1
}
}
}
4.4.2 案例2: 求1-5数据和
public class Demo {
public static void main(String[] args) {
int sum = 0;
for(int i=1;i<=5;i++) {
sum += i;
}
System.out.println(sum); //15
}
}
4.4.3 案例3: 求1-100偶数数据和
public class Demo {
public static void main(String[] args) {
int sum = 0;
for(int i=1;i<=100;i++) {
//判断i是否为偶数
if(i%2==0){
sum += i;
}
}
System.out.println(sum);
}
}
4.4.4 案例4: 打印1-100的数每行10个
public class Demo {
public static void main(String[] args) {
//打印1-100,每行10个
int a = 0;
for(int i=0;i<100;i++){
a++;
System.out.print(i+" ");
if(a % 10 == 0){ //10代表每行10个,可以换为所需个数
System.out.println(); //10个后换行
}
}
}
}
4.4.5 案例5: 水仙花数
- 什么是水仙花数?
1、水仙花数是一个三位数
111 333 456 999 530
2、水仙花数的个位、十位、百位的数字立方和等于原数
- 怎么获取个位、十位、百位上的数
1、个位数
371 ;1就是原始数字对10进行取余的运算结果;371 % 10 = 1
2、十位数
371;371通过除以10,可以将7移动到个位上去(整数);371 / 10 = 37
37 ;37对10进行取余可以得到最后一位的值7 ; 37 % 10 = 7
3、百位数
371 ; 3就是原始数字除以100的结果(整除);371 /100 = 3
4、思考:任意数字的指定位置上的数值如何求?
123456789 ; 先10000得到12345;再对10取余得到5
public class Demo {
public static void main(String[] args) {
for(int i=100;i<=999;i++) {
int a = i % 10; //个位
int b = i / 10 % 10; //十位
int c = i / 100 ; //百位
if(aaa + bbb + ccc == i) {
System.out.println(“水仙花数:”+i); //有153、370、371、407
}
}
}
}
4.4.6 案例6: 统计水仙花个数
public class Demo {
public static void main(String[] args) {
int count = 0; //存放判断水仙花的次数
for(int i=100;i<=999;i++) {
int a = i % 10; //个位
int b = i / 10 % 10; //十位
int c = i / 100 ; //百位
if(aaa + bbb + ccc == i) {
count++;
}
}
System.out.print(“水仙花共有”+count+“个”); //4个
}
}
4.5 while循环语句
-
用法:用来描述未知次数循环
-
格式:
初始化语句;
while(条件判断语句) {
循环体语句;//比如:输出内容
条件控制语句;
}
- 执行流程:
1、执行初始化语句;
2、执行条件判断语句,看其结果为true还是false
如果是false,循环结束;如果是true,继续执行
3、执行循环体语句
4、执行条件控制语句
5、回到2继续
- 案例:珠穆朗玛峰
public class Demo {
public static void main(String[] args) {
//需求:世界最高山峰是珠穆朗玛峰(8844.43米=8844430毫米)
//假如我有一张足够大的纸,它的厚度是0.1毫米。
//请问,我折叠多少次,可以折成珠穆朗玛峰的高度?
//1.定义计数器变量,用于统计折叠的次数
int count = 0;
//2.定义纸张厚度变量
double paper = 0.1;
//3.定义珠峰高度变量
int zf = 8844430;
//不知道循环次数,更适合使用while
while(paper<=zf) {
//循环过程中每次纸张堆叠,厚度加倍
paper *= 2;
//在循环中累加次数
count++;
}
//循环结束后打印
System.out.println(count); //27
}
}
4.6 do…while循环语句
- 格式:
初始化语句;
do{
循环体语句;//比如:输出内容
条件控制语句;
}while(条件判断语句);
- 执行流程:
1、执行初始化语句
2、执行循环体语句
3、执行条件控制语句
4、执行条件判断语句,看其结果为true还是false
如果是false,循环结束;如果是true,继续执行
5、回到2继续
4.7 三个循环的区别
4.7.1 第一
-
do…while:先输出一次再进行判断(最少输出一次)
-
for、while:先判断再输出
4.7.2第二
-
for循环结束后变量不能使用
-
while循环结束后还可以使用(打印变量次数)
4.7.3死循环
- for语句
for(;😉{
System.out.println(“死循环”);
}
- while语句
while(true){
System.out.println(“死循环了”);
}
- do…while语句
do{
System.out.println(“死循环”);
}while(true);
4.8 跳转控制语句
-
continue:用于循环中,基于条件控制,跳过某次循环体内容的执行,继续下一次执行
-
break:用于循环中,基于条件控制,终止循环体内容执行,结束当前整个循环
-
范例:
public class Demo {
public static void main(String[] args) {
for(int i=1;i<=5;i++) {
if(i%2==0) {
//continue; //为偶数时跳过输出,1 3 5
break; //当遇到偶数终止循环,只输出1
}
System.out.println(i);
}
}
}
4.9 循环嵌套
public class Demo {
public static void main(String[] args) {
//九九乘法表
for(int i=1;i<=9;i++) {
for(int j=1;j<=i;j++) { //j<=i,当i=1时,j=1,输入一次后循环结束;i的值加1,i=2,j=1,输出两次后跳出…
System.out.print(i +“"+j + “=” + ij +” ");
}
System.out.println();
}
}
}
4.10 Random使用步骤
-
作用:用于产生一个随机数
-
步骤:
-
1.导包:
import java.util.Random
- 2.创建对象:
Random r = new Random(); //r是变量名可变
- 3.获取随机数:
int number = r.nextInt(10);
//获取数据的范围是:[0,10),包括0,不包括10
//number是变量名可变,数字10可变
- 案例:猜数字游戏
import java.util.Scanner;
import java.util.Random;
public class Demo {
public static void main(String[] args) {
//1.生成随机数1-100
Random r = new Random();
int number = r.nextInt(100)+1; //
//4.不确定次数用while,死循环
while(true) {
//2.键盘输出数字
Scanner b = new Scanner(System.in);
System.out.println(“请输入要猜的数字:”);
int guessnumber = b.nextInt();
//3.比较
if(guessnumber>number) {
System.out.println(“你猜的数字”+guessnumber+“大了”);
}else if(guessnumber<number) {
System.out.println(“你猜的数字”+guessnumber+“小了”);
}else {
System.out.println(“猜对了”);
break;
}
}
}
}
- 数组(array [əˈreɪ] )是一种用来存储多个相同类型数据的存储模型
5.1 数组定义格式
- 格式1(常用)
//数据类型[] 变量名;
int[] arr; //定义了一个int类型的数组,数组名是arr
- 格式2
//数据类型 变量名[];
int arr[]; //定义了一个int类型的变量,变量名是arr数组
5.2 数组初始化
5.2.1 动态初始化
-
初始化时只指定初始化长度,由系统为数组分配默认初始化值
-
默认值:
-
int:默认值0
-
float:默认值0.0
-
boolean:默认值false
-
char:默认值是空字符
-
引用数据类型:默认值null
-
格式:
数据类型[] 变量名 = new 数据类型[数组长度];
- 范例:
//new:为数组申请内存空间 3:数组长度/数组中元素个数
int[] arr = new int[3];
System.out.print(arr[0]) //0 系统分配的默认初始化值
5.2.2 静态初始化
-
初始化指定数组元素,系统会根据元素个数,计算出数组的长度
-
格式:
数据类型[] 变量名 = new 数据类型[]{数据1,数据2,数据3,…}
数据类型[] 变量名 = {数据1,数据2,数据3,…} //简化格式
- 范例:
int[] arr = new int[]{1,2,3};
System.out.println(arr[0]);
int[] arr1 = {1,2,3};
System.out.println(arr1[0]); //1
5.3 数组元素访问
-
数组变量访问方式
-
格式:变量名
-
数组内部保存数据访问方式
-
格式:数组名[索引] //0、1、2、3…
int[] arr1 = {1,2,3};
System.out.println(arr1); //[I@1b6d3586:内存空间地址值
System.out.println(arr1[0]); //1
System.out.println(arr1[1]); //2
System.out.println(arr1[2]); //3
5.4 内存分配
-
栈内存:存储局部变量(定义在方法中的变量,如:arr,使用完毕立刻消失)
-
堆内存:存储new出来的内容(实体、对象)(垃圾回收器空闲时回收)
5.5 遍历数组
- 获取数组元素个数,格式:
数组名.length
public class Demo {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
for(int i=0;i<arr.length;i++) {
System.out.println(arr[i]); // 1 2 3 4 5
}
}
}
5.6 获取数组最值
- 执行流程:
1、假设数组中的第一个元素为最大值
2、遍历数组,获取每一个元素,准备进行比较
3、如果比较的过程,出现了比max更大的,让max记录更大的值
4、循环结束后,打印最大值
public class Demo {
public static void main(String[] args) {
int[] arr = {2,6,7,8,1,3,5,4,9};
int max = arr[0];
for(int i=1;i<arr.length;i++) {
if(arr[i] > max) {
max = arr[i];
}
}
System.out.println(max); //循环结束后打印
}
}
6.1 二维数组格式
- 格式一 :数据类型[ ][ ] 变量名;
int[][] arr;
- 格式二 :数据类型 变量名[][];
int arr[][];
- 格式三 :数据类型[] 变量名[];
int[] arr[];
6.2 动态初始化
-
格式:数据类型[ ][ ] 变量名 = new 数据类型[m][n];
-
m:行
-
n:列(每行可以存放多少数据)
-
范例:
public class Demo {
public static void main(String[] args) {
int[][] arr = new int[2][3];
for(int[] row : arr) {
for(int data : row) {
System.out.printf(“%d\t”,data); // 0 0 0
} // 0 0 0
System.out.println();
}
}
}
6.3 访问元素
public class Demo{
public static void main(String[] args){
/*
问题:二维数组中存储的是一维数组,那能不能存入[提前创建好的一维数组]呢?
*/
int[] arr1 = {11,22,33};
int[] arr2 = {44,55,66};
int[] arr3 = {77,88,99,100};
int[][] arr = new int[3][3];
arr[0] = arr1;
arr[1] = arr2;
arr[2] = arr3;
//输出二维数组
for(int[] row : arr) {
for(int data : row) {
System.out.printf(“%d\t”,data); //11 22 33
} //44 55 66
System.out.println(); //77 88 99 100
}
System.out.println(arr[1][2]); //66
System.out.println(arr[2][3]); //100
}
}
6.4 静态初始化
- 格式1:格式: 数据类型[ ][ ] 变量名 = new 数据类型[ ][ ] {{元素1,元素2…},{元素1,元素2…}};
int[][] arr = new int[][]{{11,22},{33,44}};
- 格式2(简化格式):数据类型[][] 变量名 ={{元素1,元素2},{元素1,元素2…}};
int[][] arr = {{11,22},{33,44}};
6.5 遍历二维数组
public class Demo{
/*
需求:已知一个二维数组 arr = {{11,22,33},{44,55,66}}
遍历该数组,取出所有元素并打印
*/
public static void main(String[] args){
int[][] arr = {{11,22,33},{44,55,66}};
// 遍历二维数组,取出里面每一个一维数组
for(int i = 0;i < arr.length;i++){
// 遍历一维数组,arr[i]就是每一个一维数组
for(int j = 0;j < arr[i].length;j++){
System.out.print(arr[i][j]+" "); //11 22 33 44 55 66
}
}
}
}
1.缝七过
最后
小编利用空余时间整理了一份《MySQL性能调优手册》,初衷也很简单,就是希望能够帮助到大家,减轻大家的负担和节省时间。
关于这个,给大家看一份学习大纲(PDF)文件,每一个分支里面会有详细的介绍。
这里都是以图片形式展示介绍,如要下载原文件以及更多的性能调优笔记(MySQL+Tomcat+JVM)!
for(int[] row : arr) {
for(int data : row) {
System.out.printf(“%d\t”,data); //11 22 33
} //44 55 66
System.out.println(); //77 88 99 100
}
System.out.println(arr[1][2]); //66
System.out.println(arr[2][3]); //100
}
}
6.4 静态初始化
- 格式1:格式: 数据类型[ ][ ] 变量名 = new 数据类型[ ][ ] {{元素1,元素2…},{元素1,元素2…}};
int[][] arr = new int[][]{{11,22},{33,44}};
- 格式2(简化格式):数据类型[][] 变量名 ={{元素1,元素2},{元素1,元素2…}};
int[][] arr = {{11,22},{33,44}};
6.5 遍历二维数组
public class Demo{
/*
需求:已知一个二维数组 arr = {{11,22,33},{44,55,66}}
遍历该数组,取出所有元素并打印
*/
public static void main(String[] args){
int[][] arr = {{11,22,33},{44,55,66}};
// 遍历二维数组,取出里面每一个一维数组
for(int i = 0;i < arr.length;i++){
// 遍历一维数组,arr[i]就是每一个一维数组
for(int j = 0;j < arr[i].length;j++){
System.out.print(arr[i][j]+" "); //11 22 33 44 55 66
}
}
}
}
1.缝七过
最后
小编利用空余时间整理了一份《MySQL性能调优手册》,初衷也很简单,就是希望能够帮助到大家,减轻大家的负担和节省时间。
关于这个,给大家看一份学习大纲(PDF)文件,每一个分支里面会有详细的介绍。
[外链图片转存中…(img-qFiJSspR-1715640673279)]
这里都是以图片形式展示介绍,如要下载原文件以及更多的性能调优笔记(MySQL+Tomcat+JVM)!