栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java开发面试题

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java开发面试题

Java面试题整理 1、Java基础 1、JDK 和 JRE 有什么区别?
JDK:Java Development Kit 的简称,Java 开发工具包,提供了 Java 的开发环境和运行环境。
JRE:Java Runtime Environment 的简称,Java 运行环境,为 Java 的运行提供了所需环境。
具体来说 JDK 其实包含了 JRE,同时还包含了编译 Java 源码的编译器 Javac,还包含了很多 Java 程序调试和分析的工具。简单来说:如果你需要运行 Java 程序,只需安装 JRE 就可以了,如果你需要编写 Java 程序,需要安装 JDK。
2、简述Java的jvm虚拟机的运行原理
1)JVM是可运行Java代码的假想计算机 ,包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收,堆 和 一个存储方法域。JVM是运行在操作系统之上的,它与硬件没有直接的交互。
Java平台由Java虚拟机和Java应用程序接口搭建,Java语言则是进入这个平台的通道,用Java语言编写并编译的程序可以运行在这个平台上。
2)运行期环境代表着Java平台,开发人员编写Java代码(.java文件),然后将之编译成字节码(.class文件),
再然后字节码被装入内存,一旦字节码进入虚拟机,它就会被解释器解释执行
    Java源文件—->编译器—->字节码文件
    字节码文件—->JVM—->机器码
    
    每一种平台的解释器是不同的,但是实现的虚拟机是相同的,这也就是Java为什么能够跨平台的原因了 ,当一个程序从开始运行,这时虚拟机就开始实例化了,多个程序启动就会存在多个虚拟机实例。程序退出或者关闭,则虚拟机实例消亡,多个虚拟机实例之间数据不能共享。

参考:https://blog.csdn.net/yunzhaji3762/article/details/81038711
3、GC是什么? 为什么要有GC
Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,在使用JAVA的时候,一般不需要专门编写内存回收和垃圾清理代码。这是因为在Java虚拟机中,存在自动内存管理和垃圾清扫机制。

电脑的内存大小的不变的,当我们使用对象的时候,如使用new关键字的时候,就会在内存中生产一个对象,但是我们在使用JAVA开发的时候,当一个对象使用完毕之后我们并没有手动的释放那个对象所占用的内存,就这样在使用程序的过程中,对象越来越多,当内存存放不了这么多对象的时候,内存不够就会导致溢出等错误导致程序崩溃.

JAVA为了解决这个问题就推出了这个自动清除无用对象的功能,或者叫机制,这就是GC,或者叫垃圾回收,其实就在用来帮你清理垃圾对象的,好让你安心写代码,不用管内存释放,对象清理的事情了。

Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,且Java语言没有提供释放已分配内存的显示操作方法。

垃圾回收只与内存有关,清理内存外的资源依靠finalize()方法。垃圾回收机制在回收某个对象的内存前会调用该对象的finalize()方法。

垃圾回收以单独的线程在后台运行,为减少虚拟机额外消耗,一般在内存不足时会进行垃圾回收,所以就算强制系统垃圾回收,垃圾回收也不一定发生 
4、解释内存中的栈(stack)、堆(heap)和静态区(static area)的用法;
通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用内存中的栈空间;
而通过new关键字和构造器创建的对象放在堆空间;
程序中的字面量(literal)如直接书写的100、”hello”和常量都是放在静态区中。
栈空间操作起来最快但是栈很小,通常大量的对象都是放在堆空间,理论上整个内存没有被其他进程使用
的空间甚至硬盘上的虚拟内存都可以被当成堆空间来使用。
5.说出一些常用的类,包,异常请各举5个
常用的类:BufferedReader BufferedWriter FileReader FileWirter String Integer Math Random Date
SimpleDateFormat Calendar System BigDecimal ...
常用的包:java.lang  java.awt  java.io  java.util  java.sql  java.text
常用的异常:
    RuntimeException            Java.lang 包中多数异常的基类
        ArithmeticException         算术错误,如除以 0
        IllegalArgumentException    方法收到非法参数
        IndexOutOfBoundsException   地址下标越界
        NullPointerException        空指针异常
        ClassCastException          类转换异常
        NumberFormatException       数据格式异常
    ClassNotFoundException      不能加载请求的类
    IOException I/O             异常的根类
    FileNotFoundException       不能找到文件
    IllegalAccessException      对类的访问被拒绝
    NoSuchMethodException       请求的方法不存在
    InterruptedException        线程中断  
    SQLException                SQL异常  
6、switch是否能作用在byte上,是否能作用在long上,是否能作用在String上
switch(expr1)中,expr1是一个整数表达式。
因此传递给 switch 和 case 语句的参数应该是 int、 short、 char 或者 byte。
现在1.7及更高版本中String可以用于swtich,还有枚举类型也支持
7、String s= new String(“abc”) 创建了几个String Object ?如果是多个,那么他们之间有什么区别?
两个或一个,“abc”对应一个对象,这个对象放在字符串常量池,
常量“abc”不管出现多少遍,都是缓冲区中的那一个。new String每写一遍,
就创建一个新的对象,它依据常量“abc”对象的内容来创建出一个新String对象。
如果以前就用过“abc”,这句代表就不会创建”abc”自己了,直接从缓冲区拿。
8、为什么说String是不可变的
String类被final修饰,不可被继承。
String的成员变量char数组value被final修饰,初始化后不可更改引用。
String的成员变量value访问修饰符为private,不对外界提供修改value数组值的方法。

由于String对象的内容(对象内存地址所存的内容)是不能改变的,但String引用(变量)是可以改变的,可以让其指向另外一个字符串。(不能修改字符串的内容,但可以修改字符串的引用)
String str = "hello";
str = str + "world";
System.out.println(str);// hello world
虽然str打印的结果变了,但不是String对象本身发生改变,而是str引用到了其他String对象(创建了一个新的字符串 "helloworld")。要区分修改的是"地址"还是"地址对应内存的内容"。

如果非要改,只能就借助反射进行修改
9、Java的访问修饰符是什么?
访问权限修饰符是表明类成员的访问权限类型的关键字。使用这些关键字来限定程序的方法或者变量的访问权限。
它们包含:
    public: 所有类都可以访问 
    protected: 同一个包内以及所有子类都可以访问
    默认: 归属类及相同包下的子类可以访问
    private: 只有本类才能访问
