腾讯云智一面---后台开发(凉经)
一、java的特性是什么?
二、什么是封装、继承、多态(面向对象的角度,最好用项目中 / 生活中的例子),贯穿始终,看你能不能讲清楚)?再讲一下什么是抽象?(我举了汽车的例子)
三、面向对象 和 面向过程有什么区别?
四、for循环有多少中写法?(常见的写法,不包含迭代器)
五、for循环分成好几部分,讲它的每一部分和每一部分的作用。
六、数组,有五个元素【1,2,3,4,5】,如何通过for循环打印1 3 5 用for循环怎么写?
while循环打印 数组【1,2,3,4,5】怎么写?
七、多线程了解吗?举一个多线程的例子?什么情况下用多线程做事情?用多线程要注意什么问题?
八、比如说有两个线程、一个文件,一个线程要更新文件中的内容,另一个线程要读取里面的内容,这个时候代码的执行的循序是什么?,包括加锁、写文件、解锁这些顺序是什么?
九、线程之间,两个线程在并行做事情,那两个线程有时候也要进行一些通信,如何进行通信呢?
十、private、protect、public 三种修饰符有什么区别?
十一、栈和队列有什么区别?举个生活中的例子?(讲清楚,讲完全)
十二、二叉树什么是平衡二叉树?堆排序中堆是一种什么二叉树?
十三、你知道的排序算法有多少种?(说至少五种),选一种讲清楚?
十四、MySQL中有一张表,
A:学号 姓名
B:学号 性别
①连表查出来学号,姓名,性别 ?
②如果要清空一个表的数据用什么命令?
③更新某个学生的姓名,怎么更新?
④删一个表命令
十五、redis是一个什么样的数据库?和别的数据库比它的显著特征?
十六、redis一般作为缓存系统,因为读写速度比较快,那它的缺陷是什么?
十七、计算机网络分层结构,七层,从下往上是什么?
十八、linux关于目录和文件的基本命令?(说十个)
查文件中的某个词用什么命令?
只想查看前十行?
后十行?
十九、①查看一个机器的 ip 地址,想连接一个机器,登录一个机器用什么命令?
②看当前到别的服务器网络通不通用什么命令?
③看他的端口号能不能连接上这个用什么命令?
二十、域名解析具体是做什么事情?可以举个例子吗?
二十一、前后端协作开发,后端写的接口文档内容有什么?
二十二、讲一下项目经历?每段控制在3分钟,两个都介绍一下
(项目背景、为什么做这个项目、有什么功能、项目的架构、是怎么设计这个项目的、这个项目过程中间,分模块设计,设计过程中有没有遇到什么问题,开发完了后是要测试,你具体怎么测的、有没有分场景、写用例,最后这个项目的背景亮点在哪,用到的核心技术)
二十三、事务的话和普通的SQL有什么区别?
二十四、k8s 和 docker容器听说过吗? docker部署几步就能把mysql数据库部署起来?
二十五、docker中容器运行期间,你有没有看过容器的日志?
二十六、docker的网络你知道吗,网桥的名字叫什么,docker0你知道吗
有没有听过容器的主机网络模式?
二十七、有没有了解过什么是云,腾讯云嘛,云包含几层?有没有听过 IaaS、PaaS、SaaS?
CI/CD?
一、java的特性是什么?
封装、继承、多态
二、具体什么是封装、继承、多态(面向对象的角度,最好用项目中 / 生活中的例子),贯穿始终,看你能不能讲清楚)?再讲一下什么是抽象?(我举了汽车的例子)
那我举一个汽车的例子
1. 封装(Encapsulation)
定义:将数据(属性)和操作数据的方法(行为)捆绑在一起,并隐藏内部实现细节,仅对外提供必要接口。
类比:汽车的发动机舱。通俗解释:
封装的话就是比如把发动机、变速箱藏在引擎盖下面,只留给用户几个简单的“按钮”
(方向盘、油门、刹车)
关键作用:
- 保护数据:用户不能直接修改发动机转速,只能通过油门间接控制。
- 简化操作:用户不需要懂内燃机原理,踩油门就能加速。
代码示例:
public class Car {private int speed; // 隐藏速度,不让外部直接修改// 提供公共方法控制速度public void pressAccelerator(int force) {if (force > 0) {speed += force;if (speed > 200) speed = 200; // 限速保护}}public int getSpeed() {return speed;} }
2. 继承(Inheritance)
定义:子类(派生类)继承父类(基类)的属性和方法,实现代码复用和扩展。
类比:汽车的分类体系。
- 父类:
Car
(有speed
、start()
等通用属性和方法)。- 子类:
ElectricCar
和GasCar
继承Car
,并扩展各自特性。通俗解释:
所有汽车(子类)都继承 “汽车” 这个大类的基本特性(轮子、方向盘),但可以添加自己的特色(如给汽车的充电功能)。// 父类:普通汽车 public class Car {public void drive() {System.out.println("开车前进");} }// 子类:电动车 public class ElectricCar extends Car {public void charge() { // 新增充电功能System.out.println("新增充电功能");}@Overridepublic void drive() { // 修改父类行为System.out.println("电动引擎安静地启动");} }
3. 多态(Polymorphism)
定义:同一方法调用,根据对象类型不同表现出不同行为。
类比:汽车的喇叭。
- 无论是什么品牌的汽车(奔驰、宝马、特斯拉),按喇叭时都发出 “哔~” 声,但具体音色可能不同。
关键点:
- 接口 / 抽象类:定义统一方法(如
honk()
)。- 动态绑定:运行时根据实际对象类型决定调用哪个实现。
- 可扩展性:新增车型(如
BMW
)时,无需修改honkAll()
方法。代码示例:
// 接口:定义汽车的行为 public interface Car {void honk(); // 按喇叭方法 }// 奔驰车 public class Benz implements Car {@Overridepublic void honk() {System.out.println("优雅的:哔~");} }// 特斯拉 public class Tesla implements Car {@Overridepublic void honk() {System.out.println("电子合成音:哔~");} }// 测试多态 public class Main {public static void main(String[] args) {Car benz = new Benz();Car tesla = new Tesla();honkAll(benz, tesla); // 统一调用按喇叭方法}public static void honkAll(Car... cars) {for (Car car : cars) {car.honk(); // 不同汽车的喇叭声自动区分}} }
4. 抽象(Abstraction)
定义:忽略细节,提取共性,用抽象类或接口定义规范。
类比:汽车设计蓝图。通俗解释:
汽车设计图只规定 “必须有四个轮子”“必须能启动”,但不规定具体用什么材料(钢轮还是铝轮)。关键点:
- 抽象类 / 接口:不能实例化,仅作为规范(如
Car
不能直接new Car()
)。- 强制实现:抽象方法(如
start()
)必须由子类实现。- 分离设计与实现:上层代码只依赖抽象(如
Car
接口),不依赖具体类。// 抽象类:汽车设计蓝图 public abstract class Car {public abstract void start(); // 抽象方法:必须启动public void stop() { // 具体方法:默认实现System.out.println("踩刹车停车");} }// 燃油车实现 public class GasCar extends Car {@Overridepublic void start() {System.out.println("点火启动燃油发动机");} }// 电动车实现 public class ElectricCar extends Car {@Overridepublic void start() {System.out.println("按下启动按钮,电动引擎就绪");} }
代码示例:
// 抽象类:汽车设计蓝图 public abstract class Car {public abstract void start(); // 抽象方法:必须启动public void stop() { // 具体方法:默认实现System.out.println("踩刹车停车");} }// 燃油车实现 public class GasCar extends Car {@Overridepublic void start() {System.out.println("点火启动燃油发动机");} }// 电动车实现 public class ElectricCar extends Car {@Overridepublic void start() {System.out.println("按下启动按钮,电动引擎就绪");} }
5. 接口(Interface)
官方定义:
接口是一种抽象类型,它只定义方法签名(名称、参数、返回值),但不包含方法体。实现接口的类必须实现接口中所有的方法。汽车类比:
- 充电接口(如国标、特斯拉超充)就是一种物理接口,它规定:
- 必须有几个针脚(如直流正极、负极、通信线)。
- 每个针脚的功能和电压标准。
- 插头的形状和尺寸。
- 但不规定:
- 充电桩内部如何转换电能(用 IGBT 模块还是 SiC 模块)。
- 具体用什么品牌的充电桩。
通俗解释:
汽车的 “充电接口”(如 Type-C、国标快充口),只要符合这个接口标准,任何充电桩都能充电。关键作用:
汽车场景中的作用:
- 标准化:所有电动车和充电桩必须遵循同一接口标准(如国标),否则无法兼容。
- 解耦:车厂不用关心充电桩的实现,充电桩厂商也不用关心车的品牌。
- 扩展性:未来可以新增接口标准(如无线充电接口),而不影响现有系统。
3. 代码示例:汽车充电接口
// 充电接口(规定必须有充电方法) public interface Chargeable {void charge(); }// 特斯拉实现了充电接口 public class Tesla implements Chargeable {public void charge() {System.out.println("插入Type-C充电桩,开始充电");} }// 比亚迪也实现了充电接口 public class BYD implements Chargeable {public void charge() {System.out.println("插入国标充电桩,开始充电");} }
总结对比
三、面向对象 和 面向过程有什么区别?
首先,
面向对象:是一种以对象为中心的编程风格,把类或对象作为基本单元来组织代码。
并且运用提来出来的:封装、继承、多态来作为代码设计指导。
面向过程:是一种以过程或函数为中心的编码风格。以过程作为基本单元来组织代码。
主要区别如下:
1.思维方式:
面向对象:通过定义对象的属性和行为来解决问题,关注对象之间的关系和交互
面向过程:通过函数或过程一步一步实现业务逻辑,关注执行的步骤和顺序。
2.数据与方法的关系:
面向对象:数据和方法封装在对象内部,数据操作由对象方法进行管理。
面向过程:数据和方法是分离的,函数对数据进行操作。
3.可扩展性和复用性:
面向对象:通过继承、接口、多态等机制支持代码的高复用性和扩展性
面向过程:复用性较低,扩展需要修改已有代码,影响整体稳定性。
4.适用场景
面向对象:适合处理复杂的系统和模块化设计,便于维护和发展
面向过程:适用于一些简单的,顺序性强的小型程序,开发效率较高。
四、for循环有多少种写法?(常见的写法,不包含迭代器)
①普通for
循环
这是最基本的
for
循环形式,通过设置循环变量、循环条件以及更新循环变量的方式来控制循环的执行。
// 示例:计算1到10的整数之和
public class ForLoopExample {public static void main(String[] args) {int sum = 0;for (int i = 1; i <= 10; i++) {sum += i;}System.out.println("1到10的整数之和为:" + sum);}
}
②增强for
循环(for-each
循环)
增强
for
循环主要用于遍历数组或实现了Iterable
接口的集合(如List
、Set
等),它的语法更加简洁,不需要显式地操作索引。
// 示例:遍历数组并打印每个元素
public class ForEachLoopExample {public static void main(String[] args) {int[] numbers = {1, 2, 3, 4, 5};for (int num : numbers) {System.out.print(num + " ");}}
}
下面这段代码展示了使用增强for
循环遍历List
集合的过程。
import java.util.ArrayList;
import java.util.List;public class ForEachListExample {public static void main(String[] args) {List<String> fruits = new ArrayList<>();fruits.add("apple");fruits.add("banana");fruits.add("cherry");for (String fruit : fruits) {System.out.println(fruit);}}
}
③ 标签for
循环
标签
for
循环用于在嵌套循环中,更灵活地控制循环的执行和跳出。可以给外层循环添加一个标签,然后使用break
或continue
语句配合标签,实现直接跳出外层循环或者直接进入外层循环的下一次迭代。
// 示例:使用标签for循环跳出嵌套循环
public class LabeledForLoopExample {public static void main(String[] args) {outerLoop:for (int i = 1; i <= 3; i++) {for (int j = 1; j <= 3; j++) {if (i == 2 && j == 2) {break outerLoop; // 直接跳出外层循环}System.out.println("i = " + i + ", j = " + j);}}}
}
在上述代码中:
outerLoop:
:这是给外层for
循环定义的标签。break outerLoop;
:当满足条件i == 2 && j == 2
时,直接跳出被标记为outerLoop
的外层循环,而不是仅仅跳出内层循环。在这个例子中,当满足条件
i == 2 && j == 2
时,continue outerLoop;
语句会让程序跳过内层循环剩余的代码,直接进入外层循环的下一次迭代 。
五、for循环分成好几部分,讲它的每一部分和每一部分的作用。
for (初始化表达式; 循环条件; 迭代表达式) {循环体
}
六、数组,有五个元素【1,2,3,4,5】,如何通过for循环打印1 3 5 用for循环怎么写?
int[] arr = {1, 2, 3, 4, 5};
for (int i = 0; i < arr.length; i += 2) { // i每次递增2System.out.println(arr[i]);
}
while循环打印 数组【1,2,3,4,5】怎么写?
先定义一个变量 比如说 i = 0
然后 i < 数组 长度
打印数字
i++
进入下一次循环。
int[] arr = {1, 2, 3, 4, 5};
int i = 0; // 初始化索引while (i < arr.length) {System.out.println(arr[i]); // 打印当前元素i++; // 索引递增
}
七、多线程了解吗?举一个多线程的例子?什么情况下用多线程做事情?用多线程要注意什么问题?
①、多线程的例子(用做饭类比)
假设你要做一顿饭,需要完成三件事:
- 煮米饭(需要 10 分钟)
- 炒青菜(需要 5 分钟)
- 煎鸡蛋(需要 3 分钟)
单线程方式:
- 先煮米饭 → 等米饭熟了再炒青菜 → 再煎鸡蛋,总耗时
10+5+3=18分钟
。多线程方式:
- 启动一个线程煮米饭(同时进行),主线程先炒青菜,再煎鸡蛋。
- 总耗时≈10 分钟(米饭煮好的时间,其他事情在等待米饭时完成)。
②、什么情况下用多线程?
简单说:需要 “同时做多个事情” 来提高效率,或避免程序 “卡住”。
常见场景:
- 耗时操作不阻塞主线程:
- 如 App 加载时,后台线程下载图片,主线程继续响应用户点击(否则界面会卡顿)。
- 充分利用 CPU 资源:
- 处理大量数据(如统计多个文件的字数),用多线程同时处理不同文件,比单线程逐个处理快。
- 并发任务处理:
- 服务器同时接收多个用户的请求(如微信同时接收多条消息),每个请求用一个线程处理。
③、用多线程要注意的问题
线程安全问题:
- 多个线程同时操作共享数据(如多个线程同时修改一个变量),可能导致结果错误。
- 例:两个线程同时给账户存钱,原本存 2 次 100 元,结果可能只存了 100 元。
- 解决:用
synchronized
锁或Lock
保证同一时间只有一个线程操作共享资源。死锁:
- 两个线程互相等待对方释放资源,导致都卡住。
- 例:线程 A 持有锁 1,等待锁 2;线程 B 持有锁 2,等待锁 1,永远僵持。
- 解决:按固定顺序获取锁,避免循环等待。
线程过多消耗资源:
- 每个线程占用内存,线程太多会导致内存不足或 CPU 切换频繁(“上下文切换” 耗时)。
- 解决:用线程池(如
ThreadPoolExecutor
)控制线程数量。线程通信复杂:
- 线程间需要协作(如 “生产者 - 消费者” 模型),若处理不好会导致逻辑混乱。
- 解决:用
wait()
/notify()
或BlockingQueue
等工具协调线程。
八、比如说有两个线程、一个文件,一个线程要更新文件中的内容,另一个线程要读取里面的内容,这个时候代码的执行的循序是什么?,包括加锁、写文件、解锁这些顺序是什么?
加解锁的一个线程:
只读锁(共享的):多个读线程可以同时读取文件。
若一个读的线程先获取到资源,那么就要加一个只读锁、
在只读锁没有被释放的时候,别的线程就不能去更新(写)这个文件。
如果A线程把这个文件读完了,这个时候就可以把锁给释放掉。
就是说这个文件我不用了,
写锁(排他的):同一时间只允许一个线程写入,且写入时不允许其他线程读取。
解锁之后更新的线程可以获取一把写锁
他告诉别人我正在写,你们看着读,写完之后他把锁一解。
九、线程之间,两个线程在并行做事情,那两个线程有时候也要进行一些通信,如何进行通信呢?
线程间通信是多线程编程核心概念,在多线程编程中,有时候需要让线程之间进行数据交换,协作工作。以下是几种线程间的通信方式:
1.共享内存:线程之间可以通过访问同一块共享内存区域来实现数据交换
2.消息队列:一个线程向消息队列中放入一条消息,另一个线程从消息队列中取出消息
3.管道(Pipe):管道是一种半双工的通信方式,一个进程可以向管道中写入数据,另一个线程可以从管道中取出数据
4.信号(signal):信号是一种异步通信方式,进程收到信号后,会根据信号的类型做出相应的判断
5.互斥锁(Mutex):用于同步访问共享资源,防止多个线程同时访问共享资源,产生冲突
6.条件变量:用于线程之间的协调和通信,一个线程可以通过条件变量等待某个条件的出现,另一个线程可以通过条件变量通知正在等待的线程。
7.RPC调用:远程过程调用(RPC)是一种跨网络进行远程调用,可以实现在不用的线程或机器之间进行信息交换。
还可以延伸到你在编程时怎么让多线程共享变量,避免冲突。