一、深入理解Java中的堆跟栈
Java把内存划分为两种:一种是栈内存、一种是堆内存;
1、堆(heap)和栈(stack)都是java用来在Ram中存放数据的,java是自动管理栈和堆的,程序员不可以直接设置堆栈;
2、栈的优势是存取速度比堆要快,仅次于寄存器,缺点是栈中的数据大小跟生命周期必须是确定的,缺乏灵活,栈的数据可以共享;
3、堆的优势在于自动分配内存的大小,生存期也不必告诉编译器,Java垃圾收集器会自动回收不用的数据,缺点是运行时自动分配内存的大小,存取速度慢;
4、java存储数据的六个地方
(1)寄存器
(2)堆栈(stack)
(3)堆(heap)
(4)静态变量
(5)常用变量
(6)非RAM存储
5、栈中存储的有:在函数中定义的一些基本类型的变量和对象的引用变量
堆中存储的有:new的对象跟数组
6、对象的引用变量理解
java中,这里的“=”不是赋值的意思,而是对象的地址传给了变量;
对象创建出来,其实连名字都没有,因此必须通过变量来对其进行操作;
二、Java的设计模式
1、单例模式
具备典型的3个特点:1、只有一个实例。 2、自我实例化。 3、提供全局访问点。
比如:redis的使用只需要是实例化一次,要用的时候直接使用getinstance的方法直接进行操作;service跟dao层也是单例模式,实例化一次,大家一起用,在项目启动的时候只扫描一次
创建一个单例模式
public class MyJava{
//创建 SingleObject 的一个对象
private static MyJava myJava= new MyJava();
//让构造函数为 private,这样该类就不会被实例化
private MyJava(){};
public static MyJava getinstance(){
return myJava;
}
public void showMessage(){
System.out.println("Hello World!");
}
}
2、工厂模式
作为抽象工厂模式的孪生兄弟,工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个,也就是说工厂方法模式让实例化推迟到子类。
3、代理模式
代理模式就是给一个对象提供一个代理,并由代理对象控制对原对象的引用。它使得客户不能直接与真正的目标对象通信。代理对象是目标对象的代表,其他需要与这个目标对象打交道的操作都是和这个代理对象在交涉。
代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了的作用和保护了目标对象的,同时也在一定程度上面减少了系统的耦合度。
4、其余的:
设计模式的六大原则
-
开闭原则:实现热插拔,提高扩展性。
-
里氏代换原则:实现抽象的规范,实现子父类互相替换;
-
依赖倒转原则:针对接口编程,实现开闭原则的基础;
-
接口隔离原则:降低耦合度,接口单独设计,互相隔离;
-
迪米特法则,又称不知道原则:功能模块尽量独立;
-
合成复用原则:尽量使用聚合,组合,而不是继承;
三、八种基本数据类型的大小以及它们的封装类
八种基本数据类型:byte,short,int,long,double,float,boolean,char
封装类:byte,short,Integer,long,double,float,boolean,character
四、Switch能否用String作为参数?
java1.7之前byte,short,int,char四种基本数据类型跟封装类,
jdk1.7以后,整形、枚举、字符串
jdk1.7并没有新的指令来处理switch string,而是通过调用switch中string.hashCode,将string转换为int从而进行判断。
五、枚举的创建以及用法
https://blog.csdn.net/testcs_dn/article/details/78604547
创建:
public enum Color{
HUANGSE,LANSE,LVSE,ZISE;
//RED("红色", 1) 注释:VALUE("NAME",INDEX)
}
六、equals与==的区别
(1)==是指两个变量或者对象是不是指向一个内存空间
equals是指两个变量或者对象所指向内存空间的值是不是相同
(2)==是内存地址的比较
equals 是字符串内容的比较
(3)==是指引用相同
equals是指值是否相同
七、自动装箱 拆箱
比如:
int s= 1;//常量
Integer s1 = new Integer(100);
s1 = s;//自动装箱
int s2 = s1;//自动拆箱
八、Java中公共方法有那些?8个
(1)clone();
(2)hashode();
(3)equals();
(4)wait();
(5)notify();
(6)notifyAll();
(7)toString();
(8)getClass();
九、Java的四种引用,强弱软虚?
(1)String a = "1";垃圾回收站不会回收
(2)用于描述但不是必须的,内存不满的时候不会回收,内存不够的时候就会回收
(3)垃圾回收站的扫描器扫描到的时候才会进行回收
(4)虚引很弱,不管有没有对象有没有它,在任何时候都有可能被垃圾回收站回收,虚引必须跟引用队列联合使用,当回收站回收对象的时候,如果发现该对象存在虚引,把这个虚引加入到与之关联的引用队列当中;
十、HashCode的作用
主要是用于查找的快捷性,如:hashMap,HashTable中hashCode用来确定存储地址
从Object的角度来说,JVM每次new一个Object,它都会将这个Object丢掉Hash表中,如果这个Object要做比较或者读取的时候,会根据HashCode是不是一致,一直的话再去进行equals()方法;
十一、HashMap的hashcode的作用
hashCode主要是用于查找的快捷性,如HashTable、HashCode是用来在散列存储结果中确定对象的存储地址;
十二、为什么要重载equals()跟hashCode()方法呢?
一般不需要重载,只有类需要放在HashMap,HashMap,HashSet等Hash结构的集合时才需要重载,比如:要收集某一个属性相同的几个对象,这时候就需要重写
equals为true时,HashCode一定相等,HashCode相等时,equals不一定是true;
十三、ArrayList、LinkedList、Vector的区别
ArrayList数组结构,查询快,增删慢,非安全性,效率高
LinkedList链表结构,查询慢,效率低,增删快,安全性高
Vector 数组结构,查询快,增删慢、线程安全、效率低
十四、String、StringBuilder、StringBuffer的区别
String:适用于少量的字符串操作的情况。 StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况。 StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况。 StringBuilder:是线程不安全的,而StringBuffer是线程安全的。
这三个类之间的区别主要是在两个方面,即运行速度和线程安全这两方面。 首先说运行速度,或者说是执行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer > String。
String最慢的原因
String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的。
再来说线程安全
在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的。
十五、Map、Set、List、Queue、Stack的特点与用法
https://blog.csdn.net/baidu_34122324/article/details/83388175
Map是键值对,键Key是唯一不能重复的,一个键对应一个值,值可以重复。
-
TreeMap可以保证顺序。
-
HashMap不保证顺序,即为无序的。
-
Map中可以将Key和Value单独抽取出来,其中KeySet()方法可以将所有的keys抽取正一个 Set。而Values()方法可以将map中所有的values抽取成一个集合。
-
HashTable 和 HashMap 是 Map 的实现类。
-
HashTable 是线程安全的,不能存储 null 值。
-
HashMap 不是线程安全的,可以存储 null 值。
Set
-
不包含重复元素的集合,set中最多包含一个null元素。
-
只能用Lterator实现单项遍历,Set中没有同步方法。
List
-
有序的可重复集合。
-
可以在任意位置增加删除元素。
-
用Iterator实现单向遍历,也可用ListIterator实现双向遍历。
Queue
-
Queue遵从先进先出原则。
-
使用时尽量避免add()和remove()方法,而是使用offer()来添加元素,使用poll()来移除元素,它的优点是可以通过返回值来判断是否成功。
-
LinkedList实现了Queue接口。
-
Queue通常不允许插入null元素。
Stack
-
Stack遵从后进先出原则。
-
Stack继承自Vector。
-
它通过五个操作对类Vector进行扩展,允许将向量视为堆栈,它提供了通常的push和pop操作,以及取堆栈顶点的peek()方法、测试堆栈是否为空的empty方法等。
十六、HashMap和HashTable的区别
1、hashMap去掉了HashTable?的contains方法,但是加上了containsValue()和containsKey()方法,HashTable线程安全性,hashMap线程不安全
2、Hashtable不允许 null 值(key 和 value 都不可以),HashMap允许 null 值(key和value都可以)。
3、两者的遍历方式大同小异,Hashtable仅仅比HashMap多一个elements方法。
4、HashTable使用Enumeration,HashMap使用Iterator,HashTable直接使用对象的HashCoded值,但是HashMap重新计算的hashCode的值
十七、JDK7与JDK8中HashMap的实现
当向 HashMap 中 put 一对键值时,它会根据 key的 hashCode 值计算出一个位置, 该位置就是此对象准备往数组中存放的位置。
如果该位置没有对象存在,就将此对象直接放进数组当中;如果该位置已经有对象存在了,则顺着此存在的对象的链开始寻找(为了判断是否是否值相同,map不允许<key,value>键值对重复), 如果此链上有对象的话,再去使用 equals方法进行比较,如果对此链上的每个对象的 equals 方法比较都为 false,则将该对象放到数组当中,然后将数组中该位置以前存在的那个对象链接到此对象的后面。
JDK8中的HashMap
JDK8中采用的是位桶+链表/红黑树(有关红黑树请查看红黑树)的方式,也是非线程安全的。
十八、如何使用安全的HashMap?
三种方式:Hashtable ConcurrentHashMap SynchronizedMap
例子
//Hashtable Map<String, String> hashtable = new Hashtable<>(); //synchronizedMap Map<String, String> synchronizedHashMap = Collections.synchronizedMap(new HashMap<String, String>()); //ConcurrentHashMap Map<String, String> concurrentHashMap = new ConcurrentHashMap<>();
ConcurrentHashMap 性能是明显优于 Hashtable 和 SynchronizedMap 的,CHM 花费的时间比前两个的一半还少。
十九、TreeMap、HashMap、LindedHashMap的区别
LinkedHashMap可以保证H ashMap集合有序,存入的顺序和取出的顺序一致。
TreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。
HashMap不保证顺序,即为无序的,具有很快的访问速度。 HashMap最多只允许一条记录的 键为Null;允许多条记录的值为 Null。 HashMap不支持线程的同步。
我们在开发的过程中使用HashMap比较多,在Map中在Map 中插入、删除和定位元素,HashMap 是最好的选择。
但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。
如果需要输出的顺序和输入的相同,那么用LinkedHashMap 可以实现,它还可以按读取顺序来排列。
二十、Collection包结构,与Collections的区别?
Collection 是集合类的上级接口,子接口主要有Set、List 。
Collecions 是针对集合类的一个帮助类, 提供了操作集合的工具方法,一系列静态方法实现对各种集合的搜索、排序线性、线程安全化等操作。
例如
Map<String, Object> map4 = Collections.synchronizedMap(new HashMap<String, Object>()); 线程安全 的HashMap Collections.sort(List<T> list, Comparator<? super T> c); 排序 List
二十一、try?catch?finally,try里有return,finally还执行么
肯定会执行。finally{}块的代码。 只有在try{}块中包含遇到System.exit(0)。 之类的导致Java虚拟机直接退出的语句才会不执行。
当程序执行try{}遇到return时,程序会先执行return语句,但并不会立即返回——也就是把return语句要做的一切事情都准备好,也就是在将要返回、但并未返回的时候,程序把执行流程转去执行finally块,当finally块执行完成后就直接返回刚才return语句已经准备好的结果
二十二、Excption与Error包结构。OOM你遇到过哪些情况,SOF你遇到过哪些情况 异常分为Checked异常跟RUNTIME(运行时)异常
常见的RUNTIME运行时异常:空指针、数组越界、运算异常
-
IndexOutOfBoundException:数组越界异常;
-
NullPointerException:空指针异常;
-
ClassCastException:类转换异常;
-
NumberFormatException:数字格式异常;
-
ArithmeticException:运算异常。
Checked异常(非运行时异常):
-
SQLException:SQL异常;
-
IOException:IO异常;
-
FileNotFoundException:文件找不到异常,是IOException的子类;
-
InterruptedException:中断异常,一般用在多线程编程;
-
ClassNotFoundException:类找不到。
Error:一般指的虚拟机运行异常,如系统崩溃、虚拟机错误、动态链接失效等,这种错误无法恢复或不可被捕获,将导致应用程序中断。通常应用程序也无法处理这些错误,因此程序中不应该试图使用catch来捕获Error对象。在方法定义时,也无需throws Error对象。
OOM(堆内存溢出)的情况:
Java heap溢出,一般我们不断的创建对象就会出现这种情况
SOM(栈内存溢出)的情况:
Java StackOverflowError ,一般递归调用,出现大量的循环或者死循环,全局变量是否过多。数组、List、map数据过大。
二十三、Java(OOP)面对对象的三个特征与含义
1、封装
public(都可以访问)
protect (本包中类以及其他包的子类)
defalut(默认本包中可以访问)
private(只有本类可以访问)
2、继承
对象可以继承父对象的属性和行为,父类有的属性跟行为,子类也同样有
3、多态
重写(override)
规则:
-
方法名、参数、返回值相同。
-
子类方法不能缩小父类方法的访问权限。
-
子类方法不能抛出比父类方法更多的异常(但子类方法可以不抛出异常)。
-
存在于父类和子类之间。
-
方法被定义为final不能被重写。
重载(overload)
规则:
-
参数类型、个数、顺序至少有一个不相同。
-
不能重载只有返回值不同的方法名。
-
存在于父类和子类、同类中。
重载:(1)必须具有不同的参数列表。
(2)可以有不同的返回类型,只要参数列表不同就可以了。
(3)可以有不同的访问修饰符。
(4)可以抛出不同的异常。
二十四、Java接口interface
接口:描述对象有哪些属性,只能有成员变量,只能由方法的声明
示例:
创建接口:
public interface MyInterface{
public int NUM_PHONE = 5;//成员变量 默认用public static final来修饰
String display(); //方法声明 默认用public abstract
}
定义接口
public class Lecture inplements MyInterface{
@Override//对接口方法进行重写
public String display(){
system.out.printIn("1111");
return "接口MyInteeface的重写,读取lecture"
}
}
接口的继承
public interface Sport{
public void setName();
public void setId();
}
public interface baseball extends Sport{
public void setY();
public void setF();
}
baseball 就会有四个方法声明,接口可以进行多继承。
接口的特性:
1、接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。
2、接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是public,用 private 修饰会报编译错误)。
3、接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。
4、接口没有构造方法。
5、接口中所有的方法必须是抽象方法。
抽象方法的理解(https://blog.csdn.net/robert_chen1988/article/details/93171938)
6、接口不能包含成员变量,除了 static 和 final 变量。
7、接口不是被类继承了,而是要被类实现。
8、接口支持多继承。
9、除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。
10、接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。
二十五、Java的抽象类/抽象方法
java抽象类的特点:用abstract来修饰
1、抽象类无法被实例化
2、子类继承抽象类然后实例化子类
3、子类继承抽象类必须实现抽象类中的抽象方法
示例:
定义一个抽象类:
抽象类无法被实例化,我们可以让子类继承然后实例化:
然后实例化子类:
注:子类继承父类必须实现父类的所有抽象方法,如果抽象类继承抽象类的话就可以不用继承抽象方法,显然抽象子类也不可以进行实例化。
二十六、Java中Interface跟abstract类的区别
interface只能有成员变量,只能是方法的声明,Abstract class(抽象类)可以有成员变量,也可以有抽象方法跟普通方法
Interface是接口,所有的方法都是抽象方法,成员变量默认的是public static final 类型,接口不能实例化自己。
Abstract class是抽象类,至少包含一个方法是抽象方法,抽象类不能被自身实例化,并且用abstract关键字来修饰。
二十七、Static class与non Static class的区别?
static class(内部静态类)
1、用static修饰的都是内部类,此时这个内部类变为静态内部类,对测试有用
2、静态内部类不需要有指向外部类的引用
3、静态类只能访问外部类的静态成员,不能访问外部类的非静态成员
non static class(非静态内部类)
1、非静态内部类需要持有对外部类的引用
2、非静态内部类能够访问外部类的静态和非静态成员
3、一个非静态内部类不能脱离外部类实体被创建
4、一个非静态内部类可以访问外部类的数据和方法
二十八、foreach跟for循环效率对比
如果是arraylist,底层是数据结构的集合,采用小标访问,for循环的效率高,
如果是linklist,底层是链表结构的,foreach的循环效率高 插入删除效率高,查询慢
二十九、Java的IO跟NIO
概念:NIO是为了弥补 IO 操作不足而产生的,NIO有一些新特性:非阻塞I/O,选择器,缓冲以及管道,管道、缓冲、选择器是其主要特征。
Channel——管道实际上就像传统IO中的流,到任何目的地(或来自任何地方)的所有数据都必须 通过一个 Channel 对象。一个 Buffer 实质上是一个容器对象。
每一种基本 Java 类型都有一种缓冲区类型:
ByteBuffer——byte CharBuffer——char ShortBuffer——short IntBuffer——int LongBuffer——long FloatBuffer——float DoubleBuffer——double
Selector——选择器用于监听多个管道的事件,使用传统的阻塞IO时我们可以方便的知道什么时候可以进行读写,而使用非阻塞通道,我们需要一些方法来知道什么时候通道准备好了,选择器正是为这个需要而诞生的。
NIO跟IO的区别?
(1)IO是面向流的,NIO是面向块(缓冲区)的;
(2)IO是阻塞的,NIO是非阻塞的
使用场景:
如果是有成千上万的连接,每个连接的数据量很小,这样的话可以使用NIO
如果连接很小,但是每个连接都有很多的数据,这样的话使用传统的IO
三十、Java的反射
通过class对象来获取它的方法、属性、父类等类的内部信息机制。
作用:在任意的方法里面
1.如果我知道一个类的名称/或者它的一个实例对象, 我就能把这个类的所有方法和变量的信息 找出来(方法名,变量名,方法,修饰符,类型,方法参数等等所有信息)
2.如果我还明确知道这个类里某个变量的名称,我还能得到这个变量当前的值。
3.当然,如果我明确知道这个类里的某个方法名+参数个数类型,我还能通过传递参数来运行那个类里的那个方法。
反射机制主要提供了以下功能:
-
在运行时判断任意一个对象所属的类。
-
在运行时构造任意一个类的对象。
-
在运行时判断任意一个类所具有的成员变量和方法。
-
在运行时调用任意一个对象的方法。
-
生成动态代理。
反射的原理?
Java编译之后会生成一个class文件,反射就是通过字节码文件找到某一个类、类中的方法以及属性。
反射的实现API有哪些?
反射的实现主要借助以下四个类:
Class:类的对象 Constructor:类的构造方法 Field:类中的属性对象 Method:类中的方法对象
三十一、泛型常用特点
List<String>能否转为List<Object>
不可以强转类型的
这个问题涉及到了,范型向上转型 和 范型向下转型问题。 List向上转换至List(等价于List)会丢失String类的身份(String类型的特有接口)。 当需要由List向下转型时,你的程序必须明确的知道将对象转换成何种具体类型,不然这将是不安全的操作。
如果要强转类型,Json 序列化转型
List<String> str = new ArrayList<String>(); List<Object> obj= JSONObject.parseArray(JSONObject.toJSONString(str));
或者遍历,或者克隆,但是取出来就是(Object)了,需要强转,String 因为类型丢了。
三十一、XML的解析方式
第一种:DOM解析出来之后是一个树状结构,搜索、查找都比较方便。如果是大的文件,解析起来就很耗内存
第二种:SAX,它是基于流的,可以边解析边处理问题,sax解析器核心是事件处理机制。
例如解析器发现一个标记的开始标记时,将所发现的数据会封装成为一个标记开始事件,并把这个报告给时间处理器。
三十二、Java1.7与1.8,1.9,10 新特性
1.5
-
自动装箱与拆箱
-
枚举(常用来设计单例模式)
-
静态导入
-
可变参数
-
内省
1.6
-
Web服务元数据
-
脚本语言支持
-
JTable的排序和过滤
-
更简单,更强大的JAX-WS
-
轻量级Http Server
-
嵌入式数据库 Derby
1.7
-
switch中可以使用字串了
-
运用List tempList = new ArrayList<>(); 即泛型实例化类型自动推断
-
语法上支持集合,而不一定是数组
-
新增一些取环境信息的工具方法
-
Boolean类型反转,空指针安全,参与位运算
-
两个char间的equals
-
安全的加减乘除
-
map集合支持并发请求,且可以写成 Map map = {name:"xxx",age:18};
1.8
-
允许在接口中有默认方法实现
-
Lambda表达式
-
函数式接口
-
方法和构造函数引用
-
Lambda的范围
-
内置函数式接口
-
Streams
-
Parallel Streams
-
Map
-
时间日期API
-
Annotations
1.9
-
Jigsaw 项目;模块化源码
-
简化进程API
-
轻量级 JSON API
-
钱和货币的API
-
改善锁争用机制
-
代码分段缓存
-
智能Java编译, 第二阶段
-
HTTP 2.0客户端
-
Kulla计划: Java的REPL实现
10
-
本地变量类型推断
-
统一JDK仓库
-
垃圾回收器接口
-
G1的并行Full GC
-
应用程序类数据共享
-
ThreadLocal握手机制
三十三、AOP跟OOP
AOP是面向切面,利用AOP对业务逻辑的各个部分隔离,提高程序的可复用性,降低耦合度
OOP是面向对象变成,是针对业务处理中的实体以及其实体属性进行抽象封装,以获得更加清晰高校的逻辑单元划分。
举例:
对于“雇员”这样一个业务实体进行封装,自然是OOP的任务,我们可以建立一个“Employee”类,并将“雇员”相关的属性和行为封装其中。而用AOP 设计思想对“雇员”进行封装则无从谈起。
同样,对于“权限检查”这一动作片段进行划分,则是AOP的目标领域。
OOP面向名次领域,AOP面向动词领域。
总之AOP可以通过预编译方式和运行期动态代理实现在不修改源码的情况下,给程序动态同意添加功能的一项技术。
三十四、过滤器(Filter)跟拦截器(Interceptor)的区别?
过滤器配置在web.xml中,将传入的request、response提前过滤掉一些信息,或者提前设置参数,然后在传入servlet中的action进行处理业务,比如过滤掉非法的URL等。
拦截器在SringMVC的配置文件中,在访问action之前或者之后触发
区别:
①:拦截器是基于java的反射机制的,而过滤器是基于函数的回调。
②:拦截器不依赖于servlet容器,而过滤器依赖于servlet容器。
③:拦截器只对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
④:拦截器可以访问action上下文、值、栈里面的对象,而过滤器不可以。
⑤:在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
⑥:拦截器可以获取IOC容器中的各个bean,而过滤器不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。
三十五、如何让索引失效?
如果是同样的sql如果在之前能够使用到索引,那么现在使用不到索引,以下几种主要情况:
-
随着表的增长,where条件出来的数据太多,大于15%,使得索引失效(会导致CBO计算走索引花费大于走全表)
-
统计信息失效 需要重新搜集统计信息
-
索引本身失效 需要重建索引
具体情况:
1.单独引用复合索引里非第一位置的索引列
2.对索引列运算,运算包括(+、-、*、/、!、<>、%、like’%_’(%放在前面)、or、in、exist等),导致索引失效。
3.对索引应用内部函数,这种情况下应该建立基于函数的索引。
4.类型错误,如字段类型为varchar,where条件用number。
5.如果MySQL预计使用全表扫描要比使用索引快,则不使用索引
6.like的模糊查询以%开头,索引失效
7.索引列没有限制 not null,索引不存储空值,如果不限制索引列是not null,oracle会认为索引列有可能存在空值,所以不会按照索引计算
三十六、多线程的使用
使用线程池使用线程Excutetor
多线程使用方式://https://www.cnblogs.com/10158wsj/p/8338367.html
三十七、重定向、转发的区别
1、转发用的是getRequestDispatcher();重定向使用的是sendRedirect();
2、转发浏览器器地址栏地址不变,重定向浏览器的地址会改变
3、转发是服务器端的,重定向是客户端
4、转发浏览器只发送了一次请求,重定向浏览器至少做了两次请求
5、转发两次跳转之间传输的数据不会丢失,重定向两次跳转之后信息会丢失
三十八、Filter、Interceptor、Spring AOP
Filter过滤器:拦截web访问url地址。
Interceptor拦截器:拦截以 .action结尾的url,拦截Action的访问。
Spring AOP拦截器:只能拦截Spring管理Bean的访问(业务层Service)