10.方法重载和方法重写区别?
方法重载:同一个类中,方法名相同,参数的类型、顺序和个数不同,与返回值类型和方法访问修饰符无关
方法重写:不同类中,发生在继承类中,方法名称、参数类型、返回值类型全部相同,被重写的方法不能拥有比父类更严格的权限
11.Java实现多态的必要条件?
继承:在多态中必须存在有继承关系的子类和父类。
重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法
12.抽象类和接口的区别?
抽象类 是一个不能被实例化的类,因为它其中存在抽象方法,但它的其它行为和一个普通类没什么不同。
接口是java为了弥补不能多继承提供的概念,接口之间支持多继承,接口中只允许存在公有静态常量或公有的抽象方法,一个类可实现多个接口,从而扩展不同的功能。java1.8之后,支持默认方法。
13.this、super、static、final关键字的用法
this:代表本类当前对象的引用,谁调用我,我就代表谁。
super:代表当前对象父类的内存空间标识。(可以理解为父类的引用,通过super可以访问父类的成员)
static:静态,可以修饰以下
    变量:将实例变量升级为类变量,通过类名可以直接.出来
    方法:将实例方法升级为类方法,通过类名可以直接.出来
    代码块:静态代码块随着类的加载而加载,一般是用来加载驱动的。只在类加载的时候执行一次,优先于构造方法执行
final:最终的,可以修饰以下
    变量:由变量变成常量,值不可修改
    方法:表示此方法不能被重写
    类:表示此类不能被继承
14、字符串对象String,StringBuilder ,StringBuffer之间的区别?
String是不可变对象,经常改变内容的字符串最好不要使用String,任何对String的改变都会引发新的String对象的生成

StringBuffer是可变的字符串,字符串经常改变的情况可使用StringBuffer,更高效,任何对它所指代的字符串的改变都不会产生新的对象。

JDK1.5后提供了StringBuilder,等价StringBuffer。作为一个简易替代,他们的原理和操作基本相同,区别在于StringBuffer支持并发操作,线性安全的,适合多线程中使用。StringBuilder不支持并发操作,线性不安全的,不适合多线程中使用,而且大量字符操作时候,相对来说执行会快.

因此:
        String:适用于少量的字符串操作的情况
        StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
        StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况
        
回顾扩容机制
15、对比HashMap和HashTable?
两者都是用key-value方式获取数据。它们之间有以下区别: 
1)线程安全性不同
  	Hashtable 中的方法是Synchronize的,而HashMap中的方法在缺省情况下是非Synchronize的。在多线程并发的环境下,可以直接使用Hashtable,不需要自己为它的方法实现同步,但使用HashMap时就必须要自己增加同步处理。
  	
  	虽然HashMap不是线程安全的,但是它的效率会比Hashtable要好很多。这样设计是合理的。在我们的日常使用当中,大部分时间是单线程操作的。HashMap把这部分操作解放出来了。当需要多线程操作的时候可以使用线程安全的ConcurrentHashMap。ConcurrentHashMap虽然也是线程安全的,但是它的效率比Hashtable要高好多倍。因为ConcurrentHashMap使用了分段锁,并不对整个数据进行锁定。

2)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()方法来判断。

3)内部实现使用的数组初始化和扩容方式不同
  HashTable在不指定容量的情况下的默认容量为11,而HashMap为16,Hashtable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂。
  Hashtable扩容时,将容量变为原来的2倍加1,而HashMap扩容时,将容量变为原来的2倍。

扩展:在使用 HashMap 的时候,用 String 做 key 有什么好处?

    HashMap 内部实现是通过 key 的 hashcode 来确定 value 的存储位置,因为字符串是不可变的,所以当创建字符串时,它的 hashcode 被缓存下来,避免重复计算hashCode,所以相比于其他对象更快。

    如何将类作为一个HashMap的key?
        实现对象作为键需要重写hashCode()和equals()方法。

    两个方法的作用参考:https://www.cnblogs.com/Qian123/p/5703507.html
16、ArrayList和LinkedList、Vector的区别?
1)ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 
2)对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。 
3)对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据
    Vector和ArrayList类似,但是是线程安全的,所以开销大,效率低, Vector和ArrayList在更多元素添加进来时会请求更大的空间。Vector每次请求其大小的双倍空间,而ArrayList每次对size增长50%.
17、编写多线程程序有几种实现方式?
1) 一种是继承Thread类;
2) 一种是实现Runnable接口。
两种方式都要通过重写run()方法来定义线程的行为,推荐使用后者,因为Java中的继承是单继承,一个类有一个父类,如果继承了Thread类就无法再继承其他类了,显然使用Runnable接口更为灵活。
3)启动一个线程使用的是start方法,自动调用线程的run方法。
4)通过Callable和FutureTask创建线程,最大特点就是可以有返回值
5)通过线程池创建线程
18、sleep和wait的区别。
整体的区别其实是有四个:
1、sleep是线程中的方法,但是wait是Object中的方法。
2、sleep方法不会释放lock,但是wait会释放,而且会加入到等待队列中。
3、sleep方法不依赖于同步器synchronized,但是wait需要依赖synchronized关键字。
4、sleep不需要被唤醒(休眠之后推出阻塞),但是wait需要(不指定时间需要被别人中断)。
参考:https://baijiahao.baidu.com/s?id=1647423693517849309&wfr=spider&for=pc
19、java如何停止一个线程
1)要终止一个线程,并不是简单的调用stop()方法,stop()就像linux中的kill一个线程一样是非常暴力的,虽然在Java的API中仍然可以调用stop()方法,但是和suspend,resume方法一样,是过期了的,不建议使用的,因为stop()在结束一个线程时并不会保证线程的资源正常释放,会导致程序可能会出现一些不确定的状态。 
正确终止一个线程的方法有以下几种:
1)interrupt方法 
    当其他线程调用当前线程的interrupt方法时,即设置了一个标识,表示当前线程可以中断了,至于什么时候中断,取决于当前线程。当前线程通过调用isInterrupted()方法来判断自身是否被中断,如果返回true,则说明当前线程已经中断,这种通过标识位或中断操作的方式能够使线程在终止时有机会清理资源,而这种方式也更加安全。
    
2)volatile关键字 
    定义一个用volatile修饰的成员变量来控制线程的停止,这点是利用了volatile修饰的成员变量可以在多线程之间达到共享,也就是可见性来实现的,同一时刻只能由一个线程来修改该变量的值。

3)程序运行结束或者出现异常
    当一个程序运行结束或者出现异常后,当前线程自然也就终止了
20、final、finally、finalize的区别。
1)final:修饰符(关键字)有三种用法:如果一个类被声明为final,意味着它不能再派生出新的子类,即不能被继承,因此它和abstract是反义词。将变量声明为final,可以保证它们在使用中不被改变,被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取不可修改。被声明为final的方法也同样只能使用,不能在子类中被重写。 

