前言

java研发工程师实习,,HR面试实习生更多的注重基础,一面一般是面试java相关基础,二面会涉及到项目,三面就是对公司,自己的职业规划方面的考量。一般是三面,大厂实习有四面五面,java学完了,感觉掌握了很多,也感觉问到问题又不能很好的回答出来,这就需要自己去整理知识点,系统的复习。本文整理的是HR常问问题以及我自己不能够很完整答出来的问题。希望能帮到大家。
注:需要这部分md文档的可以
微信搜索:松鼠技术站
回复:
java面试基础
也可以直接在本博客看。

文章目录

第一部分:java基础问题

1.java的跨平台原理

Java实现跨平台无非就是JVM起的作用,可以这样想,如果是C/C++的编译方式,一旦换了一个平台,那么我们就需要重新编译一份对应的可执行代码,但是Java则不同,我们编译好了一份Java字节码,换到不同的平台上时,并不需要重新编译,前提是这些平台上都装了相应平台的JVM,JVM不是跨平台的,但是这是Sun公司的工作:为不同平台提供对应的JVM。所以,实现跨平台的根本机制还是JVM

2.java面向对象的特征

有三大特征:

封装、继承、多态

一、封装(类)

1、封装的概念

封装性是面向对象编程的核心思想

指的就是将描述某种实体的数据和基于这些数的操作集合到一起,形成一个封装体

封装的思想保证了类内部数据结构的完整性,使用户无法轻易直接操作类的内部数据,这样降低了对内部数据的影响,提高了程序的安全性和可维护性。

2、封装的好处

  • 只能通过规定方法访问数据
  • 隐藏类数实现细节
  • 方便修改实现
  • 方便加入控制语句

二、继承

1、继承的概念和特点

概念:

继承是Java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。

继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或类从父 类继承方法,使得子类具有父类相同的行为。

特点:

继承鼓励类的重用
继承可以多层继承
一个类只能继承一个父类
父类中private修饰的不能被继承
构造方法不能被继承

三、多态(方法重写、抽象类、接口)

1、多态的概念

生活中的多态:

不同类型的打印机打印效果不同

黑白打印机  黑白纸张

打印机

彩色打印机  彩色纸张

程序中的多态 :父类引用,子类对象

同一种事物,由于条件不同,产生的结果也不同

多态:同一个引用类型,使用不同的实例而执行不同操作

2、使用多态实现思路

编写父类

编写子类,子类重写父类方法

运行时,使用父类的类型,子类的对象

3、实现多态的三个必要条件

  • 继承
  • 重写
  • 父类引用指向子类对象

在Java语言中,多态性主要表现在以下几个方面:

  • 方法重写
  • 抽象类
  • 接口

3.面向过程和面向对象有什么区别

一、编程思想不同

1、面向过程是一种以过程为中心的编程思想。都是以什么正在发生为主要目标进行编程。

2、面向对象语言:是一类以对象作为基本程序结构单位的程序设计语言,指用于描述的设计是以对象为核心,而对象是程序运行时刻的基本成分。

二、特点不同

1、面向过程:就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。

2、面向对象:识认性,系统中的基本构件可识认为一组可识别的离散对象,对象具有唯一的静态类型和多个可能的动态类型,在基本层次关系的不同类***享数据和操作。

三、优势不同

1、面向过程不支持丰富的“面向对象”特性(比如继承、多态),并且不允许混合持久化状态和域逻辑。

2、面向对象语言:在内部被表示为一个指向一组属性的指针。任何对这个对象的操作都会权经过这个指针操作对象的属性和方法

4.java中char占几个字节

Java中,内码(运行内存)的char使用UTF16的方式编码,一个char占用两个字节,但是某些字符需要两个char来表示。所以,一个字符会占用2个或4个字节。

Java中,外码中char使用UTF8的方式编码,一个字符占用1~6个字节。

5.java的自动装箱和拆箱

装箱:将基本类型用它们对应的引用类型包装起来;

拆箱:将包装类型转换为基本数据类型;

装箱就是自动将基本数据类型转换为包装器类型;拆箱就是自动将包装器类型转换为基本数据类型。

当一个基础数据类型与封装类进行==、+、-、*、/运算时,会将封装类进行拆箱,对基础数据类型进行运算。

1、需要知道什么时候会引发装箱和拆箱
2、装箱操作会创建对象,频繁的装箱操作会消耗许多内存,影响性能,所以可以避免装箱的时候应该尽量避免。

3、equals(Object o) 因为原equals方法中的参数类型是封装类型,所传入的参数类型(a)是原始数据类型,所以会自动对其装箱,反之,会对其进行拆箱

4、当两种不同类型用==比较时,包装器类的需要拆箱, 当同种类型用==比较时,会自动拆箱或者装箱

6.==和equals的区别

== : 它的作用是判断两个对象的地址是不是相等。即判断两个对象是不是同 一个对象。(基本数据类型==比较的是值,引用数据类型==比较的是内存地址)

equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况:

情况 1:类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。

情况 2:类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来两个对象的内容相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。

7.String、StringBuilder、StringBuffer的 区别

这三个类之间的区别主要是在两个方面,即运行速度和线程安全这两方面

首先说运行速度,或者说是执行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer > String

String最慢的原因:

String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的。

Java中对String对象进行的操作实际上是一个不断创建新的对象并且将旧的对象回收的一个过程,所以执行速度很慢。

在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的

如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。

8.java的集合有哪些?

一.List集合:(有序,元素可以重复)

1.ArrayList集合:

1).底层数据结构是数组,查找快,增删慢。

2). 线程不安全,效率高

2.Vector集合:

1) 底层数据结构是数组,查询快,增删慢

2)线程安全,效率低

3.LinkedList集合:

1) 底层数据结构是链表,查询慢,增删快

2)线程不安全,效率高

二、Set集合(元素不可重复,元素唯一)
1.Hashset集合:

1) 底层数据结构是哈希表,哈希表依赖两个方法hascode ()和equals()方法

2)两个方法的执行顺序:
首先判断hascode()值是否相同
是:继续执行equals()方法,看其返回值
是true:说明元素重复,不添加
是false:就直接添加元素
否:就直接添加到集合

2.Treeset集合:

1)底层数据结构是二叉树

9.ArrayList和LinkList的区别

