JAVA基础

99 阅读7分钟
  • 面向对象和面向过程的区别

    • 面向过程
      • 面向过程性能比面向对象高:因为类调用时需要实例化,开销比较大,
    • 面向对象
      • 易维护,易复用,易扩展
  • Constructor 是否可被override

    • 不能override 重写
    • 可以overload 重载
  • overload 和override的区别

    • overload
      • 发生在同一个类中
      • 方法名必须相同
      • 参数类型不同、个数不同、顺序不同
    • override:子类继承父类
      • 发生在运行期
      • 返回值类型、方法名、参数列表必须相同,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类
      • 构造方法无法别重写
  • JAVA面向对象变成三大特性:封装 继承 多态

    • 封装
      • 把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法
    • 继承
      • 子类拥有父类对象所有的属性和方法,但是父类中的似有属性和方法子类是无法访问的,只是拥有
      • 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展
      • 子类可以用自己的方式实现父类的方法
    • 多态
      • 所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。
      • 继承 接口
  • String StringBuilder StringBuffer的区别

    • 可变性
      • String 类中使用 final 关键字修饰字符数组来保存字符串,private final char value[],所以 String 对象是不可变的。
      • 而 StringBuilder 与 StringBuffer 都继承自 AbstractStringBuilder 类,在 AbstractStringBuilder 中也是使用字符数组保存字符串char[]value 但是没有用 final 关键字修 饰,所以这两种对象都是可变的。
    • 线程安全性
      • String中的对象是不可变的,线程安全
      • StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,线程安全
      • StringBuilder 没有,非线程安全
    • 性能
      • 每次对String进行改变的时候,都会生成一个新的String对象,然后将指针指向新的String对象。
      • StringBuffer 每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用
    • 总结
      1. 操作少量的数据: 适用 String
      2. 单线程操作字符串缓冲区下操作大量数据: 适用 StringBuilder
      3. 多线程操作字符串缓冲区下操作大量数据: 适用 StringBuffer
  • 在一个静态方法内调用一个非静态成员为什么是非法的

    • 由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非静态变量,也不可以访问非静态变量成员
  • 接口和抽象类的区别

    • 一个类可以implement多个接口,但只能extend一个抽象类
    • 从设计层面来说,抽象是对类的抽象,是一种模板设计,而接口是对行为的抽象,是一种行为的规范
  • == 和 equals

    • == 的作用是判断两个对象的地址是不是相等,即,判断两个对象是不是同一个对象
    • equals: 类没有覆盖equals方法,则通过equals比较两个对象时,等价于==
    • equals:类覆盖了equals方法,一般用来比较两个对象的内容是否相等
  • hashcode 和equals

    • java任何类都包含hashCode函数
    • 如果两个对象相等,则hashcode一定相等
    • 两个对象hashcode值相等,他们也不一定是相等的
  • final关键字

    • 主要用在 变量,方法,类
    • 对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改,如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象
    • 当final修饰一个类时,这个类不能被继承,final类中所有成员方法都会被隐式地指定为final方法
    • 使用final的原因:锁定方法;效率
  • 异常处理总结

    • try:捕获异常
    • catch:处理捕获的异常
    • finally:无论是否捕获或处理异常,finally块里的语句都会被执行。当在try块或catch块雨中return语句时,finally语句块将在方法返回之前被执行
    • 当 try 语句和 finally 语句中都有 return 语句时,在方法返回之前,finally 语句的内容将被执行,并且 finally 语句的返回值将会覆盖原始的返回值
  • 获取键盘输入的方法

    • Scanner
    Scanner input = new Scanner(System.in);
    String s  = input.nextLine();
    input.close();
    
    • 通过BufferedReader
    BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
    String s = input.readLine();
    
  • ArrayList LinkedList区别

    • 都不是线程安全的
    • 底层数据结构: Arraylist 底层使用的是 Object 数组;LinkedList 底层使用的是 双向链表 数据结构
    • 内存空间占用: ArrayList的空 间浪费主要体现在在list列表的结尾会预留一定的容量空 间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗比ArrayList更多的空间
    • 是否支持快速随机访问: LinkedList 不支持高效的随机元素访问,而 ArrayList 支 持。快速随机访问就是通过元素的序号快速获取元素对象(对应于get(int index)方法)
  • HashMap 和 HashTable的区别

    • 是否线程安全: HashMap是非线程安全的,HashTable是线程安全的。HashTable内部的方法基本都经过synchronized修饰。如果要保证线程安全的话就使用 ConcurrentHashMap。
    • 效率: 因为线程安全的问题,HashMap要比HashTable效率高一点。另外,HashTable基本被淘汰,不要在代码中使用它。
    • Null key和Null value的支持:HashMap中,null可以作为key,这样的key只有一个,可以有一个或多个键所对应的值为null。但是在HashTable中put进的key-value,只要又一个为null,就会抛出异常
  • HashMap和HashSet的区别

    • HashSet底层就是基于HashMap实现的。
    • HashSet如何检查重复:先检查有没有相同的hashcode,有的话再调用equals方法来检查hashcode相等的对象是否相同
  • HashMap的底层实现

    • HashMap 的⻓度为什么是2的幂次方:为了能让 HashMap 存取高效,尽量􏰀少碰撞,也就是要尽量把数据分配均匀。用之前还要先做对数组的⻓度取模运算,得到的余数才能用来要存放 的位置也就是对应的数组下标。这个数组下标的计算方法是“ (n - 1) & hash” (n的二进制,100000,n-1就是1111111)

  • 多线程

    • 并发和并行的区别
      • 并发:同一时间段,多个任务都在执行
      • 并行:单位时间内,多个任务同时执行
    • 死锁的四个条件
      • 互斥条件:该资源一个时刻只由一个线程占用
      • 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放
      • 不剥夺条件:线程已获得的资源在未使用完之前不能被其他线程强行剥夺,只有自己使用完毕后才释放资源
      • 循环等待条件:若干进程之间形成一种头尾想接的循环等待资源关系
    • 如何避免线程死锁
      • 破坏四个条件被同时满足
    • wait和sleep的异同
      • 最主要区别:sleep方法没有释放锁,wait方法释放了锁

      • 两者都可以暂停线程的执行

      • wait通常被用于线程间交互/通信,sleep通常被用于暂停执行

      • wait方法被调用后,线程不会自动苏醒,需要背的线程调用同一个对象伤的notify或者notifyall方法。sleep方法执行完成后,线程会自动苏醒