2)finally:通常放在try…catch…的后面构造总是执行代码块,这就意味着程序无论正常执行还是发生异常,这里的代码只要JVM不关闭都能执行,可以将释放外部资源的代码写在finally块中。 

3)finalize:Object类中定义的方法,Java中允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在销毁对象时调用的,通过重写finalize()方法可以整理系统资源或者执行其他清理工作。
21、JVM调优,线程,同步锁等相关内容。
java面试汇总中的JVM篇,多线程&并发篇。
22、如何比较日期的大小,如何格式化日期
1)获取毫秒数,判断大小
2)使用Date类提供的方法after或者before方法
3)SimpleDateFormat的format方法可以格式化日期,格式为yyyy-MM-dd HH:mm:ss
4)java8的新用法:使用LocalDateTime
23、如何将字符串反转?
1)使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。
2)将字符串转为字符数组,循环倒序输出
3)直接使用charAt方法从后往前输出
24、String 类的常用方法都有那些?
indexOf():返回指定字符的索引。
charAt():返回指定索引处的字符。
replace():字符串替换。
trim():去除字符串两端空白。
split():分割字符串,返回一个分割后的字符串数组。
getBytes():返回字符串的 byte 类型数组。
length():返回字符串长度。
toLowerCase():将字符串转成小写字母。
toUpperCase():将字符串转成大写字符。
substring():截取字符串。
equals():字符串比较。
25、java 中 IO 流分为几种?
按流向来分:
	输入流(InputStream/Reader)、输出流(OutputStream/Writer)。
按类型来分:
	字节流(InputStream/OutputStream)和字符流(Reader/Writer)(非纯文本文件,不要用字符流,会导致文件格式破坏)。
	字节流和字符流的区别是:字节流按 8 位传输以字节为单位输入输出数据,字符流按 16 位传输以字符为单位输入输出数据。
还可以划分为:
	节点流(低级流直接跟输入输出源对接,如:FileInputStream/FileOutputStream/FileReader/FileWriter)和处理流(高级流建立在低级流的基础上,如:BufferedReader/BufferedReader可对节点流经行包装,使读写更快)
	
实际用法,回顾上课的代码案例

26、Collection 和 Collections 有什么区别?
1)java.util.Collection 是一个集合接口(集合类的一个顶级接口)。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式,其直接继承接口有List与Set。

2)Collections则是集合类的一个工具类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。
27、如何实现数组和 List 之间的转换?
1)List转换成为数组:调用ArrayList的toArray方法。
2)数组转换成为List:调用Arrays的asList方法。这种方法执行后,是不能再调用add方法的,这个要注意。
28、线程的五种状态
创建、就绪、运行、阻塞和死亡。

创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态。

就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。

运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。

阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend,wait等方法都可以导致线程阻塞。

死亡状态。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪
29、java反射的原理,作用,和用法
原理:
    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;
这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

作用:
    在运行时根据一个对象,获取所属的类
    在运行时获取任意一个对象所在类所具有的成员变量和方法
用法:
    要想操作反射,必须先拿到反射的类对象,方法三种:
    1)通过通过Class.forName("全类名")
    2)类名.class
    3)对象.getClass()
参考:https://blog.csdn.net/weixin_42724467/article/details/84311385
30、Java序列化的作用
序列化的原本意图是希望对一个Java对象作一下“变换”,变成字节序列,这样一来方便持久化存储到磁盘,避免程序运行结束后对象就从内存里消失,
另外变换成字节序列也更便于网络运输和传播,所以概念上很好理解:
    序列化:把Java对象转换为字节序列。
    反序列化:把字节序列恢复为原先的Java对象。

序列化是不是靠Serializable接口实现的
    不是,它仅仅只是做一个标记用!!!它告诉代码只要是实现了Serializable接口的类都是可以被序列化的!然而真正的序列化动作不需要靠它完成。否则异常NotSerializableException

serialVersionUID是序列化前后的唯一标识符
    serialVersionUID序列化ID,可以看成是序列化和反序列化过程中的“暗号”,在反序列化时,JVM会把字节流中的序列号ID和被序列化类中的序列号ID做比对,只有两者一致,才能重新反序列化,否则就会报异常来终止反序列化的过程。

默认如果没有人为显式定义过serialVersionUID,那编译器会为它自动声明一个!
    如果在定义一个可序列化的类时,没有人为显式地给它定义一个serialVersionUID的话,则Java运行时环境会根据该类的各方面信息自动地为它生成一个默认的serialVersionUID,一旦像上面一样更改了类的结构或者信息,则类的serialVersionUID也会跟着变化!

参考:https://blog.csdn.net/qq_32575047/article/details/80070590
2、前端(HTML+JS+JQuery) 1、页面导入样式时,使用link和@import有什么区别?
   1)本质的差别:link属于XHTML标签,而@import完全是CSS提供的一种方式。

  2)加载顺序的差别:当一个页面被加载的时候(就是被浏览者浏览的时候),link引用的CSS会同时被加载,而@import引用的CSS会等到页面全部被下载完再被加载。所以有时候浏览@import加载CSS的页面时开始会没有样式(就是闪烁),网速慢的时候还挺明显。

  3)兼容性的差别:@import是CSS2.1提出的,所以老的浏览器不支持,@import只有在IE5以上的才能识别,而link标签无此问题。

  4)使用dom(document o bject model文档对象模型  )控制样式时的差别:当使用javascript控制dom去改变样式的时候,只能使用link标签,因为@import不是dom可以控制的.

2、 $(this) 和 this 关键字在 jQuery 中有何不同?
$(this) 返回一个 jQuery 对象,你可以对它调用多个 jQuery 方法,比如用 text() 获取文本,用val() 获取值等等。

而 this 代表当前元素,它是 JavaScript 关键词中的一个,表示上下文中的当前 DOM 元素。你不能对它调用 jQuery 方法,直到它被 $() 函数包裹,例如 $(this)。
3、清楚浮动的方法?
1)父级div定义 height 
    原理:父级div手动定义height,就解决了父级div无法自动获取到高度的问题。 
    优点:简单、代码少、容易掌握

    缺点:只适合高度固定的布局,要给出精确的高度,如果高度和父级div不一样时,会产生问题

2)结尾处加空div标签 clear:both

    原理:添加一个空div,利用css提高的clear:both清除浮动,让父级div能自动获取到高度 
    优点:简单、代码少、浏览器支持好、不容易出现怪问题 
    缺点:不少初学者不理解原理;如果页面浮动布局多,就要增加很多空div,让人感觉很不好