ArrayList是实现了基于动态数组的数据结构,LinkedList是基于链表结构。
对于随机访问的get和set方法,ArrayList要优于LinkedList,因为LinkedList要移动指针。
对于新增和删除操作add和remove,LinkedList比较占优势,因为ArrayList要移动数据。

10.HashMap和HashTable的区别

1.继承的父类不同

Hashtable继承自Dictionary类,而HashMap继承自AbstractMap类。但二者都实现了Map接口。

2.线程安全不同

Hashtable 中的方法是Synchronize的,而HashMap中的方法在缺省情况下是非Synchronize的。在多线程并发的环境下,可以直接使用Hashtable,不需要自己为它的方法实现同步,但使用HashMap时就必须要自己增加同步处理。

3.是否提供contains方法

HashMap把Hashtable的contains方法去掉了,改成containsValue和containsKey,因为contains方法容易让人引起误解。

Hashtable则保留了contains,containsValue和containsKey三个方法,其中contains和containsValue功能相同。

4.Key和Value是否允许null值

其中key和value都是对象,并且不能包含重复key,但可以包含重复的value。

Hashtable中,key和value都不允许出现null值。但是如果在Hashtable中有类似put(null,null)的操作,编译同样可以通过,因为key和value都是Object类型,但运行时会抛出NullPointerException异常,这是JDK的规范规定的。

HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,可能是 HashMap中没有该键,也可能使该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。

5.两个遍历方式的内部实现上不同

Hashtable、HashMap都使用了 Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式 。

6.hash值不同

哈希值的使用不同,HashTable直接使用对象的hashCode。而HashMap重新计算hash值。

hashCode是jdk根据对象的地址或者字符串或者数字算出来的int类型的数值。

Hashtable计算hash值,直接用key的hashCode(),而HashMap重新计算了key的hash值,Hashtable在求hash值对应的位置索引时,用取模运算,而HashMap在求位置索引时,则用与运算,且这里一般先用hash&0x7FFFFFFF后,再对length取模,&0x7FFFFFFF的目的是为了将负的hash值转化为正值,因为hash值有可能为负数,而&0x7FFFFFFF后,只有符号外改变,而后面的位都不变。

7.内部实现使用的数组初始化和扩容方式不同

HashTable在不指定容量的情况下的默认容量为11,而HashMap为16,Hashtable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂。

​ Hashtable扩容时,将容量变为原来的2倍加1,而HashMap扩容时,将容量变为原来的2倍。

​ Hashtable和HashMap它们两个内部实现方式的数组的初始大小和扩容的方式。HashTable中hash数组默认大小是11,增加的方式是 old*2+1。

11.实现一个拷贝文件的类是用字节流还是字符流

字节流和字符流概念

(1).字节流和字符流都有输入和输出方式

(2).字节输入流和输出流的祖先:InputStream和OutputStream

(3).字符输入流和输出流的祖先:Reader和Writer

(4).以上这些类都是abstract修饰的抽象类,不能直接实例化对象

(5).字节流可以处理所有文件类型的数据(图片,视频,文本·····),字符流只能处理纯文本数据(txt文本文档)

我们拷贝的文件不确定是只包含字符流,有可能有字节流(图片、声音、图像等),为考虑通用性,要使用字节流。

12.java多线程有哪几种实现方式

JAVA多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。

13.是否了解过线程并发库和线程池

jdk1.5后,java.util.current包提供了很多关于线程并发的类
java通过Executor提供的四个静态方法进行创建4种线程池
使用线程池的作用:
1.限制线程的个数,不会导致由于线程过多导致系统运行缓慢或崩溃
2.节约了资源,免去了不停的去创建线程销毁线程的过程

14.JDK和JRE

JDK 它拥有 JRE 所拥有 的一切,还有编译器(javac)和工具(如 javadoc 和 jdb)。它能够创建和编

译程序。

**JRE 是 Java 运行时环境。**它是运行已编译 Java 程序所需的所有内容的集合, 包括 Java 虚拟机(JVM),Java 类库,java 命令和其他的一些基础构件。但 是,它不能用于创建新程序。

如果你只是为了运行一下 Java 程序的话,那么你只需要安装 JRE 就可以了。

如果你需要进行一些 Java 编程方面的工作,那么你就需要安装 JDK 了。

但是,这不是绝对的。有时,即使不打算在计算机上进行任何 Java 开发,仍然需要安装 JDK。例如,如果要使用 JSP 部署 Web 应用程序,那么从技术上讲, 只是在应用程序服务器中运行 Java 程序。那你为什么需要 JDK 呢?因为应用程序服务器会将 JSP 转换为 Java servlet,并且需要使用 JDK 来编译 servlet。

15.java和c++的区别

都是面向对象的语言,都支持封装、继承和多态

Java 不提供指针来直接访问内存,程序内存更加安全

Java 的类是单继承的,C++ 支持多重继承;虽然 Java 的类不可以多继承,但是接口可以多继承。

Java 有自动内存管理机制,不需要程序员手动释放无用内存

16.字符常量和字符串常量的区别

  1. 形式上: 字符常量是单引号引起的一个字符,字符串常量是双引号引起的

若干个字符

  1. 含义上: 字符常量相当于一个<mark>整形值( ASCII 值)</mark>,可以参加表达式运算,字

符串常量代表一个<mark>地址值</mark>(该字符串在内存中存放位置)

  1. 占内存大小:字符常量只占 2 个字节 字符串常量占若干个字节(至少一个

字符结束标志) (注意: char Java 中占两个字节)

17.构造器Constructor 是否可被 override

在讲继承的时候我们就知道父类的私有属性和构造方法并不能被继承,所以

Constructor 也就不能被 override(重写),但是可以 overload(重载),所以

你可以看到一个类中有多个构造函数的情况。

18.重载和重写的区别

重载: 发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序

不同,方法返回值和访问修饰符可以不同,发生在编译时。

重写: 发生在父子类中,方法名、参数列表必须相同,返回值范围小于等于父

类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类;如果父类

方法访问修饰符为 private 则子类就不能重写该方法。

19.在一个静态方法内调用一个非静态成员为什么是非法的

由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非

静态变量,也不可以访问非静态变量成员。

解释:

