美文网首页
高端基础面试题

高端基础面试题

作者: 任笙_8b8c | 来源:发表于2020-08-13 22:04 被阅读0次
    接口和抽象类的区别
    比较点 抽象类 接口
    默认方法 抽象类可以有默认的方法实现 java 8之前,接口中不存在方法的实现
    实现方式 子类使用extends关键字来继承抽象类.如果子类不是抽象类,子类需要提供抽象类中所声明方法的实现 子类使用implements来实现接口,需要提供接口中所有声明的实现.
    构造器 抽象类中可以有构造器 接口中不能
    和正常类区别 抽象类不能被实例化 接口则是完全不同的类型
    访问修饰符 抽象方法可以有public,protected和default等修饰 接口默认是public,不能使用其他修饰符
    多继承 一个子类只能存在一个父类 一个子类可以存在多个接口
    添加新方法 抽象类中添加新方法,可以提供默认的实现,因此可以不修改子类现有的代码 如果往接口中添加新方法,则子类中需要实现该方法
    什么是不可变对象?好处是什么?

    不可变对象指对象一旦被创建,状态就不能再改变,任何修改都会创建一个新的对象,如 String、Integer及其它包装类.不可变对象最大的好处是线程安全.

    switch中能否使用string做参数?

    在JDK 1.7之前,switch只能支持byte,short,char,int或者其对应的包装类以及Enum类型.从JDK 1.7之后switch开始支持String类型.但到目前为止,switch都不支持long类型.

    String s = new String("abc")创建了几个String对象?

    2个.一个是字符串字面常数,在字符串常量池中;另一个是new出来的字符串对象,在堆中.

    请问s1==s3是true还是false,s1==s4是false还是true?s1==s5呢?
       String s1 = "abc";   
    String s2 = "a";   
    String s3 = s2 + "bc";  
     String s4 = "a" + "bc"; 
     String s5 = s3.intern();
    

    s1==s3返回false,
    s1==s4返回true,
    s1==s5返回true.

    “abc"这个字符串常量值会直接方法字符串常量池中,s1是对其的引用.由于s2是个变量,编译器在编译期间无法确定该变量后续会不会改,因此无法直接将s3的值在编译器计算出来,因此s3是堆中"abc"的引用.因此s1!=s3.对于s4而言,其赋值号右边是常量表达式,因此可以在编译阶段直接被优化为"abc”,由于"abc"已经在字符串常量池中存在,因此s4是对其的引用,此时也就意味s1和s4引用了常量池中的同一个"abc".所以s1==s4.String中的intern()会首先从字符串常量池中检索是否已经存在字面值为"abc"的对象,如果不存在则先将其添加到字符串常量池中,否则直接返回已存在字符串常量的引用.此处由于"abc"已经存在字符串常量池中了,因此s5和s1引用的是同一个字符串常量.

    以下代码中,s5==s2返回值是什么?
    String s1="ab";
    String s2="a"+"b";
    String s3="a";
    String s4="b";
    String s5=s3+s4;
    

    返回false.在编译过程中,编译器会将s2直接优化为"ab",将其放置在常量池当中;而s5则是被创建在堆区,相当于s5=new String(“ab”);

    你对String对象的intern()熟悉么?

    Stirng中的intern()是个Native方法,它会首先从常量池中查找是否存在该常量值的字符串,若不存在则先在常量池中创建,否则直接返回常量池已经存在的字符串的引用. 比如

     String s1="aa"; 
    String s2=s1.intern(); 
    System.out.print(s1==s2);
    

    上述代码将返回true.因为在"aa"会在编译阶段确定下来,并放置字符串常量池中,因此最终s1和s2引用的是同一个字符串常量对象.

    String,StringBuffer和StringBuilder区别?

    String是字符串常量,final修饰;
    StringBuffer字符串变量(线程安全);
    StringBuilder 字符串变量(线程不安全).
    此外StringBuilder和StringBuffer实现原理一样,都是基于数组扩容来实现的.

    String和StringBuffer的区别?

    String和StringBuffer主要区别是性能:
    String是不可变对象,每次对String类型进行操作都等同于产生了一个新的String对象,然后指向新的String对象.所以尽量不要对String进行大量的拼接操作,否则会产生很多临时对象,导致GC开始工作,影响系统性能.

    StringBuffer是对象本身操作,而不是产生新的对象,因此在有大量拼接的情况下,我们建议使用StringBuffer(线程安全).
    需要注意现在JVM会对String拼接做一定的优化,比如

    String s="This is only "+ "simple" +"test";
    

    以上代码在编译阶段会直接被优化成会`String s=“This is only simple test”.

    ####### StringBuffer和StringBuilder
    StringBuffer和StringBuilder的实现原理一样,其父类都是AbstractStringBuilder.StringBuffer是线程安全的,StringBuilder是JDK 1.5新增的,其功能和StringBuffer类似,但是非线程安全.因此,在没有多线程问题的前提下,使用StringBuilder会取得更好的性能.

    java当中使用什么类型表示价格比较好?

    如果不是特别关心内存和性能的话,使用BigDecimal.否则使用预定义精度的 double 类型.
    在数据库中不使用BigDecimal,而是使用decimal

    a=a+b与a+=b有什么区别吗?

    +=操作符会进行隐式自动类型转换,此处a+=b隐式的将加操作的结果类型强制转换为持有结果的类型,而a=a+b则不会自动进行类型转换如:

        byte a = 127;
        byte b = 127;
        b = a + b; // 报编译错误:cannot convert from int to byte
        b += a; 
    
    以下代码是否有错,有的话怎么改?
    short s1= 1;s1 = s1 + 1;
    

    有错误.short类型在进行运算时会自动提升为int类型,也就是说s1+1的运算结果是int类型,而s1是short类型,此时编译器会报错. 强转就能解决.

      short i=1;
      i = (short) (i+1);
    

    线程池是否有用到,在什么场景下使用的,平常用的那种线程池?

    • 有用到, 适合单系统的异步交互,在发送短信,存入日志时

      • 说说创建线程池的重要参数
        corePoolSize:线程池的大小。线程池创建之后不会立即去创建线程,而是等待线程的到来。当前执行的线程数大于该值时,线程会加入到缓冲队列。
        maximumPoolSize:线程池中创建的最大线程数。
        keepAliveTime:空闲的线程多久时间后被销毁。默认情况下,该值在线程数大于corePoolSize时,对超出corePoolSize值的这些线程起作用。
        unit:TimeUnit枚举类型的值,代表keepAliveTime时间单位。
        handler:线程拒绝策略。
    • 线程池调优怎么做?
      基本思想:
      高并发、任务执行时间短的业务,线程池线程数可以设置为CPU核数+1,减少线程上下文的切换。
      并发不高、任务执行时间长的业务要区分开:
      IO密集型的任务,因为IO操作并不占用CPU,可以加大线程池中的线程数目,让CPU处理更多的业务
      CPU密集型任务,线程池中的线程数设置得少一些,减少线程上下文的切换。
      并发高、业务执行时间长,在于整体架构的设计,能否使用中间件对任务进行拆分和解耦。

    • 平常用的那种线程池
      newSingleThreadExecutor:一个单线程的线程池。如果因异常结束,会再创建一个新的,保证按照提交顺序执行。
      newFixedThreadPool:创建固定大小的线程池。根据提交的任务逐个增加线程,直到最大值保持不变。如果因异常结束,会新创建一个线程补充。
      newCachedThreadPool:创建一个可缓存的线程池。会根据任务自动新增或回收线程。
      newScheduledThreadPool:支持定时以及周期性执行任务的需求。
      newWorkStealingPool:JDK8新增,根据所需的并行层次来动态创建和关闭线程,通过使用多个队列减少竞争,底层使用ForkJoinPool来实现。优势在于可以充分利用多CPU,把一个任务拆分成多个“小任务”,放到多个处理器核心上并行执行;当多个“小任务”执行完成之后,再将这些执行结果合并起来即可。

    在高并发场景下使用了那些锁的机制?

    • 悲观锁(synchronize)
      Java 中的重量级锁 synchronize
      数据库行锁
    • 乐观锁
      Java 中的轻量级锁 volatile 和 CAS
      数据库版本号
    • 分布式锁(Redis锁)

    相关文章

      网友评论

          本文标题:高端基础面试题

          本文链接:https://www.haomeiwen.com/subject/zrwbdktx.html