笔试面经:笔试题杂记

因为这不是一套笔试题,而是我正在找工作的朋友们零零碎碎提供的,所以叫做杂记(主要来源于一个对我帮助贼大的朋友还有一些狗群友)。
背景的话:两到三年的经验,属于中级开发,然后坐标上海,广东。
我都是听到说面试问了就记下来,今天正好闲着所以整理了一下,顺序也是随缘写的。

短信限制功能怎么做?(这个是面试题,问答形式的)

首先,大多数时候现在一个app发送短信是很正常的功能,起码注册百分之九十都会有这个功能。但是如果不做限制,一个多线程跑下去平台里有多少短信费用都能刷没了(这句话是我朋友说的)。所以这个短信限制要怎么做呢?
这个问题问的好,其实我还真做过这块的功能,之前也写了一个帖子具体实现每个手机号每天只发送20条短信的限制。java发送短信验证码限制
这个用到了redis缓存,然后当一个号码一天发送短信到20次则直接报错。
不过!上述解决办法还有一个bug:那就是如果人家随机生成手机号码呢?这样多线程跑着,中国现有的手机号这么多,还是有多少钱都不够跑的!所以如果想继续维护安全,还有一个设置:
如果是手机端,是肯定有设备码的,这个设备码对于一个手机唯一的。
如果是web端,一个电脑有一个IP和MAC。相比于ip,MAC更加可靠。
大不了就是调用短信接口的时候获取设备标识(设备码和MAC),然后设置每个每天只能发送多少多少次短信。
问:如果是随机生成的虚拟ip,设备码,mac码呢?
答:那就没救了,等着被攻击吧,毕竟如果设备码虚拟生成烂大街,美团早就黄了。判断新用户就是根据手机号和设备码的(笑脸)。

String a = "hello";String b = "he"+new String("llo");System.out.println(a==b);

这个其实是很基础的题,但是我心目中那个贼厉害的朋友居然答错了(兴奋ing),这个输出结果肯定是false啦。
要从String说起,在java中String一直是个很特殊的存在,例如a这种直接等于的,是存放在常量池中的,而不是堆中,但是b中的new String("llo"),就是存放在堆中的,同样由字符串拼接的b相当于创建了一个新对象,所以也是存在堆中。就这样一个常量区中的字符串和一个堆中的字符串,怎么可能地址一样?所以自然结果是false啦。
然后这个题稍微变一下,变成String a = "hello";String b = "he"+"llo"; System.out.println(a==b);
这样的话,结果是true,源于java的优化(具体哪里优化我忘记了)反正字符串拼接的时候两边都是常量会直接运算结果。所以"he"+"llo"直接就变成了"hello",于是两个常量池中的hello自然地址相同。

case问题

这个题我觉得是非常简单的,但是因为有人说遇到了,所以也还是写了出来(因为这个需要代码判断,所以直接贴代码题目)

public static int getValue(int i) {
        int result = 0;
        switch (i) {
        case 1:
            result = result+i;      
        case 2:
            result = result+i*2;
        case 3:
            result = result+i*3;
        }
        return result;
    }

如上代码片段,i为2时结果是多少?
其实这个考的就是case选中后继续往下走的问题,正常i为2,进入到第二个分支,走完继续走第三个分支,出来的结果是10.只要知道这个机制就可以答出来了。
其实我们在用switch-case时,通常要搭配一个关键字break。在具体是case下面配上这个字,选择分支走完自动退出,不再继续往下执行。
上面的题目因为没有这个关键字所以顺序往下执行。


朋友提供

list问题

list问题:一个list初始化为{5,3,1},执行以下代码后结果是多少?

        list.add(6);
        list.add(0,4);
        list.remove(1);

反正从良心的角度出发,我觉得这个题应该也是很基础的,然后我居然不会!!对的,第一眼看到题有点蒙,尤其是第二个代码句,不过还好面试的不是我,看到题目的时候正好闲着就.了一下list,然后才知道add如果有两个参数,第一个参数是下标。
然后list的remove方法,如果是integer类型 参数,也会被认为是下标(我不知道这个题是真出的好还是碰巧,list中元素是int类型,这个remove(1)如果你误解为是移除1这个元素就大错特错了,因为实际代码跑了一遍,这里的remove被认为是移除下标为1的元素)
三行代码,两行知识盲区,深感自己基础不足。
闲话少叙,说正经的,这个答案是{4,3,1,6},我觉得我说到这已经解释的很明白啦,再有问题的自己跑代码吧。