因为非静态变量对每个对象而言都是不同的,而静态方法又可以直接类名调用不进行实例化,所以不创建对象时非静态变量是空的,即便是调用方法之前有了实例化对象,直接通过类名调用方法依然不知道你要返回哪个对像的属性,因为非静态变量每个对象都是私有的,与众不同。
就比如有一个学生类Student,他有两个属性,静态变量职业,非静态变量姓名。有一个静态方法返回学生的信息,你可以返回身份类型,因为每个Student都是学生,你不可以返回姓名,因为每个学生都有自己的名字,不是共性。

20.在Java中定义一个不做事且没有参数的构造方法的作用

Java 程序在执行子类的构造方法之前,如果没有用 super() 来调用父类特定 的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用 super() 来调用父类 中特定的构造方法,则编译时将发生错误,因为 Java 程序在父类中找不到没 有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。

21.接口和抽象类的区别

参数 抽象类 接口
默认的方法实现 它可以有默认的方法实现 接口完全是抽象的。它根本不存在方法的实现
实现 子类使用extends关键字来继承抽象类。如果子类不 是抽象类的话,它需要提供抽象类中所有声明的方法的实现。 子类使用关键字implements来实现接口。 它需要提供接口中所有声明的方法的实现
构造器 抽象类可以有构造器 接口不能有构造器
与正常Java类的区别 除了你不能实例化抽象类之外,它和普通Java类没有任何区别 接口是完全不同的类型
访问修饰符 抽象方法可以有public、protected和default这些修饰符 接口方法默认修饰符是public。你不可以使用其它修饰符。
main方法 抽象方法可以有main方法并且我们可以运行它 接口没有main方法,因此我们不能运行它。 (java8以后接口可以有default和static方法,所以可以运行main方法)
多继承 抽象方法可以继承一个类和实现多个接口 接口只可以继承一个或多个其它接口
速度 它比接口速度要快 接口是稍微有点慢的,因为它需要时间去寻找在类中实现的方法。
添加新方法 如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。 如果你往接口中添加方法,那么你必须改变实现该接口的类。

22.成员变量和局部变量的区别有哪些

  1. 从语法形式上,看成员变量是属于类的,而局部变量是在方法中定义的 变量或是方法的参数;成员变量可被 public,private,static 等修饰符所修饰,而局部变量不能被访问控制修饰符及 static 所修饰;但是,成员变量和局部变量都能被 final 所修饰;
  2. 从变量在内存中的存储方式来看,成员变量是对象的一部分,而对象存在于堆内存,局部变量存在于栈内存
  3. 从变量在内存中的生存时间上看,成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动消失。
  4. 成员变量如果没有被赋初值,则会自动以类型的默认值而赋值(一种情况例外被 final 修饰的成员变量也必需显式地赋值);而局部变量则不会自动赋值。

23.创建一个对象用什么运算符?对象实体与对象引用有何不同?

new 运算符,new 创建对象实例(对象实例在堆内存中),对象引用指向对象实例(对象引用存放在栈内存中)。一个对象引用可以指向 0 个或 1 个对象 (一根绳子可以不系气球,也可以系一个气球);一个对象可以有 n 个引用指向 它(可以用 n 条绳子系住一个气球)。

<mark>对象实体</mark>:就是类的这时体现,每个对象都是独立的内存。
<mark>引用</mark>就是表示的对象所在内存的位置。其实就是对象的线索。
比如你是对象,能够与你关联的信息都可成为引用,比如你的电话,QQ号。邮箱等等。。。

24.构造方法有哪些特性

  1. 名字与类名相同;
  2. 没有返回值,但不能用 void 声明构造函数;
  3. 生成类的对象时自动执行,无需调用。

25.静态方法和实例方法有何不同

  1. 在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用 静态方法可以无需创建对象
  2. 静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量 和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制。

26.为什么Java中只有值传递

值传递(pass by value)是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

引用传递(pass by reference)是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

在 Java 中,没有引用的概念,Java 中只要定义变量就会开辟一个存储单元。因此,对 Java 语言来说只有值传递,没有引用传递是正确的。

27.java的数据类型和引用类型

Java 中有八种基本数据类型“byte、short、int、long、float、double、char、boolean”
引用类型:new 创建的实体类、对象、及数组

28.基本数据类型、引用类型在内存中的存储方式

基本数据类型:存放在栈内存中。用完就消失。
引用类型:在栈内存中存放引用堆内存的<mark>地址</mark>,在堆内存中存储类、对象、数组等。当没用引用指向堆内存中的类、对象、数组时,由 GC回收机制不定期自动清理。

29.简述线程,程序、进程的基本概念。以及他们之间关系是什么

线程与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。

程序是含有指令和数据的文件,被存储在磁盘或其他的数据存储设备中,也就是说程序是静态的代码。

进程程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。简单来说,一个进程就是一个执行中的程序,它在计算机中一个指令接着一个指令地执 着,同时,每个进程还占有某些系统资源如 CPU 时间,内存空间,文件,输入输出设备的使用权等等。

线程和进程最大的不同 在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。从另一角度来说,进程属于操作系统的范畴,主要是同一段时间内,可以同时执行一个以上的程序,而线程则是在同一程序内几乎同时执行一个以上的程序段。

30.线程有哪些基本状态?

java中,每个线程都需经历新生、就绪、运行、阻塞和死亡五种状态,线程从新生到死亡的状态变化称为来生命周期。
用new运算符和Thread类或其子类建立一个线程对象后,该线程就处于新生状态。
新生—>就绪:通过调用start()方法
就绪—>运行:处于就绪状态的线程一旦得到CPU,就进入运行状态并自动调用自己的run()方法
运行—>阻塞源:处于运行状态的线程百,执行sleep()方法,或等待I/O设备资度源,让出CPU并暂时中止自己运行,进入阻塞状态
阻塞—>就绪:睡眠时间已到,或等待的I/O设备空闲下来,线程便进入就绪状态,重新到就绪队列中等待CPU。当再次获得CPU时,便从原来中止位置开始继续运行。
运行—>死亡:(1)(正常情况下)线程任务完成
(2)(非正常状况)线程被强制性的中止,如通过执行stop()或destroy()方法来终止一个线程

31.关于final 关键字的一些总结

final 关键字主要用在三个地方:变量、方法、类。

  1. 对于一个 final 变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。
  2. 当用 final 修饰一个类时,表明这个类不能被继承。final 类中的所有成员方法都会被隐式地指定为 final 方法。
  3. 使用 final 方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。在早期的 Java 实现版本中,会将final 方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用 带来的任何性能提升(现在的 Java 版本已经不需要使用 final 方法进行这些优化了)。类中所有的 private 方法都隐式地指定为 final。

