Java面试突击篇

Mybatis

  1. #{} 和 $ {}的区别?
    #{}是预编译处理 而${}是字符串替换
    #{}可以防止SQL注入,先将#{}里面替换成?,然后调用PreparedStatement.set()来赋值
  2. 模糊查询like怎么写?
<if test="keyword != null and keyword != ''">
  and
  name like concat('%',#{keyword},'%')
</if>
  1. Mapper里面的方法能够重载吗?
    是不能的,Mybatis通过namespace接口的全路径加上方法名作为key放在一个map当中定位到唯一的mapperStatement,每一个标签就会被解析为一个MapperStatement对象,mapper接口工作原理是JDKProxy
  2. 如何获取自动生成的主键ID?
    首先insert成功会返回一个int类型的值表示插入的行数
    在Mybatisinsert标签里面有个userGenerator默认也是true,这个值已被赋值给对象id
  3. 如何执行批量插入?
    使用sqlSession的里面的一个executorType.batch
    还有一个就是NameMapper里面有个SqlSession.getMapper获取一个mapper
SqlSession s = SqlSessionFactory.openSession(exexutor.batch);
try{
    
    
	NameMapper mapper = SqlSession.getMapper(NameMapper.class);
	for(String name : names){
    
    
		mapper.insert(name);
	}
	s.commit();
}catch(Exception e){
    
    
	s.rollback();
}finally{
    
    
	s.close();
}
  1. mapper当中如何传递多个参数?
    推荐使用@param注解,或者封装成map也行
  2. resultMap的联合查询和嵌套查询怎么做,一对一 和 一对多?
    一对一association
    一对多collection
  3. Mybatis是否支持延迟加载?
    在配置文件mybatisConfig可以配置lazyLoadingEnable=true or false
    Mybatis仅支持association和collection的延时加载,通过CGLib创建目标对象的代理对象,当调用目标方法时进入拦截器方法,拦截器方法invoke发现调用的是null就会
    单独发送事先

网络通信

参考文章

  1. 什么是OIS七层协议 和 TCP/IP四层协议?
    在这里插入图片描述
  2. TCP/IP三次握手了解吗?为什么是三次呢?
  3. TCP和UDP的区别 分别说一下?
  4. HTTP和HTTPS的区别
  5. get和POST的优缺点
  6. 网络IO和磁盘IO
  7. 在网络IO当中Socket和ServerSocket
  8. BIO和NIO
  9. Connection:keep-alive的作用?
  10. 一个完整的HTTP请求的过程
  11. socket.accept()为啥阻塞?什么是BIO
    会阻塞当前线程,这里可以说javaIO流是阻塞流
    ,因为前面提到过,Socket连接里面的输入输出流也是阻塞的,如果这个Socket连好过后,客户端和服务器迟迟不发数据,那么这个新创建的线程也会阻塞在那里,(除非这个新创建的线程里面不操作Socket里面的IO),为了阻止这种情况,就要像上面说的,在新创建的线程里面在新创建一个线程处理Socket里面的流的问题
    详细描述

JAVA核心基础

  1. Arrays.asList()方法的理解,以及数组和List的转化

Arrays.asList(strArray)返回值是java.util.Arrays类中一个私有静态内部类java.util.Arrays.ArrayList,它并非java.util.ArrayList类。java.util.Arrays.ArrayList类具有 set(),get(),contains()等方法,但是不具有添加add()或删除remove()方法,所以调用add()方法会报错

数组转List:更详细博客

String[] arr = new String[]{
    
    "q","qw","qwe","qwer"};
List<String> list0 = Arrays.asList(arr);
//list0.add("qwert");// java.lang.UnsupportedOperationException
List<String> list = new ArrayList<>(Arrays.asList(arr));
list.add("qwert");
list.forEach(System.out::print);
System.out.println();
list0.forEach(System.out::print);
// list转Array
String[] strArr = list1.toArray(new String[list1.size()]);
String[] strArr1 = list1.stream().toArray(String[]::new);
Arrays.stream(strArr).forEach(System.out::print);
System.out.println();
Arrays.stream(strArr1).forEach(System.out::print);
  1. ArrayList的扩容机制?
    如果没有手动初始化容量默认创建一个空数组,然后在add的时候初始化默认容量10,每次add之前都回去调用ensureCapacityInternal(size+1)
    如果初始化指定容量会立即初始化一个指定容量大小的数组
public ArrayList(int initialCapacity) {
    
    
    if (initialCapacity > 0) {
    
    
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
    
    
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
    
    
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}

list.add()方法源码

public boolean add(E e) {
    
    
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

ensureCapacityInternal()源码

//直到添加第11个元素,minCapacity(为11)比elementData.length(为10)要大。
//进入grow方法进行扩容
private void grow(int minCapacity) {
    
    
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);// 1.5倍扩容
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
    
    
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
        // 如果到达Integer.MAX_VALUE再add就会OOM异常
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;// 为什么是Integer.MAX_VALUE-8?
}

灵魂问题:那个MAX_ARRAY_SIZE是干什么的?为什么是Integer.MAX_VALUE-8
当我们的 newSize=1.5倍oldSize=1.5倍element.length>MAX_ARRAY_SIZE的时候
避免每次直接扩容成对应newSize,取一个缓冲值统一扩容为MAX_ARRAY_SIZE
直到element.length大于缓冲值MAX_ARRAY_SIZE时候,再进行统一扩容为Integer.MAX_VALUE;如果element.length=Integer.MAX_VALUE时候再add就会抛出异常OOM;
好了 说了这么多 虽然把流程搞明白了 但是为啥设置MAX_ARRAY_SIZE=Integer.MAX_VALUE-8这个问题 好像还是没得到解决啊?
所以 我们来模拟一下扩容过程:
首先是10->15->22->33->49->73->109->163->…->计算了一下
  l o g 1.5 214748364.7 ≈ 47 \ log_{1.5}214748364.7\approx47  log1.5214748364.747也就是说正常情况下大概扩容47次就到最大值了,实际这个不准确,因为1.5倍小数部分就被省略了;但是大概就47次。
所以这个事儿我的理解就是 一个缓冲作用 避免每次都跟最大值比较,避免无效的扩容(实际用不到那么多空间)。

  1. 怎么理解Java的多态?
  2. 说一说抽象类?
  3. String类型为啥不可变?new一个String产生了几个对象?
  4. this可以作为锁对象吗?

猜你喜欢

转载自blog.csdn.net/blackxc/article/details/108233542