排序

其实这个问题真的,腻腻歪歪由不可避免。当年被要求手写冒泡还有点小情绪,现在看来是正常操作了。


与朋友聊天记录

不过既然问的频率这么高,所以我觉得还是整理几种排序的写法,毕竟多会点总没错的。

冒泡排序

这个是最基本的操作,原理也稍微了解就能明白。主要核心就是双循环,两数互换(追尾且绕圈),这个是我当时学习的时候老师的讲解,觉得蛮形象的记到现在。
最简版冒泡排序:

public static void BubbleSort(int [] arr){
     int temp;//临时变量
     for(int i=0; i<arr.length-1; i++){   //表示趟数,一共arr.length-1次。
         for(int j=arr.length-1; j>i; j--){

             if(arr[j] < arr[j-1]){
                 temp = arr[j];
                 arr[j] = arr[j-1];
                 arr[j-1] = temp;
             }
         }
     }
 }

这个从大到小或者从小到大排序在于比较时候arr[j] 和 arr[j-1]的关系,想要大到小就是大于,这样后一个比前一个大则会交换,否则不会交换。大的往前挪,小的往后,最后结果才是大到小的排序。
同理小到大就如上文的代码一样小于,大的往后挪,小的往前,最终才能达到排序的目的。
冒泡优化:

public static void BubbleSort1(int [] arr){
   int temp;//临时变量
   boolean flag;//是否交换的标志
   for(int i=0; i<arr.length-1; i++){   //表示趟数,一共arr.length-1次。

       flag = false;
       for(int j=arr.length-1; j>i; j--){

           if(arr[j] < arr[j-1]){
               temp = arr[j];
               arr[j] = arr[j-1];
               arr[j-1] = temp;
               flag = true;
           }
       }
       if(!flag) break;
   }
}

这个就是设置一个flag,如果已经排序完毕,但是遍历没走完,正常的冒泡还是会继续挨个比对。而使用这个flag可以保证在已经排序完毕后立刻跳出循环,不用做无畏的比对。

选择排序

基本思想就是在一个数组中,找到最小的元素,放到第一个元素。然后在除了第一个元素其余中选出最小的,放到第二个元素位置。然后在剩下的元素中选择最小的,放在第三个元素的位置,以此类推。
选择排序代码实现:

public static void select_sort(int array[],int lenth){

   for(int i=0;i<lenth-1;i++){

       int minIndex = i;
       for(int j=i+1;j<lenth;j++){
          if(array[j]<array[minIndex]){
              minIndex = j;
          }
       }
       if(minIndex != i){
           int temp = array[i];
           array[i] = array[minIndex];
           array[minIndex] = temp;
       }
   }
}

剩下还有归并,快排等,不过我其实也不咋熟悉,这里就不献丑了。


与朋友聊天记录

String StringBuilder和StringBuffer的区别

好吧,又涉及到我知识盲区了(基础真的渣)。
以前我只知道String是定长的,SB是变长的,如果经常更改的字符串用SB。但是这两个StringBuilder和StringBuffer就不是很清晰了。
因为看到这个问题,所以就直接看了下源码:

StringBuilder部分源码

StringBuffer部分源码

其实看到这就很显而易见了,二者的区别就是线程安全问题。StringBuilder是非线程安全的,StringBuffer是线程安全的。
然后一个我看来比较奇怪的点:StringBuffer比StringBuilder要出现的早。

StringBuilder是jdk1.5才出现的。一个非线程安全的对象后出现,并且占据主流。
原因就是因为非线程安全,所以执行速度快,效率高。

抽象类和接口的区别

这个有点太基础了,属于每个能都能说点,但是准不准确全不全面又不好定义。
下面是我看到的说的不错的几点,说的很深刻,而且看着高大上。
语法层面上的区别:

  1. 一个类只能继承一个抽象类,而一个类却可以实现多个接口;
  2. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;
  3. 接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
  4. 抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
  5. 抽象类的抽象方法可以是public,protected,default类型,而接口的方法只能是public。

设计层面上的区别:

  1. 抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。
    继承是一个 "是不是"的关系,而 接口 实现则是 "有没有"的关系。
  2. 设计层面不同,抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。

for循环里的执行顺序(最小白的一个问题)