32.java的异常处理

在 Java 中,所有的异常都有一个共同的祖先 java.lang 包中的 Throwable类**。Throwable: 有两个重要的子类:**Exception(异常)和 Error(错误) ,二者都是 Java 异常处理的重要子类,各自都包含大量子类。

Error(错误):是程序无法处理的错误,表示运行应用程序中较严重问题。

Exception(异常):是程序本身可以处理的异常。Exception 类有一个重要的 子类 RuntimeException。RuntimeException 异常由 Java 虚拟机抛出。

注意:异常和错误的区别:异常能被程序本身可以处理,错误是无法处理。

try 块:用于捕获异常。其后可接零个或多个 catch 块,如果没有 catch

块,则必须跟一个 finally 块。

catch 块:用于处理 try 捕获到的异常。

finally 块:无论是否捕获或处理异常,finally 块里的语句都会被执行。

当在 try 块或 catch 块中遇到 return 语句时,finally 语句块将在方法返回之前被执行。

在以下4 种特殊情况下,finally块不会被执行:

  1. 在 finally 语句块中发生了异常。
  2. 在前面的代码中用了 System.exit()退出程序。
  3. 程序所在的线程死亡。
  4. 关闭 CPU。

33.java的序列化与反序列化

把对象转换为字节序列的过程称为对象的序列化

把字节序列恢复为对象的过程称为对象的反序列化

当两个进程进行远程通信时,可以相互发送各种类型的数据,包括文本,图片,音频,视频等,而这些数据都会以二进制的形式在网络上传送。

当两个java进行进行通信时,要传送对象,怎么传对象,通过序列化与反序列化。

也就是说,发送方需要把对象转换为字节序列,然后在网络上传送,另一方面,接收方需要从字节序列中恢复出java对象。

对象序列化包括如下步骤:

1) 创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;

2) 通过对象输出流的writeObject()方法写对象。

对象反序列化的步骤如下:

1) 创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;

2) 通过对象输入流的readObject()方法读取对象。

34.获取用键盘输入常用的的两种方法

方法 1:通过 Scanner

方法 2:通过 BufferedReader

35.java的反射机制

是指在程序运行时获取已知名称的类或已有对象的相关信息的一种机制。

例如,在使用Strut2框架的开发过程中,我们一般会在struts.xml里去配置Action

比如,加载数据库驱动的,用到的也是反射

36.java的常用设计模式

37. java的锁机制

在java中,解决同步问题,很多时候都会使用到synchronized和Lock,这两者都是在多线程并发时候常使用的锁机制。

synchronized是java中的一个关键字,也就是说是java内置的一个特性。当一个线程访问一个被synchronized修饰的代码块,会自动获取对应的一个锁,并在执行该代码块时,其他线程想访问这个代码块,会一直处于等待状态,自有等该线程释放锁后,其他线程进行资源竞争,竞争获取到锁的线程才能访问该代码块。

38.java多线程和线程池

在java中,如果每个请求到达就创建一个新线程,开销是相当大的。在实际使用中,服务器在创建和销毁线程上花费的时间和消耗的系统资源都相当大,甚至可能要比在处理实际的用户请求的时间和资源要多的多。除了创建和销毁线程的开销之外,活动的线程也需要消耗系统资源。如果在一个jvm里创建太多的线程,可能会使系统由于过度消耗内存或“切换过度”而导致系统资源不足。为了防止资源不足,服务器应用程序需要采取一些办法来限制任何给定时刻处理的请求数目,尽可能减少创建和销毁线程的次数,特别是一些资源耗费比较大的线程的创建和销毁,尽量利用已有对象来进行服务,这就是“池化资源”技术产生的原因。

线程池主要用来解决线程生命周期开销问题和资源不足问题。

线程池的组成部分

一个比较简单的线程池至少应包含线程池管理器、工作线程、任务列队、任务接口等部分。其中线程池管理器的作用是创建、销毁并管理线程池,将工作线程放入线程池中;工作线程是一个可以循环执行任务的线程,在没有任务是进行等待;任务列队的作用是提供一种缓冲机制,将没有处理的任务放在任务列队中;任务接口是每个任务必须实现的接口,主要用来规定任务的入口、任务执行完后的收尾工作、任务的执行状态等,工作线程通过该接口调度任务的执行。

39.Java的泛型

泛型的本质是为了参数化类型在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,

操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。

泛型只在编译阶段有效。

泛型类型在逻辑上看以看成是多个不同的类型,实际上都是相同的基本类型。

第二部分:javaweb基础问题

1.http中get post请求的区别

(1)get是从服务器上获取数据,post是向服务器传送数据。

(1) 在客户端,Get方式在通过URL提交数据,数据在URL中可以看到;POST方式,数据放置在HTML HEADER内提交。(get显式提交)

(2) 对于get方式,服务器端用Request.QueryString获取变量的值,对于post方式,服务器端用Request.Form获取提交的数据。

(2) GET方式提交的数据最多只能有1024字节,而POST则没有此限制。

(3) **安全性问题。**正如在(1)中提到,使用 Get 的时候,参数会显示在地址栏上,而 Post 不会。所以,如果这些数据是中文数据而且是非敏感数据,那么使用 get;如果用户输入的数据不是中文字符而且包含敏感数据,那么还是使用 post为好。

2.servlet

事实上,servlet就是一个Java接口,interface!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TfeBcoY6-1591845760632)(C:\Users\lenovo\Desktop\java面试问题\2_2.jpg)]

所以,提问中说的网络协议、http什么的,servlet根本不管!也管不着!

那servlet是干嘛的?很简单,接口的作用是什么?规范呗!

servlet接口定义的是一套处理网络请求的规范,所有实现servlet的类,都需要实现它那五个方法,其中最主要的是两个生命周期方法 init()和destroy(),还有一个处理请求的service(),也就是说,所有实现servlet接口的类,或者说,所有想要处理网络请求的类,都需要回答这三个问题:

  • 你初始化时要做什么
  • 你销毁时要做什么
  • 你接受到请求时要做什么

这是Java给的一种规范!

servlet是一个规范,那实现了servlet的类,就能处理请求了吗?

答案是,不能。

