面试题

Java面试题(日常更新)

前言

每日一个面试题

一、java中String、StringBuffer、StringBuilder的区别

1.可变与不可变

String类中使用字符数组保存字符串,如下就是,因为有“final”修饰符,所以可以知道string对象是不可变的。

private final char value[];

StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,如下就是,可知这两种对象都是可变的。

char[] value;

2.是否多线程安全

String中的对象是不可变的,也就可以理解为常量,显然线程安全

AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。

StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。看如下源码:

1 public synchronized StringBuffer reverse() {
2     super.reverse();
3     return this;
4 }
5 
6 public int indexOf(String str) {
7     return indexOf(str, 0);        //存在 public synchronized int indexOf(String str, int fromIndex) 方法
8 }

StringBuilder并没有对方法进行加同步锁,所以是非线程安全的

3.为什么尽量用StringBuilder和StringBuffe

进行多个字符串对象拼接时会产生多个中间对象,造成了内存的消耗

StringBuilder和StringBuffe 是为解决上面提到拼接产生太多中间对象的问题而提供的类,我们可以用append或者add方法,把字符串添加到已有序列的末尾或者指定位置。

4.使用StringBuilder与StringBuffer的不同

StringBuilder、StringBuffer的方法都会调用AbstractStringBuilder中的公共方法,如super.append(…)。只是StringBuffer会在方法上加synchronized关键字,进行同步。

最后,如果程序不是多线程的,那么使用StringBuilder效率高于StringBuffer。

jdk1.8及以前String使用的是char数组,jdk1.9及以后使用的是byte数组。

二、int和Integer的不同

  1. int是Java八大基本数据类型之一;Integer是int的包装类
  2. int的默认值是0;Integer的默认值的null
  3. int直接存储数值;Integer实际是对象的引用
  4. JDK1.5之后自动拆箱、自动装箱。javac替我们自动把装箱转换为Integer.valueOf(),把拆箱替换为Integer.intValue()
  5. Java定义在装箱的过程中,将-128~127之间的数值进行重复利用,超出这个范围的就会new出一个新的Integer对象
  6. -128~127之间的数值是保存在静态常量池中的IntegerCache数组中的。

三、Java如何保证集合是线程安全的

在Java中绝大部分的集合像什么ArrayList、HashMap等绝大部分都是线程不安全的。仅有的线程安全的实现,像HashTable、Vector等在性能上又不好。

1.在传统的集合框架:除了Hashtable、Vector等同步容器,他们是将自己的方法都加上了同步锁。

List list = Collections.synchronizedList(new ArrayList<>());

我们可以使用同步包装器创建一个线程安全的容器。但是这种方式用的是非常粗的同步方式,在高并发情况下,性能比较低下。

2.并发包:适合高并发,

 //关于map的ConcurrentHashMap
        ConcurrentHashMap<String,Object> map2 = new ConcurrentHashMap<>();
        map2.put("1","我是并发包直接构建的");
        map2.put("2","我是线程安全的Map容器,ConcurrentHashMap");
        map2.forEach((key,value) ->{
            System.out.println("map2:" + key + "," + value);
        });    
//关于list的CopyOnWriteArrayList
    CopyOnWriteArrayList<Integer> list2 = new CopyOnWriteArrayList<>();
    list2.add(67612);
    list2.add(67362);
    list2.forEach(list ->{
        System.out.println(list);
    });

    /**
     * 并发包中的线程安全队列
     */
    //ArrayBlockingQueue
    ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue(10);
    arrayBlockingQueue.add("1");
    arrayBlockingQueue.add("3");
    arrayBlockingQueue.forEach(queue->{
        System.out.println(queue);
    });
}

ConcurrentHashMap如何实现高效地线程安全

ConcurrentHashMap的设计实现是一直都在不断的演化,性能也是在不断的提高。

早期的ConcurrentHashMap,其实现主要是基于:

分离锁。在内部进行分段(Segment),里面则是HashEntry的数组,和HashMap类似,哈希相同的

条目也是以链表的形式存放。不对整个Map加锁,而是为每个Segment加锁。

那么在Java8中,这个有什么变化呢?

在结构上,哈希表+红黑树,虽然仍然有Segment定义,但是仅仅是为了给旧版本兼容。

并且引入了懒加载机制。(JDK1.7一上来就初始化,JDK1.8 在第一次put时才初始化),有效避免了初始化开销。

  • 由原先的ReentrantLock替换为Sychronized+CAS:

四、谈谈你知道的设计模式?

设计模式是人们对软件开发中出现相同表征的问题,抽象出的可重复利用的解决方案。在某种程度上,设计模式已经代表了一些特定情况的最佳实践,同时也起到了软件工程师之间沟通的“行话”的作用。理解和掌握典型的设计模式,有利于我们提高沟通、设计的效率和质量。

大致按照模式的应用目标分类,设计模式可以分为创建型模式、结构型模式和行为型模式。

  • 创建型模式,是对对象创建过程的各种问题和解决方案的总结,包括各种工厂模式(Factory、Abstract Factory)、单例模式(Singleton)、构建器模式(Builder)、原型模式( Prototype)。
  • 结构型模式,是针对软件设计结构的总结,关注于类、对象继承、组合方式的实践经验。常见的结构型模式,包括桥接模式( Bridge)、适配器模式( Adapter)、装饰者模式(Decorator)、代理模式(Proxy)、组合模式(Composite)、外观模式(Facade)、享元模式( Flyweight)等。
  • 行为型模式,是从类或对象之间交互、职责划分等角度总结的模式。比较常见的行为型模式有策略模式( Strategy)、解释器模式( Interpreter)、命令模式( Command)、观察者模式( Observer)、迭代器模式( Iterator)、模板方法模式( Template Method)、访问者模式( Visitor)。

单例模式:

public class Singleton {
  private static volatile Singleton singleton = null;
  private Singleton() {
  }

  public static Singleton getSingleton() {
      if (singleton == null) { // 尽量避免重复进入同步块
          synchronized (Singleton.class) { // 同步.class,意味着对同步类方法调用
              if (singleton == null) {
                  singleton = new Singleton();
              }
          }
      }
      return singleton;
  }
}
public class Singleton {
  private Singleton(){}
  public static Singleton getSingleton(){
      return Holder.singleton;
  }

  private static class Holder {
      private static Singleton singleton = new Singleton();
  }
}

常见的设计模式应用场景:

  • AOP 领域则是使用了代理模式、装饰器模式、适配器模式等。
  • 各种事件监听器,是观察者模式的典型应用。
  • 类似 JdbcTemplate 等则是应用了模板模式。

总结

提示:面试题每日一篇,话说大前端最近两年是真🔥

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值