欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

面试总结v1.0

程序员文章站 2024-03-19 11:25:04
...

面试总结v1.0

  • 基本数据类型
  • String相关问题
  • final,finally ,finalize
  • hashmap相关
  • 索引相关
  • Spring注解

1. 基本数据类型

整型: byte , short,int ,long
浮点型:float ,double
字符型:char
布尔类型:boolean

2.String 相关问题

2.1 String 是否是基本数据类型?

答:不是。String 是引用数据类型,除了string之外,引用数据类型还有:接口,枚举,数组,注解类型,共5种

扩展:基本数据类型和应用数据类型的区别
基本数据类型在被创建时,在栈上给其划分一块内存,将数值直接存储在栈上。
引用数据类型在被创建时,首先要在栈上给其引用(句柄)分配一块内存,而对象的具体信息都存储在堆内存上,然后由栈上面的引用指向堆中对象的地址。

2.2 String是否是可变的?

答:不可变,因为String 有final 修饰(这是表象),不可以被继承,这样做的目的是为了线程安全着想。
String 底层是一个char[]数组,而且是用final修饰的;这里的final修饰不可变指的是stack里的这个value的应用地址是不可变的,但是在堆中value本身数据是可以发生变化的。(也可以理解为一个被final 修饰的数组,地址不会发生变化,但是其数据会发生变化)

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage.(值用char保存)*/
    private final char value[];

以int数组为例做示范:

    final int[] arr = {1, 2, 3};
    System.out.println(arr);
    arr[2] = 100;
    System.out.println(arr);
    System.out.println(Arrays.toString(arr));
    /**
    输出结果:
    [aaa@qq.com
    [aaa@qq.com
    [1, 2, 100]
    */
2.3 final修饰在方法,类,变量,对象前的区别
  • 修饰在方法前:方法不可重写
  • 修饰在类前:无子类,不可被继承或重写
  • 修饰在变量前:修饰的变量,为常量,值不可变
  • 修饰在对象前:值可变,引用不可变

3.final,finally ,finalize

  • final:用于声明属性,方法和类,表示属性不可变,方法不可被重写,类不可被继承。
  • finally: 是异常处理语句结构的一部分,表示总会执行
  • finalize:finalize是方法名,是object类的一个方法,在垃圾收集器执行的时候会调用这个对象回收的方法。finalize()方法是在垃圾收集器删除对象之前对这个对象调用的,子类覆盖finalize()方法以整理系统资源或者执行其他清理工作。

4. hashmap 相关

4.1 hashmap的数据结构是什么?

答:JDK1.8之前 链表+数组
JDK1.8之后 数组+红黑树(下面详解)
面试总结v1.0

4.2 hashmap的默认容量(长度)时多少?

答:默认长度是16

    /**
     * The default initial capacity - MUST be a power of two.(默认容量 16)
     */
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

    /**
     * The maximum capacity, used if a higher value is implicitly specified
     * by either of the constructors with arguments.
     * MUST be a power of two <= 1<<30. (最大容量1*2^30)
     */
    static final int MAXIMUM_CAPACITY = 1 << 30;

    /**
     * The load factor used when none specified in constructor.(负载因子0.75)
     */
    static final float DEFAULT_LOAD_FACTOR = 0.75f;
     /**  8就从 链表  转 树
     * The bin count threshold for using a tree rather than list for a
     * bin.  Bins are converted to trees when adding an element to a
     * bin with at least this many nodes. The value must be greater
     * than 2 and should be at least 8 to mesh with assumptions in
     * tree removal about conversion back to plain bins upon
     * shrinkage.
     */
    static final int TREEIFY_THRESHOLD = 8;

    /**   6就从树转链表
     * The bin count threshold for untreeifying a (split) bin during a
     * resize operation. Should be less than TREEIFY_THRESHOLD, and at
     * most 6 to mesh with shrinkage detection under removal.
     */
    static final int UNTREEIFY_THRESHOLD = 6;
4.3 HashMap和Hashtable的区别

答:

  1. 产生的时间不同:hashtable 是java一开始发布就提供的键值映射的数据结构;hashmap产生于JDK1.2(目前hashtable基本已启用,且没有遵循驼峰命名法)
  2. 继承的父类不同:HashMap 继承的是AbstracMap类,Hashtable继承的是Dictionary类。但是他们都实现了map,Cloneable(可复制)、Serializable(可序列化)这三个接口
  3. 对Null key 和Null value的支持不同 :Hashtable既不支持Null key也不支持Null value。HashMap中null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null
  4. 线程安全性不同 :Hashtable是线程安全的,它的每个方法中都加入了Synchronize方法;HashMap不是线程安全的,在多线程并发的环境下,可能会产生死锁等问题.(ConcurrentHashMap使用了分段锁,并不对整个数据进行锁定。是将HashMap安全的一种方式)
  5. 遍历方式的内部实现上不同 (JDK8之前):Hashtable、HashMap都使用了 Iterator。由于历史原因,Hashtable还使用了Enumeration的方式 ,HashMap的Iterator是fail-fast迭代器。JDK8之后都是fail-fast迭代器。
  6. 初始容量大小和每次扩充容量大小的不同 :Hashtable默认的初始大小为11,之后每次扩充,容量变为原来的2n+1(素数,奇数)。HashMap默认的初始化大小为16。之后每次扩充,容量变为原来的2倍(2的幂次方大小)。
  7. 计算hash值的方法不同 :Hashtable直接使用对象的hashCode;HashMap为了提高计算效率,将哈希表的大小固定为了2的幂,这样在取模预算时,不需要做除法,只需要做位运算。位运算比除法的效率要高很多。