你可以随便谷歌一个servlet的hello world教程,里面都会让你写一个servlet,相信我,你从来不会在servlet中写什么监听8080端口的代码,servlet不会直接和客户端打交道!

那请求怎么来到servlet呢?答案是servlet容器,比如我们最常用的tomcat,同样,你可以随便谷歌一个servlet的hello world教程,里面肯定会让你把servlet部署到一个容器中,不然你的servlet压根不会起作用。

tomcat才是与客户端直接打交道的家伙,他监听了端口,请求过来后,根据url等信息,确定要将请求交给哪个servlet去处理,然后调用那个servlet的service方法,service方法返回一个response对象,tomcat再把这个response返回给客户端。

3.servlet的生命周期

Servlet运行在Servlet容器中,其生命周期由容器来管理。Servlet的生命周期通过javax.servlet.Servlet接口中的init()、service()和destroy()方法来表示

Servlet的生命周期包含了下面4个阶段:

1.加载和实例化

2.初始化

3.请求处理

4.服务终止

在整个Servlet的生命周期过程中,创建Servlet实例、调用实例的init()和destroy()方法都只进行一次,当初始化完成后,Servlet容器会将该实例保存在内存中,通过调用它的service()方法,为接收到的请求服务

4.请求转发和重定向,Forward与Redirect的区别是什么

转发过程:客户浏 览器发送http请求----》web服务器接受此请求–》调用内部的一个方法在容器内部完成请求处理和转发动作----》将目标资源发送给客户;在这 里,转发的路径必须是同一个web容器下的url,其不能转向到其他的web路径上去,中间传递的是自己的容器内的request。在客户浏览器路径栏显 示的仍然是其第一次访问的路径,也就是说客户是感觉不到服务器做了转发的。转发行为是浏览器只做了一次访问请求。

重定向过程:其实是两次request,第一次,客户端request A,服务器响应,并response回来,告诉浏览器,你应该去B。这个时候IE可以看到地址变了,而且历史的回退按钮也亮了。重定向可以访问自己web应用以外的资源。在重定向的过程中,传输的信息会被丢失。

以下是区别:

  1. 从数据共享上

​ Forward是一个请求的延续,可以共享request的数据

​ Redirect开启一个新的请求,不可以共享request的数据

  1. 从地址栏

​ Forward转发地址栏不发生变化

​ Redirect转发地址栏发生变化

  1. 从运用地方来说
    forward:一般用于用户登陆的时候,根据角色转发到相应的模块.
    redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等
  2. 从效率来说
    forward:高.
    redirect:低.

5.jsp和servlet的相同点和不同点

jsp和servlet的区别和联系:

  1. jsp经编译后就变成了Servlet.(JSP的本质就是Servlet,JVM只能识别java的类,不能识别JSP的代码,Web容器将JSP的代码编译成JVM能够识别的java类)
  2. jsp更擅长表现于页面显示,servlet更擅长于逻辑控制.
  3. Servlet中没有内置对象,Jsp中的内置对象都是必须通过HttpServletRequest对象,HttpServletResponse对象以及HttpServlet对象得到.
    Jsp是Servlet的一种简化,使用Jsp只需要完成程序员需要输出到客户端的内容,Jsp中的Java脚本如何镶嵌到一个类中,由Jsp容器完成。而Servlet则是个完整的Java类,这个类的Service方法用于生成对客户端的响应。
  4. 联系: JSP是Servlet技术的扩展,本质上就是Servlet的简易方式。JSP编译后是“类servlet”。Servlet和JSP最主要的不同点在于,Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp的文件。JSP侧重于视图,Servlet主要用于控制逻辑

6.MVC模式和MVC各部分的实现

mvc模式

M-model 模型 ——javabean 相当于后台

v-view 视图 ——jsp,html 相当于前台

c-controller 控制器 ——servlet 相当于控制页面跳转

最经典的mvc开发模式:jsp+javabean+servlet

model:应用的业务逻辑(如:数据库的操作),通过JavaBean实现
(hibernate、mybatis、ibatis)
view:视图层,用于与用户的交互,主要由jsp页面产生。
(jsp、FreeMarker、tails、taglib、EL、Velocity )
controller:处理过程控制,一般是一个servlet。它可以分派用户的请求并选择恰当的视图以用于显示
同时它也可以解释用户的输入并将它们映射为模型层可执行的操作。
(servlet、struts、spring、action)

7.session和cookie的区别以及应用场景

①Cookie可以存储在浏览器或者本地,Session只能存在服务器
②session 能够存储任意的 java 对象,cookie 只能存储 String 类型的对象
③Session比Cookie更具有安全性(Cookie有安全隐患,通过拦截或本地文件找得到你的cookie后可以进行攻击)
④Session占用服务器性能,Session过多,增加服务器压力
⑤单个Cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个Cookie,Session是没有大小限制和服务器的内存大小有关。

应用场景:

cookie:

(1)判断用户是否登陆过网站,以便下次登录时能够实现自动登录(或者记住密码)。如果我们删除cookie,则每次登录必须从新填写登录的相关信息。

(2)保存上次登录的时间等信息。

(3)保存上次查看的页面

(4)浏览计数

session:Session用于保存每个用户的专用信息,变量的值保存在服务器端,通过SessionID来区分不同的客户。

(1)网上商城中的购物车

(2)保存用户登录信息

(3)将某些数据放入session中,供同一用户的不同页面使用

(4)防止用户非法登录

8.内置对象和四大作用域和页面传值

九大内置对象:

pageContext JSP页面容器
request 请求对象
response 响应对象
session会话
application 全局对象

config配置对象
out 输出对象
page当前JSP页面对象
exception 异常对象

四大作用域:(由小->大)

pageContext 当前页面有效(页面跳转后无效)
request 同一次请求有效(请求转发后有效,重定向后无效)
session 同一次对话有效(同一个浏览器在退出关闭之前都有效)
application 全局有效(整个项目)
共同的方法:
void setAttribute(String name,Object obj);
Object getAttribute(String name);
void removeAttribute(String name);

第三部分:数据库基础问题

1.数据库的分类,和常用数据库

