1丶异常
1.1在Java异常体系中,Error与Exception的区别是什么?
相同点
1.都是java.lang.Throwable类的子类
2.都用于处理程序运行中发生的特殊情况
区别
1.处理方式不同
Error 通常无法在程序中予以处理,需要交给JVM来处理,而Exception通常由程序员通过throw或try catch等方式告知JVM如何处理
2.严重程度不同
Error 表示由JVM所无法预期的错误,是一种可能,能恢复但恢复起来很困难的问题
Exception表示JVM可预期的,是一种可以捕获并由在程序中做出处理的特殊情况
常见的Error
OOMError,Stack OverflowError
常见的Exception
空指针异常,数组下标越界异常,类转换异常,类找不到异常,文件找不到异常,算术异常
抛异常的顺序 从小到大
1.2 Throw 和 throws 的区别:
相同点
两者都是消极处理异常的方式,只是抛出或者可能抛出异常,但是不会由函数去处理异
常,真正的处理异常由函数的上层调用处理。
区别
位置不同:
throws 用在函数上,后面跟的是异常类,可以跟多个;而 throw 用在函数内,后面跟的
是异常对象。
功能不同:
throws 表示出现异常的一种可能性,并不一定会发生这些异常;throw 则是抛出了异常,
执行 throw 则一定抛出了某种异常对象。
2丶集合框架
2.1 List Set Map 三个区别
Collection集合主要有List和Set两大接口
List:一个有序(元素存入集合的顺序和取出的顺序一致)容器,元素可以重复,可以插入多个null元素,元素都有索引。常用的实现类有 ArrayList、LinkedList 和 Vector。
Set:一个无序(存入和取出顺序有可能不一致、)容器,不可以存储重复元素,只允许存入一个null元素,必须保证元素唯一性。Set 接口常用实现类是 HashSet、LinkedHashSet 以及 TreeSet。
Map是一个键值对集合,存储键、值和之间的映射。 Key无序,唯一;value 不要求有序,允许重复。Map没有继承于Collection接口,从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。Map 的常用实现类:HashMap、TreeMap、HashTable、LinkedHashMap、ConcurrentHashMap
2.2 ArrayList、Vector、LinkedList的区别?
相同
都是java.util.List接口的实现类
都是有序、可排序、可重复的集合
都支持迭代器操作
区别
实现接口不同
ArrayList 和 Vector 未实现 Queue接口、Deque接口、不支持队列操作
LinkedList实现了Queue接口和Deque接口,支持队列操作,同事支持栈操作
内部实现不同
ArrayList内部采用数组来存储元素
Vector 内部采用数组来存储元素
LinkedList内部采用链表来存储元素
线程安全
ArrayList 非线程安全,适用于单线程环境
Vector 线程安全,适用于多线程环境
LinkedList 非线程安全,适用于单线程环境
扩容方式不同
ArrayList 内部采用 倍数增长
的方式扩容
Vector 内部采用 增加固定增量
的方式扩容
LinkedList 内部采用链表实现,不需要扩容
增删效率不同
ArrayList 和 Vector 内部采用数组实现,因此增删慢
LinkedList 内部采用链表实现,因此增删块
是否支持随机访问
ArrayList 和 Vector 内部采用数组实现,因此随机访问效率较高
LinkedList 内部采用链表实现,因此随机访问效率较低
2.3HashSet 与TreeSet
HashSet:底层数据结构是哈希表,线程是不同步的。无序,高效;
HashSet集合保证元素唯一性:通过元素的hashCode方法,和equals方法完成的。HashSet 首先判断两个元素的哈希值,如果哈希值一样,接着会比较equals 方法 如果 equls 结果为 true ,HashSet 就视为同一个元素。如果 equals 为 false 就不是同一个元素。
TreeSet(二叉树)
TreeSet集合排序有两种方式,Comparable和Comparator区别:
1. 让元素自身具备比较性,需要元素对象实现Comparable接口,覆盖compareTo方法。
2. 让集合自身具备比较性,需要定义一个实现了Comparator接口的比较器,并覆盖compare方法,并将该类对象作为实际参数传递给TreeSet集合的构造函数。
2.4LinkHashSet(HashSet+LinkedHashMap)
对于 LinkedHashSet 而言,它继承与 HashSet、又基于 LinkedHashMap 来实现的。
LinkedHashSet 底层使用 LinkedHashMap 来保存所有元素,它继承于HashSet,其所有的方法操作上又与HashSet 相同.
2.5 HashMap 和 Hashtable 的区别
相同
两者都实现 Map 接口,用于存放 键-值对
内部都采用 哈希表 实现,都采用 哈希算法计算 键-值对 的存放位置
区别
是否支持线程安全
HashMap 非线程安全,理论上效率较高
Hashtable 线程安全,理论上效率较低
内部实现不同
从 JDK 1.8 ( Java 8 ) 开始,HashMap 内部采用 数组 + 链表 + 红黑树 方式存储
当链表长度大于8时会自动转换成红黑树,当链表长度小于6时,红黑树重新转换成链表 而 Hashtable 内部则采用 数组 + 链表 实现
两者所继承的类不同
HashMap 类继承 AbstraceMap 类
Hashtable 类继承 Dictionary 类
是否支持 null
HashMap 支持 null 键 和 null 值
Hashtable 不支持 null 键 和 null 值
2.6 Map遍历的的两种方式
1:Set keySet() :获取到所有的键,存储到一个Set集合中,并返回该集合,因为Set有迭代器, 每次迭代出来的是一个键,再根据键来得到值
2:Set<Map.Entry<K,V>> entrySet():获取到所有的键值对儿形成的映射关系,存到一个Set集合中,再迭代这个集合 ,每次迭代出来的是一个映射关系,从这个映射关系中既可以得到键,也可以得到值这种映射关系是Map.Entry<K,V>类型的 ,Entry是定义在Map中的一个静态成员,是一个接口,因为有了集合,有了集合中的键值对儿,才会存在映射关系,所以映射关系是对集合内部的事物描述所以定义在Map的内部
2.7 Treemap
TreeMap 实现 SortedMap 接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用 Iterator 遍历 TreeMap 时,得到的记录是排过序的。
2.8 LinkHashMap(记录插入顺序)
LinkedHashMap 是 HashMap 的一个子类,保存了记录、+入- ,在用 Iterator 遍历
LinkedHashMap 时,先得到的记录肯定是先插入的,也可以在构造时带参数,按照访问次序排序。
2.9 Collection 和 Collections 有什么区别?
- Collections是个java.util下的类,是针对集合类的一个工具类,提供一系列静态方法,实现对集合的查找、排序、替换、线程安全化(将非同步的集合转换成同步的)等操作。
- Collection是个java.util下的接口,它是各种集合结构的父接口,继承于它的接口主要有Set和List,提供了关于集合的一些操作,如插入、删除、判断一个元素是否其成员、遍历等。
2.10 TreeMap 和 TreeSet 在排序时如何比较元素?
TreeSet 要求存放的对象所属的类必须实现 Comparable 接口,该接口提供了比较元素的 compareTo()方法,当插入元素时会回调该方法比较元素的大小。TreeMap 要求存放的键值对映射的键必须实现 Comparable 接口从而根据键对元素进行排序。
3丶 抽象类和接口的区别
相同: 抽象类和接口中都可以包含静态成员变量;
抽象类和接口都不能被实例化
不同:
- 接口的方法默认是 public,所有方法在接口中不能有实现(Java 8 开始接口方法可以有默认实 现),而抽象类可以有非抽象的方法。
- 接口中除了 static、final 变量,不能有其他变量,而抽象类中则不一定。
- 一个类可以实现多个接口,但只能实现一个抽象类。接口自己本身可以通过 implement 关键字扩展 多个接口。
- 接口方法默认修饰符是 public,抽象方法可以有 public、protected 和 default 这些修饰符(抽象 方法就是为了被重写所以不能使用 private 关键字修饰!)。
- 从设计层面来说,抽象是对类的抽象,是一种模板设计,而接口是对行为的抽象,是一种行为的规范。
4丶 重写eqauls()方法需要满足的条件
自反性:对任意x,x.epauls(x)一定返回true;
对称性:对任意x和y,如果y.eqauls(x)返回true,则x.eqauls(y)也返回true;
传递性:对任意x,y,z,如果x.eqauls(y)返回true,y.eqauls(z)返回true,则x.eqauls(z)一定返回true;
一致性:对任意x和y,如果对象中用于等价比较的信息没有改变,那么无论调用x.eqauls(y)多少次,返回的结 果应该保持一致,要么一直是true,要么一直是false;对任何不是null的x,x.eqauls(null)一定返回 false
5丶 final 、finally 、finalize 的区别
相同
这三个词除了长的像,没啥区别
final 关键字是个修饰符表示最终的、不可更改
被 final 修饰的类,不能被继承
被 final 修饰的方法,不能被重写
被 final 修饰的变量,在初始化后不能再次赋值 (不能二次赋值)
finally 关键字用于异常处理
finally 不能单独使用,必须跟 try … 语句 或 try … catch 语句连用
程序运行时,不论是否发生异常,finally 代码块都会执行
除非遇到 System.exit 方法,否则 finally 代码块一定会执行
finalize 是 Object 类中定义的一个实例方法
当垃圾回收器(GC)执行垃圾回收操作时,可能会通过调用某个对象的 finalize 方法
6丶 this 和 super 的区别
相同
this 和 super 都表示实例的引用因此 this 和 super 都不能出现在 static 区域
this 和 super 都可以用于调用构造方法
当通过 this( ) 或 super( ) 调用构造方法时,它们必须位于构造方法的第一行
同一个构造方法内部 this( ) 或 super( ) 不能同时出现
区别
所表示实例不同
this 表示本类的实例 , super 表示父类的实例
调用的构造方法不同
this 用于调用本类内部的其它重载的构造方法, super 用于调用父类中的构造方法
访问的成员不同
通过 this. 可以访问本类中以及从父类中继承的、可见的 成员 ( 方法 和 属性(字 段) ), 通过 super. 可以访 问从父类中继承的、可见的成员 ( 方法、字段(属性) )
使用方式不同
this 关键字可以单独使用,比如 直接输出 this 或当作返回值, this 关键字在本类中可以省略 ( 比如 getName 方法 中,return this.name; 可以写作 `return name ; ) , super 关键字不可以单独使用,必须通过 super( )或 super. 形式来使用
7丶 break continue return的区别
相同点:
break和continue都是用来控制循环的语句
不同点:
break用于完全结束一个循环,跳出循环,执行循环后面的语句
continue用于跳出本次循环,执行下次循环
return关键字并不是专门用于跳出循环的,return的功能是结束一个方法。一旦在循环体内执行到一个return语句,return语句将会结束该方法,循环自然也随之结束。与continue和break不同的是,return直接结束整个方法,不管这个return处于多少层循环之内。
8丶 成员变量与局部变量的区别有哪些
变量:在程序执行的过程中,在某个范围内其值可以发生改变的量。从本质上讲,变量其实是内存中的一小块区域
成员变量:方法外部,类内部定义的变量
局部变量:类的方法中的变量。
成员变量和局部变量的区别
作用域
成员变量:针对整个类有效。
局部变量:只在某个范围内有效。(一般指的就是方法,语句体内)
存储位置
成员变量:随着对象的创建而存在,随着对象的消失而消失,存储在堆内存中。
局部变量:在方法被调用,或者语句被执行的时候存在,存储在栈内存中。当方法调用完,或者语句结束后,就自动释放。
生命周期
成员变量:随着对象的创建而存在,随着对象的消失而消失
局部变量:当方法调用完,或者语句结束后,就自动释放。
初始值
成员变量:有默认初始值。
局部变量:没有默认初始值,使用前必须赋值。
使用原则
在使用变量时需要遵循的原则为:就近原则, 首先在局部范围找,有就使用;接着在成员位置找
9丶 String StringBuffer 和 StringBuilder 的区别是什么?String 为什么是不可变的?
可变性
简单的来说:String 类中使用 final 关键字修饰字符数组来保存字符串, private final char[[ ] value,所以 String 对象是不可变的。在 Java 9 之后,String 类的实现改用 byte 数组存储字符串private final byte[] value 好处:使用byte数组可以减少一半的内存,byte使用一个字节来存储一个char字符,char使用两个字节来存储一个char字符。只有当一个char字符大小超过0xFF时,才会将byte数组变为原来的两倍,用两个字节存储一个char字符。
而 StringBuilder 与 StringBuffer 都继承自 AbstractStringBuilder 类,在AbstractStringBuilder 中也是使用字符数组保存字符串 char[] value 但是没有用 final 关键字修饰,所以这两种对象都是可变的。
StringBuilder 与 StringBuffer 的构造方法都是调用父类构造方法也就是AbstractStringBuilder实现
的。
线程安全性
String 中的对象是不可变的,也就可以理解为常量,线程安全。
StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。
StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。
性能
相同情况下使用 StringBuilder 相比使用 StringBuffer 仅能获得10%~15% 左右的性能提升,但却要冒
多线程不安全的风险。
对于三者使用的总结:
- 操作少量的数据(不频繁改变的): 适用 String
- 单线程操作字符串缓冲区下操作大量数据(频繁改变的): 适用 StringBuilder
- 多线程操作字符串缓冲区下操作大量数据: 适用 StringBuffer
10丶 Eunm你在哪里用过?
如何高效的创建一个线程安全的单例?
一种是通过枚举,一种是通过静态内部类。
10.1 枚举概念
枚举类是实现单例的一个不错选择,枚举类构造函数默认为private。
Enum 一般用来表示一组相同类型的常量。如性别、日期、月份、颜色等。
枚举类对象在枚举类中以public static final 修饰,但自定义枚举类时,可以添加任意访问修饰符的类变量和实例变量。
使用enum声明的枚举类默认为final class 因此不能被继承。
10.2 枚举类在实际开发中的应用
由于在数据库表的设计中,经常会有表示状态的字段,值为1、2、3…用来表示不同的状态,比如1代表待付款,2代表待发货,3代表已发货。使用枚举类来作为数据库状态字段值的映射,在数据存入、查询时会使代码变的更加可读。
11丶 final与static区别
final关键字修饰变量:
1.如果是基本数据类型的变量,那么这个变量一旦初始化就不能更改,相当于一个常量
2.如果是引用数据类型的变量,则初始化后就不能更改它的引用,不过引用对象变量的值可以更改
final关键字修饰方法:
1.表明这个方法不能被子类重写,防止类修改它的含义
与static比较都不能重写但可以被子类继承调用,不同在于static可以写一个同名方法隐藏父类的方法,而final不行
final关键字修饰类:
表明这个类不能被继承
static关键字修饰变量:
1.static关键字修饰的变量也叫类变量,整个类共享这一个静态变量,使用类名.变量访问。
2.与非静态变量区别,静态变量在内存中只有一个,随类加载而加载,程序结束时销毁,非静态每个对象都有单独的一个,随着对象一起创建销毁
static关键字修饰方法:
1.静态方法是不在对象上执行的方法,不需要类的实例化,可以直接通过类调用。
12丶 日期如何比较
-
使用 Date.compareTo()
-
使用 Date.before()、Date.after() 和 Date.equals()
-
使用 Calender.before()、Calender.after() 和 Calender.equals()
-
使用 getTime()
-
使用 Java 8 的 isBefore()、isAfter()、isEqual() 和 compareTo()
在 Java 8 中,可以使用新的 isBefore()、isAfter()、isEqual() 以及 compareTo() 来比较 LocalDate、LocalTime 和 LocalDateTime
13丶 泛型
泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。比如我们要写一个排序方法,能够对整型数组、字符串数组甚至其他任何类型的数组进行排序,我们就可以使用 Java 泛型。
类型擦除:java编译器生成的字节码不包含泛型信息,所以在编译时擦除:
1.泛型用最顶级父类替换;2.移除。
泛型的好处:
- 将运行时期的ClassCastException转移到编译时期变成编译失败(提前发现错误,在写程序的时候就能看到)。
- 避免类型强转的麻烦。
14丶 传统JDBC连接数据库
首先工作0
(1)user用户名
(2)password密码
(3)URL定义了连接数据库时的协议、子协议、数据源标识,它们之间用冒号隔开
(4)driverClass连接数据库所需的驱动。
1、加载JDBC驱动程序
2、创建数据库的连接
3、创建一个语句发送器Statement
4、编写SQL语句
5、执行SQL语句 遍历结果集
6、关闭连接 释放资源(从里往外关)
数据库连接池
数据库连接是一种关键的有限的昂贵的资源 一个数据库连接对象均对应一个物理数据库连接,每次操作都打开一个物理连接,使用完都关闭连接,这样造成系统的 性能低下。 数据库连接池的解决方案是在应用程序启动时建立足够的数据库连接,并讲这些连接组成一个连接池,由应用程序动态地对池中的连接进行申请、使用和释放。对于多于连接池中连接数的并发请求,应该在请求队列中排队等待。并且应用程序可以根据池中连接的使用率,动态增加或减少池中的连接数。 连接池技术尽可能多地重用了消耗内存地资源,大大节省了内存,提高了服务器地服务效率,能够支持更多的客户服务。
连接池的工作原理主要由三部分组成,分别为
- 连接池的建立
- 连接池中连接的使用管理
- 连接池的关闭
使用连接池时,要配置一下参数
- 最小连接数
- 最大连接数
- 最大空闲时间
- 获取连接超时时间
- 超时重试连接次数
Druid首先是一个数据库连接池。Druid是目前最好的数据库连接池,在功能、性能、扩展性方面,都超过其他数据库连接池,包括DBCP、C3P0、BoneCP、Proxool、JBoss DataSource。Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。Druid是阿里巴巴开发的号称为监控而生的数据库连接池!
1.可以监控数据库访问性能,
2.SQL执行日志
15丶线程问题
15.1 进程与线程?
进程 代表一个运行中的程序,是资源分配与调度的基本单位。进程有三大特性:
1、独立性:独立的资源,私有的地址空间,进程间互不影响。
2、动态性:进程具有生命周期。
3、并发性:多进程可以在单核CPU上并发运行。
线程 代表进程中的一个顺序执行流,多线程就是一个进程中的多个顺序执行流。线程也被称为轻量级的进程,是系统运行的基本单位。
多线程的优势(进程线程区别):
1、进程之间不能共享内存,线程之间共享内存更容易,多线程可协作完成进程工作;
2、创建进程进行资源分配的代价较创建线程要大得多,所以多线程在高并发环境中效率更高。
15.2并行与并发:
并行 是指:多核多CPU或多机器处理同一段处理逻辑的时候,同一时刻多个执行流共同执行。
并发 是指:通过CPU的调度算法,使用户感觉像是同时处理多个任务,但同一时刻只有一个执行流占用CPU执行。即使多核多CPU环境还是会使用并发,以提高处理效率。
主要的CPU调度算法有如下两种:
1、分时调度:每个线程轮流获取CPU使用权,各个线程平均CPU时间片。
2、抢占式调度:Java虚拟机使用的就是这种调度模型。这种调度方式会根据线程优先级,先调度优先级高的线程,如果线程优先级相同,会随机选取线程执行。
16丶Java创建线程的方式?
1、继承Thread类,实现run()方法。
**2、实现Runnable接口,实现run()方法。**Runnable实例对象作为Thread构造方法中的target参数传入,充当线程执行体。这种方式适用于多个线程共享资源的情况。
3、实现Callable接口,实现call()方法。
17丶sleep()方法与wait()方法区别是什么?wait()方法为什么属于Object类?
它们的都是使线程“等待”一段时间,但是:
sleep()方法是Thread类下的方法,控制线程休眠,休眠过程中不会释放锁,sleep()时间到后进入就绪态等待调度。
wait()方法是Object类下的方法,控制线程等待,等待过程会释放锁,被notify()后会进入就绪态等待调度。
至于wait()方法为什么属于Object类,而不是Thread类,是因为:
wait()方法用于多个线程争用一把锁的情况,同一时刻只有一个线程能够获得锁,其他线程就要在线程队列等待。作用对象就是被锁住的对象,所以线程队列的维护工作应该交给Object。如果交给Thread,那么每个Thread都要知道其他Thread的状态,这并不合理。
18丶start()方法与run()方法区别?
start()方法用于启动线程,会把线程状态由新建态转为就绪态,为线程分配线程私有的方法栈、程序计数器等资源,而start()方法会自动把run()方法作为线程执行体。
run()方法本身与普通方法并无二致,直接调用run()方法不会具有线程的意义。
19丶Java常见的锁类型有哪些?请简述其特点。
**1、synchronized对象同步锁:**synchronized是对对象加锁,可作用于对象、方法(相当于对this对象加锁)、静态方法(相当于对Class实例对象加锁,锁住的该类的所有对象)以保证并发环境的线程安全。同一时刻只有一个线程可以获得锁。
其底层实现是通过使用对象监视器Monitor,每个对象都有一个监视器,当线程试图获取Synchronized锁定的对象时,就会去请求对象监视器(Monitor.Enter()方法),如果监视器空闲,则请求成功,会获取执行锁定代码的权利;如果监视器已被其他线程持有,线程进入同步队列等待。
**7、死锁:**是当两个线程互相等待获取对方的对象监视器时就会发生死锁。一旦出现死锁,整个程序既不会出现异常也不会有提示,但所有线程都处于阻塞状态。死锁一般出现于多个同步监视器的情况。
20丶死锁的必要条件
1 互斥条件:
进程要求对所分配的资源(如打印机)进行排他性控制,即在一段时间内某资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。
2 不可剥夺条件:
进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能由获得该资源的进程自己来释放(只能是主动释放)。
3 请求与保持条件:
进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。
4 循环等待条件:
存在一种进程资源的循环等待链,链中每一个进程已获得的资源同时被 链中下一个进程所请求。即存在一个处于等待状态的进程集合{Pl, P2, …, pn},其中Pi等 待的资源被P(i+1)占有(i=0, 1, …, n-1),Pn等待的资源被P0占有
以上这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。
21丶 避免死锁
-
加锁顺序(线程按照一定的顺序加锁)
-
加锁时限(线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁)
-
死锁检测
死锁检测是一个更好的死锁预防机制,它主要是针对那些不可能实现按序加锁并且锁超时也不可行的场景。
每当一个线程获得了锁,会在线程和锁相关的数据结构中(map、graph等等)将其记下。除此之外,每当有线程请求锁,也需要记录在这个数据结构中。
当一个线程请求锁失败时,这个线程可以遍历锁的关系图看看是否有死锁发生。例如,线程A请求锁7,但是锁7这个时候被线程B持有,这时线程A就可以检查一下线程B是否已经请求了线程A当前所持有的锁。如果线程B确实有这样的请求,那么就是发生了死锁(线程A拥有锁1,请求锁7;线程B拥有锁7,请求锁1)。
22丶 mysql,oracle分页
(1)MySql的Limit m,n语句
Limit后的两个参数中,参数m是起始下标,它从0开始;参数n是返回的记录数。我们需要分页的话指定这两个值即可
(2)Oracle数据库的rownum
在Oracle数据库中,分页方式没有MySql这样简单,它需要依靠rownum来实现.Rownum表示一条记录的行号,值得注意的是它在获取每一行后才赋予.因此,想指定rownum的区间来取得分页数据在一层查询语句中是无法做到的,要分页还要进行一次查询.
SELECT * FROM (SELECT A.*, ROWNUM RN FROM (SELECT * FROM TABLE_NAME) A WHERE ROWNUM <= 40)WHERE RN >= 21
其中最内层的查询SELECT * FROM TABLE_NAME表示不进行翻页的原始查询语句。ROWNUM <= 40和RN >= 21控制分页查询的每页的范围。
上面给出的这个分页查询语句,在大多数情况拥有较高的效率。分页的目的就是控制输出结果集大小,将结果尽快的返回。在上面的分页查询语句中,这种考虑主要体现在WHERE ROWNUM <= 40这句上。
选 择第21到40条记录存在两种方法,一种是上面例子中展示的在查询的第二层通过ROWNUM <= 40来控制最大值,在查询的最外层控制最小值。而另一种方式是去掉查询第二层的WHERE ROWNUM <= 40语句,在查询的最外层控制分页的最小值和最大值。
23 丶 == 与 equal的区别
== :
它的作用是判断两个对象的地址是不是相等。即判断两个对象是不是同一个对象。(基本数据类型比较的是值,引用数据类型比较的是内存地址)
因为 Java 只有值传递,所以,对于 == 来说,不管是比较基本数据类型,还是引用数据类型的变量,其本质比较的都是值,只是引用类型变量存的值是对象的地址。
equals() :
它的作用也是判断两个对象是否相等,它不能用于比较基本数据类型的变量。 equals()方法存在于 Object 类中,而 Object 类是所有类的直接或间接父类。equals() 方法存在两种使用情况:
情况 1:类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通
过“==”比较这两个对象。使用的默认是 Object 类 equals() 方法。
情况 2:类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来两个对象的内容相等;若
它们的内容相等,则返回 true(即,认为这两个对象相等)。
24丶 servlet九大内置对象
1、Request对象
该对象封装了用户提交的信息,通过调用该对象相应的方法可以获取封装的信息,即使用该对象可以获取用户提交的信息。
2、Response对象
对客户的请求做出动态的响应,向客户端发送数据。
3.Session对象
(1)什么是Session对象
Session对象是一个JSP内置对象,它在第一个JSP页面被装载时自动创建,完成会话期管理。从一个客户打开浏览器并连接到服务器开始,到客户关闭浏览器离开这个服务器结束,被称为一个会话。当一个客户访问一个服务器时,可能会在这个服务器的几个页面之间切换,服务器应当通过某种办法知道这是一个客户,就需要Session对象。
(2)Session对象的ID
当一个客户首次访问服务器上的一个JSP页面时,JSP引擎产生一个Session对象,同时分配一个String类型的ID号,JSP引擎同时将这换个ID号发送到客户端,存放在Cookie中,这样Session对象,直到客户关闭浏览器后,服务器端该客户的Session对象才取消,并且和客户的会话对应关系消失。当客户重新打开浏览器再连接到该服务器时,服务器为该客户再创建一个新的Session对象。
(3)Session对象的常用方法
● public String getId():获取Session对象编号。
● public void setAttribute(String key,Object obj):将参数Object指定的对象obj添加到Session对象中,并为添加的对象指定一个索引关键字。
● public Object getAttribute(String key):获取Session对象中含有关键字的对象。
● public Boolean isNew():判断是否是一个新的客户。
4、Application对象
(1)什么时Application对象
服务器启动后就产生了这个Application对象,当客户再所访问的网站的各个页面之间浏览时,这个Application对象都时同一个,直到服务器关闭。但是与Session对象不同的时,所有客户的Application对象都时同一个,即所有客户共享这个内置的Application对象。
(2)Application对象的常用方法
● setAttribute(String key,Object obj):将参数Object指定的对象obj添加到Application对象中,并为添加的对象指定一个索引关键字。
● getAttribute(String key):获取Application对象中含有关键字的对象。
5、Out对象
Out对象时一个输出流,用来向客户端输出数据。Out对象用于各种数据的输出。其常用方法如下。
● out.print():输出各种类型数据。
● out.newLine():输出一个换行符。
● out.close():关闭流。
6、Config对象
配置对象
7、Page对象
页面对象。
8.PageContext对象
页面上下文对象
Jsp引入了一个名位PageContext的类,通过它可以访问页面的许多属性。
PageContext类拥有getRequest,getResponse,getOut,getSession等方法。
pageContext变量存储与当前页面相关联的PageContext对象的值。
补:
如果方法需要访问多个与页面相关的对象,
传递pageContext要比传递request,response,out等的独立引用更容易。(虽然两种方式都能达到同样的目的)
9、Exception对象
在处理异常的网页中可以直接访问exception隐式对象。
25丶cookie和session区别。
1、存储位置不同
cookie的数据信息存放在客户端浏览器上。
session的数据信息存放在服务器上。
2、存储容量不同
单个cookie保存的数据<=4KB,一个站点最多保存20个Cookie。
对于session来说并没有上限,但出于对服务器端的性能考虑,session内不要存放过多的东西,并且设置session删除机制。
3、存储方式不同
cookie中只能保管ASCII字符串,并需要通过编码方式存储为Unicode字符或者二进制数据。
session中能够存储任何类型的数据,包括且不限于string,integer,list,map等。
4、隐私策略不同
cookie对客户端是可见的,别有用心的人可以分析存放在本地的cookie并进行cookie欺骗,所以它是不安全的。
session存储在服务器上,对客户端是透明对,不存在敏感信息泄漏的风险。
5、服务器压力不同
cookie保管在客户端,不占用服务器资源。对于并发用户十分多的网站,cookie是很好的选择。
session是保管在服务器端的,每个用户都会产生一个session。假如并发访问的用户十分多,会产生十分多的session,耗费大量的内存。
6、跨域支持上不同
cookie支持跨域名访问。
session不支持跨域名访问
26丶如何解决cookie安全性问题
第一步:设置cookie有效期不要过长,合适即可
第二步:设置复杂的cookie,加密cookie
(1)cookie的key使用uuid,随机生成;
(2)cookie的value可以使用复杂组合,比如:用户名+当前时间+cookie有效时间+随机数。
这样可以尽可能使得加密后的cookie更难解密,也是保护了cookie中的信息。
第三步:session和cookie同时使用
sessionId虽然放在cookie中,但是相对的session更安全,可以将相对重要的信息存入session。
第四步:如果网站支持https,尽可能使用https
如果网站支持https,那么可以为cookie设置Secure属性为true,它的意思是,cookie只能使用https协议发送给服务器,而https比http更加安全。
,
27丶什么是过滤器?
1)过滤器(Filter):它依赖于servlet容器。在实现上,基于函数回调,它可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的,是用来做一些过滤操作,获取我们想要获取的数据,比如:在Javaweb中,对传入的request、response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者Controller进行业务逻辑操作。通常用的场景是:在过滤器中修改字符编码(CharacterEncodingFilter)、在过滤器中修改HttpServletRequest的一些参数(XSSFilter(自定义过滤器)),如:过滤低俗文字、危险字符等
28丶监听器
监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法将立即被执行。
监听器原理
监听原理
1、存在事件源
2、提供监听器
3、为事件源注册监听器
4、操作事件源,产生事件对象,将事件对象传递给监听器,并且执行监听器相应监听方法
29丶 switch 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String 上
在 Java 5 以前,switch(expr)中,expr 只能是 byte、short、char、int。从 Java5 开始,Java 中引入了枚举类型,expr 也可以是 enum 类型,从 Java 7 开始,expr 还可以是字符串(String),但是长整型(long)在目前所有的版本中都是不可以的。
30丶 抽象,封装,继承,多态
抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。
封装
封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果属性不想被外界访问,我们大可不必提供方法给外界访问。但是如果一个类没有提供给外界访问的方法,那么这个类也没有什么意义了。
继承
;】使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承我们能够非常方便地复用以前的代码。
关于继承如下 3 点请记住:
- 子类拥有父类非 private 的属性和方法。
- 子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
- 子类可以用自己的方式实现父类的方法。
多态
所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。
在Java中有两种形式可以实现多态:继承(多个子类对同一方法的重写)和接口(实现接口并覆盖接口中同一方法)。
31、重载(Overload)和重写(Override)的区别。
区别点 | 重载(overload) | 重写(override) |
---|---|---|
发生范围 | 同一个类 | 子类中 |
参数列表 | 必须不同 | 必须相同 |
返回类型 | 可以不同 | 必须相同 |
异常 | 可以不同 | 可以减少或删除,一定不能抛出新的或者更⼴的异常 |
访问修饰符 | 可以不同 | 可以提高 |
发生阶段 | 编译期 | 运行期 |
32丶 Java内部类
一、 含义
在Java编程语言里,程序是由类(class)构建而成的。在一个类的内部也可以声明类,我们把这样的类叫做内部类。Java内部类可分为成员内部类、局部内部类、匿名内部类、静态内部类。
静态内部类
定义在类内部的静态类,就是静态内部类
1.静态内部类可以访问外部类所有的静态变量和方法,即使是 private 的也一样。
- 静态内部类和一般类一致,可以定义静态变量、方法,构造方法等。
成员内部类
定义在类内部的非静态类,就是成员内部类。成员内部类不能定义静态方法和变量(final 修饰的
除外)。这是因为成员内部类是非静态的,类初始化的时候先初始化静态成员,如果允许成员内
部类定义静态变量,那么成员内部类的静态变量初始化顺序是有歧义的。
局部内部类(定义在方法中的类)
定义在方法中的类,就是局部类。如果一个类只在某个方法中使用,则可以考虑使用局部类
匿名内部类(要继承一个父类或者实现一个接口、直接使用new 来生成一个对象的引用)
匿名内部类我们必须要继承一个父类或者实现一个接口,当然也仅能只继承一个父类或者实现一
个接口。同时它也是没有 class 关键字,这是因为匿名内部类是直接使用 new 来生成一个对象的引
用。
二、 作用
- 实现了更好的封装,我们将内部类声明为private时,只有外部类可以访问内部类,很好地隐藏了内部类。
- 内部类可以继承(extends)或实现(implements)其他的类或接口,而不受外部类的影响。
- 内部类可以直接访问外部类的字段和方法,即使是用private修饰的,相反的,外部类不能直接访问内部类的成员。
33丶 Java加锁方式
-
synchronized关键字
-
实现接口Lock,ReentrantLock是唯一实现了Lock接口的类,并且ReentrantLock提供了更多的方法,
lock()方法是平常使用得最多的一个方法,就是用来获取锁。如果锁已被其他线程获取,则进行等待。在上面提到如果采用Lock,必须主动去释放锁,并且在发生异常时,不会自动释放锁
Lock 和 synchronized的选择:
总结来说,Lock 和 synchronized有以下几点不同:
两者区别:
- Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;
- synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;
- Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;
- 通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。
- Lock可以提高多个线程进行读操作的效率。
34丶MYSQL 四大隔离级别
Read Uncommitted(读取未提交内容)
在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。
Read Committed(读取提交内容)
它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可 能返回不同结果;
Repeatable Read(可重读)
这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。
InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题
Serializable(可串行化)
这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
可能发生的问题
一、脏读:
事物A修改了数据表中的一个数据num,但是没有提交,此时事物B读取了num,事物A rollback ,num改变为原来的值,那么事物B读到的num即为脏数据。
二、幻读:
事物A在用一个表,此时事物B在表中增加/删除了一条数据,A发现多了/少了一条数据,即为幻读。
三、不可重复度:
A在用num为1,B将num改为2,且已经提交,A再读num为2,1 != 2 ,重复读取一个数据,前后不一致。
四、丢失更新:
A、B同时操作一条数据,B的修改覆盖了A的,即出现丢失更新。
35丶IOC/DI/AOP
控制反转是把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的”控制反转”就是对组件对象控制权的转移,从程序代码本身转移到了外部容器,由容器来创建对象并管理对象之间的依赖关系。
DI是对IoC更准确的描述,即组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动态的将某种依赖关系注入到组件之中。
解释Spring支持的几种bean的作用域
Spring框架支持以下五种bean的作用域:
- singleton : bean在每个Spring ioc 容器中只有一个实例。
- prototype:一个bean的定义可以有多个实例。
- request:每次http请求都会创建一个bean,该作用域仅在基于web的Spring ApplicationContext情形下有效。
- session:在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
- global-session:在一个全局的HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
解释一下什么叫AOP(面向切面编程)?
AOP(Aspect-Oriented Programming)指一种程序设计范型,该范型以一种称为切面(aspect)的语言构造为基础,切面是一种新的模块化机制,用来描述分散在对象、类或方法中的横切关注点(crosscutting concern)。
36丶SpringMVC的核心
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E8Y0oO8M-1602209328801)(C:\Users\Administrator\Desktop\QQ截图20200930083724.png)]
37丶索引原则
mysql 最多一张表能建立16个索引
索引(Index)是帮助 MySQL 高效获取数据的数据结构
- 选择唯一性索引
唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录。 - 为经常需要排序、分组和联合操作的字段建立索引:
- 为常作为查询条件的字段建立索引。
- 删除不再使用或者很少使用的索引
- 尽量的扩展索引,不要新建索引。
38丶索引有哪几种类型?
主键索引: 数据列不允许重复,不允许为NULL,一个表只能有一个主键。
唯一索引: 数据列不允许重复,允许为NULL值,一个表允许多个列创建唯一索引。
- 可以通过
ALTER TABLE table_name ADD UNIQUE (column);
创建唯一索引 - 可以通过
ALTER TABLE table_name ADD UNIQUE (column1,column2);
创建唯一组合索引
普通索引: 基本的索引类型,没有唯一性的限制,允许为NULL值。
- 可以通过
ALTER TABLE table_name ADD INDEX index_name (column);
创建普通索引 - 可以通过
ALTER TABLE table_name ADD INDEX index_name(column1, column2, column3);
创建组合索引
全文索引: 是目前搜索引擎使用的一种关键技术。
- 可以通过
ALTER TABLE table_name ADD FULLTEXT (column);
创建全文索引
39丶数据库三大范式是什么
第一范式:每个列都不可以再拆分。
第二范式:在第一范式的基础上,非主键列完全依赖于主键,而不能是依赖于主键的一部分。
第三范式:在第二范式的基础上,非主键列只依赖于主键,不依赖于其他非主键。
在设计数据库结构的时候,要尽量遵守三范式,如果不遵守,必须有足够的理由。比如性能。事实上我们经常会为了性能而妥协数据库的设计。
40丶Innodb与MyIASM
行级锁特点:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。(默认行锁)
表级锁特点:开销小,加锁快;不会出现死锁;锁定粒度大,发出锁冲突的概率最高,并发度最低
页级锁特点:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般
41丶ACID
事务(TRANSACTION)是作为单个逻辑工作单元执行的一系列操作,这些操作作为一个整体一起向
系统提交,要么都执行、要么都不执行 。事务是一个不可分割的工作逻辑单元
事务必须具备以下四个属性,简称 ACID 属性:
原子性(Atomicity)
事务是一个完整的操作。事务的各步操作是不可分的(原子的);要么都执行,要么都不执
行。
一致性(Consistency)
当事务完成时,数据必须处于一致状态。
隔离性(Isolation)
对数据进行修改的所有并发事务是彼此隔离的,这表明事务必须是独立的,它不应以任何方
式依赖于或影响其他事务。
永久性(Durability)
事务完成后,它对数据库的修改被永久保持,事务日志能够保持事务的永久性
42丶视图
为了提高复杂SQL语句的复用性和表操作的安全性,视图根本用途:简化sql查询,提高开发效率。如果说还有另外一个用途那就是兼容老的表结构。
下面是视图的常见使用场景:
- 重用SQL语句;
- 简化复杂的SQL操作。在编写查询后,可以方便的重用它而不必知道它的基本查询细节;
- 使用表的组成部分而不是整个表;
- 保护数据。可以给用户授予表的特定部分的访问权限而不是整个表的访问权限;
- 更改数据格式和表示。视图可返回与底层表的表示和格式不同的数据。
43丶SQL 约束有哪几种?
SQL 约束有哪几种?
- NOT NULL: 用于控制字段的内容一定不能为空(NULL)。
- UNIQUE: 控件字段内容不能重复,一个表允许有多个 Unique 约束。
- PRIMARY KEY: 也是用于控件字段内容不能重复,但它在一个表只允许出现一个。
- FOREIGN KEY: 用于预防破坏表之间连接的动作,也能防止非法数据插入外键列,因为它必须是它指向的那个表中的值之一。
- CHECK: 用于控制字段的值范围。
44丶六种关联查询
- 内连接(INNER JOIN)
- 外连接(LEFT JOIN/RIGHT JOIN)
内连接分为三类
- 等值连接:ON A.id=B.id
- 不等值连接:ON A.id > B.id
- 自连接:SELECT * FROM A T1 INNER JOIN A T2 ON T1.id=T2.pid
外连接(LEFT JOIN/RIGHT JOIN)
- 左外连接:LEFT OUTER JOIN, 以左表为主,先查询出左表,按照ON后的关联条件匹配右表,没有匹配到的用NULL填充,可以简写成LEFT JOIN
- 右外连接:RIGHT OUTER JOIN, 以右表为主,先查询出右表,按照ON后的关联条件匹配左表,没有匹配到的用NULL填充,可以简写成RIGHT JOIN
45丶Mysql优化
- 表的设计要规范,即要符合数据库设计三范式。
- 适当建立索引,在频繁作为检索条件,更新较少的字段上建立索引,以提高查询速度。
- 分表查询,有水平分割、垂直分割。读写分离,读(read)、写(create、update、delete)。
- 建立存储过程。
-
为查询缓存优化你的查询
-
EXPLAIN 你的 SELECT 查询
使用 EXPLAIN 关键字可以让你知道 MySQL 是如何处理你的 SQL 语句的
-
当只要一行数据时使用 LIMIT 1
当你查询表的有些时候,你已经知道结果只会有一条结果,但因为你可能需要去 fetch 游标,或是你也许会去检
查返回的记录数。在这种情况下,加上 LIMIT 1 可以增加性能
- 为搜索字段建索引
某个字段 你总要会经常用来做搜索,那么,请为其建立索引吧
-
避免 SELECT *
从数据库里读出越多的数据,那么查询就会变得越慢。并且,如果你的数据库服务器和 WEB 服务器是两台独
立的服务器的话,这还会增加网络传输的负载。
-
永远为每张表设置一个 ID
-
Prepared Statements
Prepared Statements 很像存储过程,是一种运行在后台的 SQL 语句集合,我们可以从使用 prepared
statements 获得很多好处,无论是性能问题还是安全问题。
-
选择正确的存储引擎
46丶对象的序列化
目的:将一个具体的对象进行持久化,写入到硬盘上。
注意:静态数据不能被序列化,因为静态数据不在堆内存中,是存储在静态方法区中。
如何将非静态的数据不进行序列化?用transient 关键字修饰此变量即可。
47丶正则表达式
其实是用来操作字符串的一些规则。
好处:正则的出现,对字符串的复杂操作变得更为简单。
特点:将对字符串操作的代码用一些符号来表示。只要使用了指定符号,就可以调用底层的代码对字符串进行操作。符号的出现,简化了代码的书写。
弊端:符号的出现虽然简化了书写,但是却降低了阅读性。
其实更多是用正则解决字符串操作的问题。
48丶线程池
在一个应用程序中初始化一个线程集合,然后在需要执行新的任务时重用线程池中的线程,而不是创建一个新的线程。线程池中的每个线程都有被分配一个任务,一旦任务完成,线程就回到线程池中,等待下一次的任务分配
Java 里面线程池的顶级接口是 Executor,但是严格意义上讲 Executor 并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是 ExecutorService
newCachedThreadPool
创建一个可根据需要创建新线程的线程池。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。
newFixedThreadPool
创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。在任意点,在大多数 nThreads 线程会处于处理任务的活动状态。
newScheduledThreadPool
创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行
newSingleThreadExecutor
Executors.newSingleThreadExecutor()返回一个线程池(这个线程池只有一个线程),这个线程
池可以在线程死后(或发生异常时)重新启动一个线程来替代原来的线程继续执行下去!
49丶buffer流与其他流的区别
FileInputStream是读一个字节就要进行处理一次(写入另一个文件或者其他业务处理),这个过程就会进行更多的磁盘io操作,BufferInputStream是带有字节缓冲区的功能,将每次读取的字节,存储到缓冲区。设置缓冲区大小,当读取的字节达到设置的大小,就进行一次写入或者数据处理。所以BufferInputStream比FileInputStream效率要高。
语法:BufferInputStream bis=new BufferInputStream(new FileInputStream(“d:file/test.txt”))
50丶jsp servlet区别
Servlet:
Servlet 是一种服务器端的Java应用程序,具有独立于平台和协议的特性,可以生成动态的Web页面。它担当客户请求(Web浏览器或其他HTTP客户程序)与服务器响应(HTTP服务器上的数据库或应用程序)的中间层。 Servlet是位于Web服务器内部的服务器端的Java应用程序,与传统的从命令行启动的Java应用程序不同,Servlet由Web服务器进行加载,该Web服务器必须包含支持Servlet的Java虚拟机。
Jsp:
JSP 全名为Java Server Pages,中文名叫java服务器页面,其根本是一个简化的Servlet设计。JSP技术使用Java编程语言编写类XML的tags和scriptlets,来封装产生动态网页的处理逻辑。网页还能通过tags和scriptlets访问存在于服务端的资源的应用逻辑。JSP将网页逻辑与网页设计的显示分离,支持可重用的基于组件的设计,使基于Web的应用程序的开发变得迅速和容易。 JSP(JavaServer Pages)是一种动态页面技术,它的主要目的是将表示逻辑从Servlet中分离出来。
相同点
jsp经编译后就变成了servlet,jsp本质就是servlet,jvm只能识别java的类,不能识别jsp代码,web容器将jsp的代码编译成jvm能够识别的java类。
分析
其实就是当你通过 http 请求一个 JSP 页面是,首先 Tomcat 会调用 service()方法将JSP编译成为 Servlet,然后执行 Servlet。
不同点
JSP侧重视图,Sevlet主要用于控制逻辑。
Servlet中没有内置对象 。
JSP中的内置对象都是必须通过HttpServletRequest对象,HttpServletResponse对象以及HttpServlet对象得到。
51丶Statement与preparedStatement区别
preparedStatement会预编译sql语句,能够提高批量的数据操作的执行效率,Statement执行slq的时候才进行编译
Preparedstatement在第一次执行sql的时候,比较耗费资源。如果只对数据库进行一次操作,使用statement比较好。
Statement会出现sql注入的问题,使用preparedstatment可以解决sql注入
52丶重定向和请求转发的区别?
请求转发只能将请求转发给同一个Web应用中的其他资源,而重定向不仅可以定向到当前应用程序中的其他资源,也可以重定向到其他站点上的资源。
重定向结束后,浏览器地址栏显示URL会发生改变,由初始的URL地址变成重定向的目标URL。而请求转发过程结束后,浏览器地址栏保持初始的URL地址不变。
请求转发的发起者和接受者之间共享相同的HttpServletRequest实例和HttpServletResponse实例,而重定向的发起者和接受者使用各自的HttpServletRequest实例和HttpServletResponse实例。
转发是一次请求,重定向是二次请求。转发是在服务器进行的,重定向在客服端进行的。
53丶如何使session失效
Session.invalidate()
54丶 如何在jsp页面上显示一些特定格式的数字或者日期
使用jstl标签库,使用numberformat或者dateformat标签
55丶 Sql中delete与truncate的区别
DELETE:选择性地删除数据,当删除整张表的数据时效率较低;truncate只能删除整张表的数据,但是效率高于使用DELETE语句;不能选择性地删除。当truncate执行删除之后,自动生成的主键值重新从默认值开始。
56丶Xml的java解析有几种方式?
Java API解析xml主要有两种方式;
Dom解析:一次性加载整个文档,生成树形结构。在生成的文档对象中,可以对节点进行增删改查的操作。当xml文本当较小的时候,可以使用dom解析。
Sax解析:基于事件的解析方式,解析速度比较快,解析的文档大小理论上是没有限制的。
还有一些开源的技术可以解析xml,dom4j或者jdom。
57丶**#{}和${}的区别是什么**
#{}是预编译处理,KaTeX parse error: Expected 'EOF', got '#' at position 21: …串替换。 Mybatis在处理#̲{}时,会将sql中的#{}替…{}时,就是把${}替换成变量的值。
使用#{}可以有效的防止SQL注入,提高系统安全性。
58丶 Mybatis是如何进行分页的?分页插件的原理是什么?
Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页。可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
59丶Files的常用方法都有哪些?
Files.exists( ):检测文件路径是否存在。
Files.createFile():创建文件。
Files.createDirectory():创建文件夹。
Files.delete():删除一个文件或目录。
Files.copy():复制文件。
Files.move():移动文件。
Files.size():查看文件个数。
Files.read():读取文件。
Files.write():写入文件。
60丶数据结构
栈(stack)是限制插入和删除只能在一个位置上进行的表,该位置是表的末端,叫做栈顶
(top)。它是后进先出(LIFO)的。对栈的基本操作只有 push(进栈)和 pop(出栈)两种,
前者相当于插入,后者相当于删除最后的元素
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的
后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为
队尾,进行删除操作的端称为队头。
链表是一种数据结构,和数组同级。比如,Java 中我们使用的 ArrayList,其实现原理是数组。而
LinkedList 的实现原理就是链表了。链表在进行循环遍历时效率不高,但是插入和删除时优势明显。