**///**
- 公平锁和非公平锁
在ReentrantLock中同步包括两种,分别是公平的FairSync和非公平的NonfairSync。公平锁的作用就是严格按照线程启动的顺序来执行的,不允许其他线程插队执行的;而非公平锁是允许插队的。
- 默认情况下ReentrantLock是通过非公平锁来进行同步的,包括synchronized关键字都是如此,因为这样性能会更好。因为从线程进入了RUNNABLE状态,可以执行开始,到实际线程执行是要比较久的时间的。而且,在一个锁释放之后,其他的线程会需要重新来获取锁。其中经历了持有锁的线程释放锁,其他线程从挂起恢复到RUNNABLE状态,其他线程请求锁,获得锁,线程执行,这一系列步骤。如果这个时候,存在一个线程直接请求锁,可能就避开挂起到恢复RUNNABLE状态的这段消耗,所以性能更优化。
- Condition介绍
Condition的作用是对锁进行更精确的控制。Condition中的await()方法相当于Object的wait()方法,Condition中的signal()方法相当于Object的notify()方法,Condition中的signalAll()相当于Object的notifyAll()方法。不同的是,Object中的wait(),notify(),notifyAll()方法是和"同步锁"(synchronized关键字)捆绑使用的;而Condition是需要与"互斥锁"/"共享锁"捆绑使用的。
**///**
HashMap和LinkedHashMap的区别
HashMap可以允许一条键为null的键值对,允许多条值为null的键值对,其并发不安全,如果想并发安全操作可以使用Collections.synchronizedMap()方法或ConcurrentHashMap来代替。
LinkedHashMap是HashMap的一个子类,其特殊实现的仅仅是保存了记录的插入顺序,所以在Iterator迭代器遍历LinkedHashMap时先得到的键值是先插入的(也可以在构造时用带参构造方法来改变顺序为按照使用进行排序),由于其存储沿用了HashMap结构外还多了一个双向顺序链表,所以在一般场景下遍历时会比HashMap慢,此外具备HashMap的所有特性和缺点。
所以一般情况下,我们用的最多的是HashMap,如果需要按照插入或者读取顺序来排列时就使用LinkedHashMap。
**///**
synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:
1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
3. 修饰一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
4. 修饰一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。
**///**
- HashMap,LinkedHashMap,TreeMap的区别
HashMap
HashMap 是一个最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度。遍历时,取得数据的顺序是完全随机的。
HashMap最多只允许一条记录的键为Null;允许多条记录的值为 Null。
HashMap不支持线程的同步(即任一时刻可以有多个线程同时写HashMap),可能会导致数据的不一致。如果需要同步,可以用 Collections的synchronizedMap方法使HashMap具有同步的能力,或者使用ConcurrentHashMap。
Hashtable与 HashMap类似,它继承自Dictionary类。不同的是:它不允许记录的键或者值为空;它支持线程的同步(即任一时刻只有一个线程能写Hashtable),因此也导致了 Hashtable在写入时会比较慢。
LinkedHashMap
LinkedHashMap保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的。也可以在构造时带参数,按照应用次数排序。
在遍历的时候会比HashMap慢,不过有种情况例外:当HashMap容量很大,实际数据较少时,遍历起来可能会比LinkedHashMap慢。因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和他的容量有关。
TreeMap
TreeMap实现SortMap接口,能够把它保存的记录根据键排序。
默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。
三种类型分别在什么时候使用
1、一般情况下,用的最多的是HashMap。HashMap里面存入的键值对在取出的时候是随机的,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。在Map 中插入、删除和定位元素,HashMap 是最好的选择。
2、TreeMap取出来的是排序后的键值对。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。
3、LinkedHashMap 是HashMap的一个子类,如果需要输出的顺序和输入的相同,那么用LinkedHashMap可以实现,它还可以按读取顺序来排列,像连接池中可以应用。
**///**
1、map
Java为数据结构中的映射定义了一个接口java.util.Map,此接口主要有四个常用的实现类,分别是HashMap、Hashtable、LinkedHashMap和TreeMap
hashMap:
HashMap中capacity、loadFactor、threshold、size等概念的解释
1)size表示HashMap中存放KV的数量(为链表和树中的KV的总和)。
2)capacity译为容量。capacity就是指HashMap中桶的数量。默认值为16。
扩容时会扩容到之前的两倍
3)loadFactor译为装载因子。装载因子用来衡量HashMap满的程度。loadFactor的默认值为0.75f。计算HashMap的实时装载因子的方法为:size/capacity,而不是占用桶的数量去除以capacity。
装载因子的作用:当创建 HashMap 时,有一个默认的负载因子(load factor),其默认值为 0.75,这是时间和空间成本上一种折衷:增大负载因子可以减少 Hash 表(就是那个 Entry 数组)所占用的内存空间,但会增加查询数据的时间开销,而查询是最频繁的的操作(HashMap 的 get() 与 put() 方法都要用到查询);减小负载因子会提高数据查询的性能,但会增加 Hash 表所占用的内存空间。
4)threshold表示当HashMap的size大于threshold时会执行resize操作。
threshold=capacity*loadFactor
5)hashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,hashCode是用来在散列存储结构中确定对象的存储地址的;
6)hash中桶的概念
哈希表中同一个位置可能存有多个元素,以应对哈希冲突问题。这样,哈希表中的每个位置表示一个哈希桶。
7)hashMap存取的特点
HashMap通过键的hashCode来快速的存取元素。
当不同的对象发生碰撞时,HashMap通过单链表来解决,将新元素加入链表表头,通过next指向原有的元素。单链表在Java中的实现就是对象的引用(复合)。
8)为什么Hash冲突会造成HashMAp的查询效率低下?
HashMap里面没有出现hash冲突时,没有形成单链表时,hashmap查找元素很快,get()方法能够直接定位到元素,但是出现单链表后,单个bucket 里存储的不是一个 Entry,而是一个 Entry 链,系统只能必须按顺序遍历每个 Entry,直到找到想搜索的 Entry 为止——如果恰好要搜索的 Entry 位于该 Entry 链的最末端(该 Entry 是最早放入该 bucket 中),那系统必须循环到最后才能找到该元素。
9)为什么要用数组加链表实现存储?
数组:存储区间连续,占用内存严重,寻址容易,插入删除困难
链表:存储区间离散,占用内存比较宽松,寻址困难,插入删除容易
10)put的原理
我们用table[index]表示已经找到的元素需要存储的位置。先判断该位置上有没有元素(这个元素是HashMap内部定义的一个类Entity, 基本结构它包含三个类,key,value和指向下一个Entity的next),没有的话就创建一个Entity<K,V>对象,在 table[index]位置上插入,这样插入结束;如果有的话,通过链表的遍历方式去逐个遍历,看看有没有已经存在的key,有的话用新的value替 换老的value;如果没有,则在table[index]插入该Entity,把原来在table[index]位置上的Entity赋值给新的 Entity的next,这样插入结束。
10 HashMap和HashTable对比?
hashMap可以接受null值但是HashTable不可以
HAshMap是线程不安全的但是HashTable是线程安全的
由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap 慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。
hashMap中去掉了Contions方法
HashTable比HashMAp老旧,HAshTable继承自Dictionary类,Dictionary类现在已经过时的一个类
11)LinkedHashMap
LinkedHashMap是HashMap的一个子类,能保存记录的插入顺序,在遍历的时候会比HashMap慢,不过有种情况例外,当HashMap容量很大,实际数据较少时,遍历起来可能会比 LinkedHashMap慢,因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和他的容量有关。
12)treeMap
TeeMap能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。
**///**
一般情况下,我们用的最多的是HashMap,在Map 中插入、删除和定位元素,HashMap 是最好的选择。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。如果需要输出的顺序和输入的相同,那么用LinkedHashMap 可以实现,它还可以按读取顺序来排列.
TreeMap:基于红黑二叉树的NavigableMap的实现,线程非安全,不允许null,key不可以重复,value允许重复,存入TreeMap的元素应当实现Comparable接口或者实现Comparator接口,会按照排序后的顺序迭代元素,
2、对比currentHashMap
currentHashMap是JDK1.5的并发包下提供的一个线程安全的Map但是相对于HashTable来说效率要高,该类并没有直接实现Map接口而是实现ConCurrentMap接口
ConCurrentMap接口继承map接口
currentHashMap使用分段锁的概念,它只会锁操作的那一段数据而不是整个Map都上锁。
ConcurrentHashMap有很好的扩展性,在多线程环境下性能方面比做了同步的HashMap要好,做了同步的HashMap和HashTable在并发效率上区别不大,但是在单线程下HashMap的效率高于ConcurrentHashMap
concurrentHashMap的原理:
一个ConcurrentHashMap由多个segment组成,每一个segment都包含了一个HashEntry数组的hashtable, 每一个segment包含了对自己的hashtable的操作,比如get,put,replace等操作,这些操作发生的时候,对自己的hashtable进行锁定。由于每一个segment写操作只锁定自己的hashtable,所以可能存在多个线程同时写的情况,性能无疑好于只有一个hashtable锁定的情况。
Segment继承了ReentrantLock,所以它就是一种可重入锁(ReentrantLock)。在ConcurrentHashMap,一个Segment就是一个子哈希表,Segment里维护了一个HashEntry数组,并发环境下,对于不同Segment的数据进行操作是不用考虑锁竞争的。(就按默认的ConcurrentLeve为16来讲,理论上就允许16个线程并发执行)
**///**
1.7的JDK
List
JAVA中为java.util.List接口提供的几个常用的实现类讲解ArrayList,LinkedList,Vector
1、ArrayList
2、LinkedList
也是线程不安全的
List list = Collections.synchronizedList(new LinkedList(…));可创建一个线程安全的LinkedList
3、Vector
Vector是线程安全的
ArrayList和Vector都采用线性连续存储空间,当存储空间不足的时候,ArrayList默认增加为原来的50%,Vector默认增加为原来的一倍;
Vector可以设置capacityIncrement(容量增量)
而ArrayList不可以,从字面理解就是capacity容量,Increment增加,容量增长的参数。
**///**
JDK1.7
Set接口的实现类 HashSet, LinkedHashSet, TreeSet
1、hashSet
HashSet类的特点:能够快速定位集合中的元素、集合中的元素无序(这里所谓的无序并不是完全无序,只是不像List集合按对象的插入顺序保存对象)。
由HashSet类实现的Set集合中的对象必须是惟一的,因此需要添加到HashSet集合中的对象,需要重新实现equals()方法,从而保证插入集合中对象的标识的惟一性。
由HashSet类实现的Set集合的排列方式为按照哈希码排序,根据对象的哈希码确定对象的存储位置,因此需要添加到由HashSet类实现的Set集合中的对象,还需要重新实现hashCode()方法,从而保证插入集合中的对象能够合理地分布在集合中,以便于快速定位集合中的对象。
2、LinkedHashSet
LinkedHashSet是HashSet的子类,该类的方法全部是父类的方法
父类HashSet再利用内部集成的LinkedHashMap来实现按元素的最后访问次序来迭代遍历
对LinkedHashSet的支持
HashSet有一个默认访问权限的构造方法,其中创建了LinkedHashMap用来存储对象
这个构造方法只有LinkedHashSet会调用
3、TreeSet
TreeSet 是一个有序的集合,它的作用是提供有序的Set集合。它继承于AbstractSet抽象类,实现了NavigableSet<E>, Cloneable, java.io.Serializable接口。
TreeSet 继承于AbstractSet,所以它是一个Set集合,具有Set的属性和方法。
TreeSet 实现了NavigableSet接口,意味着它支持一系列的导航方法。比如查找与指定目标最匹配项。
TreeSet 实现了Cloneable接口,意味着它能被克隆。
TreeSet 实现了java.io.Serializable接口,意味着它支持序列化。
TreeSet是基于TreeMap实现的。
TreeSet是非线程安全的。
**///**
自动装箱和自动拆箱:
因为不可以直接把基本数据类型赋值给引用数据类型。所以在JDK1.5之前,构建一个包装类需要通过构造器来构造包装类对象,但是这显得代码过于麻烦,所以从1.5之后就提供了自动装箱和自动拆箱的功能。
自动装箱:就是可以把一个基本类型变量直接赋值给对应的包装类变量,或者赋值给Object变量(因为Object类是所有类的父类);
自动拆箱:与自动装箱相反,允许直接把包装类对象直接赋值给一个对应的基本类型变量。
自动拆箱装箱的原理:
自动拆装箱不是虚拟机完成的,这个过程实际上是由编译器完成的,当编译器对 .java 源代码进行编译时,如果发现你没有进行拆箱,那么编译器来来帮你拆;如果你没有装箱,那么编译器来帮你装,而不是由虚拟机完成的。这个原理我们可以对代码进行反编译来解释,如下。
编译之前:
public class Demo1 {
// 自动拆箱
public void method1() {
Integer i = new Integer(100);
int a = i;
}
// 自动装箱
public void method2() {
Integer i = 100;
}
}
反编译以后:
public class Demo1
{
public void method1()
{
Integer i = new Integer(100);
int a = i.intValue();
}
public void method2()
{
Integer i = Integer.valueOf(100);
}
}
………………………………………………………………………………………………………
- HashMap和LinkedHashMap的区别
HashMap可以允许一条键为null的键值对,允许多条值为null的键值对,其并发不安全,如果想并发安全操作可以使用Collections.synchronizedMap()方法或ConcurrentHashMap来代替。
LinkedHashMap是HashMap的一个子类,其特殊实现的仅仅是保存了记录的插入顺序,所以在Iterator迭代器遍历LinkedHashMap时先得到的键值是先插入的(也可以在构造时用带参构造方法来改变顺序为按照使用进行排序),由于其存储沿用了HashMap结构外还多了一个双向顺序链表,所以在一般场景下遍历时会比HashMap慢,此外具备HashMap的所有特性和缺点。
所以一般情况下,我们用的最多的是HashMap,如果需要按照插入或者读取顺序来排列时就使用LinkedHashMap。 - HashMap,LinkedHashMap,TreeMap的区别
HashMap
HashMap 是一个最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度。遍历时,取得数据的顺序是完全随机的。
HashMap最多只允许一条记录的键为Null;允许多条记录的值为 Null。
HashMap不支持线程的同步(即任一时刻可以有多个线程同时写HashMap),可能会导致数据的不一致。如果需要同步,可以用 Collections的synchronizedMap方法使HashMap具有同步的能力,或者使用ConcurrentHashMap。
Hashtable与 HashMap类似,它继承自Dictionary类。不同的是:它不允许记录的键或者值为空;它支持线程的同步(即任一时刻只有一个线程能写Hashtable),因此也导致了 Hashtable在写入时会比较慢。
LinkedHashMap
LinkedHashMap保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的。也可以在构造时带参数,按照应用次数排序。
在遍历的时候会比HashMap慢,不过有种情况例外:当HashMap容量很大,实际数据较少时,遍历起来可能会比LinkedHashMap慢。因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和他的容量有关。
TreeMap
TreeMap实现SortMap接口,能够把它保存的记录根据键排序。
默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。
三种类型分别在什么时候使用
1、一般情况下,用的最多的是HashMap。HashMap里面存入的键值对在取出的时候是随机的,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。在Map 中插入、删除和定位元素,HashMap 是最好的选择。
2、TreeMap取出来的是排序后的键值对。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。
3、LinkedHashMap 是HashMap的一个子类,如果需要输出的顺序和输入的相同,那么用LinkedHashMap可以实现,它还可以按读取顺序来排列,像连接池中可以应用。
…………………………………………………………………………………………………………………………………………………….
0 HashMap 是基于数组与链表来实现的,默认容量16,默认装载系数0.75,阀值【默认长度X0.75】数组查询比较快,而链表增删改比较快,其中的put方法,看table是否为空,若为空,进行初始化.首先传入K与V键值对判断key的值是否为nullkey若为null 则放在hash表首位,不为null 求出hash值,根据hash值与数组的长度 做与的运算 来判断把元素放到hash表的那个位置首先看当前key与我要放的位置元素的key是否一致,一致时执行更新操作 ,旧值返回存储新值 不一致时 调用AndEntry方法在内部判断hashmap是否需要扩容,当前key与value值的个数大于等于他的阀值时 进行扩容 一次扩为原来的两倍 否则无需扩容,完成后调用caryentry方法,在方法内部先把储存的hash桶下标所对应的entry对象 先拿出来 把新值存进去 ,旧值放到新的entry对象对应的next引用中去若已存在值,则产生hash碰撞产生链表 //处理旧对象放到 新entry内部map引用指向位置 旧值赋给map引用
…………………………………………………………………………………………………………………………………………………….
-
- Spring M V C运行原理
- 客户端发出一个http请求给web服务器,web服务器对http请求进行解析,如果匹配Dispatcher Servlet的请求映射路径(在web.xml中指定),web容器将请求转交给Dispatcher Servlet.
- Dispatcher Servlet接收到这个请求之后将根据请求的信息(包括URL、Http方法、请求报文头和请求参数Cookie等)以及Handler Mapping的配置找到处理请求的处理器(Handler)。
- Dispatcher Servlet根据Handler Mapping找到对应的Handle,将处理权交给Handler(Handler将具体的处理进行封装),再由具体的Handler Adapter对Handler进行具体的调用。
- Handle对数据处理完成以后将返回一个Model And View()对象给Dispatcher Servlet。
- Handler返回的Model And View()只是一个逻辑视图并不是一个正式的视图,Dispatcher Servlet通过View Resolver将逻辑视图转化为真正的视图View。
- Dispatcher通过model解析出Model And View()中的参数进行解析最终展现出完整的view并返回给客户端。
………………………………………………………………………………………………………………………
常用注解:
@Configuration把一个类作为一个IoC容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean。
@Scope注解 作用域
@Lazy(true) 表示延迟初始化
@Service用于标注业务层组件、
@Controller用于标注控制层组件(如struts中的action)
@Repository用于标注数据访问组件,即DAO组件。
@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
@Scope用于指定scope作用域的(用在类上)
@PostConstruct用于指定初始化方法(用在方法上)
@PreDestory用于指定销毁方法(用在方法上)
@DependsOn:定义Bean初始化及销毁时的顺序
@Primary:自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
@Autowired 默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。如下:
@Autowired @Qualifier("personDaoBean") 存在多个实例配合使用
@Resource默认按名称装配,当找不到与名称匹配的bean才会按类型装配。
@PostConstruct 初始化注解
@PreDestroy 摧毁注解 默认 单例 启动就加载
@Async异步方法调用
………………………………………………………………………………………………………………………
final,finally,finalize 三者区别
Final是一个修饰符:
当final修饰一个变量的时候,变量变成一个常量,它不能被二次赋值
当final修饰的变量为静态变量(即由static修饰时必须在声明这个变量的时候给它赋值
当final修饰方法时,该方法不能被重写
当final修饰类时,该类不能被继承
Final不能修饰抽象类,因为抽象类中会有需要子类实现的抽 象方法,(抽 象类中可以有抽象方法,也可以有普通方法,当一个抽象类中没有抽象方 法时,这个抽象类也就没有了它存在的必要)
Final不能修饰接口,因为接口中有需要其实现类来实现的方法
Finally:
Finally只能与try/catch语句结合使用,finally语句块中的语句一定会执行, 并且会在return,continue,break关键字之前执行
finalize:
Finalize是一个方法,属于java.lang.Object类,finalize()方法是GC (garbage collector垃圾回收)运行机制的一部分,finalize()方法是在 GC清理它所从 属的对象时被调用的
synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:
1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
3. 修改一个静态的方法,其作用的范 围是整个静态方法,作用的对象是这个类的所有对象;
4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。
**///**
Forword(请求转发)与Redirect(重定向)
1、从数据共享上
Forword是一个请求的延续,可以共享request的数据
Redirect开启一个新的请求,不可以共享request的数据
2、从地址栏
Forword转发地址栏不发生变化
Redirect转发地址栏发生变化
List,Set,Collection,Collections
- List和Set都是接口,他们都继承于接口Collection,List是一个有序的可重复的集合,而Set的无序的不可重复的集合。Collection是集合的顶层接口,Collections是一个封装了众多关于集合操作的静态方法的工具类,因为构造方法是私有的,所以不能实例化。
2.List接口实现类有ArrayList,LinkedList,Vector。ArrayList和Vector是基于数组实现的,所以查询的时候速度快,而在进行增加和删除的时候速度较慢LinkedList是基于链式存储结构,所以在进行查询的时候速度较慢但在进行增加和删除的时候速度较快。又因为Vector是线程安全的,所以他和ArrayList相比而言,查询效率要低。
**///**
HashMap不是线程安全的,HashTable是线程安全。
HashMap允许空(null)的键和值(key),HashTable则不允许。
HashMap性能优于Hashtable。
==和equals方法的区别
“==”如果前后比较的是对象,则比较的是对象的地址,如果前后是数字,则比较的数值。
“equals”如果前后是对象,比较的是对象的地址。如果比较的对象重写了equals方法,则有可能比较的是“值”。像八个基本数据类型的封装类、String、File、Date都比较的是值。
Integer和int的区别
int是java提供的8种原始数据类型之一,意思整型,占用4字节。
Integer是java为int提供的封装类,是引用数据类型。
int的默认值为0,而Integer的默认值为null,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况。
-
- 线程和进程的区别
- 进程定义的是应用程序与应用程序之间的边界,通常来说一个进程就代表一个与之对应的应用程序。不同的进程之间不能共享代码和数据空间,而同一进程的不同线程可以共享代码和数据空间。
- 一个进程可以包括若干个线程,同时创建多个线程来完成某项任务,便是多线程。实现线程的两种方式:继承Thread类,实现Runable接口。
- 九大隐式对象
输入/输出对象: request(也属于作用域通信对象) response out
作用域通信对象: session application pageContext
Servlet 对象: page config
错误对象: exception
-
- 四大作用域介绍
四个作用域从大到小:appliaction>session>request>page
- application:全局作用范围,整个应用程序共享.生命周期为:应用程序启动到停止。
- session:会话作用域,当用户首次访问时,产生一个新的会话,以后服务器就可以记住这个会话状态。
- request:请求作用域,就是客户端的一次请求。
- page:一个JSP页面。
以上作用范围使越来越小, request和page的生命周期都是短暂的,他们之间的区别就是:一个request可以包含多个page页(include,forward)。
-
- page和pageContext的区别
page是servlet对象;使用this关键字,它的作用范围是在同一页面。
pageContext是作用域通信对象;通常使用setAttribute()和getAttribute()来设置和获取存放对象的值。
-
- GET和POST的区别
- get是从服务器上获取数据,post是向服务器传送数据。
- get传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制。
- get安全性非常低,post安全性较高。但是执行效率却比Post方法好。
- 在进行文件上传时只能使用post而不能是get。
- 转发与重定向的区别
- 从数据共享上区别:forword是一个请求的延续,可以共享request作用域的数据。redirect开启一个新的请求,不可以共享request作用域的数据,但可以通过URL方式进行数据发送。
- 从地址栏上区别:forword转发地址栏不发生变化,redirect转发地址栏发生变化。
- 从性能上区别:forword性能要高于redirect。
- 常见使用上的区别:因为上性能上有区别,在本系统中请求跳转建议使用forword,如果是跨域访问,建议使用redirect。
session和cookie的区别
session是存储在服务器端,cookie是存储在客户端的,所以从安全来讲session的安全性要比cookie高,然后我们获取session里的信息是通过存放在会话cookie里的sessionid获取的。又由于session是存放在服务器的内存中,所以session里的东西不断增加会造成服务器的负担,所以需要把很重要的信息才存储在session中,而把一些次要东西存储在客户端的cookie里,然后cookie确切的说分为两大类分为会话cookie和持久化cookie,会话cookie确切的说是,存放在客户端浏览器的内存中,所以说他的生命周期和浏览器是一致的,浏览器关了会话cookie也就消失了,然而持久化cookie是存放在客户端硬盘中,而持久化cookie的生命周期就是我们在设置cookie时候设置的那个保存时间,然后我们考虑一问题当浏览器关闭时session会不会丢失,从上面叙述分析session的信息是通过会话cookie的sessionid获取的,当浏览器关闭的时候会话cookie消失所以我们的sessionid也就消失了,但是session的信息还存在服务器端,这时我们只是查不到所谓的session但它并不是不存在。那么,session在什么情况下丢失,就是在服务器关闭的时候,或者是session过期(默认时间是30分钟),再或者调用了invalidate()的或者是我们想要session中的某一条数据消失调用session.removeAttribute()方法,然后session在什么时候被创建呢,确切的说是通过调用getsession()来创建,这就是session与cookie的区别。
访问HTML页面是不会创建session,但是访问index.JSP时会创建session(JSP实际上是一个Servlet,Servlet中有getSession方法)。
-
- request和session的区别
- 他们的生命周期不同,request对应的是一次请求,session对应的是一次会话。
- request占用资源比较少,相对来说缺乏持续性,而session资源消耗比较大,所以通常使用request来保存信息。
- JDBC连接数据库步骤
向DriverManager类注册驱动数据库驱动程序
(2)调用DriverManager.getConnection方法, 通过JDBC URL,用户名,密码取得数据 库连接的Connection对象。
(3)获取Connection后, 便可以通过createStatement创建Statement用以执行SQL语 句。
(4) 有时候会得到查询结果,比如select,得到查询结果,查询(SELECT)的结果存放于 结果集(ResultSet)中。
(5)关闭数据库语句,关闭数据库连接
JDK、JRE、JVM区别
Jdk【Java Development ToolKit】就是java开发工具箱, JDK是整个JAVA的核心里边包含了jre,它除了包含jre之外还包含了一些javac的工具类,把java源文件编译成class文件,java文件是用来运行这个程序的,除此之外,里边还包含了java源生的API,java.lang.integer在rt的jar包里边【可以在项目中看到】,通过rt这个jar包来调用我们的这些io流写入写出等。
JDK有以下三种版本:
J2SE,standard edition,标准版,是我们通常用的一个版本
J2EE,enterpsise edtion,企业版,使用这种JDK开发J2EE应用程序
J2ME,micro edtion,主要用于移动设备、嵌入式设备上的java应用程序
Jre【Java Runtime Enviromental】是java运行时环境,那么所谓的java运行时环境,就是为了保证java程序能够运行时,所必备的一基础环境,也就是它只是保证java程序运行的,不能用来开发,而jdk才是用来开发的,所有的Java程序都要在JRE下才能运行。
包括JVM和JAVA核心类库和支持文件。与JDK相比,它不包含开发工具——编译器、调试器和其它工具。Jre里边包含jvm。
Jvm:【Java Virtual Mechinal】因为jre是java运行时环境,java运行靠什么运行,而底层就是依赖于jvm,即java虚拟机,java虚拟机用来加载类文件,java中之所以有跨平台的作用,就是因为我们的jvm。
三者关系:J2se是基于jdk和jre,JDK是整个JAVA的核心里边包含了jre,Jre里边包含jvm。
jvm的内存结构
java虚拟机的内存结构分为堆(heap)和栈(stack),堆里面存放是对象实例也就是new出来的对象。栈里面存放的是基本数据类型以及引用数据类型的地址。
对于所谓的常量是存储在方法区的常量池里面
内存泄露和内存溢出
内存泄露 (memory leak),是指应用程序在申请内存后,
无法释放已经申请的内存空间.一次内存泄露危害可以忽略,
但如果任其发展最终会导致内存溢出(out of memory).
如读取文件后流要进行及时的关闭以及对数据库连接的释放。
内存溢出(out of memory)是指应用程序在申请内存时,
没有足够的内存空间供其使用。
如我们在项目中对于大批量数据的导入,采用分段批量提交的方式。
-
- String、StringBuffer、StringBuilder区别
String | 字符串常量 | 不可变 | 使用字符串拼接时是不同的2个空间。 |
StringBuffer | 字符串变量 | 可变 | 线程安全,字符串拼接直接在字符串后追加。 |
StringBuilder | 字符串变量 | 可变 | 非线程安全,字符串拼接直接在字符串后追加。 |
- StringBuilder执行效率高于StringBuffer高于String。
- String是一个常量,是不可变的,所以对于每一次+=赋值都会创建一个新的对象,StringBuffer和StringBuilder都是可变的,当进行字符串拼接时采用append方法,在原来的基础上进行追加,所以性能比String要高,又因为StringBuffer是线程安全的而StringBuilder是线程非安全的,所以StringBuilder的效率高于StringBuffer。
- 对于大数据量的字符串的拼接,采用StringBuffer,StringBuilder。
- 另一种说法,JDK1.6做了优化,通过String声明的字符串在进行用“+”进行拼接时,底层调用的是StringBuffer,所以性能上基本和后两者没有什么区别。
- JDK常用的包
java.lang: 这个是系统的基础类,比如String、Math、Integer、System和Thread,提供常用功能。
java.io: 这里面是所有输入输出有关的类,比如文件操作等。
java.net: 这里面是与网络有关的类,比如URL,URLConnection等。
java.util : 这个是系统辅助类,特别是集合类Collection,List,Map等。
java.sql: 这个是数据库操作的类,Connection,Statememt,ResultSet等。
、switch接受的几种数据类型short, int, byte,char
enum(JDK1.5以后支持)
String(JDK1.7以后支持)
单例
单例就是该类只能返回一个实例。
单例所具备的特点:
1.私有化的构造函数
2.私有的静态的全局变量
3.公有的静态的方法
单例分为懒汉式、饿汉式和双层锁式
饿汉式:
public class Singleton1 {
private Singleton1() {};
private static Singleton1 single = new Singleton1();
public static Singleton1 getInstance() {
return single;
}
}
懒汉式:
public class Singleton2 {
private Singleton2() {}
private static Singleton2 single=null;
public tatic Singleton2 getInstance() {
if (single == null) {
single = new Singleton2();
}
return single;
}
}
线程安全:
public class Singleton3 {
private Singleton3() {}
private static Singleton3 single ;
public static Singleton3 getInstance() {
if(null == single){
synchronized(Singleton3.class){
if(null == single){
single = new Singleton3();
}
}
}
return single;
}
}
- Hashtable与HashMap的区别
HashMap不是线程安全的,HashTable是线程安全。
HashMap允许空(null)的键和值(key),HashTable则不允许。
HashMap性能优于Hashtable。
Map
1.Map是一个以键值对存储的接口。Map下有两个具体的实现,分别是HashMap和HashTable.
2.HashMap是线程非安全的,HashTable是线程安全的,所以HashMap的效率高于HashTable.
3.HashMap允许键或值为空,而HashTable不允许键或值为空.
一、封装
封装指的是,任何对象都应该有一个明确的边界,对这个对象内部属性和方法起到保护作用。
二、继承
1、父类,是对子类共性的抽象。
继承的基本概念:父类是对子类共性的抽象,父类和子类的关系,是由一般到特殊的关系。在设计类的继承关系时,应当把共性放在父类,特性放在子类。
2、什么能被继承?
访问权限修饰符:private、default、protected、public
方法覆盖:
1)访问 修饰符 相同或更宽
2)返回值类型相同
3)方法名相同。
4)参数表相同
3、有了继承关系之后对象的创建过程?
1)分配空间。要注意的是,分配空间不光是指分配子类的空间,子类对象中包含的父类对象所需要的空间,一样在这一步统一分配。在分配空间的时候,会把所有的属性值都设为默认值。
2)递归的构造父类的对象
3)初始化本类的属性
4)调用本类的构造方法
4、super关键字
用法一、super关键字的第一种用法,就是可以指定在递归构造父类对象的时候,调用父类的哪一个构造方法。
要格外注意的是,super用在构造方法中时,只能作为构造方法的第一句。否则编译报错
this()和super(),在构造方法中不能同时使用。(因为这两个关键字在构造方法中都要放在第一句)
这样,我们构造方法的第一个语句,就有了三种可能
1. super (参数) 指明调用父类哪个构造方法
2. this (参数) 指明调用本类哪个构造方法
3. 既不是this(参数)又不是super(参数)。
在第3种情况下,编译器就会自动加上一句“super()”,即调用父类的无参构造方法。
用法二、super用作引用,这个引用指向父类对象
最典型的用途是,使用super在子类中,调用父类被覆盖的方法。
super除了可以调用父方法,还可以用来指向属性
5、单继承
三、多态
1、引用类型和对象类型
01 : Animal a;
02: a= new Animal();
第一行代码中,我们定义了一个引用a,而约束这个引用的类型为Animal。
在这里我们称“a引用的引用类型为Animal”。
第二行代码中,创建了一个Animal类型的对象,将这个对象的地址赋给a引用。
每当我们创建对象时,总要指定这个对象的类型。对象的类型我们会写在“new”关键字的后面。在这里,称“a引用所指向的对象类型为Animal”。
(子类的对象可以放入父类的引用中)
2、多态的语法特性
1)对象类型永远不变
2)只能对一个引用调用其引用类型中定义的方法
3)运行时,根据对象类型调用子类覆盖之后的方法
4)子类的引用可以直接赋值给父类引用。
5)父类的引用赋值给子类引用,必须强制类型转换,并有可能在运行时得到一个类型转换异常。
3、强制类型转换和instanceof
4、多态的作用
多态最主要的作用在于:我们可以将若干不同子类的对象都当做统一的父类对象来使用,这样就会提高程序的通用性,屏蔽不同子类之间的差异。
………………………………………………………………………………………………………………………
spring.jar是包含有完整发布的单个jar 包,spring.jar中包含除了spring-mock.jar里所包含的内容外其它所有jar包的内容,因为只有在开发环境下才会用到 spring-mock.jar来进行辅助测试,正式应用系统中是用不得这些类的。
除了spring.jar文件,Spring还包括有其它13个独立的jar包,各自包含着对应的Spring组件,用户可以根据自己的需要来选择组合自己的jar包,而不必引入整个spring.jar的所有类文件。
(1) spring-core.jar
这个jar文件包含Spring框架基本的核心工具类,Spring其它组件要都要使用到这个包里的类,是其它组件的基本核心,当然你也可以在自己的应用系统中使用这些工具类。
(2) spring-beans.jar
这个jar文件是所有应用都要用到的,它包含访问配置文件、创建和管理bean以及进行Inversion of Control / Dependency Injection(IoC/DI)操作相关的所有类。如果应用只需基本的IoC/DI支持,引入spring-core.jar及spring-beans.jar文件就可以了。
(3) spring-aop.jar
这个jar文件包含在应用中使用Spring的AOP特性时所需的类。使用基于AOP的Spring特性,如声明型事务管理(Declarative Transaction Management),也要在应用里包含这个jar包。
(4) spring-context.jar
这个jar文件为Spring核心提供了大量扩展。可以找到使用Spring ApplicationContext特性时所需的全部类,JDNI所需的全部类,UI方面的用来与模板(Templating)引擎如Velocity、FreeMarker、JasperReports集成的类,以及校验Validation方面的相关类。
(5) spring-dao.jar
这个jar文件包含Spring DAO、Spring Transaction进行数据访问的所有类。为了使用声明型事务支持,还需在自己的应用里包含spring-aop.jar。
(6) spring-hibernate.jar
这个jar文件包含Spring对Hibernate 2及Hibernate 3进行封装的所有类。
(7) spring-jdbc.jar
这个jar文件包含对Spring对JDBC数据访问进行封装的所有类。
(8) spring-orm.jar
这个jar文件包含Spring对DAO特性集进行了扩展,使其支持 iBATIS、JDO、OJB、TopLink,因为Hibernate已经独立成包了,现在不包含在这个包里了。这个jar文件里大部分的类都要依赖spring-dao.jar里的类,用这个包时你需要同时包含spring-dao.jar包。
(9) spring-remoting.jar
这个jar文件包含支持EJB、JMS、远程调用Remoting(RMI、Hessian、Burlap、Http Invoker、JAX-RPC)方面的类。
(10) spring-support.jar
这个jar文件包含支持缓存Cache(ehcache)、JCA、JMX、邮件服务(Java Mail、COS Mail)、任务计划Scheduling(Timer、Quartz)方面的类。
(11) spring-web.jar
这个jar文件包含Web应用开发时,用到Spring框架时所需的核心类,包括自动载入WebApplicationContext特性的类、Struts与JSF集成类、文件上传的支持类、Filter类和大量工具辅助类。
(12) spring-webmvc.jar
这个jar文件包含Spring MVC框架相关的所有类。包含国际化、标签、Theme、视图展现的FreeMarker、JasperReports、Tiles、Velocity、XSLT相关类。当然,如果你的应用使用了独立的MVC框架,则无需这个JAR文件里的任何类。
(13) spring-mock.jar
这个jar文件包含Spring一整套mock类来辅助应用的测试。Spring测试套件使用了其中大量mock类,这样测试就更加简单。模拟HttpServletRequest和HttpServletResponse类在Web应用单元测试是很方便的。
如何选择这些发布包,决定选用哪些发布包其实相当简单。
如果你正在构建Web应用并将全程使用Spring,那么最好就使用单个全部的spring.jar文件;
如果你的应用仅仅用到简单的Inversion of Control / Dependency Injection(IoC/DI)容器,那么只需spring-core.jar与spring-beans.jar即可;
如果你对发布的大小要求很高,那么就得精挑细选了,只取包含自己所需特性的jar文件了。
采用独立的发布包你可以避免包含自己的应用不需要的全部类。当然你可以采用其它的一些工具来设法令整个应用包变小,节省空间的重点在于准确地找出自己所需的Spring依赖类,然后合并所需的类与包就可以了。
Eclispe有个插件叫ClassPath Helper可以帮你找找所依赖的类。
Spring包依赖说明:
1) spring-core.jar需commons-collections.jar,spring-core.jar是以下其它各个的基本。
2) spring-beans.jar需spring-core.jar,cglib-nodep-2.1_3.jar
3) spring-aop.jar需spring-core.jar,spring-beans.jar,cglib-nodep-2.1_3.jar,aopalliance.jar
4) spring-context.jar需spring-core.jar,spring-beans.jar,spring-aop.jar,commons-collections.jar,aopalliance.jar
5) spring-dao.jar需spring-core.jar,spring-beans.jar,spring-aop.jar,spring-context.jar
6) spring-jdbc.jar需spring-core.jar,spring-beans.jar,spring-dao.jar
7) spring-web.jar需spring-core.jar,spring-beans.jar,spring-context.jar
8) spring-webmvc.jar需spring-core.jar/spring-beans.jar/spring-context.jar/spring-web.jar
9) spring-hibernate.jar需spring-core.jar,spring- beans.jar,spring-aop.jar,spring-dao.jar,spring-jdbc.jar,spring- orm.jar,spring-web.jar,spring-webmvc.jar
10) spring-orm.jar需spring-core.jar,spring-beans.jar,spring-aop.jar,spring-dao.jar,spring-jdbc.jar,spring-web.jar,spring-webmvc.jar
11) spring-remoting.jar需spring-core.jar,spring-beans.jar,spring- aop.jar,spring-dao.jar,spring-context.jar,spring-web.jar,spring- webmvc.jar
12) spring-support.jar需spring-core.jar,spring-beans.jar,spring-aop.jar,spring-dao.jar,spring-context.jar,spring-jdbc.jar
13) spring-mock.jar需spring-core.jar,spring-beans.jar,spring-dao.jar,spring-context.jar,spring-jdbc.jar
一、只是使用spring框架
dist\spring.jar
lib\jakarta-commons\commons-logging.jar
如果使用到了切面编程(AOP),还需要下列jar文件
lib\aspectj\aspectjweaver.jsr 和 aspectjrt.jar
lib\cglib\cglib-nodep-2.1_3.jar
如果使用了JSR-250中的注解如@Resource/@PostConstruct/@PreDestroy
还需下列jar文件
lib\j2ee\common-annotations.jar
二、只是使用spring框架若使用注解方式
只要加一些命名空间和开启解析器
并且@Resource需要加lib\j2ee\common-annotations.jar
<context:annotation-config/>打开处理器
三、要自动扫描
只要开启解析器和一些命名空间
<context:component-scan base-package=""/>
四、spring框架采用aop编程
需要导入一些命名空间
xmlns:aop.......
<aop:aspectj-autoproxy/>开启解析器
如果使用到了切面编程(AOP),还需要下列jar文件
lib\aspectj\aspectjweaver.jsr 和 aspectjrt.jar
lib\cglib\cglib-nodep-2.1_3.jar
五、spring+Jdbc开发
需要数据源文件 lib\jakarta-commons\commons-pool.jar、lib\jakarta-commons\commons-dbcp.jar
1、spring文件 :
dist\spring.jar、
lib\jakarta-commons\commons-logging.jar
2、jdbc驱动文件 mysql**** sql*** :
导入tx命名空间
<tx:annotation-driven transaction-manager=""/>
对事务注解的解析器
六、spring2.5+hibernate3.3+struts1.3
(1)、hibernate核心包
hibernate3.jar
lib\required\*.jar
lib\optional\ehcache-1.2.3.jar (二级缓存文件)
hibernate注解包
lib\test\slf4j-log4j12.jar
(2)、spring包
dist\spring.jar
lib\jakarta-commons\commons-logging.jar 和commons-pool.jar、commons-dbcp.jar(后为数据源文件)
dist\modules\spring-webmvc-struts.jar (与struts1的集成)
lib\aspectj\aspectjweaver.jsr 和 aspectjrt.jar (Aop文件)
lib\cglib\cglib-nodep-2.1_3.jar (Aop文件)
lib\j2ee\common-annotations.jar (注解文件)
lib\log4j\log4j-1.2.15.jar
(3)、sturs1.3.8
建议将jstl-1.0.2.jar和standard-1.0.2.jar文件更换为1.1版本 此时JSTL文件
还有spring已存在antlr-2.7.6.jar文件所以将struts中的antlr-2.7.6.jar文件删除以免冲突
数据库驱动
mysql*** sql****根据需求换
如果在web容器实例spring容器
加文件到web.xml......
如果action让容器管理,则path(Struts的配置文件)和name(Spring配置文件)要一致
还必须在struts的配置文件里加一个控制器
spring为struts1.3解决乱码问题
在web.xml配置一个filter
七、spring2.5+hibernate3.3+struts2整合开发
struts2文件lib里面所有不带-plugin结尾的jar文件,但除了struts2-spring-plugin-2.0.11.1.jar
JVM
public class HelloWorld { public static void main(String[] args) { System.out.print("Hello world"); } }
这段程序从编译到运行,最终打印出“Hello world”中间经过了哪些步骤呢?我们直接上图:
内存空间:
JVM内存空间包含:方法区、java堆、java栈、本地方法栈。
方法区是各个线程共享的区域,存放类信息、常量、静态变量。
java堆也是线程共享的区域,我们的类的实例就放在这个区域,可以想象你的一个系统会产生很多实例,因此java堆的空间也是最大的。如果java堆空间不足了,程序会抛出OutOfMemoryError异常。
java栈是每个线程私有的区域,它的生命周期与线程相同,一个线程对应一个java栈,每执行一个方法就会往栈中压入一个元素,这个元素叫“栈帧”,而栈帧中包括了方法中的局部变量、用于存放中间状态值的操作栈,这里面有很多细节,我们以后再讲。如果java栈空间不足了,程序会抛出StackOverflowError异常,想一想什么情况下会容易产生这个错误,对,递归,递归如果深度很深,就会执行大量的方法,方法越多java栈的占用空间越大。
本地方法栈角色和java栈类似,只不过它是用来表示执行本地方法的,本地方法栈存放的方法调用本地方法接口,最终调用本地方法库,实现与操作系统、硬件交互的目的。
PC寄存器,说到这里我们的类已经加载了,实例对象、方法、静态变量都去了自己改去的地方,那么问题来了,程序该怎么执行,哪个方法先执行,哪个方法后执行,这些指令执行的顺序就是PC寄存器在管,它的作用就是控制程序指令的执行顺序。
执行引擎当然就是根据PC寄存器调配的指令顺序,依次执行程序指令。