目前关系型数据库主要有MySQL、SQL Server、数蚕数据库、Oracle数据库。
MySQL:免百费产品,中小企业使用度广泛。
SQL Server:微软的商业化产品,微软SQL语句兼容性好,商业化成熟度高。
数蚕数据库:数蚕科技针对中小型企业的数据库,c++接口特性良问好,SQL特性较弱。
Oracle 数据库:商业化程度最高的关系数据库, 优良答的性能和企业扩展能力。
非关系型数据库主要有FastDB、Memcached和Redis等主流内存数据库。一般内应用于缓存等非关键数据存储,其优点是数据查询速度快,对容下层编程接口良好。

2.关系型数据库的三范式

第一范式(1NF):要求数据库表的每一列都是<mark>不可分割</mark>的原子数据项。

第二范式(2NF):在1NF的基础上,非码属性必须<mark>完全依赖</mark>于候选码(在1NF基础上消除非主属性对主码的部分函数依赖)

第三范式(3NF):在2NF基础上,任何非主属性不依赖于其它非主属性(在2NF基础上消除<mark>传递依赖</mark>)

第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关

3.事务的四个特性(ACID)

原子性(Atomicity):操作这些指令时,要么全部执行成功,要么全部不执行。只要其中一个指令执行失败,所有的指令都执行失败,数据进行回滚,回到执行指令前的数据状态。

一致性(Consistency):事务的执行使数据从一个状态转换为另一个状态,但是对于整个数据的完整性保持稳定。

隔离性(Isolation):隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

持久性(Durability):当事务正确完成后,它对于数据的改变是永久性的。

4.mysql数据库的最大连接数

MySQL服务器的最大并发连接数是16384。

5.mysql的分页语句

客户端通过传递start(页码)pageSize(每页显示的条数)两个参数去分页查询数据库表中的数据,那我们知道MySql数据库提供了分页的函数limit m,n

6.触发器的使用场景

而触发器主要是通过事件(增、删、改)进行触发而被执行的。其在表中数据发生变化时自动强制执行。常见的触发器有两种:after(for)、instead of,用于insert、update、delete事件。
after(for) 表示执行代码后,执行触发器
instead of 表示执行代码前,用已经写好的触发器代替你的操作

一、实施复杂的安全性检查

二、数据的确认

三、数据库基于值的审计

四、数据的备份

7.存储过程的优缺点

存储过程是事先经过编译并存储在数据库中的一段SQL语句的集合,调用存储过程可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的。

优点:

1、重复使用:存储过程可以重复使用,从而可以减少数据库开发人员的工作量。

2、减少网络流量:存储过程位于服务器上,调用的时候只需要传递存储过程的名称以及参数就可以了,因此降低了网络传输的数据量。

3、安全性:参数化的存储过程可以防止SQL注入式攻击,而且可以将回Grant、Deny以及Revoke权限应用于存储过程。

缺点:

1、更改比较繁琐:如果更改范围大到需要对输入存储过程的参数进行更改,或者要更改由其返回的数据,则仍需要更新程序集中的代码以添加参数、更新 GetValue() 调用,等等,这时候估计比较繁琐。

2、可移植性差:由于存储过程将应用程序绑定到 SQL Server,因此使用存储过程封装业务逻辑将限制应用程序的可移植性。如果应用程序的可移植性在您的环境中非常重要,则需要将业务逻辑封装在不特定于 RDBMS 的中间层中。

8.jdbc调用存储过程

在JDBC API中提供了调用存储过程的方法,通过CallableStatement对象进行操作。CallableStatement对象位于java.sql包中,它继承于PreparedStatement对象,PreparedStatement对象又继承于Statement对象。CallableStatement对象主要用于执行数据库中定义的存储过程和存储函数

9.对jdbc的理解

它是Java编程语言和广泛的数据库之间独立于数据库的连接标准的Java API,根本上说JDBC是一种规范,它提供的接口,一套完整的,允许便捷式访问底层数据库。可以用JAVA来写不同类型的可执行文件:JAVA应用程序、JAVA Applets、Java Servlet、JSP等,不同的可执行文件都能通过JDBC访问数据库,又兼备存储的优势。

简单说它就是JAVA与数据库的连接的桥梁或者插件,用JAVA代码就能操作数据库的增删改查、存储过程、事务等。

10.jdbc中preparedstatement比statement好处

  1. PreparedStatement可以写动态参数化的查询
  2. PreparedStatement比 Statement 更快
    使用 PreparedStatement最重要的一点好处是它拥有更佳的性能优势,SQL语句会预编译在数据库系统中。
  3. PreparedStatement可以防止SQL注入式攻击
  4. 可读写好

尽管PreparedStatement非常实用,但是它仍有一定的限制:

为了防止SQL注入攻击,PreparedStatement不允许一个占位符(?)有多个值,在执行有IN子句查询的时候这个问题变得棘手起来。

11.数据库连接池的作用

  1. 基本原理:在内部对象池中,维护一定数量的数据库连接,并对外暴露数据库连接的获取和返回方法。

如外部使用者可通过getConnection方法获取数据库连接,使用完毕后再通过releaseConnection方法将连接返回,注意此时的连接并没有关闭,而是由连接池管理器回收,并为下一次使用做好准备。

  1. 作用

    ①资源重用 (连接复用)

​ 由于数据库连接得到重用,避免了频繁创建、释放连接引起的大量性能开销。在减少系统消耗的基础上,增进了系统环境的平稳性(减少内存碎片以级数据库临时进程、线程的数量)

②更快的系统响应速度

​ 数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于池内备用。此时连接池的初始化操作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而缩减了系统整体响应时间。

③新的资源分配手段

​ 对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接的配置,实现数据库连接技术。

④统一的连接管理,避免数据库连接泄露

​ 在较为完备的数据库连接池实现中,可根据预先的连接占用超时设定,强制收回被占用的连接,从而避免了常规数据库连接操作中可能出现的资源泄露

第四部分:框架基础问题

1.什么是框架

框架是一个半成品,已经对基础的代码进行了封装并提供相应的API,开发者在使用框架是直接调用封装好的api可以省去很多代码编写,从而提高工作效率和开发速度。

2.传统MVC模式存在的问题

  1. 所有的servlet和servlet的映射都要配置在web.xml中,如果项目太大,web.xml就太庞大,并且不能实现模块化管理。
  2. servlet的主要功能是接收参数、调用逻辑、跳转页面,比如像其他文字的编码、文件上传功能等也要写在servlet中,不能让servlet功能单一。
  3. 接收参数比较麻烦,不能通过model接收,只能单一接收,接收完后转换封装成model
  4. 跳转页面方式比较单一(转发和重定向),并且当我的页面名称发生改变时,需要修改servlet源码。

