零散知识点

  • Jsp页面中获得当前页面的上下文路径和全路径

    1
    2
    3
    4
    5
    6
    <%
    //获得上下文路径
    String path = request.getContextPath();
    //获得全路径
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>

    下文中就可以使用 <%= basePath %> 来代表当前页面全路径了.

  • JavaScript获得页面的上下文路径和全路径

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    function getContextPath() {
    var pathName = document.location.pathname;
    var index = pathName.substr(1).indexOf("/");
    var result = pathName.substr(0,index+1);
    return result;
    }

    function getRootPath_web() {
    //获取当前网址,如: http://localhost:8083/uimcardprj/share/meun.jsp
    var curWwwPath = window.document.location.href;
    //获取主机地址之后的目录,如: /uimcardprj/share/meun.jsp
    var pathName = window.document.location.pathname;
    //获取索引
    var pos = curWwwPath.indexOf(pathName);
    //获取主机地址,如: http://localhost:8083
    var localhostPaht = curWwwPath.substring(0, pos);
    //获取带"/"的项目名,如:/uimcardprj
    var projectName = pathName.substring(0, pathName.substr(1).indexOf('/') + 1);
    //http://localhost:8083/uimcardprj
    return (localhostPaht + projectName);
    }
  • Jsp页面乱码问题
    Jsp页面中用:

    1
    <%@ page contentType="text/html;charset=UTF-8" language="java"%>

    Servlet中用:

    1
    2
    req.setCharacterEncoding("UTF-8");
    resp.setContentType("text/html;charset=utf-8");
  • IDEA中配置文件存在引用关系的配置文件都应该写在Resources中.

  • VO、DTO、DO和PO

    1. VO(View Object):视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。

    2. DTO(Data Transfer Object):数据传输对象,这个概念来源于J2EE的设计模式,原来的目的是为了EJB的分布式应用提供粗粒度的数据实体,以减少分布式调用的次数,从而提高分布式调用的性能和降低网络负载,但在这里,我泛指用于展示层与服务层之间的数据传输对象。

    3. DO(Domain Object):领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。

    4. PO(Persistent Object):持久化对象,它跟持久层(通常是关系型数据库)的数据结构形成一一对应的映射关系,如果持久层是关系型数据库,那么,数据表中的每个字段(或若干个)就对应PO的一个(或若干个)属性。

    VO—SpringMVC中传输的对象;
    DTO—SpringMVC中向Service层传递的对象;
    DO—Entity;—有与数据库中各列对应的属性的对象;

  • HashMap与HashTable的区别是什么?各有什么特性?

    1. HashMap几乎可以等价于Hashtable,除了HashMap是非synchronized的,并可以接受null(HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行)。
    2. HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。
    3. 另一个区别是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。
    4. 由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。
    5. HashMap不能保证随着时间的推移Map中的元素次序是不变的。
  • ArrayList与LinkedList的区别?

    1. ArrayList是实现了基于动态数组的数据结构,而LinkedList是基于链表的数据结构;
    2. 对于随机访问get和set,ArrayList要优于LinkedList,因为LinkedList要移动指针;
    3. 对于添加和删除操作add和remove,一般大家都会说LinkedList要比ArrayList快,因为ArrayList要移动数据。但是实际情况并非这样,对于添加或删除,LinkedList和ArrayList并不能明确说明谁快谁慢,下面会详细分析;

    从源码可以看出,ArrayList想要get(int index)元素时,直接返回index位置上的元素,而LinkedList需要通过for循环进行查找,虽然LinkedList已经在查找方法上做了优化,比如index < size / 2,则从左边开始查找,反之从右边开始查找,但是还是比ArrayList要慢。这点是毋庸置疑的。

    ArrayList想要在指定位置插入或删除元素时,主要耗时的是System.arraycopy动作,会移动index后面所有的元素;LinkedList主耗时的是要先通过for循环找到index,然后直接插入或删除。这就导致了两者并非一定谁快谁慢;

  • HashSet,TreeSet和LinkedHashSet的区别
    HashSet

    1. 不能保证元素的排列顺序,顺序有可能发生变化
    2. 不是同步的
    3. 集合元素可以是null,但只能放入一个null
      LinkedHashSet
      LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的次序。这样使得元素看起 来像是以插入顺序保存的,也就是说,当遍历该集合时候,LinkedHashSet将会以元素的添加顺序访问集合的元素。
      LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet。
      TreeSet
      TreeSet是SortedSet接口的唯一实现类,TreeSet可以确保集合元素处于排序状态。TreeSet支持两种排序方式,自然排序 和定制排序,其中自然排序为默认的排序方式。
  • List,Set,Map的区别?

    Collection下的有List和Set,List下有ArrayList,LinkedList,Vector,Set下有HashSet,TreeSet
    Map下有HashMap,HashTable,TreeMap
    List表示有序可重复,Set无序不可重复,Map是Key-Value形式保存数据.

  • String和StringBuffer、StringBuilder的区别是什么?String为什么是不可变的?

    可变性  String类中使用字符数组保存字符串,private final char value[],所以string对象是不可变的。StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,char[]value,这两种对象都是可变的。
    线程安全性  String中的对象是不可变的,也就可以理解为常量,线程安全。AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。
    性能  每次对String 类型进行改变的时候,都会生成一个新的String对象,然后将指针指向新的String 对象。StringBuffer每次都会对StringBuffer对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用StirngBuilder 相比使用StringBuffer 仅能获得10%~15% 左右的性能提升,但却要冒多线程不安全的风险。
    对于三者使用的总结:

    • 如果要操作少量的数据用 = String
    • 单线程操作字符串缓冲区 下操作大量数据 = StringBuilder
    • 多线程操作字符串缓冲区 下操作大量数据 = StringBuffer
  • Arraylist与Vector的区别是什么?

    1. Vector是线程安全的,ArrayList不是线程安全的。
    2. ArrayList在底层数组不够用时在原来的基础上扩展0.5倍,Vector是扩展1倍。
  • Java多线程-死锁的出现和解决

    死锁出现的原因:

    • 互斥条件:线程要求对所分配的资源进行排他性控制,即在一段时间内某 资源仅为一个进程所占有.此时若有其他进程请求该资源.则请求进程只能等待.
    • 不剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能由获得该资源的线程自己来释放(只能是主动释放).
    • 请求和保持条件:线程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他线程占有,此时请求线程被阻塞,但对自己已获得的资源保持不放.
    • 循环等待条件:存在一种线程资源的循环等待链,链中每一个线程已获得的资源同时被链中下一个线程所请求。

    避免:加锁顺序 ,加锁时限 ,死锁检测