3)父级div定义 overflow:hidden

    原理:overflow:hidden时,浏览器会自动检查浮动区域的高度 
    优点:简单、代码少、浏览器支持好 
    缺点:不能和position配合使用,因为超出的尺寸的会被隐藏。

4)父级div定义 伪类:after

    原理:IE8以上和非IE浏览器才支持:after,原理和方法2有点类似
    优点:浏览器支持好、不容易出现怪问题(目前:大型网站都有使用,如:腾迅,网易,新浪等等) 
    缺点:代码多、不少初学者不理解原理,要两句代码结合使用才能让主流浏览器都支持
4、$(document).ready()方法和window.onload有什么区别?
1)、window.onload方法是在网页中所有的元素完全加载到浏览器后才执行的。且只能写一个

2)、$(document).ready() 方法可以在DOM载入就绪时就对其进行操纵,并调用执行绑定的函数,可以写多个。
5、jquery中 . g e t ( ) 提 交 和 .get()提交和 .get()提交和.post()提交有区别吗?
相同点:都是异步请求的方式来获取服务端的数据;
异同点:
    1)请求方式不同:$.get() 方法使用GET方法来进行异步请求的。$.post() 方法使用POST方法来进行异步请求的。
    2)参数传递方式不同:get请求会将参数跟在URL后进行传递,而POST请求则是作为HTTP消息的实体内容发送给Web服务器的,这种传递是对用户不可见的。
    3)数据传输大小不同:get方式传输的数据大小有限制 而POST内容要大很多
    4)安全问题: GET 方式请求不安全。
6、js 字符串操作函数有哪些
    indexOf() – 返回字符串中一个子串第一处出现的索引。如果没有匹配项,返回 -1 。
    lastIndexOf() – 返回字符串中一个子串最后一处出现的索引,如果没有匹配项,返回 -1 。  
    charAt() – 返回指定位置的字符。 
    match() – 检查一个字符串是否匹配一个正则表达式。
    substr() 函数 -- 返回从string的startPos位置,长度为length的字符串
    substring() – 返回字符串的一个子串。传入参数是起始位置和结束位置,注意被问到跟Java的区别
    replace() – 用来查找匹配一个正则表达式的字符串,然后使用新字符串代替匹配的字符串。 
    split() – 通过将字符串划分成子串,将一个字符串做成一个字符串数组。
    length – 返回字符串的长度,所谓字符串的长度是指其包含的字符的个数。
    toUpperCase() – 将整个字符串转成大写字母。
    。。。。               
7、你是如何使用jquery中的ajax的?
如果是一些常规的ajax程序的话,使用$.get(),$.post(),一般使用的是$.post() 方法。
如果需要设定beforeSend(提交前回调函数),error(失败后处理),success(成功后处理)及complete(请求完成后处理)回调函数等,
标准语法是$.ajax()。
其中ajax的基本语法是:
1)url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址。

2)type: 要求为String类型的参数,请求方式(post或get)默认为get。注意其他http请求方法,例如put和delete也可以使用,但仅部分浏览器支持。

3)timeout: 要求为Number类型的参数,设置请求超时时间(毫秒)。此设置将覆盖$.ajaxSetup()方法的全局设置。

4)async: 要求为Boolean类型的参数,默认设置为true,所有请求均为异步请求。如果需要发送同步请求,请将此选项设置为false。注意,同步请求将锁住浏览器,用户其他操作必须等待请求完成才可以执行。

5)cache: 要求为Boolean类型的参数,默认为true(当dataType为script时,默认为false),设置为false将不会从浏览器缓存中加载请求信息。

6)data: 要求为Object或String类型的参数,发送到服务器的数据。如果已经不是字符串,将自动转换为字符串格式。get请求中将附加在url后。防止这种自动转换,可以查看  processData选项。对象必须为key/value格式,例如{foo1:"bar1",foo2:"bar2"}转换为&foo1=bar1&foo2=bar2。如果是数组,JQuery将自动为不同值对应同一个名称。例如{foo:["bar1","bar2"]}转换为&foo=bar1&foo=bar2。

7)dataType: 要求为String类型的参数,预期服务器返回的数据类型。如果不指定,JQuery将自动根据http包mime信息返回responseXML或responseText,并作为回调函数参数传递。可用的类型如下:
xml:返回XML文档,可用JQuery处理。
html:返回纯文本HTML信息;包含的script标签会在插入DOM时执行。
script:返回纯文本JavaScript代码。不会自动缓存结果。除非设置了cache参数。注意在远程请求时(不在同一个域下),所有post请求都将转为get请求。
json:返回JSON数据。
jsonp:JSONP格式。使用SONP形式调用函数时,例如myurl?callback=?,JQuery将自动替换后一个“?”为正确的函数名,以执行回调函数。
text:返回纯文本字符串。

8.beforeSend:要求为Function类型的参数,发送请求前可以修改XMLHttpRequest对象的函数,例如添加自定义HTTP头。在beforeSend中如果返回false可以取消本次ajax请求。XMLHttpRequest对象是惟一的参数。
        function(XMLHttpRequest){
           this;   //调用本次ajax请求时传递的options参数
        }
9)complete:
要求为Function类型的参数,请求完成后调用的回调函数(请求成功或失败时均调用)。参数:XMLHttpRequest对象和一个描述成功请求类型的字符串。
      function(XMLHttpRequest, textStatus){
         this;    //调用本次ajax请求时传递的options参数
      }

10)success:要求为Function类型的参数,请求成功后调用的回调函数,有两个参数。
     (1)由服务器返回,并根据dataType参数进行处理后的数据。
     (2)描述状态的字符串。
     function(data, textStatus){
        //data可能是xmlDoc、jsonObj、html、text等等
        this;  //调用本次ajax请求时传递的options参数
     }

11)error:要求为Function类型的参数,请求失败时被调用的函数。该函数有3个参数,即XMLHttpRequest对象、错误信息、捕获的错误对象(可选)。ajax事件函数如下:
       function(XMLHttpRequest, textStatus, errorThrown){
      //通常情况下textStatus和errorThrown只有其中一个包含信息
      this;   //调用本次ajax请求时传递的options参数
       }

12)contentType:要求为String类型的参数,当发送信息至服务器时,内容编码类型默认为"application/x-www-form-urlencoded"。该默认值适合大多数应用场合。
案例代码:
$(function(){
    $('#send').click(function(){
     $.ajax({
         type: "GET",
         url: "test.json",
         data: {username:$("#username").val(), content:$("#content").val()},
         dataType: "json",
         success: function(data){
             $('#resText').empty();   //清空resText里面的所有内容
             var html = ''; 
             $.each(data, function(){
                   。。。;
             });
             $('#resText').html(html);
              }
     });
    });
});
8、http常见状态码有哪些?
2xx (成功)表示成功处理了请求的状态代码
    200 (成功) 服务器已成功处理了请求。
    204 表示请求处理成功,但没有资源返回