3.MVC框架的理解

是为了解决传统mvc模式问题而出现的框架,例如:

struts2

SpringMVC

4.struts2的执行流程(工作原理)

(1) 客户端(Client)向Action发用一个请求(Request)
(2) Container通过web.xml映射请求,并获得控制器(Controller)的名字
(3) 容器(Container)调用控制器(StrutsPrepareAndExecuteFilter或FilterDispatcher)。在Struts2.1以前调用FilterDispatcher,Struts2.1以后调用StrutsPrepareAndExecuteFilter
(4) 控制器(Controller)通过ActionMapper获得Action的信息
(5) 控制器(Controller)调用ActionProxy
(6) ActionProxy读取struts.xml文件获取action和interceptor stack的信息。
(7) ActionProxy把request请求传递给ActionInvocation
(8) ActionInvocation依次调用action和interceptor
(9) 根据action的配置信息,产生result
(10) Result信息返回给ActionInvocation
(11) 产生一个HttpServletResponse响应
(12) 产生的响应行为发送给客服端

5.struts2拦截器是什么?以及用途

拦截器(interceptor)是Struts2最强大的特性之一,也可以说是struts2的核心,拦截器可以让你在Action和result被执行之前或之后进行一些处理。

struts-default.xml这个文件,它定义了Struts的所有拦截器。因为我们在启动服务器的时候会自动装载这个文件,因此我们才可以在Action中使用到Struts为我们提供的功能【数据自动封装…文件上传】。

6.拦截器和过滤器的区别

1)拦截器是基于JAVA反射机制的,而过滤器是基于函数回调的。
2)过滤器依赖于Servlet容器,而拦截器不依赖于Servlet容器
3)拦截器只能对Action请求起作用,而过滤器可以对几乎所有的请求起作用。
4)拦截器可以访问Action上下文、值栈里的对象,而过滤器不能
5)在Action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。

7.SpringMVC原理以及工作流程

SpringMVC是一种web层的mvc框架,用于替代servlet(处理响应请求,获取表单参数,表单验证等)

SpringMVC提供了前端控制器DispatcherServlet;处理器映射(Handler Mapping)和处理器适配器(Handler Adapter),视图解析器(View Resolver)进行视图管理;动作处理器Controller接口(包含ModelAndView,以及处理请求响应对象request和response),配置灵活,支持文件上传,数据简单转化等强大功能。

1.客户端发送请求,携带url地址;
2-3.前端控制器Dispatcher Servlet接收到请求,调用处理器映射Handler Mapping找到对应的处理器,生成并返回handler对象;
4.前端控制器Dispatcher Servlet调用处理器适配器Handler Adapter;
5-7.Handler Adapter经过适配,调用相应的适配器执行handler对象斌返回结果给Handler Adapter,再返回给前端控制器Dispatcher Servlet,结果包括数据结构和视图对象;
8-9.前端控制器Dispatcher Servlet调用视图解析器View Resolver将携带的数据结构和视图对象进行解析,解析完成后响应给Dispatcher Servlet;
10.核心控制器将结果返回给客户端。

8.SpringMVC与Struts2的主要区别

区别1:

Struts2 的核心是基于一个拦截器Filter即StrutsPreparedAndExcuteFilter
SpringMvc的核心是基于一个Servlet即DispatcherServlet(前端控制器)

区别2:

Struts2是基于类开发的,传递的参数是通过类的属性传递(属性驱动和模型驱动),所以只能设计成多例prototype

SpringMvc是基于类中的方法开发的,也就是一个url对应一个方法,传递参数是传到方法的形参上面,所以既可以是单例模式也可以是多例模式singiton

区别3:

Struts2采用的是值栈存储请求以及响应数据,OGNL存取数据

SpringMvc采用request来解析请求内容,然后由其内部的getParameter给方法中形参赋值,再把后台处理过的数据通过ModelAndView对象存储,Model存储数据,View存储返回的页面,再把对象通过request传输到页面去。

9.spring的两大特性

IOC(inversion of controller)指的是控制反转,简单来说,就是讲创建对象的过程或者创建对象的权限交给了spring框架来帮我们处理,我们不用再通过new的方式来创建JavaBean对象,这个过程就叫做IOC。

DI(dependency injection)指的是依赖注入,简单来说就是使用spring框架对我们的JavaBean对象赋值的过程。

10.AOP是什么意思?它用来做什么?

“面向切面编程”

Aspect,的确是“方面”的意思。不过,汉语传统语义中的“方面”,大多数情况下指的是一件事情的不同维度、或者说不同角度上的特性,比如我们常说:“这件事情要从几个方面来看待”,往往意思是:需要从不同的角度来看待同一个事物。这里的“方面”,指的是事物的外在特性在不同观察角度下的体现。而在AOP中,Aspect的含义,可能更多的理解为“切面”比较合适。

主要意图

将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

11.Spring事务的传播特性和隔离级别

传播特性:

  1. REQUIRED(默认):支持使用当前事务,如果当前事务不存在,创建一个新事务。
  2. SUPPORTS:支持使用当前事务,如果当前事务不存在,则不使用事务。
  3. MANDATORY:中文翻译为强制,支持使用当前事务,如果当前事务不存在,则抛出Exception。
  4. REQUIRES_NEW:创建一个新事务,如果当前事务存在,把当前事务挂起。
  5. NOT_SUPPORTED:无事务执行,如果当前事务存在,把当前事务挂起。
  6. NEVER:无事务执行,如果当前有事务则抛出Exception。
  7. NESTED:嵌套事务,如果当前事务存在,那么在嵌套的事务中执行。如果当前事务不存在,则表现跟REQUIRED一样。

四种隔离级别:

注解配置时如:@Transactional(isolation = Isolation.READ_UNCOMMITTED)

事务隔离级别 脏读 不可重复读 幻读
读未提交(Read-Uncommitted)
不可重复读(Read-Committed)
可重复读(Repeatable-Read)
串行化(Serializable)

其中:可重复读(repeatable-read)表示:在开始读取数据(事务开启)时,不再允许修改操作

mysql默认的事务隔离级别为repeatable-read

12.事务的并发问题:

  1. 脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
  2. 不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致
  3. 幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

