Java基础面试

* 如有错误,请指正。

  1. 八大基本类型 

    1. 整型:byte、short、int、long
    2. 浮点型:double、float
    3. 字符型:char
    4. 布尔型:boolean
  2. 装箱和拆箱

    1. 装箱:从基本类型自动提升到对应的引用类型,为自动装箱
    2. 拆箱:从引用类型自动转为对应的基本类型,为自动拆箱。
  3. 面向对象的三大特性

    1. 继承:指一个类派生出新的类,即子类,有子类继承父类,并拥有父类所包含的属性和方法(使用private修饰的除外),并且子类可以拥有自己的属性和方法。
    2. 多态:指父类引用指向子类对象,指向不同的子类,拥有不同的方法或属性,如动物类、猫类、狗类,由猫类和狗类继承动物类。当用动物类接收狗类或猫类的对象时,动物类就拥有了猫或狗类的功能,
    3. 封装:如一个类中定义了对应的属性,将该属性进行私有化,通过提供的get/set来进行调用,这就是封装。
  4. String、StringBuffer、StringBuilder的区别

    1. String:被final所修饰,长度不可变,初始化后不能变化。在定义变量赋值后,重新给该变量赋值,打印时该变量值发生变化。这是因为重新new了一个对象,并将该变量指向了新new出来的对象的地址 。
    2. StringBuffer:长度可变,线程安全的,被synchronized修饰,性能低。
    3. StringBuilder:长度可变,线程不安全的,性能高。
    4. 当经常改变字符串长度时,建议使用StringBuffer或StringBuilder,当有线程安全问题时,使用StringBuffer,线程安全。
  5. equals和==的区别

    1. ==:通常用来比较值类型
    2. equals:当比较对象时,原则上和==一样,比较地址,一般一样内容的,返回的结果为false。重写后,比较对象的内容,返回结果为true
  6. final、finally、finalize的区别

    1. final:是修饰符关键字,如果一个类被final修饰,那么该类则不能被继承,被修饰的方法不能够重写,修饰的变量不能够被改变。
    2. finally:try-catch异常块的后面部分,当catch后面有finaly的时候,该finaly块总会被执行。
    3. finalize:是一个方法名。finalize()是Object中的方法,当垃圾回收器将要回收对象所占内存之前被调用,即当一个对象被虚拟机宣告死亡时会先调用它finalize()方法。
  7. 抽象类和接口的区别

    1. 抽象类被关键字abstract修饰,接口关键字为interface。
    2. 抽象类中可以有非抽象方法,接口中只能是抽象方法(jdk8可以有一个默认的非抽象方法),并且接口中的变量通常为常量,被final修饰。
    3. 抽象类只能被一个类单继承,关键字为extends,接口可以被一个类多实现,关键字为implements。
  8. sleep和wait的区别

    1. sleep是使线程进入休眠,当休眠时间结束后,自动会进入就绪状态,然后继续执行该线程,不具备改变锁的状态功能。
    2. wait是是使线程进入等待状态,同时释放锁,必须要去进行唤醒,通常是由notify进行唤醒,或者由notifyAll进行唤醒。notifyAll为唤醒所有线程。
  9. 多线程

    1. 创建线程方法一:
      1. 创建类,继承Thread类,重写run方法。实例化该类,调用start()启动线程。    
         1 public class ThreadLesson extends Thread{
         2 
         3     @Override
         4     public void run() {
         5         //执行代码
         6     }
         7 
         8     public static void main(String[] args) {
         9         new ThreadLesson().start();
        10     }
        11 }
    2. 创建线程方法二:
      1. 创建一个类,实现RUnable接口,重写run方法,实例化Thread对象,将创建的类实例化,以参数的形式传入,调用start()方法。  
         1 public class Thread02 implements Runnable {
         2     @Override
         3     public void run() {
         4         //执行代码
         5     }
         6 
         7     public static void main(String[] args) {
         8         new Thread(new Thread02()).start();
         9     }
        10 }
  10. 集合

    1. 集合分为Collection和Map,其中Collection分为List和Set。
      1. List集合
        1. List集合下分为LinkedList和ArrayList,其中LinkedList底层为双向链表,ArrayList底层为动态数组,并且二者为有序可重复的。
        2. LinkedList为链表结构,所以不存在扩容情况。
        3. ArrayList默认大小为10.当检测到容量不够需要扩容时,是按照1.5倍进行扩容,然后之前的数组放入到新数组里面。
        4. 从头到尾查询时,两者性能差距不大。随机访问时。ArrayList的性能要优于LinkedList,因为LinkedList底层是双向链表需要前后移动,而ArrayList底层是数组,直接通过下标获取。
        5. 添加数据在头部或者中间部位的时候,LinkedList的性能要优于ArrayList,因为LinkedList只需要断开指针,然后将插入的数据前后连接起来即可。而ArrayList需要找到位置后,将数据加入进去,后面的其他数据都需要往后移动。
        6. 删除数据的时候LinkedList的性能要优于ArrayList,因为当删除某个数据的时候,LinkedList只需要断开前后指针,然后连接即可,而ArrayList删除后,需要移动后面的其他数据往前移动。
        7. 注意:具体情况具体分析,当数据量过大时,可能LinkedList的性能将低于ArrayList,因为在LinkedList在移动指针时可能会耗费大量的时间。
      2. Set集合
        1. Set集合分为HashSet和TreeSet,HashSet的底层为哈希表,TreeSet的底层为二叉树。
        2. HashSet为无序且不可重复的,TreeSet默认是排好序的,且不可重复的。
        3. HashSet源码中,构造函数对HashMap进行实例化的。底层原理:当存入一个key-value的时候,会先对key进行哈希值获取,根据哈希值将数据放到对应的位置中,如果发现该位置已经有数据了,则会用链表的形式将数据链接起来;没有数据直接放到该位置。
        4. TreeSet源码中,构造函数实例化了TreeMap。底层原理:当存入一个数据时,会按照指定的顺序进行排序,每增加一条数据,进行对比排序一次。
      3. Map集合
        1. HashMap:看HashSet,HashSet的底层跟HashMap一样,HashSet由HashMap进行了包装,允许键值对为null,线程是不安全的。
        2. TreeMap:看TreeSet,TreeSet底层同TreeMap一样,TreeSet由TreeMap进行了包装。
        3. HashTable:线程安全的,不允许键值对为null。
        4. HashMap和HashTable的区别
          1. HashTable是线程安全的,HashMap是线程不安全的。
          2. HashTable的key和value不允许为null,HashMap的key和value可以为null。
          3. HashTable继承Dictionary,HashMap继承Map。
          4. HashMap 的迭代器(Iterator)是 fail-fast 迭代器,HashTable的 enumerator 迭代器不是 fail-fast 的。
          5. HashTable是直接使用了对象的hashCode,而HashMap是重新计算了hash值。
          6. HashTable在不指定容量的情况下,默认容量为11,而HashMap的默认容量是16。
          7. Hashtable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂。
          8. Hashtable扩容时,将容量变为原来的2倍加1,而HashMap扩容时,将容量变为原来的2倍。
        5. ConCurrentHashMap:线程安全的,在多线程情况下,使用ConCurrentHashMap而不使用HashTable,ConCurrentHashMap不允许键值对为null。ConcurrentHashMap 对整个桶数组进行了分割分段(Segment),然后在每一个分段上都用 lock 锁进行保护,相对于Hashtable 的 syn 关键字锁的粒度更精细了一些,并发性能更好。因为ConCurrentHashMap采取分段加锁,所以当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。Hashtable的线程都必须竞争同一把锁,同一时间点只能有一个线程持有。

   

posted @ 2021-06-20 01:25  浮or沉  阅读(29)  评论(0编辑  收藏  举报