java基础知识

  1. 0.常用知识点解析
  2. 1.java三种技术架构
  3. 2.内存模型的发展
    1. 2.1 java内存模型图
    2. 2.2 jvm 的主要组成部分和作用
    3. 2.3 jvm 运行时数据区组成?
    4. 2.4 队列和栈区别联系?
    5. 2.5 说一下类加载的执行过程?
  • 3.java面向对象内存管理
    1. (1).堆:
    2. (2).栈:
    3. (3).方法区:
    4. (4).堆栈的区别
  • 4.javac命令和java命令区别联系
  • 5.为什么使用变量?
  • 5.1 数据类型
  • 6 java中IO流分为几种?
    1. FileOutputStream和FileInputStream:
    2. BufferedOutputStream和BufferedInputStream:
    3. ObjectOutputStream和ObjectInputStream:
    4. Reader和Writer:
    5. OutputStreamWriter和InputStreamReader:
    6. BufferedWriter和BufferedReader:
  • 7.运算符号:
  • 8.循环语句解析
    1. 8.1 判断固定个数的值时,可用if,也可用switch
    2. 8.2 当判断数据范围,获取判断运行结果boolean类型时,用if
    3. 8.3 当某些语句需要执行很多次时,使用循环结构,
  • 9.数组
  • 10.成员变量和局部变量的区别:
    1. 10.1 成员变量:
    2. 10.2 局部变量:
  • 11.面向对象相关:
    1. 11.1 面向对象的特点
    2. 11.2 重写遵循的 “两同两小一大” 原则
  • 12.面向对象的特征
  • 13.List、Set、Map 之间的区别是什么?
  • 14.HashMap 和 Hashtable 有什么区别?
  • 14.1 HashMap、Hashtable和CurrentHashMap底层技术实现比较?
  • 15.如何决定使用 HashMap 还是 TreeMap?
  • 16.HashMap 的实现原理?
  • 17.HashSet 的实现原理?
  • 18.如何实现数组和 List 之间的转换?
  • 19.Array 和 ArrayList 有何区别?
  • 20. Iterator 和 ListIterator 有什么区别?
  • 21.多线程学习
  • 22.runnable 和 callable 有什么区别?
  • 23. sleep() 和 wait() 有什么区别?
    1. 23.1 sleep()方法
    2. 23.2 wait()方法
    3. 23.3 互斥锁和同步锁
  • 24. notify()和 notifyAll()有什么区别?
  • 25.线程的 run()和 start()有什么区别?
  • 26.比较Executor和new Thread()创建线程的优劣?
  • 27.创建线程池有哪几种方式?
  • 28.线程池中 submit()和 execute()方法有什么区别?
  • 29.在 java 程序中怎么保证多线程的运行安全?
  • 30.什么是死锁?
  • 31.如何防止死锁?
  • 32.synchronized 底层实现原理?
  • 33.synchronized 和 volatile 的区别是什么?
    1. 33.1 volatile
    2. 33.2 synchronized
  • 34.synchronized 和 Lock 有什么区别?
    1. 34.1 synchronized
    2. 34.2 Lock
  • 35.什么是java反射机制?
  • 36.什么是 java 序列化?什么情况下需要序列化?
  • 37.动态代理是什么?有哪些应用?
  • 38. 如何实现对象克隆?
  • 39. 深拷贝和浅拷贝区别是什么?
  • 40. throw 和 throws 的区别?
  • 41. final、finally、finalize 有什么区别?
  • 42.try-catch-finally 中哪个部分可以省略?
  • 43.http 响应码 301 和 302 代表的是什么?
  • 44.forward 和 redirect 的区别?
  • 45. 简述 tcp 和 udp的区别?
    1. 45.1 tcp简述:
    2. 45.2 udp简述:
    3. 45.3 四次挥手:
  • 46.1 tcp 为什么要三次握手,两次不行吗?
  • 46.2 为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?
  • 47.tcp 粘包是怎么产生的?
    1. 47.1 发送方产生粘包
    2. 47.2 接收方产生粘包
  • 48.OSI 的七层模型都有哪些?
  • 49.get 和 post 请求有哪些区别?
  • 50.设计模式
  • 51.spring 常用的注入方式有哪些?
  • 52. spring 事务实现方式有哪些?
  • 53. spring 的事务隔离?
  • 54.spring mvc 运行流程?
  • 55.spring cloud 核心组件有哪些?
  • 56. mybatis中 #{}和 ${}的区别是什么?
  • 57.mybatis 逻辑分页和物理分页的区别是什么?
  • 58.mybatis 是否支持延迟加载?延迟加载的原理是什么?
  • 59.mybatis 和 hibernate 的区别有哪些?
  • 60.mybatis 有哪些执行器(Executor)?
  • 61.数据库
  • 62.rabbitmq 的使用场景有哪些?
  • 63.
  • 0.常用知识点解析

    基础模块   
    容器  
    多线程  
    反射  
    对象拷贝  
    JavaWeb  

    异常  
    网络  
    设计模式  
    Spring/SpringMVC  
    Spring Boot / Spring Cloud  
    JVM  

    Hibernate  
    Mybatis  
    RabbitMQ  
    Kafka  
    Zookeeper  
    MySql  
    Redis  

    1.java三种技术架构

    JAVAEE:开发企业环境下的应用程序,主要针对web程序开发;

    JAVASE:完成桌面应用程序的开发,是其它两者的基础;

    JAVAME:开发电子消费产品和嵌入式设备,如手机中的程序;

    2.内存模型的发展

    内存模型参考

    2.1 java内存模型图

    可见性:当某个线程修改某个共享变量的值,并把该共享变量写回主内存中,其它线程要知道该变量已经被修改过了。

    java内存模型同步规定

    (1).线程解锁前,必须把共享变量的值刷新回主内存

    (2).线程加锁前,必须读取主内存的最新值到自己的工作内存

    (3).加锁解锁是同一把锁

    2.2 jvm 的主要组成部分和作用

    (1).jvm 组成:类加载器(ClassLoader)、运行时数据区(Runtime Data Area)、执行引擎(Execution Engine)、本地库接口(Native Interface)

    (2).作用:

    第一步:javac编译器把类加载器(ClassLoader)加载的 Java 代码转换成字节码,

    第二步:运行时数据区(Runtime Data Area)把字节码加载到内存中,

    第三步:执行引擎(Execution Engine),将字节码翻译成底层系统指令,再由 CPU 去执行

    第四步:执行过程中需要调用其他语言的本地库接口(Native Interface)来实现整个程序的功能。

    温馨提示:字节码文件只是 JVM 的一套指令集规范,并不能直接交给底层操作系统去执行,因此需要特定的命令解析器,即执行引擎

    (3).java数据交互原理

    数据交互处理:java应用程序-JVM-操作系统-硬件驱动-硬件

    Java做到字节码跨平台,底层由JVM处理字节序。若没有中间平台语言,比如C/C++(只能源代码跨平台),需要针对硬件平台(或者硬件驱动)去重新编译一套可执行文件,即不跨平台的原因。

    高低位只有汇编和C才可能去考虑,更高一层的语言有着更加抽象的封装。

    2.3 jvm 运行时数据区组成?

    程序计数器、虚拟机栈、本地方法栈、堆、方法区、

    温馨提示:有的区域随着虚拟机进程的启动而存在;有的区域依赖用户进程的启动和结束而创建和销毁。

    2.4 队列和栈区别联系?

    (1).队列和栈均被用来预存储数据的;

    (2).队列–先进先出检索元素,但Deque 接口允许从两端检索元素;

    (3).栈 – 先进后出检索元素;

    2.5 说一下类加载的执行过程?

    第一步:加载—查找路径找到相应的 class 文件导入;

    第二步:检查—检查加载的 class 文件的正确性;

    第三步:准备—给类中的静态变量分配内存空间;

    第四步:解析—虚拟机将常量池中的符号引用替换成直接引用;

      符号引用:一个标示;直接引用:直接指向内存中的地址;

    第五步:初始化—对静态变量和静态代码块执行初始化工作;

    3.java面向对象内存管理

    (1).堆:

    用于存储数组和对象

    (1).存储new出来的对象,包括实例变量(属性);

    (2).实例变量的生命周期:创建时存储在堆中,对象被回收时一并被收回;

    (3).垃圾:没有任何引用所指向的对象,垃圾回收器(Gc)不定时到内存中去清扫垃圾,Gc的回收过程是透明的,不一定发现垃圾就立刻回收可以调用System.gc()建议虚拟机尽快调度Gc来回收垃圾

    (4).内存泄漏:不再使用的内存还没有被及时的回收

    (5).建议:若对象不再使用时应及时将其引用设置为null

    (2).栈:

    (1).存储正在调用的方法中的所有局部变量(函数中定义的变量,方法上的参数,语句中的变量)

    (2).局部变量的生命周期:方法调用完成之后

    (3).调用方法时会为该方法在栈中分配一块对应的栈帧,栈帧中包含方法的局部变量(包括参数),当方法调用结束时,栈帧被清除,局部变量一并被清除

    (4).基本类型放栈里存数值,引用类型放栈里存地址

    (3).方法区:

    (1).存储.class字节码文件(包括方法,静态变量),

    温馨提示:static final常量在编译时被直接替换成具体值,效率高。

    (2).方法只有一份,通过this来区分具体的访问对象

    (4).堆栈的区别

    (1).栈内存存储的是局部变量;堆内存存储的是实体;

    (2).栈内存的更新速度要快于堆内存,因为局部变量的生命周期很短;

    (3).栈内存存放的变量生命周期一旦结束就会被释放;堆内存存放的实体会被垃圾回收机制不定时回收。

    4.javac命令和java命令区别联系

    (1).要知道java是分两部分的:一个是编译,一个是运行。

    (2).javac:负责的是编译的部分,当执行javac时,会启动java的编译器程序。对指定扩展名的.java文件进行编译。生成了jvm可以识别的字节码文件。也就是class文件,也就是java的运行程序。

    (3).java:负责运行的部分.会启动jvm.加载运行时所需的类库,并对class文件进行执行.

    (4).一个文件要被执行,必须要有一个执行的起始点,这个起始点就是main函数.

    5.为什么使用变量?

      变量详细参考

    (1).概念:内存中的一个存储空间,用于存储常量数据。当数据不确定时就定义为变量。

    (2).作用:方便于运算。因为有些数据不确定。所以确定该数据的名词和存储空间。

    (3).特点:变量空间可以重复使用

    (4).变量的作用域:从变量定义的位置开始,到该变量所在大括号结束;

    (5).生命周期:变量从定义的位置开始就在内存中活了;到达它所在的作用域的时候就在内存中消失;

    (6).变量空间的开辟要素:数据类型、变量名称、变量的初始化值。

    5.1 数据类型

    (1).基本数据类型:byte、short、int、long、float、double、char、boolean

    (2).引用数据类型: 数组、类、接口。

    (3).级别从低到高为:byte,char,short(这三个平级)–>int–>float–>long–>double

    (4).自动类型转换:从低级别到高级别,系统自动转的;

    (5).强制类型转换:把一个高级别的数赋给一个比该数的级别低的变量;

    6 java中IO流分为几种?

    (1).字节流

    FileOutputStream和FileInputStream:

       低级流,字节流读写数据会在文件中顺序读写,不可插入某条数据,当有true时,会在文件末尾追加读写,无true时,覆盖读写

    BufferedOutputStream和BufferedInputStream:

       缓冲流(高级流),基于字节流,操作低级流

    ObjectOutputStream和ObjectInputStream:

       对象流(高级流),基于字节流,对象的序列化与反序列化

    (2).字符流

    Reader和Writer:

       所有字符流的父类,底层对字节流操作,读写单元:字符,将字节与字符的转换工作交给了字符流来完成。

    OutputStreamWriter和InputStreamReader:

       字符输出输入流,转换流,字节流与字符流互转

    BufferedWriter和BufferedReader:

       缓冲字符流,可以按行读写字符串

    printwriter具有自动行刷新的缓冲字符输出流,创建pw时,一定会在内部创建bufferwriter作为缓冲功能的叠加,只有调用pw.println()才能自动行刷新。

    BufferReader:缓冲字符输入流,按行读取字符串,它提供了按行读取的方法,readline()连续读取若干个字符,直到读取到换行符为止,并将换行符之间读取的字符以一个字符串返回,若返回null,则表示读取到末尾,该字符串不包含最后的换行符。

    7.运算符号:

    (1).算术运算符。

     + - * / %
    
    %:任何整数模2不是0就是1,所以只要改变被模数就可以实现开关运算。 +:连接符    ++,--

    (2).赋值运算符。

    = += -= *= /= %=

    (3).比较运算符。

    运算完的结果,要么是true,要么是false。

    (4).逻辑运算符。

    &(并且)        有false则false    
    
    |(或者)        有true则true    ,两边false结果是false
    
    !(非)         非false则true,非true则false    
    
    ^(异或)        相同为false,不同为true。    
    
    &&(短路与)        若&&左边表达式或者值为false则右边不进行计算        有false则false,  
    
    ||(短路或)        若||左边表达式或者值为true则右边不进行计算        有true则true,    

    (5).位运算符:用于操作二进制位的运算符。

    A & 按位与 对应的两个二进位均为1时,结果位才为1,否则为0

     9&5=1
    
     00001001     (9的二进制补码)
    &00000101     (5的二进制补码)
     00000001     (1的二进制补码)

    | 按位或 只要对应的二个二进位有一个为1时,结果位就为1

     9|5=13
    
     00001001
    |00000101
     00001101    (十进制为13)       

    ^ 按位异或 两对应的二进位相异时,结果为1

    9^5=12
    
     00001001
    ^00000101 
     00001100    (十进制为12)

    ~ 取反

    ~9
    
    ~0000000000001001
     1111111111110110

    << 左移,相当与*2 <<右边的数指定移动的位数,高位丢弃,低位补0

     a<<4
    
    a=00000011(十进制3),左移4位后
      00110000(十进制48)

    .>> 右移,正数高位补0,负数由计算机决定 >>右边的数指定移动的位数

    a=15,        a>>2
    
    000001111  右移2位
     00000011  (十进制3)

    8.循环语句解析

    8.1 判断固定个数的值时,可用if,也可用switch

      建议使用switch,效率相对较高

    switch(变量){
        case:执行语句;break;
        ... 
        default:执行语句
        }

    (1):break是可以省略的,如果省略了就一直执行到遇到break为止;

    (2):switch 后面变量应该是byte,char,short,int四种类型中的一种;

    (3):default可写在switch结构中的任意位置;若将default语句放在第一行,不管expression与case中的value是否匹配,程序会从default开始执行直到第一个break出现。

    (4).break语句单独存在时,下面不要定义其他语句,由于执行不到,编译会失败。

    8.2 当判断数据范围,获取判断运行结果boolean类型时,用if

    8.3 当某些语句需要执行很多次时,使用循环结构,

    while和for可进行互换

      区别:若需要定义变量控制循环次数,建议使用for。因为for循环完毕,变量在内存中释放。

    9.数组

    (1).概念:用于存储同一类型数据的一个容器。

    (2).作用:可以对容器中的数据进行编号,从0开始;数组用于封装数据,就是一个具体的实体

    10.成员变量和局部变量的区别:

    10.1 成员变量:

    (1).定义在类中,方法外,

    (2).由系统设定默认值,可以不显示初始化。

    (3).所在类被实例化后存在堆中,对象被回收时,成员变量失效。

    10.2 局部变量:

    (1).定义在方法中

    (2).没有默认值,必须自行设定初始值,

    (3).方法被调用时,存在栈中,方法调用结束后,从栈中清除。

    11.面向对象相关:

    11.1 面向对象的特点

    (1).将复杂的事情简单化。

    (2).面向对象将以前的过程中的执行者,变成了指挥者。

    (3).面向对象这种思想是符合现在人们思考习惯的一种思想。

    11.2 重写遵循的 “两同两小一大” 原则

    (1).两同:方法名相同;参数列表相同

    (2).两小:子类返回值类型小于或等于父类的;子类抛出的异常小于或等于父类

    (3).一大:子类的访问权限大于父类的访问权限

    12.面向对象的特征

    (1).封装:把属性私有化封装在一个类里面,类中的属性通常被私有化,并对外提供公共的访问方法(get,set)

    温馨提示:
    属性用于存储数据,直接被访问,容易出现安全隐患。

    (2).继承:子类继承父类,从而继承父类的方法和属性

    (3).抽象:比如一个英雄类,抽象出name,hp这些属性,使得开发过程中更加易于理解

    (4).多态:多态分操作符的多态和类的多态。类的多态指父类引用指向子类对象,并且有继承,有重写。

    温馨提示:子类能继承父类的构造方法吗?不能,super调用的,非继承的

    13.List、Set、Map 之间的区别是什么?

    14.HashMap 和 Hashtable 有什么区别?

    (1).hashMap去掉了HashTable 的contains方法,加上containsValue()和containsKey()方法。

    (2).hashTable同步的,而HashMap是非同步的,效率上比hashTable要高。

    (3).hashMap允许空键值,而hashTable不允许。

    14.1 HashMap、Hashtable和CurrentHashMap底层技术实现比较?

    (1).HashMap线程不安全原因:(并发情况下,HashMap操作会引起死循环,导致CPU占有量达100%),多线程会导致HashMap的Entry链表会形成环形数据结构,查找时陷入死循环。

    (2).HashTable线程安全的原因:使用synchronize来保证线程安全,当有一个线程拥有锁时,其他线程进入阻塞或者轮询状态,使得效率越来越低,因为所有线程竞争同一把锁。

    (3).CurrentHashMap:线程安全且高效的一种容器,采用锁分段技术提高并发访问率.容器中有多把锁,不同锁锁定不同位置,线程间就不会存在锁的竞争,将数据一段一段的存储,每一段都配一把锁,当一个线程占用其中一个数据段时,其他段的数据也能被其他线程访问.

    15.如何决定使用 HashMap 还是 TreeMap?

    (1).对于在Map中插入、删除和定位元素这类操作,HashMap是最好的选择.

    (2).对一个有序的key集合进行遍历,TreeMap是更好的选择.

    (3).基于collection大小,也许向HashMap中添加元素会更快.

    (4).将map换为TreeMap进行有序key的遍历.

    16.HashMap 的实现原理?

    (1).HashMap是基于哈希表的Map接口的非同步实现。

    (2).允许使用null值和null键。无序。

    (3).HashMap是 数组 和 链表 的结合体(链表散列结构)。

    (4).hashmap添加元素原理:

    第一步:当put元素时,先根据key的hashcode重新计算hash值,根据hash值得到该元素在数组中的位置(下标).

    第二步:若数组在该位置上已经存放了其他元素,则该位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放入链尾.

    第三步:若数组中该位置没有元素,将此元素放到数组的该位置上。

    第四步:Jdk 1.8中对HashMap的实现做了优化,当链表中的节点数据超过八个之后,该链表会转为红黑树来提高查询效率。

    17.HashSet 的实现原理?

    (1).HashSet底层由HashMap实现

    (2).HashSet的值存放于HashMap的key上

    (3).HashSet的value统一为相同的固定值

    18.如何实现数组和 List 之间的转换?

    (1).List转换成为数组:调用ArrayList的toArray方法。

    (2).数组转换成为List:调用Arrays的asList方法。

    19.Array 和 ArrayList 有何区别?

    (1).Array可以容纳基本类型和对象,而ArrayList只能容纳对象。

    (2).Array是指定大小后不可变的,而ArrayList大小是可变的。

    (3).Array没有提供ArrayList那么多功能,比如addAll、removeAll和iterator等

    20. Iterator 和 ListIterator 有什么区别?

    (1).Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。

    (2).Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。

    (3).ListIterator实现了Iterator接口,添加了新功能,如:增加元素,替换元素,获取前一个和后一个元素的索引。

    21.多线程学习

    多线程详细参考

    22.runnable 和 callable 有什么区别?

    (1).Runnable接口中的run()方法的返回值是void,它仅仅去执行run()方法中的代码;

    (2).Callable接口中的call()方法是有返回值的,是一个泛型,和Future、FutureTask配合可以用来获取异步执行的结果。

    23. sleep() 和 wait() 有什么区别?

    23.1 sleep()方法

    (1).线程类(Thread)的静态方法

    (2).让调用线程进入睡眠状态,让出执行机会给其他线程,等到休眠时间结束后,线程进入就绪状态和其他线程一起竞争cpu的执行时间。

    (3).对象的机锁没有被释放

    温馨提示:

    当一个synchronized块中调用了sleep(),线程虽然进入休眠,但对象的机锁没有被释放,其他线程依然无法访问这个对象。

    (由于sleep() 是static静态方法,它不能改变对象的机锁)

    23.2 wait()方法

    (1).wait()是Object类的方法

    (2).当一个线程执行到wait方法时,它就进入到一个和该对象相关的等待池,同时释放对象的机锁,使得其他线程能够访问,可以通过notify,notifyAll方法来唤醒等待的线程.

    23.3 互斥锁和同步锁

    (1).互斥锁:synchronized 称为互斥锁,多段代码使用synchronized修饰,当有线程访问这些代码时,代码间就是互斥关系(监视器对象相同)。

    (2).同步锁:多个线程看到同一段代码,该代码用synchronized修饰,则就形成同步锁(同步监视器对象相同)

    24. notify()和 notifyAll()有什么区别?

    (1).若线程调用了对象的 wait()方法,线程便处于该对象的等待池中,等待池中的线程不会竞争该对象的锁。

    (2).调用notify()后仅一个线程会由等待池进入锁池,

    (3).notifyAll会将该对象等待池内的所有线程移动到锁池中,

    (4).只有锁池中的线程才去竞争该对象锁,

    (5).优先级高的线程竞争到对象锁的概率大,

    (6).某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用 wait()方法,它才会重新回到等待池中。

    (7).竞争到对象锁的线程继续往下执行,直到执行完 synchronized 代码块,释放该对象锁,这时锁池中的线程会继续竞争该对象锁.

    25.线程的 run()和 start()有什么区别?

    (1).方法run()称为线程体,即线程的执行内容,Run()运行结束,线程终止,CPU再调度其它线程

    (2).start()启动线程,线程就处于就绪状态,获取到cpu后,调用Thread类的方法run()来完成运行状态。

    (3).若直接调用run(),相当于是调用了一个普通函数,并没有线程的特征。

    26.比较Executor和new Thread()创建线程的优劣?

    (1).new Thread的弊端如下:

    a. 每次new Thread新建对象性能差。

    b. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机

    c. 缺乏更多功能,如定时执行、定期执行、线程中断。

    (2).对比new Thread,Executor提供的四种线程池的优点:

    a. 重用存在的线程,减少对象创建、消亡的开销,性能佳。

    b. 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。

    c. 提供定时执行、定期执行、单线程、并发数控制等功能。

    27.创建线程池有哪几种方式?

    ExecutorService fixedPool = Executors.newFixedThreadPool(2);
    
    ExecutorService scheduledPool = Executors.newScheduledThreadPool(2);
    
    ExecutorService cachedPool = Executors.newCachedThreadPool();
    
    ExecutorService singlePool = Executors.newSingleThreadExecutor();

    (1). newFixedThreadPool(int nThreads)

    固定长度的线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,线程规模将不再变化,当线程发生未预期的错误而结束时,线程池会补充一个新的线程。

    (2). newScheduledThreadPool(int corePoolSize)

    固定长度的线程池,以延迟或定时的方式来执行任务,类似于Timer。

    (3). newCachedThreadPool()

    可缓存的线程池,当线程池规模超过了处理需求时,自动回收空闲线程;

    当需求增加时,自动添加新线程,线程池的规模不存在任何限制。

    (4). newSingleThreadExecutor()

    单线程的Executor,创建单个工作线程来执行任务,若该线程异常结束,会创建一个新线程来替代,

    特点:确保依照任务在队列中的顺序来串行执行。

    28.线程池中 submit()和 execute()方法有什么区别?

    (1).Executor 中的 execute() 方法不返回任何结果,

    (2).ExecutorService 中的 submit()方法可以通过一个 Future 对象返回运算结果,调用 shutDown() 方法终止线程池.

    (3).execute()方法接收Runnable接口的对象,submit()方法接收Runnable和Callable接口的对象

    (4).submit方便Exception处理

    29.在 java 程序中怎么保证多线程的运行安全?

    (1).原子性:提供互斥访问,同一时刻只能有一个线程对数据进行操作,(atomic,synchronized);

    (2).可见性:一个线程对主内存的修改可以及时地被其他线程看到,(synchronized,volatile);

    (3).有序性:一个线程观察其他线程中的指令执行顺序,由于指令重排序,该观察结果一般杂乱无序,(happens-before原则)。

    30.什么是死锁?

    (1).死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。

    (2).永远在互相等待的进程称为死锁进程。

    (3).操作系统层面的一个错误

    31.如何防止死锁?

    死锁的四个必要条件

    (1).互斥条件:进程对所分配到的资源不允许其他进程进行访问,若其他进程访问该资源,只能等待,直至占有该资源的进程使用完成后释放该资源

    (2).请求和保持条件:进程获得一定的资源之后,又对其他资源发出请求,但是该资源可能被其他进程占有,此时请求阻塞,但又对自己获得的资源保持不放

    (3).不可剥夺条件:进程已获得的资源,在未完成使用之前,不可被剥夺,只能在使用完后自己释放

    (4).环路等待条件:是指进程发生死锁后,若干进程之间形成一种头尾相接的循环等待资源关系

    若系统发生死锁,上述四个条件必然成立,上述条件之一不满足,就不会发生死锁。

    32.synchronized 底层实现原理?

    synchronized可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时它还可以保证共享变量的内存可见性。

    33.synchronized 和 volatile 的区别是什么?

    33.1 volatile

    (1).volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取。

    (2).volatile仅使用在变量级别;

    (3).volatile仅实现变量的修改可见性,不能保证原子性;

    (4).volatile不会造成线程的阻塞

    (5).volatile标记的变量不会被编译器优化

    33.2 synchronized

    (1).synchronized是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。

    (2).synchronized可以使用在变量、方法、和类级别的。

    (3).synchronized可以保证变量的修改可见性和原子性。

    (4).synchronized可能会造成线程的阻塞。

    (5).synchronized标记的变量可以被编译器优化。

    34.synchronized 和 Lock 有什么区别?

    34.1 synchronized

    (1).synchronized是java内置关键字;

    (2).synchronized无法判断是否获取锁的状态;

    (3).synchronized会自动释放锁( 线程执行完同步代码会释放锁;线程执行过程中发生异常会释放锁);

    (4).synchronized关键字线程1和线程2,若线程1获得锁,线程2线程等待;若线程1阻塞,线程2会一直等待下去

    (5).synchronized的锁可重入、不可中断、非公平,

    (6).synchronized锁适合代码少量的同步问题;

    34.2 Lock

    (1).在jvm层面,Lock是个java类;

    (2).Lock可以判断是否获取到锁;

    (3).Lock需在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁;

    (4).Lock锁就不一定会等待下去,如果尝试获取不到锁,线程不用一直等待就结束了;

    (5).Lock锁可重入、可判断、可公平(两者皆可);

    (6).Lock锁适合大量同步的代码的同步问题;

    35.什么是java反射机制?

    代码参考

    (1).在运行时判断任意一个对象所属的类。

    (2).在运行时构造任意一个类的对象。

    (3).在运行时判断任意一个类所具有的成员变量和方法。

    (4).在运行时调用任意一个对象的方法。

    36.什么是 java 序列化?什么情况下需要序列化?

    (1).序列化:保存内存中的各种对象的状态,并且可以把保存的对象状态再读出来。

    (2).Java提供一种最好保存对象状态的机制–序列化。

    (3).什么情况下需要序列化:

      a)把内存中的对象状态保存到一个文件中或者数据库;

      b)用套接字在网络上传送对象的时候;(socket 套接字)

      c)通过RMI传输对象的时候;

    37.动态代理是什么?有哪些应用?

    (1).动态代理:

    当给类的某个接口方法,加一些额外的处理(日志,事务)等.
    可以给这个类创建一个代理,即创建一个新的类,包含原来类方法的功能,而且在原来的基础上添加额外处理的新功能。代理类并不是定义好的,是动态生成的。

    动态代理作用:解耦,灵活,扩展性强。

    (2).动态代理的应用:SpringAOP,加事务,加权限,加日志.

    38. 如何实现对象克隆?

    (1).实现Cloneable接口并重写Object类中的clone()方法;

    (2).实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆;

    上述两种方案比较:

    实现Serializable接口: 通过泛型限定,编译期检查克隆的对象是否支持序列化,不是在运行时抛出异常,这种方案优于Object类的clone方法克隆对象。

    39. 深拷贝和浅拷贝区别是什么?

    (1).浅拷贝—复制对象的引用地址,两个对象指向同一个内存地址,若修改其中任意的值,另一个值都会随之变化;

    (2).深拷贝—将对象及值复制过来,两个对象修改其中任意的值另一个值不会改变;

    40. throw 和 throws 的区别?

    (1).throws是用来声明一个方法可能抛出的所有异常信息,throws是将异常声明但是不处理,而是将异常往上传,谁调用就交给谁处理。

    (2).throw则是指抛出的一个具体的异常类型

    41. final、finally、finalize 有什么区别?

    (1).final可以修饰类、变量、方法,修饰类表示该类不能被继承;修饰方法表示该方法不能被重写;修饰变量表示该变量是一个常量不能被重新赋值;

    (2).finally一般作用在try-catch代码块中,处理异常时,将一定执行的代码放finally代码块中,不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。

    (3).finalize是一个方法,当System.gc()时,垃圾回收器会调用finalize(),回收垃圾。

    42.try-catch-finally 中哪个部分可以省略?

    (1).catch 可以省略

    (2).原因:

      编译器硬性规定:普通异常必须用catch显示声明以便进一步处理。

      运行时异常在编译时没有规定,故catch可以省略

    (3).各组件作用:

      (a).try只适合处理运行时异常

      (b).try+catch适合处理运行时异常+普通异常

      (c).finally不管有无捕获异常,都进行的“扫尾”处理。

      (d).代码加上try,意味着显示承诺编译器,对这段代码可能抛出的异常进行捕获而非向上抛出处理。

    (4).若catch 中 return,finally 执行吗?

      会执行,try中的return语句先执行但并没有立即返回执行结果,等到finally执行结束后,才返回return语句的处理结果。

    (5).两种情况下不会执行finally块

      第一种:当try代码块中有System.exit(0)时,(System.exit(0)终止Java虚拟机JVM),finally语句就不会被执行到。

      第二种:try语句还没有被执行到,程序停止了

    43.http 响应码 301 和 302 代表的是什么?

    301(永久性转移),302(暂时性转移) 是HTTP状态的编码,代表着某个URL发生了转移;

    44.forward 和 redirect 的区别?

    (1).Forward,发送一次HTTP请求,在请求对象request中,保存的对象对于每个信息资源是共享的(Servlet、HTML、JSP或其它信息资源)

    (2).Redirect,发送两次HTTP请求,服务器端在响应第一次请求的时候,让浏览器再向另外一个URL发出请求,从而达到转发的目的。

    例子:
    
        Forward 相当于:“A找B借钱,B说没有,B去找C借,借到借不到都会把消息传递给A”;
    
        Redirect 相当于:“A找B借钱,B说没有,让A去找C借”。

    45. 简述 tcp 和 udp的区别?

    45.1 tcp简述:

    (1).TCP面向连接(如打电话要先拨号建立连接);

    (2).TCP提供可靠的服务,传送的数据 (无差错,不丢失,不重复,且按序到达);

    (3).Tcp通过 校验和,重传控制,序号标识,滑动窗口、确认应答实现可靠传输;丢包时重发控制;对次序乱掉的分包进行顺序控制;

    (4).每一条TCP连接只能是点到点的;

    (5).TCP对系统资源要求较多;

    45.2 udp简述:

    (1).UDP是无连接的,发送数据前不需要建立连接;

    (2).UDP尽最大努力交付,但不保证可靠交付;

    (3).UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信;

    (4).UDP支持一对一,一对多,多对一和多对多的交互通信;

    (5).UDP对系统资源要求较少;

    45.3 四次挥手:

    (1).(client,server都可第一挥手),client发送第一次挥手后,就不能向服务器发送数据了。

    (2).server回复消息给client,同意关闭请求,但可以发送数据给client,此次挥手告诉client,我收到了关闭请求。

    (3).server向client请求关闭连接,我这边也可以关闭请求了,此时server就不能再向 client发送数据了

    (4).client接收到server请求关闭时,向server发送ack报文,当server收到client发送的ack报文时,server关闭连接,client等待2MSL(报文存活时间)后依然没有收到回复,则证明server端已正常关闭,此时,client关闭连接。

    46.1 tcp 为什么要三次握手,两次不行吗?

    (1).为了实现可靠数据传输,TCP 协议的通信双方, 都必须维护一个序列号, 以标识发送出去的数据包中, 哪些是成功被对方收到的。

    (2).三次握手的过程—通信双方相互告知序列号起始值,并确认对方已经收到了序列号起始值的必经步骤。

    (3).如果只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认。

    46.2 为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?

    (1).建立连接时:ACK和SYN可以放在一个报文里来发送。

    (2).关闭连接时:被动关闭方可能还需要发送一些数据后,再发送FIN报文表示同意现在可以关闭连接了.

    47.tcp 粘包是怎么产生的?

    47.1 发送方产生粘包

    (1).采用TCP协议传输数据的客户端与服务器经常是保持一个长连接的状态(一次连接发一次数据不存在粘包),双方在连接不断开的情况下,可以一直传输数据;

    (2).当发送的数据包过小时,TCP协议会启用Nagle算法,将较小的数据包在发送缓冲区进行合并发送,即数据发送出来就是粘包状态。

    47.2 接收方产生粘包

    (1).传输层的TCP协议处理是将其放置接收缓冲区,然后由应用层来主动获取;

    (2).程序调用读取数据函数不能及时的把缓冲区中的数据拿出来,而下一个数据又到来并有一部分放入的缓冲区末尾,等读取数据时就是一个粘包。(放数据的速度 > 应用层拿数据速度)

    48.OSI 的七层模型都有哪些?

    (1).应用层:网络服务与最终用户的一个接口。

    (2).表示层:数据的表示、安全、压缩。

    (3).会话层:建立、管理、终止会话。

    (4).传输层:定义传输数据的协议端口号,以及流控和差错校验。

    (5).网络层:进行逻辑地址寻址,实现不同网络之间的路径选择。

    (6).数据链路层:建立逻辑连接、进行硬件地址寻址、差错校验等功能。

    (7).物理层:建立、维护、断开物理连接

    49.get 和 post 请求有哪些区别?

    (1).GET在浏览器回退时是无害的,而POST会再次提交请求。

    (2).GET产生的URL地址可以被记录,而POST不可以。

    (3).GET请求会被浏览器主动cache,而POST不会,除非手动设置。

    (4).GET请求只能进行url编码,而POST支持多种编码方式。

    (5).GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。

    (6).GET请求在URL中传送的参数是有长度限制的,而POST么有。

    (7).参数的数据类型,GET只接受ASCII字符,而POST没有限制。

    (8).GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。

    (9).GET参数通过URL传递,POST放在Request body中

    50.设计模式

    设计模式参考一

    设计模式参考二

    51.spring 常用的注入方式有哪些?

    构造方法注入、setter注入、基于注解的注入;

    spring容器中的Bean本身不具备线程安全的特性,

    52. spring 事务实现方式有哪些?

    (1).编程式事务管理:代码中调用beginTransaction()、commit()、rollback()等事务管理方法,

    (2).声明式事务管理: @Transactional

    53. spring 的事务隔离?

    (1).概念:事务隔离级别指的是一个事务对数据的修改与另一个并行的事务的隔离程度

    (2).若没有进行事务隔离,产生的危害?

    (a).脏读:一个事务读到另一个事务未提交的更新数据。

    (b).幻读:第一个事务修改表A中的“全部数据行”,第二个事务插入“一行新数据”到表A中,两个事务同时进行。此时,操作第一个事务的用户发现表中还存在没有修改的数据行,就像发生了幻觉一样。

    (c).不可重复读:同一个事务中先后执行两条一模一样的select语句,在此期间事务中没有执行过任何DDL语句,但先后得到的结果不一致,即不可重复读。

    54.spring mvc 运行流程?

    流程描述:

    (1).用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServlet捕获;

    (2).DispatcherServlet 对请求URL进行解析,调用HandlerMapping匹配对应HandlerAdapter;

    (3).Handler执行完成后,向dispatcherServlet 返回一个ModelAndView对象;

    (4).根据返回的ModelAndView,选择合适的ViewResolver;

    (5).ViewResolver 结合Model和View,来渲染视图并返回给客户端;

    55.spring cloud 核心组件有哪些?

    spingcloud 内容参考

    (1).服务发现——Netflix Eureka

    由两个组件组成:Eureka服务器和Eureka客户端。Eureka服务器用作服务注册服务器;Eureka客户端是一个java客户端,用来简化与服务器的交互、作为轮询负载均衡器,并提供服务的故障切换支持。Netflix在其生产环境中使用的是另外的客户端,它提供基于流量、资源利用率以及出错状态的加权负载均衡。

    (2).客服端负载均衡——Netflix Ribbon

    Ribbon,主要提供客户侧的软件负载均衡算法。Ribbon客户端组件提供一系列完善的配置选项,比如连接超时、重试、重试算法等。Ribbon内置可插拔、可定制的负载均衡组件。

    (3).断路器——Netflix Hystrix

    断路器可以防止一个应用程序多次试图执行一个操作,即很可能失败,允许它继续而不等待故障恢复或者浪费 CPU 周期,而它确定该故障是持久的。断路器模式也使应用程序能够检测故障是否已经解决。如果问题似乎已经得到纠正,应用程序可以尝试调用操作。

    (4).服务网关——Netflix Zuul

    类似nginx,反向代理的功能,不过netflix自己增加了一些配合其他组件的特性。

    (5).分布式配置——Spring Cloud Config

    这个还是静态的,得配合Spring Cloud Bus实现动态的配置更新。

    56. mybatis中 #{}和 ${}的区别是什么?

    (1).#{}是预编译处理,Mybatis在处理#̲{}时,会把${}替换成变量的值;

    (2).使用#{}可以有效的防止SQL注入,提高系统安全性。

    57.mybatis 逻辑分页和物理分页的区别是什么?

    (1).物理分页速度上并不一定快于逻辑分页,逻辑分页速度上也并不一定快于物理分页。

    (2).物理分页总是优于逻辑分页:没有必要将数据库端的压力加到应用端来,就算速度上存在优势,然而其它性能上的优点足以弥补这个缺点。

    58.mybatis 是否支持延迟加载?延迟加载的原理是什么?

    (1).Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的是一对一,collection指的就是一对多查询。

    (2).在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。

    (3).延迟加载的基本原理:使用cglib创建目标对象的代理对象,当调用目标方法时,首先进入拦截器方法,

    比如:调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,于是单独发送事先保存好的查询关联B对象的sql,把B查询上来,再调用a.setB(b),那么a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。

    (4).Mybatis,Hibernate等数据查询框架 支持延迟加载的原理是一样的。

    59.mybatis 和 hibernate 的区别有哪些?

    (1).Mybatis和hibernate不同,它不完全是一个ORM框架,MyBatis需要编写Sql语句。

    (2).优点:Mybatis直接编写原生态sql,可以严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发:(需求变化频繁,一旦需求变化,要求迅速输出成果)

    (3).缺点:mybatis无法做到数据库无关性,若需要支持多种数据库软件,则需自定义多套sql映射文件,工作量大。

    (3).Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件,如果用hibernate开发可以节省很多代码,提高效率。

    60.mybatis 有哪些执行器(Executor)?

    (1).SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。

    (2).ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map内,供下一次使用。简言之,就是重复使用Statement对象。

    (3).BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。

    61.数据库

    数据库详细资料

    62.rabbitmq 的使用场景有哪些?

    (1).跨系统的异步通信:打电话(同步)以外,发短信,发电子邮件(异步)的通讯方式,所有需要异步交互的地方都可以使用消息队列。

    (2).多个应用之间的耦合:由于消息是平台无关、语言无关、语义上不需函数调用,因此更适合作为多个应用之间的松耦合的接口。基于消息队列的耦合,不需要发送方和接收方同时在线。文件传输,共享数据库,消息队列,远程过程调用都可以作为集成的方法。

    (3).应用内的同步变异步:由于同步通常意味着阻塞,而大量线程的阻塞会降低计算机的性能。

    比如订单处理,由前端应用将订单信息放到队列,后端应用从队列里依次获得消息处理,高峰时大量订单可以积压在队列里慢慢处理掉。

    (4).消息驱动的架构:系统分解为消息队列,消息生产者和消息消费者;前一个阶段处理的结果放入队列,后一个阶段从队列中获取消息继续处理。

    (5).灵活的耦合方式:如发布订阅,比如可以指定路由规则。

    (6).跨局域网,跨城市的通讯: 比如北京机房与广州机房的应用程序的通信。

    63.

    文章标题:java基础知识

    发布时间:2020-04-20, 11:10:26

    最后更新:2020-04-20, 11:10:26