腾讯后端开发实习一面(24届)

毫无准备的腾讯一面,最近都在忙比赛去了,突然收到腾讯一面的邮件,直接没准备。。。

总结,除了Vue其他的都挺好,但是腾讯hr为啥Vue面我四个问题,不是面的后端开发吗,好难呀,都只能随便说一点。。。

预期结果肯定没了,打完比赛再来面,以下是面经。。。

1、Vue中v-if 和v-show区别

它们的作用都是控制元素的显示和隐藏

区别在于:v-if是创建和删除元素,而v-show只是改变元素中的display样式属性

那什么时候需要用v-if,什么时候适合用v-show呢?

如果我们不会频繁的让元素在显示和隐藏之间切换,那我们比较适合使用v-if,这样可以提高我们的页面渲染速度,因为使用v-if指令的元素只有当v-if指定的值为true时,这个元素才会被创建,而不是当页面渲染时就创建。如果我们需要让元素在显示和隐藏之间频繁的切换,那这时我们就比较适合用v-show,因为这样只是改变元素的样式属性,而不用频繁的创建和删除元素,消耗性能。

2、computed和watch区别

1、computed是计算属性;watch是监听,监听data中的数据变化。
2、computed支持缓存,当其依赖的属性的值发生变化时,计算属性会重新计算,反之,则使用缓存中的属性值;watch不支持缓存,当对应属性发生变化的时候,响应执行。
3、computed不支持异步,有异步操作时无法监听数据变化;watch支持异步操作。
4、computed第一次加载时就监听;watch默认第一次加载时不监听。

3、Vue生命周期理解

Vue的生命周期就是vue实例从创建到销毁的全过程,也就是new Vue() 开始就是vue生命周期的开始。Vue 实例有⼀个完整的⽣命周期,也就是从开始创建、初始化数据、编译模版、挂载Dom -> 渲染、更新 -> 渲染、卸载 等⼀系列过程,称这是Vue的⽣命周期。钩子函数是Vue生命周期中每个阶段对外开放让程序员操作Vue的接口。Vue有8个钩子函数。

创建前:

beforeCreate 组件实例被创建之初,data 和 methods 中的数据还没有初始化

创建后:

created 组件实例已经完全创建,data 和 methods 都已经初始化好了

挂载前:

beforeMount 指令已经解析完毕,内存中已经生成dom树,但是尚未挂载到页面中去

挂载后:

mounted dom渲染完毕页面和内存的数据已经同步

更新前:

beforeUpdate 组件数据更新之前调用, 此时页面中显示的数据还是旧的,但 data 是最新的,页面尚未和最新的数据保持同步

更新后:

update 组件数据更新之后,页面和 data 数据已经保持同步,都是最新的

销毁前:

beforeDestory 组件销毁前调用,vue 实例从运行阶段进入到销毁阶段,这时 vue 实例身上所有都可用,还没有真正执行销毁

销毁后:

destoryed 组件销毁后调用,vue 实例上的所有都不可以用了

4、Vue单页面(SPA)和多页面(MPA)的理解

什么是SPA:

客户端渲染。它所需的资源,如 HTML、CSS 和 JS 等,在一次请求中就加载完成,也就是不需刷新地动态加载。浏览器(Client)渲染顾名思义就是所有的页面渲染、逻辑处理、页面路由、接口请求均是在浏览器中发生。对于 SPA 来说,页面的切换就是组件或视图之间的切换

简单来说,SPA应用程序只有一个html文件,在vue中可以通过vue-router来局部切换组件,而非刷新整个页面,来实现无刷新切换页面的技术。

SPA的优点

  • 1.页面切换快

页面每次切换跳转时,并不需要做html文件的请求,这样就节约了很多http发送时延,我们在切换页面的时候速度很快。

  • 2.用户体验好

页面片段间的切换快,包括移动设备, 尤其是在网络环境差的时候, 因为组件已经预先加载好了, 并不需要发送网络请求, 所以用户体验好

SPA的缺点

  • 1.首屏加载速度慢

首屏时需要请求一次html,同时还要发送一次js请求,两次请求回来了,首屏才会展示出来。相对于多页应用,首屏时间慢。

  • 2.不易于SEO

SEO效果差,因为搜索引擎只认识html里的内容,不认识js的内容,而单页应用的内容都是靠js渲染生成出来的,搜索引擎不识别这部分内容,也就不会给一个好的排名,会导致SPA应用做出来的网页在百度和谷歌上的排名差。

什么是MPA

MPA多页面应用 MultiPage Application ,指有多个独立页面的应用(多个html页面),每个页面必须重复加载js、css等相关资源。多页应用跳转,需要整页资源刷新。

SPA 对比最大的不同即是页面路由切换由原生浏览器文档跳转(navigating across documents)控制。 页面跳转,是返回 HTML 的。

对比

SPA和MPA的对比.png

5、TCP三次握手

1、服务端新建套接字,绑定地址信息后开始监听,进入LISTEN状态。

2、客户端新建套接字绑定地址信息后调用connect,发送连接请求SYN,并进入SYN_SENT状态,等待服务器的确认。

3、服务端一旦监听到连接请求,就会将连接放入内核等待队列中,并向客户端发送SYN和确认报文段ACK,进入SYN_RECD状态。

4、客户端收到SYN+ACK报文后向服务端发送确认报文段ACK,并进入ESTABLISHED状态,开始读写数据。

5、服务端一旦收到客户端的确认报文,就进入ESTABLISHED状态,就可以进行读写数据了