3xx (重定向) 表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向。
    301 表示永久性重定向。该状态码表示请求的资源已被分配了新的URI,以后应使用资源现在所指的URI
    302 表示临时性重定向
    304 (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容
4xx(请求错误) 这些状态代码表示请求可能出错,妨碍了服务器的处理
    400 (错误请求) 服务器不理解请求的语法。 
    401 表示未授权(Unauthorized),当前请求需要用户验证
    403 (禁止) 服务器拒绝请求。
    404 (未找到) 服务器找不到请求的网页。
5xx(服务器错误)这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错
    500 (服务器内部错误) 服务器遇到错误,无法完成请求。
    501 (尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。
    502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。
    503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。
    504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。
    505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。
3、JavaWeb 1、Tomcat目录结构及作用
bin: 存放各种平台下用于启动和停止Tomcat的脚本文件
conf: 存放Tomcat服务器的各种配置文件,如修改端口配置文件server.xml
lib: 存放Tomcat服务器所需的各种JAR文件
logs: 存放Tomcat的日志文件
temp: Tomcat运行时用于存放临时文件
webapps: 当发布Web应用时,默认情况下会将Web应用的文件存放于此目录中
work: Tomcat把由JSP生成的Servlet放于此目录下
2、JavaWeb中,如何解决乱码问题?
第一种:(get方式)
    在Tomcat目录结构confserver.xml中设置字符集
    
第二种:(get方式)     
    String name = request.getParameter("name");
    // 对请求数据进行字符解码和转码
    name = new String(name.getBytes("ISO-8859-1"), "UTF-8");
      
第三种:(post方式)      
    // 设置读取请求信息的字符编码为UTF-8,统一处理使用字符集编码过滤器
    request.setCharacterEncoding("UTF-8");   
3、转发重定向的区别?
1)请求的转发: 地址栏是初次发出请求的地址.--这个是重点,mvc架构的核心
    请求的重定向: 地址栏不再是初次发出的请求地址. 地址栏为最后响应的那个地址 
       
2)请求转发: 在最终的 Servlet 中, request 对象和中转的那个 request 是同一个对象. 
    请求的重定向: 在最终的 Servlet 中, request 对象和中转的那个 request 不是同一个对象.       
   
3)请求的转发: 只能转发给当前 WEB 应用的的资源
       请求的重定向: 可以重定向到任何资源. 
       
4)请求的转发: / 代表的是当前 WEB 应用的根目录
       请求的重定向: / 代表的是当前 WEB 站点的根目录. (站点:服务+端口)
4、JSP内置对象一共有哪些。
request: HttpServletRequest 的一个对象
response: HttpServletResponse 的一个对象(在 JSP 页面中几乎不会调用 response 的任何方法.)
pageContext: 页面的上下文(当前jsp页面), 是 PageContext 的一个对象.  可以从该对象中获取到其他 8 个隐含对象. 也可以从中获取到当前页面的其他信息.
session: 代表浏览器和服务器的一次会话跟踪(所谓的session失效,就要重新登录), 是 HttpSession 的一个对象
application: 代表当前 WEB 应用. 是 ServletContext 对象.可以获取初始化参数
out: JspWriter 对象. 调用 out.println() 可以直接把字符串打印到浏览器上. 这个是最常用的用法
config: 当前 JSP 对应的 Servlet 的 ServletConfig 对象(开发的时候几乎不使用).ServletConfig
page: 指向当前 JSP 对应的 Servlet 对象的引用, 但为 Object 类型, 只能调用 Object 类的方法(几乎不使用) 
exception: 只有在特殊的时候用,在声明了 page 指令的 isErrorPage="true" 时, 才可以使用.
5、JSP常用指令有哪些?
page指令:定义页面的一些属性,常用属性:
    contentType="text/html;charset=utf-8";    向浏览器端输出数据的编码
    pageEncoding="utf-8";                     JSP编译成java文件时所用的编码
    session="true"                            是否自动创建HttpSession对象. 
    import 属性: 指定当前 JSP 页面对应的 Servlet 需要导入的类. 
include指令:用于通知 JSP 引擎在翻译当前 JSP 页面时将其他文件中的内容合并进当前 JSP 页面转换成的 Servlet 源文件中,这种在源文件级别进行引入的方式称之为静态引入(源码级包含)
taglib指令:引入一个标签库,如jstl的核心标签库和格式化标签库,还有springform的标签库
6、cookie和session的作用、区别、应用范围
cookie数据保存在客户端,session数据保存在服务端。
cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,相当重要的数据,应该使用session保存到服务端。
session会在一定时间内保持在服务器上,但是会占用内存资源,当访问的用户过多,会加重服务器的负载,考虑到减轻服务器的压力,可以将不重要的数据放在cookie中持久的保存。
7、Servlet生命周期简述
Servlet 生命周期的方法: 以下方法都是由 Serlvet 容器负责调用. 
1). 构造器: 只被调用一次. 只有第一次请求 Servlet 时, 创建 Servlet 的实例. 调用构造器. 这说明 Serlvet 的单实例的,存在线程安全问题,不推荐创建全局变量!,如果需要在tomcat启动的时候创建实例,通过load-on-startup配置,值越小越先被创建。
2). init 方法: 只被调用一次. 在创建好实例后立即被调用. 用于初始化当前 Servlet. 
3). service: 被多次调用. 每次请求都会调用 service 方法. 实际用于响应请求的. 
4). destroy: 只被调用一次. 在当前 Servlet 所在的 WEB 应用被卸载前调用. 用于释放当前 Servlet 所占用的资源. 
8、保存session机制的方式
1)常用的保存session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。
    1、session通过SessionID来区分不同的客户, session是以cookie或URL重写为基础的,默认使用cookie来实现,系统会创造一个名为JSESSIONID的输出cookie,这称之为session cookie
    2、以区别persistent cookies(也就是我们通常所说的cookie),session cookie是存储于浏览器内存中的,并不是写到硬盘上的,通常看不到JSESSIONID,但是当把浏览器的cookie禁止后,web服务器会采用URL重写的方式传递Sessionid,这时地址栏看到
    3、session cookie针对某一次会话而言,会话结束session cookie也就随着消失了,而persistent cookie只是存在于客户端硬盘上的一段文本。 
    4、关闭浏览器,只会是浏览器端内存里的session cookie消失,但不会使保存在服务器端的session对象消失,同样也不会使已经保存到硬盘上的持久化cookie消失。

    示例:
        <% 
            Cookie cookie = new Cookie("JSESSIONID", session.getId());
            cookie.setMaxAge(20);
            response.addCookie(cookie);
        %>
    这样设置之后,下次请求后,每次都会传给服务器,就可以找到对应的session对象了(服务器端的session对象是不会自动失效的)

