java基础-面试题

Java基础

  1. JAVA中的几种基本数据类型是什么,各自占用多少字节。

    • byte 1字节、short 2字节、int 4字节、long 8字节、float 4字节 、double 8字节、char 2字节、boolean 1字节
  2. String类能被继承吗,为什么。

    • String 不能被继承,因为其实被final修饰的。其内部维护了一个char[]数组,该数组也是被final修饰的。
  3. String,Stringbuffer,StringBuilder的区别。

    • String 是不可变的、StringBuffer和StringBuilder继承自AbStractStringBuilder,其内部char[] 不是final的,即他们俩是可变的
    • String 是线程安全的、StringBuilder 不是线程安全的、StringBuffer 对其方法加同步锁 是线程安全的。
  4. ArrayList和LinkedList有什么区别。

    • ArrayList 基于数组实现,LinkedList 基于双向链表,其在不同操作下有性能区别
      • 添加元素时 LinkedList 只需操作相关元素即可,速度占优。ArrayList 默认添加元素时,如果默认空间不够需要扩容,其出发System.arraycopy 复制元素,扩展空间,性能会有影响。如果在指定位置下插入元素ArrayList 需要复制后续元素,性能也会有影响
      • 删除元素时 LinkedList 表现与添加元素一致,而ArrayList需要进行数据重组,开销较大。
      • 查询时,因数组是连续内存空间,通过首地址+偏移量可直接计算到元素位置,链表为分散内存通过只想链接,查找时时通过遍历查找,速度要比Arraylist慢
  5. 讲讲类的实例化顺序,比如父类静态数据,构造函数,字段,子类静态数据,构造函数,字段,当new的时候,他们的执行顺序。

    • 父类静态变量->父类静态代码块->子类静态变量->子类静态代码块->父类非静态变量->父类构造函数->子类非静态变量->子类构造函数
  6. 用过哪些Map类,都有什么区别,HashMap是线程安全的吗,并发下使用的Map是什么,他们内部原理分别是什么,比如存储方式,hashcode,扩容,默认容量等。

    • hashmap: 存储方式:数组+链表+红黑树,默认容量16,负载因子0.75,扩容*2,其内部实现非线程安全,计算index为 hash & (length -1),允许null key 和 value
    • hashtable: 数组+链表,默认容量11,扩容*2+1,计算index为取模,修改值时锁住整个map,其为线程安全,不允许null值
    • ConcurrentHashMap:其为hashmap的安全实现,再修改其值时采用CAS+Synchronized锁住部分区域保证线程安全,读取数据时在不加锁前提下获取最新数据。
  7. JAVA8的ConcurrentHashMap为什么放弃了分段锁,有什么问题吗,如果你来设计,你如何设计。

    • 放弃分段锁引入cas 是为了降低锁的力度,放弃ReentrantLock 是因为java8后 synchronize进行了优化,其占用的内存更小,节省空间
  8. 有没有有顺序的Map实现类,如果有,他们是怎么保证有序的。

    • TreeMap 基于key 升序,通过比较器Comparator 实现的
    • LinkedHashmap 数据插入顺序,其基于链表保证数据顺序。
  9. 抽象类和接口的区别,类可以继承多个类么,接口可以继承多个接口么,类可以实现多个接口么。

    • 接口抽象类区别
      • 抽象类:1、抽象类使用abstract修饰 2、抽象类不能实例化 3、含有抽象方法的类是抽象类,必须使用abstract关键字修饰 4、抽象类中可以有 抽象方法 和具体方法 5 抽象方法只有方法体没有具体实现
      • 接口:1、接口使用interface修饰 2、接口不能别实例化 3、一个类只能继承一个类,但是可以实现多个接口 4、接口中方法均为抽象方法 5 接口中不能包含静态方法。
      • 类不可以继承多个类
      • 接口可以继承多个接口
      • 类可以实现多个接口
  10. 继承和聚合的区别在哪

    • 继承:指的是一个类继承另外一个类的功能,并可以在此基础上进行拓展
  • 聚合:体现的是整体与部分、拥有的关系,整体与部分是可以分离的,他们可以拥有自己完整的生命周期,部分可以属于多个整体对象,也可以为多个整体所共享,如 计算机 与CPU。
  1. IO模型有哪些,讲讲你理解的nio ,他和bio,aio的区别是啥,谈谈reactor模型。
  • bio: 同步并阻塞io,服务器运用一个请求对应一个线程模式.客户端每有新的请求时,服务端都会开启新线程等待处理。
  • nio: 同步非阻塞io, nio采用多路复用机制,服务端运用一个线程维护Selector调度者,客户端发送的请求连接到多路复用器上,其轮询到有I/O请求时,开启线程处理
  • aio:异步非阻塞io,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成再通知服务器开启线程处理,依赖os版本
  • reactor模型:处理多个输入源,将其事件采用多路复用分发响应的处理
  1. 反射的原理,反射创建类实例的三种方式是什么。
  • 反射原理: java文件经过编译后生成.class文件,其在加载到jvm过程中,java可以通过反射获取所有的类信息,包括 构造方法,属性等。
  • 反射创建实例三种方式:
    • Class.forName(“类的路径”);
    • 类.class
    • 实例.getClass
  1. 反射中,Class.forName和ClassLoader.loadClass区别 。
  • Class.forName 方法,内部实际调用方法 Class.forName(className,true,classloader),默认进行初始化,静态代码块会被初始化
  • ClassLoader.loadClass 方法,内部实际调用 ClassLoader.loadClass(className,false);第二个参数表示目标对象是否进行连接,不进行连接意味着不进行一系列的初始化动作
  • java类加载国城: 加载-》验证-》准备-》解析-》初始化-》使用-》卸载
  1. 描述动态代理的几种实现方式,分别说出相应的优缺点。
  • 动态代理:利用反射和字节码,在运行期创建指定接口或类的实例对象,通过这种方式可以对代码进行无侵入式增强
  • 两种方式:
    • jdk 动态代理:利用Proxy类 一个接口InvocationHanlder.Proxy 所有动态类的父类,重写invocationHanlder 的invoke方法进行拓展
    • cglib 动态代理: 基于ASM的字节码生成库,允许运行期动态修改和生成。通过Enhancer 指定要代理的目标对象,通过MethodInterceptor的intercept 方法进行增强
  • 优缺点:
    • jdk动态代理 java原生支持,不需要外部依赖,其有接口硬性要求
    • cglib 无需接口 通过继承方式进行代理
  1. final的用途。
  • 用final修饰的类不能被拓展,不能有子类
  • 用final修饰的方法不能被替换或隐藏
  1. 写出三种单例模式实现 。

    • 懒汉式(双重校验)

      public class SingleTon {
          private volatile static SingleTon instance ;
          private SingleTon(){
          }
          public static SingleTon getSingleTon(){
              if (instance == null){
                  synchronized (SingleTon.class){
                       if (instance == null){
                           instance = new SingleTon();
                       }
                  }
              }
              return instance;
          }
      }
      
    • 饿汉式

      public class SingleTon {
          private static SingleTon instance = new SingleTon();
          private SingleTon(){
          }
          public static SingleTon getSingleTon(){
              return instance;
          }
      }
      
    • 静态内部类:低延迟,线程安全

      public class SingleTon {
          private static class innerSingleTon{
              private final static SingleTon instance = new SingleTon();
          }
          private SingleTon(){
          }
          public static SingleTon getSingleTon(){
              return innerSingleTon.instance;
          }
      }
      
      
  2. 如何在父类中为子类自动完成所有的hashcode和equals实现?这么做有何优劣。

    • 父类重写Object的hashcode 和 equals 实现,如Object默认equals是比较地址值,父类可重写为值相等等情况,子类继承后可自动引用父类定义。
  3. 请结合OO设计理念,谈谈访问修饰符public、private、protected、default在应用设计中的作用。

    • 个人理解java修饰符设计是用来封装的,类与类之间有多重关系,通过修饰符可以更好的做控制

    • 本类内 本包类 其他包子类 其他包
      public + + + +
      protected + + +
      default + +
      private +
  4. 深拷贝和浅拷贝区别。

    • 浅拷贝:增加指向已存在的内存地址
    • 深拷贝:增加一个指针并且申请新的内存,使用该指针指向新的内存
  5. ​ 数组和链表数据结构描述,各自的时间复杂度

    • 数组:元素在内存中连续存放,通过头结点和偏移量可迅速定位元素,查询的时间复杂度O(1)
    • 链表:链表中元素在内存中不是连续的,通过元素指针进行连接,查询需要从根节点开始遍历查找,时间复杂度O(N)
  6. error和exception的区别,CheckedException,RuntimeException的区别。

    • error和exception 继承与Throwable, error 是java程序运行中不可预料的异常情况,异常发生后,会直接导致JVM不可处理或者不可恢复的状况,OutOfMemoryError等。Exception是java程序运行中可预料的异常情况
    • Exception 分为检查性异常 和 运行时异常。CheckedException 是需要编译器校验的,通过throws 或者try/catch 语句块来出利益异常。RuntimeException 在定义时不需要声明抛出异常或者捕获异常,通常是由于程序逻辑引起的。
  7. 请列出5个运行时异常。

    • ClassCastException 类转换异常
    • IndexOutOfBoundsException 数组越界
    • NullPointerException 空指针
    • ArrayStoreException 数组存储异常
    • ArithmeticException 算数异常
  8. 在自己的代码中,如果创建一个java.lang.String类,这个类是否可以被类加载器加载?为什么。

    • 这个类不会被加载。jvm加载类提供了多种加载器。其关系为:自定义类加载器->应用程序类加载器->拓展类加载器->启动类加载器. 他们的层次关系被称为 双亲委派模型。如果一个类加载器收到了类加载的请求,首先不会尝试加载,而是委派父类加载器。通过该种方式来保护java已经提供的类,其中就有String类。
  9. 说一说你对java.lang.Object对象中hashCode和equals方法的理解。在什么场景下需要重写

    • Object中equals 是对两个对象的地址值比较,Object中hashcode() 是一个本地方法,其实现是根据本地环境相关的,其可以返回对象的hash地址值。
    • 集合中,例如map中存自定义对象时,需要重写这两个方法,因为map在查询比较过程中,是先判断hashcode 值,再判断equals. hashcode不同,equals一定不同。
  10. 这样的a.hashcode() 有什么用,与a.equals(b)有什么关系。

    • hashCode 的作用是获取哈希码,确定对象在哈希表中的位置
    • equals 相等 hashCode 一定相等。
    • hashCode 不相等,equals 也不等
    • hashCode 相等 , equals 不一定相等
  11. 在jdk1.5中,引入了泛型,泛型的存在是用来解决什么问题。

    • 泛型用来参数化类型,未有泛型前,对象想下转型需要显示强制类型转换,这种转换在编译器是不检查的,容易在运行期触发转换异常,引入泛型后,编译时会检查参数类型,所有转换都是隐式的,并提高代码重用率。
  12. Java中的HashSet内部是如何工作的。

    • HashSet 内部采用HashMap 来实现,由于map 需要 key 和 value,所以HashSet 中 所有的key都有个默认value. hashSet 不允许有重复的key , 其只允许有一个null对象
  13. 什么是序列化,怎么序列化,为什么序列化,反序列化会遇到什么问题,如何解决。

    • java序列化 是指把java对象转换为字节序列的过程。java反序列化是指把字节序列恢复为java对象的过程。
    • 网络通讯时传输的是字节序列,所以需要进行java序列化
    • 实现Serializable接口的类对象即可序列化,会生成个 serialVersionUID的版本号,用于校验一致性
    • 声明为static 和transient 类型的成员变量不能被序列化
  14. java8的新特性。

    • Lambda表达式和函数式接口
    • 接口的默认方法
    • 方法引用
    • 重复注解
    • 增加新的工具类
      • Optional 用于解决空指针异常
      • Streams
      • Base64
    • JVM 使用 元空间 代替 持久代

发布了6 篇原创文章 · 获赞 2 · 访问量 238

猜你喜欢

转载自blog.csdn.net/han451375136/article/details/105298047