13.hibernate和mybatis的区别

Hibernate是一个完整的ORM框架,功能更加强大,操作更加简单(性能不好控制),如果你要使用Hibernate控制性能,你必须是一个Hinernate高手。
对于一个大项目,Hibernate确实不是很合适,如果大项目一定要使用Hibernate,进行混合使用,一般的操作使用Hibernate,对于性能的要求比较高的使用原生的SQL。
mybatis不是完整的ORM框架,需要自己编写SQL语句。
好处:自己写SQL,自己控制性能。(更好控制)
坏处:自己写SQL,很麻烦

简单理解就是:
Hibernate是一个完整的ORM框架,使用更加简单,功能更加强大,性能不好控制(中小项目使用的多)
Mybatis也封装了很多的原生的JDBC,是一个半ORM框架,性能可控(SQL需要自己写)

一、两者最大的区别

针对简单逻辑,Hibernate与MyBatis都有相应的代码生成工具,可以生成简单基本的DAO层方法。

针对高级查询,MyBatis需要手动编写SQL语句,以及ResultMap,而Hibernate有良好的映射机制,开发者无需关心SQL的生成与结果映射,可以更专注于流程

二、开发难度对比

Hibernate的开发难度大于MyBatis,主要由于Hibernate比较复杂,庞大,学习周期比较长。

MyBatis则相对简单,并且MyBatis主要依赖于sql的书写,让开发者刚进更熟悉。

三、sql书写比较

Hibernate也可以自己写sql来指定需要查询的字段,但这样就破坏了Hibernate开发的简洁性,不过Hibernate具有自己的日志统计

MyBatis的sql是手动编写的,所以可以按照要求指定查询的字段,不过没有自己的日志统计,所以要借助Log4j来记录日志。

四、数据库扩展性计较

Hibernate与数据库具体的关联在XML中,所以SQL对具体是用什么数据库并不是很关心

MyBatis由于所有sql都是依赖数据库书写的,所以扩展性、迁移性比较差。

五、缓存机制比较

Hibernate的二级缓存配置在SessionFactory生成配置文件中进行详细配置,然后再在具体的表对象映射中配置那种缓存。

MyBatis的二级缓存配置都是在每个具体的表对象映射中进行详细配置,这样针对不同的表可以自定义不同的缓冲机制,并且MyBatis可以在命名空间***享相同的缓存配置和实例,通过Cache-ref来实现。

一句话总结:

Mybatis:小巧、方便、高效、简单、直接、半自动化

Hibernate:强大、方便、高效、复杂、间接、全自动化

14.ORM是什么?ORM框架是什么?

对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简单的说,它的作用是在关系型数据库和对象之间作一个映射,采用映射元数据(XML)来描述对象-关系的映射细节,封装了数据库访问细节,这样,我们在具体的操作数据库的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一样操作它就可以了 。简单来说,按通常的系统设计,使用 JDBC 操作数据库,业务处理逻辑和数据存取逻辑是混杂在一起的,逻辑语句中有SQL语句,很乱,但是ORM实现了数据存取逻辑完全分离。
优点:

  1. 提高了开发效率。由于ORM可以自动对Entity对象与数据库中的Table进行字段与属性的映射,所以我们实际可能已经不需要一个专用的、庞大的数据访问层。
  2. ORM提供了对数据库的映射,不用sql直接编码,能够像操作对象一样从数据库获取数据。

ORM框架是什么?

对象关系映射,目前数据库是关系型数据库 ORM 主要是把数据库中的关系数据映射称为程序中的对象

目前集中常见的ORM框架
1 Nhibernate
原因:用的比较多,资料也比较好找。
2 Castle ActiveRecord
原因: 不用配置对象的XML文件,这点比Nhibernate爽
3 EntityFramework
原因:微软的东西(说真的,有点不想用)
4 mybaits.net
原因:我几个搞java的朋友都说他们现在不用hibernate了都在用mybaits。

5 Dapper ORM

15.什么是Redis?Redis的使用场景是什么?

redis是一个开源的、使用C语言编写的、支持网络交互的、可基于内存也可持久化的Key-Value数据库

Redis应用场景,能做什么

​ 众多语言都支持Redis,因为Redis交换数据快,在服务器中常用来存储一些需要频繁调取的数据,节省内存开销,也极大的提升了速度。

将一些热点数据存储到Redis中,要用的时候,直接从内存取,极大的提高了速度和节约了服务器的开销。

​ 1、会话缓存(最常用)

​ 2、消息队列(支付)

​ 3、活动排行榜或计数

​ 4、发布,订阅消息(消息通知)

​ 5、商品列表,评论列表

Redis数据类型

​ Redis一共支持五种数据类型:String(字符串)、hash(哈希)、list(列表)、set(集合)和zset(sorted set有序集合)

​ String(字符串):Redis最基本的数据类型,一个键对应一个值,一个键值最大存储512MB

​ Hash(哈希):hash是一个键值对的集合,是一个String类型的field和value的映射表,适合用于存储对象

​ List(列表):是redis的简单的字符串列表,按插入顺序排序

​ Set(集合):是String字符串类型的无序集合,也不可重复

​ ZSet(sorted set 有序集合)是String类型的有序集合,也不可重复。有序集合中的每个元素都需要指定一个分数,根据分数对元素进行升序排序。

redis的服务相关命令

​ slect#选择数据库(数据库编号0-15)

​ 退出 # 退出连接

​ 信息 # 获得服务的信息与统计

​ monitor # 实时监控

​ config get # 获得服务配置

​ flushdb # 删除当前选择的数据库中的key

​ flushall # 删除所有数据库中的键

redis存储对象的方式

1、转JSON存储(需要序列化传输)

2、类型Hash存储。至于所谓的序列化只是一种传输方式,而不是一种存储方式。

redis淘汰机制

1.volatile-lru: 从已设置过期时间的数据集(server.db[i].expire)中挑选最近最少使用的数据淘汰。

2.volatile-ttl: 从已设置过期时间的数据集(server.db[i].expire)中挑选将要过期的数据淘汰。

3.volatile-random: 从已设置过期时间的数据集(server.db[i].expire)中任意数据淘汰。

4.allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰。

5.allkeys-random: 从数据集(server.db[i].dict)中挑选任意选择数据淘汰。

6.no-enviction(驱逐): 禁止驱逐数据