2)cookie可以被人为的禁用,必须有其它的机制以便在cookie被禁用时仍然能够把session id传递回服务器,经常采用的一种技术叫做URL重写,就是把session id附加在URL路径的后面,附加的方式也有两种,一种是作为URL路径的附加信息,另一种是作为查询字符串附加在URL后面。网络在整个交互过程中始终保持状态,就必须在每个客户端可能请求的路径后面都包含这个sessionid。
9、session对象如何销毁?
    1)直接调用 HttpSession 的 invalidate()
    2)HttpSession 超过过期时间. 

        > 返回最大时效: getMaxInactiveInterval() 单位是秒
        > 设置最大时效: setMaxInactiveInterval(int interval)
        > 可以在 web.xml 文件中配置 Session 的最大时效, 单位是分钟. 
        
        
            30
        

    3)卸载当前 WEB 应用. 
    注意强调:
        关闭浏览器只会使存储在客户端浏览器内存中的session cookie失效,
        不会使服务器端的session对象失效。
10、过滤器Filter基本工作原理
1)当在 web.xml 中注册了一个 Filter 来对某个 Servlet 程序进行拦截处理时,这个 Filter 就成了 Servlet 容器与该 Servlet 程序的通信线路上的一道关卡,该 Filter 可以对 Servlet 容器发送给 Servlet 程序的请求和 Servlet 程序回送给 Servlet 容器的相应进行拦截,可以决定是否将请求继续传递给 Servlet 程序,以及对请求和相应信息是否进行修改

2)在一个 web 应用程序中可以注册多个 Filter 程序,每个 Filter 程序都可以对一个或一组 Servlet 程序进行拦截。

3)若有多个 Filter 程序对某个 Servlet 程序的访问过程进行拦截,当针对该 Servlet 的访问请求到达时,web 容器将把这多个 Filter 程序组合成一个 Filter 链(过滤器链1)。Filter 链中各个 Filter 的拦截顺序与它们在应用程序的 web.xml 中映射的顺序一致
11、el表达式中默认查找顺序及jsp四大作用域在el表达式中对应关系
    默认查找顺序:
        按照page → request → session → application的作用域顺序依次查找,找到即返回,最终找不到返回null

    作用域在el中的对应关系:
        page        pageScope 例如${pageScope.username}表示在page作用域查找变量username,找不到返回null
        request     requestScope
        session     sessionScope
        application applicationScope
12、<%!…%>和<%=…%>区别
<%= ... %>:这个是jsp的表达式
  本质:在将JSP页面转换成Servlet后,使用out.print()将表达式的值输出。
  注意:
  	如果表达式是调用一个方法,那么这个方法必须要有返回值,而不应是void,方法是不能被调用的。
	在方法的后面不能有分号;例如<%= ... ;%>这是不允许的。
<%! ... %>:这个是jsp的声明
  本质:将声明的变量加入到Servlet类(在任何方法之外),方法就成了Servlet()的全局变量或者普通方法。
  
4、MySQL 1、MySQL和Oracle的区别
    1)MySQL是开源的项目(免费),Oracle数据库产品是闭源同时也是收费的。Mysql是中小型数据库,oracle是大型的
    2)主键 Mysql一般使用自动增长类型,在创建表时只要指定表的主键为auto_increment,插入记录时,不需要再指定该记录的主键值,Mysql将自动增长;Oracle没有自动增长类型,主键一般使用的序列,插入记录时将序列号的下一个值付给该字段即可。
    3)翻页的SQL语句的处理 MYSQL处理翻页的SQL语句比较简单,用LIMIT 开始位置, 记录个数;ORACLE处理翻页的SQL语句就比较繁琐了。每个结果集只有一个ROWNUM字段标明它的位置, 并且只能用ROWNUM<100, 不能用ROWNUM>80,且必须排序。
    4)MySQL对于事务默认是不支持的,只有存储引擎中如:innodb可以支持。 而Oracle对于事务是完全支持,不管是OLTP还是OLAT都是支持的。
    5)日期:MYSQL日期字段分DATE和TIME两种,ORACLE日期字段只有DATE,包含年月日时分秒信息,用当前数据库的系统时间为SYSDATE, 精确到秒。
    6)MYSQL的非空字段也有空的内容,ORACLE里定义了非空字段就不容许有空的内容
    7)MYSQL里的非空判断是ifnull(a,b),而对应oracle的nvl(a,b);
    8)日期比较:MYSQL: 可以用Date类型的日期进行比较时间比较。
    oracle:必须用to_date()函数和to_char()函数配合转换成统一格式的日期字符串,然后进行比较。
    9)MYSQL:可以用YEAR(),MONTH(),NOW()等函数获取年/月/当前日期等。oracle:必须用to_char(sysdate, 'yyyy'),to_char(sysdate, 'MM')获取。
    10)日期转换:MYSQL:DATE_FORMAT(t.col,'%Y-%m-%d')。Oracle:to_char(t.col,'yyyy-mm-dd') 
    11)表的创建  MySQL支持``符号,但是Oracle没有
    12)Oracle:可以使用“||”进行拼接。Mysql:可以使用concat(a,b)
    13) MySQL:insert into table values (),()...支持多条数据同时插入,但是Oracle没有这个写法
2、事务的基本特征
1)原子性(atomicity):一个事务必须视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作,这就是事务的原子性。
2)一致性(consistency):数据库总数从一个一致性的状态转换到另一个一致性的状态。
3)隔离性(isolation):一个事务所做的修改在最终提交以前,对其他事务是不可见的。
4)持久性(durability):一旦事务提交,则其所做的修改就会永久保存到数据库中。此时即使系统崩溃,修改的数据也不会丢失。

事务就是被绑定在一起作为一个逻辑工作单元的SQL语句分组,如果任何一个语句操作失败那么整个操作就被失败,以后操作就会回滚到操作前状态,或者是上有个节点。为了确保要么执行,要么不执行,就可以使用事务。要将有组语句作为事务考虑,就需要通过ACID测试,即原子性,一致性,隔离性和持久性。
3、事务的隔离级别
读未提交(Read uncommitted),一个事务可以读取另一个未提交事务的数据,最低级别,任何情况都无法保证。
    出现的问题是:脏读,不可重复读,幻读
        脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据;

