Java基础

1. java 8大类型

int, byte,short,long(4个整数类型), float, double(2个浮点数类型), boolean(布尔型), char(字符型)

2.抽象类和接口的区别

  • 1、抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
  • 2、抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;
  • 3、接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
  • 4、一个类只能继承一个抽象类,而一个类却可以实现多个接口。
  • https://www.jianshu.com/p/28e3b4d61945

    什么时候用抽象类,什么时候用接口
    1.  抽象类适合定义一些固有的属性(比如人的皮肤、眼睛),接口适合定义一些拓展功能(是否回一些乐器)
    2. 当需要为一些类提供公共代码时,用抽象类。因为抽象类中的非抽象方法可以被子类继承下来,使实现功能的代码更简单
    3. 当注重代码的可拓展性的时候,应该优先采用接口


    3. String为什么不可变

    1. 类本身是由final修饰的,保证了类不会被扩展
    2. 所有的域都是private final 修饰的,外界没有办法修改值
    3. String源码里面没有提供任何修改value域的方法,所有的修改函数的方法都是Arrays.copyOf()来先获取value的拷贝

    4. StringBuilder和StringBuffer

    StringBuffer支持并发操作,线性安全的,适合多线程中使用。StringBuilder不支持并发操作,线性不安全的,不适合多线程中使用

    5. 泛型

    Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。

    泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。

    泛型方法:方法在调用时可以接收不同类型的参数。根据传递给泛型方法的参数类型,编译器适当地处理每一个方法调用。
    public static < E > void printArray( E[] inputArray )
    {
       // 输出数组元素            
       for ( E element : inputArray ){        
          System.out.printf( "%s ", element );
       }
       System.out.println();
    }

    泛型类
    public class Box<T> {
       
      private T t;
     
      public void add(T t) {
        this.t = t;
      }
     
      public T get() {
        return t;
      }

    6. 多态

    多态就是同一个接口,使用不同的实例而执行不同操作
    多态的实现方式:重写、接口、抽象类和抽象方法

    7. Atomic Integer和Integer区别, Atomic Integer原理

    多线程访问Integer时,结果不正确,因此设计了一个基于多线程并且支持原子操作的Integer类

    Atomic Integer里面用的是Unsafe类的CAS操作(comapreandswap,比较并交换,是一个原子交换);
    以addAndGet为例:
    public final int addAndGet(int delta) {
        for (;;) {
            int current = get();
            int next = current + delta;
            if (compareAndSet(current, next))
                return next;
        }
    }
    死循环里面得到当前值value,然后再把当前的值加1,加完后用cas原子操作让当前值加1处理正确。cas不一定是成功的,所以做了一个死循环,让cas操作成功的时候返回数据


    8. 集合类

    ArrayList, LinkedList, HashMap

    HashMap的实现原理:
    1)存储结构:内部是一个Entry类型的数组,Entry是一个链表。HashMap使用拉链法来解决冲突,同一个链表存放哈希值和数组长度取模运算结果相同的Entry. java 1.8使用了红黑树进行优化
    2) 扩容: 当需要扩容时,capacity变为原来的两倍

    9. JVM的内存分区



    10. 面向对象以及其特性

    封装:把事务封装成一个类,减少耦合,隐藏细节
    继承:从一个已知的类中派生出一个新的类
    多态:一个程序中存在多个同名的不同方法;三种方式:1)通过子类对父类的覆盖来实现;2)在一个类中对方法进行重载 3)将子类对象作为父类对象使用

    11. 重写与重载

    重写:子类扩展了方法A并且添加了丰富的功能。我们就说子类覆盖或者重写了方法A,也就是说子类中的方法与父类中继承的方法有完全相同的返回值类型、方法名、参数个数以及参数类型。
    重载:在一个类中(包括父类)存在多个同名的不同方法,这些方法的参数个数,顺序以及类型不同均可以构成方法的重载

    12. JDK,JRE,JVM的区别与联系

    JDK是开发工具包,用来开发java程序,jre是java的运行时环境
    jdk和jre中都包含了jvm
    jvm是指java虚拟机,当我们运行一个程序时,jvm负责将字节码转换为特定的机器代码,jvm提供了内存管理/垃圾回收和安全机制等。


    13. 抽象类和接口的区别

    • 抽象类中可以没有抽象方法,也可以抽象方法和非抽象方法共存
    • 接口中的方法在jdk8之前只能是抽象的,jdk8版本开始提供了接口中方法的default实现
    • 抽象类和类一样是单继承的;接口可以实现多个父接口
    • 抽象类中可以存在普通的成员变量;接口中的变量必须是static final类型的,必须初始化,接口中只有常量,没有变量

    14. 反射机制

    动态获取信息和动态调用对象方法的功能称为反射机制。

    15. Exception和Error有什么区别

    Exception是程序运行中预料到可能会出现的错误,并且应该被捕获并进行相应的处理,是一种异常现象
    Error是正常情况下不可能发生的错误,Error会导致JVM处于一种不可恢复的状态,不需要捕获处理,比如OutOfMemoryError
    Exception又分为运行时异常和编译时异常

    16. 值传递和引用传递

    值传递:传递了一个对象的副本,即使副本被改变,也不会影响源对象(基本数据类型都是值传递)
    引用传递:传递的不是实际的对象,而是对象的引用

    操作系统

    1. 进程调度(2)

    可以分为剥夺式调度和非剥夺式调度两种方式
    调度算法:
    1)先来先服务(FCFS):适用于长作业的情况,非剥夺算法
    2)短作业优先:每次都先执行估计服务时间最短的一个或几个作业
    3)优先级调度算法:每次挑选优先级最高的一个或几个作业
    4)高响应比优先: 响应比 = (等待时间 + 服务时间) / 服务时间
    5)时间片轮转:将cpu的处理时间划分为若干个时间片,进程按照到达先后顺序排序,每次调度都选择队首的进程。执行完一个时间片,计时器发出时钟中断请求,进程移至队尾

    2. 进程状态

    就绪:进程获得了除处理机之外的一切所需资源
    运行,阻塞,新建,终止


    4. 线程安全, 为什么要线程安全

    多线程访问时,采用加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完。
    为了避免出现数据不一致或者数据污染的情况

    5. 为什么要同步

    使用多线程同步就是为了解决线程安全的问题

    6.内存泄漏如何发现

    由程序申请的一块内存,且没有任何一个指针指向它,那么这块内存就泄露了。
    1)良好的编码习惯:一旦使用了内存分配的函数,记得使用相应的函数释放掉
    2)将分配的内存的指针以链表的形式自行管理。使用完毕后就从链表里面删除,程序结束检查链表
    3)用一些工具插件来管理

    7. 多线程的通信、同步方式,volatile和synchronized的区别

    线程间的通信方式:
    1)使用全局变量:由于多个线程可能会改变全局变量,全局变量最好声明为volatile
    2)   使用消息实现通信:每一个线程都有自己的消息队列,可以采用消息进行线程间通信
    3)使用事件Cevent类实现线程间通信:Event对象有有信号和无信号两种状态,线程可以监视处于有信号状态的时间,以便在适当时候执行对事件的操作 ;

    线程间的同步方式:
    1)临界区
    2)互斥量
    3)信号量


    8. volatile和synchronized的区别

    1. volatile是变量修饰符,其修饰的遍历具有可见性;但是其不具有原子性
    2. volatile禁止指令重排
    3. synchronized既可以保证可见性,又能保证原子性


    9.  NIO和BIO的区别

    同步:使用同步IO时,Java自己处理IO读写
    异步:使用异步IO时,Java将IO读写委托给OS处理,需要将数据缓冲区地址和大小传给OS,完成后OS通知Java处理;
    阻塞:使用阻塞IO时,Java会一直阻塞到读写完成才返回
    非阻塞:使用非阻塞IO时,如果不能立马读写,Java调用会马上返回,当IO事件分发器通知可读写时在进行读写,不断循环直到读写完成;

    BIO: 同步并阻塞,服务器的实现模式是一个连接一个线程;由于客户端连接数与服务器线程数成正比关系,可能会造成不必要的线程开销,严重的还将导致服务器内存溢出
    NIO:同步非阻塞。服务器的实现模式是多个请求一个线程;请求会注册到多路复用器Selector上,多路复用器轮询到连接有IO请求时才启动一个线程处理。

    10. 零拷贝

    零拷贝就是一种避免 CPU 将数据从一块存储拷贝到另外一块存储的技术


    11. 抽象类和接口

    • 抽象类可以没有抽象方法,也可以抽象方法和非抽象方法并存
    • 接口中的方法在JDK8之前只能是抽象的,JDK8版本开始提供了接口方法中的default实现
    • 抽象类和类一样是单继承的,接口可以实现多个父接口
    • 抽象类中可以存在普通的成员变量;接口中的变量必须是static final的,必须被初始化,接口中只有常量,没有变量


    计算机网络

    1. https、重定向的状态码

    3XX是重定向的状态码;303允许重定向时改变请求方法




    数据库

    1. 数据库范式

    目前的关系型数据库有六种范式。一般来说,数据库只要满足第三范式就行了
    1) 第一范式:列不能再分为其他几列。比如电话这个列可以分为家庭电话和办公电话,就不满足第一范式
    2)第二范式:除了第一范式,还必须满足两个条件:(1)表必须有一个主键(可以是多个列的集合);(2)没有包含在主键中的列必须完全依赖于主键,不能只依赖于主键的一部分
    3)第三范式:首先满足第二范式,其次非主键必须直接依赖于主键,不能存在依赖传递