6、Java中多态的理解

通俗点讲,多态就是不同对象对同一物体或事件发出不同的反应或响应。比如stuendt是一个父类,那么在操场上上体育课的学生和在教室里面的学生就是它的子类。这时上课铃声响了,上体育课的学生去操场,在教室里面上课的学生则是回教室,不同的学生有着不同的反应,这就是多态。

实现多态的条件:

1.继承:必须要有子类继承父类的继承关系。
2.重写:子类需要对父类中的一些方法进行重写,然后调用方法时就会调用子类重写的方法而不是原本父类的方法。
3.向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备既能调用父类的方法和子类的方法。

如:List l =new ArrayList();

7、Java中的内存溢出和内存泄漏

1、内存泄漏memory leak :

是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出。

2、内存溢出 out of memory :

指程序申请内存时,没有足够的内存供申请者使用,或者说,给了你一块存储int类型数据的存储空间,但是你却存储long类型的数据,那么结果就是内存不够用,此时就会报错OOM,即所谓的内存溢出。

3、二者的关系:

内存泄漏的堆积最终会导致内存溢出
内存溢出就是你要的内存空间超过了系统实际分配给你的空间,此时系统相当于没法满足你的需求,就会报内存溢出的错误。

内存泄漏: 是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。就相当于你租了个带钥匙的柜子,你存完东西之后把柜子锁上之后,把钥匙丢了或者没有将钥匙还回去,那么结果就是这个柜子将无法供给任何人使用,也无法被垃圾回收器回收,因为找不到他的任何信息。

内存溢出:一个盘子用尽各种方法只能装4个果子,你装了5个,结果掉倒地上不能吃了。这就是溢出。比方说栈,栈满时再做进栈必定产生空间溢出,叫上溢,栈空时再做退栈也产生空间溢出,称为下溢。就是分配的内存不足以放下数据项序列,称为内存溢出。说白了就是我承受不了那么多,那我就报错。

8、Linux常用命令

推荐这个博主的博客:https://blog.csdn.net/luansj/article/details/97272672

9、Redis数据结构有哪些

Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(无序集合)及zset(有序集合)。

还有三个特殊类型。。

细节这里不叙述了。。

10、字符串翻转

方式一:栈

package src.com.wz.leetcode.test;
import java.util.Stack;

/**使用栈
 * @author lenovo
 */
public class Test10 {
    
    
    public static void main(String[] args) {
    
    
        String str = "hello!";
        char[] chars = str.toCharArray();
        Stack<Character> stack = new Stack<>();
        for (int i = 0; i < chars.length; i++) {
    
    
            stack.push(chars[i]);
        }
        StringBuilder stringBuilder = new StringBuilder();
        while (stack.size()>0){
    
    
            stringBuilder.append(stack.pop());
        }
        System.out.println(stringBuilder.toString());
    }
}

方式二:ArrayList

package src.com.wz.leetcode.test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * @author lenovo
 */
public class Test12 {
    
    
    public static void main(String[] args) {
    
    
        String str ="hello!";
        String[] split = str.split("");
        List<String> list =new ArrayList<>();
        list = Arrays.asList(split);
        Collections.reverse(list);
        for (String s : list) {
    
    
            System.out.print(s);
        }
    }
}

11、查找循环链表入环节点

package src.com.wz.leetcode.test;

import java.util.Objects;

/**
 * @author lenovo
 */
public class Test11 {
    
    
    public static void main(String[] args) {
    
    
        // 链表赋值
        int[] arr ={
    
    1,2,3,4,5,6};
        MyListNode list =new MyListNode(1);
        MyListNode cur = list;
        MyListNode cur1 = new MyListNode();
        for (int i = 1; i < arr.length; i++) {
    
    
            MyListNode node = new MyListNode(arr[i]);
            cur.next= node;
            cur = cur.next;
            if (i==3){
    
    
                cur1 = cur;
            }
        }
        System.out.println(list.toString());
        // 成环
        cur.next = cur1;
        int node = getNode(list);
        System.out.println(node);

    }

    /**
     * 快慢指针查找入环节点
     * @param myListNode 有环链表
     * @return 入环结点value
     */
    public static int getNode(MyListNode myListNode){
    
    
        MyListNode cur1 = myListNode;
        MyListNode cur2 = myListNode;
        cur1=cur1.next;
        cur2=cur2.next.next;
        while (!cur1.equals(cur2)){
    
    
            cur1=cur1.next;
            cur2=cur2.next.next;
        }
        // 第一次相遇,快指针变成慢指针
        cur2 = myListNode;
        while (!cur1.equals(cur2)){
    
    
            cur1=cur1.next;
            cur2=cur2.next;
        }
        // 第二次相遇返回入环结点
        return cur1.value;
    }
}
/**
 * 链表类
 */

class MyListNode{
    
    
    public int value;
    public MyListNode next;
    public MyListNode(){
    
    }
    public MyListNode(int value) {
    
    
        this.value = value;
    }

    @Override
    public String toString() {
    
    
        return "MyListNode{" +
                "value=" + value +
                ", next=" + next +
                '}';
    }

    @Override
    public boolean equals(Object o) {
    
    
        if (this == o) {
    
    
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
    
    
            return false;
        }
        MyListNode that = (MyListNode) o;
        return value == that.value && Objects.equals(next, that.next);
    }

    @Override
    public int hashCode() {
    
    
        return Objects.hash(value, next);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_54353206/article/details/129728701