读已提交(Read committed),一个事务要等另一个事务提交后才能读取数据,可避免脏读的发生。
    出现的问题是——不可重复读(Nonrepeatable Read):不可重复读意味着我们在同一个事务中执行完全相同的select语句时可能看到不一样的结果。
        即:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果因此本事务先后两次读到的数据结果会不一致;

        (1)这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)
        (2)它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变

可重复读(Repeatable read),就是在开始读取数据(事务开启)时,不再允许修改操作,可避免脏读、不可重复读的发生。
    (1)这是MySQL的默认事务隔离级别
    (2)它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行
    (3)此级别可能出现的问题——幻读(Phantom Read):当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行

串行(Serializable),是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。
4、什么是索引,索引的分类,索引的优缺点
索引是对数据库表中一列或多列的值进行排序的一种结构,由数据库管理,不可干预
索引一般分为:普通索引,唯一索引(不能有重复值),主键索引(唯一,非空),组合索引(多列索引)
优点:
    a. 大大加快数据的检索速度
    b. 创建唯一性索引,保证数据库表中每一行数据的唯一性
    c. 可以加速表和表之间的连接

缺点:
    a. 索引需要占物理空间。
    b. 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,
    c. 降低了数据的维护速度。
   
什么情况下应不建或少建索引
	1)表记录太少
	2)经常插入、删除、修改的表
	3)数据重复且分布平均的表字段,假如一个表有10万行记录,有一个字段A只有T和F两种值,且每个值的分布概率大约为50%,那么对这种表A字段建索引一般不会提高数据库的查询速度。
	4)经常和主字段一块查询但主字段索引值比较多的表字段
5、介绍SQL优化可以从哪些方面考虑,SQL语句的优化的关注点有哪些
SQL优化
    1)SQL语句及索引的优化
    2)数据库表结构的优化
    3)系统配置的优化
    4)硬件的优化

SQL语句的优化的关注点
    1)对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。

   2)应尽量避免在 where 子句中使用 !=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。

   3)应尽量避免在 where 子句中对字段进行 null 值 判断,否则将导致引擎放弃使用索引而进行全表扫描 ,一般可以可以给列设置默认值0,确保表中num列没有null值

    4)应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描

    5)应尽量避免全模糊查询,如like '%abc%'导致全表扫描,建议右模糊

    6)应尽量避免在 where 子句中对字段进行表达式操作,即避免在where条件中等号的左侧进行表达式、函数操作,会导致数据库引擎放弃索引进行全表扫描
        select id from t where num/2=100
       应改为:
       select id from t where num=100*2

    7)应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描

    8)在使用索引字段作为条件时,如果该索引是【复合索引】,那么必须使用到该索引中的【第一个字段】作为条件时才能保证系统使用该索引,否则该索引将不会被使用。并且应【尽可能】的让字段顺序与索引顺序相一致。(字段顺序也可以不与索引顺序一致,但是一定要包含【第一个字段】。

    9)提高查询效率,用 exists 代替 in 

    10)并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用

    11)索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。

    12)尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。

    13)尽可能的使用 varchar 代替 char ,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。

    14)任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。

    15)当数据量大时,避免使用where 1=1的条件。通常为了方便拼装查询条件,我们会默认使用该条件,数据库引擎会放弃索引进行全表扫描

    16)索引列上计算引起的索引失效及优化措施以及注意事项

        创建索引、优化查询以便达到更好的查询优化效果。但实际上,MySQL有时并不按我们设计的那样执行查询。MySQL是根据统计信息来生成执行计划的,这就涉及索引及索引的刷选率,表数据量,还有一些额外的因素。
        简而言之,当MYSQL认为符合条件的记录在30%以上,它就不会再使用索引,因为mysql认为走索引的代价比不用索引代价大,所以优化器选择了自己认为代价最小的方式。事实也的确如此
        是MYSQL认为记录是30%以上,而不是实际MYSQL去查完再决定的。都查完了,还用什么索引啊?!
        MYSQL会先估算,然后决定是否使用索引。
        
    除此之外:如果表关联字符集不统一,或者关联字段的类型不统一,也可能导致索引失效。
6、select Count (*)和Select Count(1)以及Select Count(column)区别
	一般情况下,Select Count (*)和Select Count(1)两着返回结果是一样的,但是对于大数据量的情况下,Select Count (*)比Select Count(1)执行效率慢

    如果有主键的話,那主键作为count的条件时候count(主键)最快

    count(*) 跟 count(1) 的结果一样,都包括对NULL的统计,而count(column) 是不包括NULL的统计

7、什么是sql注入,及主要特点
——官方说法:把SQL命令插入到web表单验证的输入框中,提交到服务器,以达到越过数据验证的目的。

——通俗说法:在浏览器的某个网页中,在身份验证框或者数据查询框中,通过输入sql命令,影响SQL语句字符串的拼接,从而使原本执行不通过的SQL语句可以执行通过。

sql注入的主要危害
    未经授权操作数据库的数据
    跳过验证随意登录系统,恶意纂改网页
    私自添加系统账号或者是数据库使用者账号
    网页挂木马
    
如何解决:
	增加参数值校验,非法参数不给提交
	增加安全过滤器,拦截非法请求
	底层使用PreparedStatement,即mybatis的#{}防止注入

8、什么是锁?
数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。

加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了一定的控制,在该事务释放锁之前,其他的事务不能对此数据对象进行更新操作。

基本锁类型:锁包括行级锁(InnoDB)和表级锁(MyISAM)

表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。

行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

悲观锁和乐观锁的理解及适用场景
    悲观锁(Pessimistic Lock): 
    每次获取数据的时候,都会担心数据被修改,所以每次获取数据的时候都会进行加锁,确保在自己使用的过程中数据不会被别人修改,使用完成后进行数据解锁。由于数据进行加锁,期间对该数据进行读写的其他线程都会进行等待。

    乐观锁(Optimistic Lock): 
    每次获取数据的时候,都不会担心数据被修改,所以每次获取数据的时候都不会进行加锁,但是在更新数据的时候需要判断该数据是否被别人修改过。如果数据被其他线程修改,则不进行数据更新,如果数据没有被其他线程修改,则进行数据更新。由于数据没有进行加锁,期间该数据可以被其他线程进行读写操作。

    适用场景:
    悲观锁:比较适合写入操作比较频繁的场景,如果出现大量的读取操作,每次读取的时候都会进行加锁,这样会增加大量的锁的开销,降低了系统的吞吐量。

    乐观锁:比较适合读取操作比较频繁的场景,如果出现大量的写入操作,数据发生冲突的可能性就会增大,为了保证数据的一致性,应用层需要不断的重新获取数据,这样会增加大量的查询操作,降低了系统的吞吐量。

    总结:两种所各有优缺点,读取频繁使用乐观锁,写入频繁使用悲观锁。