for循环的表达式一般如下:
for(表达式1;表达式2;表达式3){
表达式4;
}
执行顺序124324324324324...循环下去,知道2条件不符则退出循环。

线程锁问题

下面哪些操作会使线程释放锁资源?
sleep(),wait(),join(),yield()。
这个题怎么说呢,应试题吧,反正我觉得我项目中使用的不多,但是既然有人问,还是要学学的。
sleep()的作用是是当前线程陷入阻塞状态,并不会释放线程锁。关于这个sleep是否会让出cpu,一直是个争论点(ps:这是一个简友给我留言指出的问题)。
从反证法的角度来讲,循环跑线程然后sleep,并不会使cpu使用率变高,所以由此可见sleep是不占用cpu的。
但是另一种说法:

image.png

反正具体到底占用不占用我至今没有找到很权威的解释和说法。起码这道题里知道肯定不会释放线程锁就ok了!
wait()这个方法差不多就是专门用来释放锁的了我觉得,当一个线程执行到wait()方法时,它就进入到一个和该对象相关的等待池中,同时释放了锁对象,让出cpu。
当一个线程执行了wait方法后,必须持有同一个锁的线程调用notify或者notifyAll方法才能唤醒。
注意:当前线程没有拥有锁会报错,唤醒的线程没有这个锁也会报错,线程不是synchronized的调用wait也会报错。反正这个是object的方法,感觉挺不常用的,我记得是不推荐使用。
yield()这个方法是暂时让出cpu,而不会释放锁。同时这个暂时让出也是有公平竞争的,就是让cpu自己选把时间给谁,极有可能cpu下次还选择这个线程。
join()最后说说join(),因为之前看了join源码,发现在join方法内,也调用了wait方法。所以这个释放锁让出cpu好像没有什么疑问了吧?
join方法源码

然后这个会释放锁的方法:join(),wait()。

ArrayList,LinkedList,HashMap,HashTable

这几个集合真的真的是逃不过。我还觉得这次的题目说的不够全,起码没再把什么vector,ConcurrentHashMap什么的都放上。这个题目据说是谈谈对他们的了解?
我个人感觉反正是从实现方式,线程安全,增删效率,查找效率,有序性几方面来说吧。
然后这个问题我真的觉得可说性太多,而且也不是几句话甚至几十句话能说完的,主要点就是上面几个,拆开来都能长篇大论。
我就不打字了,反正大家知道这种问题面试贼容易问到就行了。

初始化问题

这些面试题收集了快一个星期吧,果然问啥的都有,现在自己看看还觉得挺全面。这个问题是群友重点强调的一个问题。因为他就因为这道题错了直接被pass的,说是基础不扎实。
题目:


题目图片

题目代码:

public class P {    
    public static int a = 123;
    static {
        System.out.println("P is init");
    }
}
public class S extends P{   
    static {
        System.out.println("S is init");
    }   
}
public class Test {
    public static void main(String[] args) {
        System.out.println(S.a);
    }
}

现在输出S.a.结果是什么?
我反正当时想也没相对,估计我去面试也会这一题就pass
不卖关子了,结果是P is init 123


结果

我觉得按照类初始化的顺序:父静态->子静态->父构造>子构造来想,怎么也想不出为什么会错啊?
后来查了资料才发现错误原因:
首先,JVM五种初始化的场景:

  • new 关键字实例化对象
  • 实用reflect对类反射调用的时候。
  • 初始化一个类,发现其父类没有被初始化的时候会先初始化其父类
  • 虚拟机启动时,包含main方法的执行主类,虚拟机会先初始化这个类
  • 实用jdk1.7语言动态支持的时候一些情况。

除了这五种情况,其他所有的引用类的方式都不会触发初始化,称为被动引用。有三个典型的例子:

  1. 子类引用父类的静态字段,不会导致子类初始化。
  2. 通过数组引用来引用类,不会触发此类的初始化
  3. 常量在编译阶段会被存入调用类的常量池中,本质上并没有引用到定义常量类类,所以自然不会触发定义常量的类的初始化。
    首先,咱们这道题的情况就是第一种情况。然後出于求真的心态,我也试了下后两种情况:


    常量引用不会初始化类

    数组引用也不会初始化类

至此,这次的面试题总结到此为止,如果稍微有帮到你,麻烦点个喜欢点个关注支持下哟。也祝大家找工作顺顺利利!全文手打,希望帮到你~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342