4.4 hashmap是线程安全的吗?

答:不安全,因为hashmap超过临界值时会进行扩容,进行resize()(rehash)操作在多线程情况下,会导致hashmap出现链表闭环,一旦进入了闭环get数据,程序就会进入死循环,所以导致HashMap是非线程安全的。

扩展:
1.HashMap的底层存储结构,HashMap底层是一个Entry数组,一旦发生Hash冲突的的时候,HashMap采用拉链法解决碰撞冲突
2.当多个线程同时检测到总数量超过门限值的时候就会同时调用resize操作,各自生成新的数组并rehash后赋给该map底层的数组table,结果最终只有最后一个线程生成的新数组被赋给table变量,其他线程的均会丢失。而且当某些线程已经完成赋值而其他线程刚开始的时候,就会用已经被赋值的table作为原始数组,这样也会有问题。
3. 代码验证HashMap线程不安全

  public static void main(String[] args) {

    Map<String, String> map = new HashMap<String, String>();
    for (int i = 0; i < 100; i++) {
      MyThread myThread = new MyThread(map, "线程名字:" + i);
      myThread.start();
    }
  }

  static class MyThread extends Thread {
    public Map map;
    public String name;

    public MyThread(Map map, String name) {
      this.map = map;
      this.name = name;
    }
    public void run() {
      double i = Math.random() * 100000;
      map.put("键" + i, "值" + i);
      try{
        Thread.sleep(1);
      }catch (Exception e){
        e.printStackTrace();
      }
      map.remove("键" + i);
      System.out.println(name + "当前时间:" + i + "   size = " + map.size());
    }
4.5 怎样让hashmap变成线程安全?

答:1.替换成Hashtable,效率比较低
2.使用Collections类的synchronizedMap方法包装一下。

方法如下:
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)  
返回由指定映射支持的同步(线程安全的)映射

3.使用ConcurrentHashMap,它使用分段锁来保证线程安全。

说明:在JDK8中 ConcurrentHashMap摒弃了 Segment(锁段)的概念,而是启用了一种全新的方式实现,利用 CAS 算法

4.6 怎样解决hash冲突?

答:1.开放定址法(线性探测在散列,二次探测再散列,伪随机探索再散列)
2.再哈希法
3.链地址法
4.建立一个公共溢出区

5.索引相关

5.1 什么是索引

答:在关系数据库中,索引是存储的表中一个特定列的值数据结构(最常见的是B-Tree)
在数据库系统中建立索引主要有以下作用:
(1)快速取数据;
(2)保证数据记录的唯一性;
(3)实现表与表之间的参照完整性;
(4)在使用ORDER by、group by子句进行数据检索时,利用索引可以减少排序和分组的时间。

5.2 索引的优缺点

优点
1.大大加快数据的检索速度;
2.创建唯一性索引,保证数据库表中每一行数据的唯一性;
3.加速表和表之间的连接;
4.在使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间。
缺点
1.索引需要占物理空间。
2.当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,降低了数据的维护速度。

5.3 索引是不是越多越好?

答:不是,因为索引也需要更新,多的时候也会影响效率

也可以自己拓展了解一下关于哈希索引

6.Spring 注解

Bean容器相关的:
  1. @Autowired:autowire=byType 就是根据类型的自动注入依赖(基于注解的依赖注入),可以被使用再属性域,方法,构造函数上。
  2. @Resource 属于JSR250标准,用于属性域额和方法上。也是 byName 类型的依赖注入。使用方式:@Resource(name=”xxBean”). 不带参数的 @Resource 默认值类名首字母小写。
  3. @Qualifier 就是 autowire=byName, @Autowired注解判断多个bean类型相同时,就需要使用 @Qualifier(“xxBean”) 来指定依赖的bean的id:
  4. @Required:表明bean的属性必须在配置时设置,可以在bean的定义中明确指定也可通过自动装配设置。如果bean的属性未设置,则抛出BeanInitializationException异常。
  5. @PostConstruct
  6. @PreDestory
  7. @Singleton(从这儿开始是Spring3.0之后开始支持的)
  8. @Scope(“prototype”)
MVC相关的
  1. @Controller
  2. @RequestMapping
  3. @RequestParam
  4. @ResponseBody
  5. @ Repository @ Repository(value=”userDao”)注解是告诉Spring,让Spring创建一个名字叫“userDao”的UserDaoImpl实例。 @Resource(name = “userDao”)注解告诉Spring,Spring把创建好的userDao注入给Service即可。
小知识点:

@Autowired和@Resource的区别:
前者是根据类型(byType)的自动注入依赖,
后者是根据名字(byName)进行依赖注入的。
spring注解觉得不错的一篇博客:https://www.cnblogs.com/digdeep/p/4525567.html