参考1:https://blog.csdn.net/Saintyyu/article/details/91269087?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param

参考2:https://blog.csdn.net/tanga842428/article/details/52748531?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param

参考3:https://blog.csdn.net/puhaiyang/article/details/72284702?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param

参考4:https://zhuanlan.zhihu.com/p/29150809


9、如何通俗地理解三个范式?
第一范式:1NF是对列字段的原子性约束,要求列字段具有原子性,不可再拆分;
第二范式:2NF是对记录的惟一性约束,要求记录(行)有惟一标识,即实体的惟一性;  
第三范式:3NF是对字段冗余性的约束,即任何字段不能由其他字段派生出来,它要求字段没有冗余。
范式化设计优缺点:
	优点:
		可以尽量得减少数据冗余,使得更新快,体积小
	缺点:
		对于查询需要多个表进行关联,减少写得效率增加读得效率,更难进行索引优化
反范式化:
	优点:
		可以减少表得关联,可以更好得进行索引优化	
	缺点:
		数据冗余以及数据异常,数据得修改需要更多的成本	
10、Mysql中varchar和char区别
区别一:定长和变长
	char表示定长、长度固定,varchar表示变长,即长度可变(允许的长度范围内)。
	即char类型是规定多少字长则必须存储多少字长,超过的长度的字段则只能截取出对应的长度进行存储,相对于要求字长长度不够的字段则用空格补齐。
	而varchar类型则是只要在规定字长之内,有多少存多少,无需补齐;超出的部分和char一样,舍去即可。
	
区别二:存储容量不同

	对于char类型来说,最多只能存放的字符个数为255,和编码无关。
	varchar最多能存放65532个字符。VARCHAR的最大有效长度由最大行大小和使用的字符集来确定。
11、MYSQL中DROp、DELETE、TRUNCATE的区别
1)truncate 和 delete只删除数据(记录)不删除表的结构;drop语句将删除表的数据(记录)和表结构依赖的约束(constrain),触发器(trigger),索引(index),保留依赖于该表的存储过程/函数,但是变为invalid状态 .
2)delete 是 DML 语句,操作完以后如果没有不想提交事务还可以回滚,truncate 和 drop 是 DDL 语句,操作完马上生效,不能回滚.
3)truncate之后的自增字段从1开始计数了[即truncate是摧毁原来的表重新创建一张结构相同的表(有原表的结构)],delete的仍保留原来的最数数值[即如果添加数据从最值+1开始],drop将表的结构也删除了(原表数据和结构都没有了)。
truncat会释放表所占的空间,而delete则不会.

总结:
    执行速度:一般,drop> truncate > delete。
    drop和truncate时虽然在备份情况下,可以恢复,但为了减少麻烦,要慎重。
    如果想删除部分数据用delete,注意带上where子句;
    如果想删除表,用drop;想保留表而将所有数据删除,如果和事务无关,用truncate即可;
    如果和事务有关,或者想触发trigger,还是用delete
    如果是整理表内部的碎片,可以用truncate跟上reuse stroage,再重新导入/插入数据
12、MySQL的存储引擎InnoDB和MyISAM区别
区别:
1. InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交
2. InnoDB支持外键,而MyISAM不支持。对一个包含外键的InnoDB表转为MYISAM会失败;
3. InnoDB是数据文件是和索引绑在一起的,通过主键索引效率很高。而MyISAM是数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。
4. InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描。而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;
5. Innodb不支持全文索引,而MyISAM支持全文索引,查询效率上MyISAM要高;
    如何选择:
    1. 是否要支持事务,如果要请选择innodb,如果不需要可以考虑MyISAM;
    2. 如果表中绝大多数都只是读查询,可以考虑MyISAM,如果既有读写也挺频繁,请使用InnoDB。
    3. 系统奔溃后,MyISAM恢复起来更困难,能否接受;
    4. MySQL5.5版本开始Innodb已经成为Mysql的默认引擎(之前是MyISAM)。
5、Mybatis 1、Mybaits的优点:
1) 基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在XML里,解除sql与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态SQL语句,并可重用。
2) 与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接;
3) 很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数据库MyBatis都支持)。
4) 能够与Spring很好的集成;
5)提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系映射标签,支持对象关系组件维护
2、MyBatis与Hibernate有哪些不同?
1) Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句。
2) Mybatis直接编写原生态sql,可以严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,因为这类软件需求变化频繁,一但需求变化要求迅速输出成果。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件,则需要自定义多套sql映射文件,工作量大。
3) hibernate开发可以节省很多代码,提高效率,但是对于复杂条件查询支持不好。

3、#{}和${}的区别是什么?
1) #{}是预编译处理,${}是字符串替换。
2) Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
3) Mybatis在处理${}时,就是把${}替换成变量的值。
4) 使用#{}可以有效的防止SQL注入,提高系统安全性。
4、当实体类中的属性名和表中的字段名不一样 ,怎么办 ?
1) 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。
2) 通过来映射字段名和实体类属性名的一一对应的关系。
5、Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?
第一种是使用标签,逐一定义数据库列名和对象属性名之间的映射关系。
第二种是使用sql列的别名功能,将列的别名书写为对象属性名。
有了列名与属性名的映射关系后,Mybatis通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。
6、resultMap和resultType的区别,以及resultMap里的元素(顺序)
1)resultType:对应的是java对象中的属性,大小写不敏感
2)resultMap: 指的是定义好了的id的,是定义好的resultType的引用
    resultMap:
        属性id:唯一标识(resultMap的名称)
        属性type:Java实体类

        标签id:一般对应数据库中该行的主键id,设置此项可提高MyBatis性能
        标签result: 映射到JavaBean的某个“简单类型”属性  
        标签association:映射到JavaBean的某个“复杂类型”属性,比如JavaBean类
        标签collection:映射到JavaBean的某个“复杂类型”属性,比如集合
7、通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?
1)Dao接口即Mapper接口,接口的全类名,就是映射文件中的namespace的值;
2)接口的方法名,就是映射文件中Mapper的id值;接口方法内的参数,就是传递给sql的参数。
3)Mapper接口是没有实现类的,当调用接口方法时,接口全类名+方法名拼接字符串作为key值,可唯一定位一个MapperStatement。在Mybatis中,每一个