java面试题
1.java基础
java的跨平台原理
由于各操作系统(windows,liunx等)支持的指令集,不是完全一致的。就会让我们的程序在不同的操作系统上要执行不同程序代码。Java开发了适用于不同操作系统及位数的java虚拟机来屏蔽个系统之间的差异,提供统一的接口。对于我们java开发者而言,你只需要在不同的系统上安装对应的不同java虚拟机、这时你的java程序只要遵循java规范,就可以在所有的操作系统上面运行java程序了。
面向对象的特性
封装:对特定代码块或变量进行归类
继承:extends,让子类具有父类的某些属性和方法(产生关系)。单继承。
多态:父类引用变量指向子类对象,提高代码的扩展性。(大范围可接受小范围)
int与Integer的区别
int是基本数据类型,Integer是引用数据类型,是对int的包装;
int的默认值是0,Integer的默认值是null;
int类型的变量可以直接使用,Integer变量需要实例化之后才能使用;
int直接存放数据值,Integer是对象的引用,创建一个实例之后就产生了一个指针指针指向这个对象。
有了基本数据类型,为什么还需要包装类型?
基本数据类型:java中提供了8中基本的数据类型。boolean int float等
包装类型:每一个基本的数据类型都会一一对应一个包装类型。
boolean ----->Boolean,Int -------->Integer
装箱:把基本的数据类型转换成对应的包装类型.
拆箱:就是把包装类型转换为基本数据类型.基本数据类型
Java是一个面向对象的语言,而基本的数据类型,不具备面向对象的特性。如null的表示 Integer--->null, int---->0 用Integer和int分别表示Person这个类的ID
Integer变量对比
1)int与Integer:只要两者的值相等,则结果为true (因为包装类Integer和基本数据类型int比较时,java会自动拆箱为int,然后进行比较,实际上就变为两个int变量的比较)
2)new Integer变量对比:通过new出来的结果都为false,原因是new出来的指向的是引用地址。
3)非new与new Integer变量对比:
4)非new变量对比:结果为false,非new出来的变量指向常量池中的对象,而new出来的指向的是堆中新建的对象,两者的地址不同。
当值在-128~127之间,则结果是true,反之是false。当值在-128~127之间,会自动拆箱进行比较,比较的是值;超过这个范围,会在堆中new一个Integer对象来存储。
Array与Arraylist的区别
Array的长度是固定的,ArrayList的长度是可变的;
效率:Array>ArrayList。原因是ArrayList动态扩容造成了效率消耗。
ArrayList list = new ArrayList(20);中的list扩充 0 次。原因是这里直接调用有参的构造,直接定义好了初始容量20,所以并没有去扩容。当没有指定初始容量时,默认是10,当超过此容量时才会按照1.5倍进行扩容。
集合归纳
HashMap底层实现原理?
Jdk1.7与jdk1.8中HashMap的区别:在1.7中,HashMap采用位桶+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。而1.8中,HashMap采用位桶+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。
HashMap的工作原理:实现了Map接口,采用key-value的形式存储数据,使用put()方法保存数据,使用get()方法获取数据。每一个键值对组成了一个Entry实体,Entry类是一个单向的链表结构,它具有Next指针,用来连接下一个Entry实体。当发生碰撞时,对象会储存在链表的下一个节点。
HashMap和HashTable的区别
相同点:HashMap和HasheTalbe都可以使用来存储key--value的数据。
区别:HashMap是可以把null作为key或者value的,而HashTable是不可以的;
HashMap是线程不安全的,效率较高。而HashTalbe是线程安全的,效率较低
HashMap与HashSet的区别?
HashSet实现了Set接口,不允许集合中出现重复的元素,而HashMap实现了Map接口,不允许出现重复的键;
HashSet存储对象,HashMap存储键值对;
HashSet通过add()方法向集合添加元素,HashMap通过put()方法向集合添加元素;
HashSet使用成员对象计算hashcode值,若值相等,则用equals判断对象的相等性,HashMap使用键计算hashcode值;
HashMap相对于HashSet较快,因为根据唯一的键获取对象。
java中代码块的介绍?
static{ 静态代码块,做初始化}
构造代码块{ },在类中的代码块
局部代码块 { },在方法中的代码块
三个的执行顺序:静态 -> 构造 -> 局部代码块。
执行顺序:父类静态代码块->子类静态代码块->父类的构造代码块->父类构造方法->子类构造代码块->子类构造方法。
heap与stack的区别
Stack(栈)是JVM的内存指令区
Heap(堆)是JVM的内存数据区
同步与异步的区别
同步:所有的操作都做完,才返回给用户。这样用户在线等待的时间太长,给用户一种卡死了的感觉。这种情况下,用户不能关闭界面,如果关闭了,即迁移程序就中断了。
异步:将用户请求放入消息队列,并反馈给用户,系统迁移程序已经启动,你可以关闭浏览器了。然后程序再慢慢地去写入数据库去。
同步,是所有的操作都做完,才返回给用户结果。即写完数据库之后,在响应用户,用户体验不好。
异步,不用等所有操作等做完,就相应用户请求。即先相应用户请求,然后慢慢去写数据库,用户体验较好。
什么是内存泄漏?
内存泄漏是指程序中已经动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行缓慢甚至系统奔溃等严重后果。
什么是死锁?解决办法?
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。
可以通过预防和避免死锁来阻止死锁的发生。
"=="和equals方法究竟有什么区别?
==用来判断两个变量之间的的值是否相等。变量就可以分为基本数据类型变量,引用类型。如果是基本数据类型的变量直接比较值,而引用类型要比较对应的引用的内存的首地址。
equals 用来比较两个对象长得是否一样,其源码如下
对于其比较,就有两种情况:
1)若类没有重写equals方法,则等同于==来比较两个对象。
2)若类重写了equals方法,则按我们定义的方式去判断是否相等。
示例1:字符串的比较
示例2:用户对象的比较
对比结果如下:
这里重写equals时,只对name和age属性进行比较,只要两者相等即可视为两个对象相等。不重写equals时,通过new的对象,一般引用的地址是不同的,但重写equals与hascode方法后,其地址都是一样的。
什么是hashCode(),其作用是什么?
hashCode()的作用是获取哈希码,返回值是int类型。而哈希码的作用是确定对象在哈希表中的索引位置,因为此表是按照key-value的形式存储的,通过哈希码可快速找到对象。
以HashSet为例,当把对象放入HashSet,首先会计算对象的hashcode判断对象加入的位置,同时也会与已加入的对象的hashcode进行比较,若没有相符的hashcode,则视为没有重复对象,然后直接插入此对象。若hashcode相等,则需要调用equals方法判断hashcode相等的两个对象是否相同,如果相同,则后进来的对象不再插入,若不相同,则会根据策略散到其他位置。
equals与hashCode的区别?
根据java规范得出结论:
①如果两个对象equals,则java运行时环境则认为它们的hashCode一定相等;
②如果两个对象不equals,则它们的hashCode有可能相等;
③如果两个对象hashCode相等,则它们不一定equals;
④如果两个对象hashCode不相等,则它们一定不equals。
补充规范:
1)若重写equals方法,则有必要重写hashCode方法,以确保通过equals()判断结果为true的两个对象具备相等的hashCode()的返回值。印证上述结论①
2)如果equals返回false,并不要求这两个对象调用hashCode()返回不同的值。印证上述结论②
那么,为什么要求重写 equals()时必须重写 hashcode() ?
原因是判断两个对象是否相同时,先比较的是hashCode,当hashCode相同时再根据equals进行判断。如果只重写equals()而不重写hashCode(),那么在判断时,在equals为true,hashCode为false的情况下,会造成两个相同的对象存入哈希表的不同位置,不仅会导致对象不能覆盖,而且也造成了资源的浪费。
权限修饰符
public:公有的,任何地方可用
protected:受保护的,同包以及子类(包括同包子类和不同包子类)可用
default:不写就是默认的,同包以及同包子类可用
private:私有的,只在本类可用
技巧:公有与私有无需记,只要区分默认的和受保护的。两者的区别在于不同包子类,受保护的不同包子类可用,而默认的则不可用。
什么是设计模式?常用的设计模式有哪些?
设计模式就是经过前人无数次的实践总结出的,设计过程中可以反复使用的、可以解决特定问题的设计方法。
常用的设计模式:单例模式:一个类仅有一个对象
工厂模式:Spring IOC就是使用了工厂模式。对象的创建交给一个工厂去创建。
代理模式:Spring AOP就是使用的动态代理
单例模式
单例模式是为了保证一个类仅有一个实例,并且自行实例化向整个系统提供。
方法:创建一个类,设置私有构造,然后使用以下一种模式。
懒汉式:需要的时候再去创建
饿汉式:先创建,可直接使用
Java中的异常处理机制的简单原理
java中使用面向对象的方式来处理异常,它把程序中发生的每一个异常分别封装到一个对象中。所有异常的根类是Throwable,Throwable又派生了两个子类Error和Exception。
Exception是程序需要捕捉和处理的异常,Error是系统级别的错误和程序不需要处理的。
Exception分为两类:Java标准定义的异常和程序员自定义异常。
Java标准定义的异常:当程序违反了Java规则时java虚拟机会把发生的错误表示为一个异常。如除数为0的异常。
程序员自定义异常:Java允许程序员扩展这种语义检查,程序员定义自己的异常处理,自由选择在何时使用throw关键字引发异常。
例如 Exception ex = new Exception("这是我自定义的异常信息");throw ex;
所有的异常都是Thowable的子类,异常处理与程序执行是并行的。
final,finally,finalize的区别?
final是来修饰属性,方法和类的,修饰属性时值不能被修改,修饰方法时不能被重写,修饰类时不能被继承。
finally用在异常处理中,try/catch/finally的格式,而finally不一定会执行:正常情况下,如果进了try或catch,则一定会finally一定会执行,若有返回值则以finally中的为主。但如果提前退出了JVM,则finally就不会被执行
finalize()是java.lang.Object中定义的,用在垃圾回收中,一个对象的finalize()方法只会被调用一次。
abstract不能与哪些关键字共用?
抽象类只定义方法名,无方法体,可以使用匿名内部类来创建对象,子类必须被重写。
1)static:被static修饰的方法是通过类名.方法名来调用的,若这个方法是抽象的,就没有方法体,毫无意义。
2)private:被private修饰的方法只能在当前类调用,抽象的方法必须被子类重写,有冲突。
3)final:被final修饰的方法不能被重写,抽象的方法必须被子类重写,有冲突。
aop与oop的区别?
aop是面向切面编程,原理是动态代理,是业务逻辑处理过程中进行切面的提取,处理某个业务逻辑,在方法调用之前做什么,在之后做什么。
oop是面向对象编程,是对实体的属性和行为的抽象与封装。
方法重载与重写的区别?
方法重载:方法名相同,参数列表不同,与返回值无关。发生在同一个类中,...表示参变参数
方法重写:子类对父类的方法进行重写编写。
this,supper与static的用法
this:表示当前类对象,谁调用就是谁。
supper:表示父类对象,使用它可以调用父类的方法,提高代码的复用性。
static:静态的,会优先加载,使用时不需要创建对象。静态的东西放在静态区,只初始化一次,没有this。
加载顺序:优先加载静态的,然后加载非静态的。因此,静态的只能使用静态的,非静态的可以使用静态和非静态的。
线程的状态
第一是创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态。
第二是就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。
第三是运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。
第四是阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend,wait等方法都可以导致线程阻塞。
第五是死亡状态。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪。
多线程的实现方式
1)继承Thread类,重写run()方法
2)实现Runnable接口,重写run()方法
3)实现Callable接口,重写call()方法,可提供返回值
java创建对象有哪些方法?
1)new 方式创建
2)使用反射机制创建:使用Class类的newInstance方法
3)使用clone()克隆方式创建:clone时,需要已经有一个分配了内存的源对象,要调用clone方法需要实现Cloneable接口,clone方法是protected的。
4)采用序列化机制创建
什么是不可变对象?
不可变对象:对象一旦被创建,对象的所有状态和属性在生命周期内不会发生变化。
创建:Collections.unmodifiableList(List<?
extends
T> list),这个是jdk提供的;
ImmutableList.copyOf(list),这个是Google的Guava包中的方法
不可变对象虽然具备不可变性,但是不是"完全不可变"的,这里打上引号是因为通过反射的手段是可以改变不可变对象的状态的。
什么是反射?
反射是在运行状态时,对于任意一个类,都能够直到这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。这种动态获取信息和动态调用对象方法的功能称为java语言的反射机制。
优点:在运行时动态获取类的实例,提高灵活性。
缺点:性能较低,需要解析字节码。
其获取的方式有多种:
①Class.forName("类的路径“): 当知道该类的全路径名时,可以使用该方法获取 Class 类对象。
②类名.class。只适合在编译前就知道操作的 Class,通常在作为参数的场景中使用。
③对象名.getClass()。只适合已有这个对象时使用。
String和StringBuilder的区别(final)?StringBuffer和StringBuilder的区别?
在java中提供三个类String StringBuillder StringBuffer来表示和操作字符串:
String是内容不可变的字符串。String底层使用了一个不可变的字符数组(final char[]);
StringBuillder StringBuffer,是内容可以改变的字符串。StringBuillder StringBuffer底层使用的可变的字符数组(没有使用final来修饰);
拼接字符串不能使用String进行拼接,要使用StringBuilder或者StringBuffer;
StringBuilder是线程不安全的,效率较高,而StringBuffer是线程安全的,效率较低。
String不可变的原因?
第一,便于实现字符串池。java中会使用大量的字符串变量,若没定一个变量就创建一个String对象,会造成极大的空间浪费。而提供字符串池,当初始化一个String变量时,先判断这个字符串是否已存在,若已存在就返回已存在字符串的引用地址,不会重新创建对象。
第二,保证多线程的安全。当多线程同时操作一个资源时,读的操作是安全的,但写的操作是不安全的,不可变对象就不能被改变,保证了线程的安全。
第三,保证物理安全。由于代码中一些url和路径等都是String类型,若是可变的则会给黑客可趁之机,不可变就提高了安全性。
字符串的拼接有哪些方法?
+:其实现原理是使用StringBuilder.append。
concat():这个是String类中的方法。其实是new了一个新的String。
append():是StringBuffer或StringBuilder类中的方法。append会直接拷贝字符到内部的字符数组中,如果字符数组长度不够,会进行扩展。
StringUtils.join :apache.commons中提供的StringUtils类,其中的join方法可以拼接字符串。是通过StringBuilder.append来实现的。
效率:用时从短到长的对比是:StringBuilder < StringBuffer < concat < + < StringUtils.join
如果不是在循环体中进行字符串拼接的话,直接使用+就好了。如果在并发场景中进行字符串拼接的话,要使用StringBuffer来代替StringBuilder。
字符串的反转怎么实现?
1)使用数组循环方式
2)使用StringBuffer的reverse()方法
3)使用StringBuffer循环方式
4)利用栈的先进后出原则
5)递归方式
字符常量与字符串常量的区别?
第一,字符常量是单引号包裹的一个字符,字符串常量是双引号包裹的若干字符;第二,字符常量代表一个ASCII码,而字符串常表示的是对象的引用;第三,字符常量占2个字节,而字符串常量占若干字节
常见的运行时异常
NullpointerException空指针异常
FileNotFoundException文件找不到异常
ClassCastException类型转换异常
ArrayIndexOutOfBoundsException数组下标越界异常
NumberFormartException数字格式异常
ClassNotFoundException类找不到异常
ArithmeticException算术异常
ConcurrentModificationException并发修改异常
Java的垃圾回收机制
垃圾收集GC(Garbage Collection)是Java语言的核心技术之一, 在Java中,程序员不需要去关心内存动态分配和垃圾回收的问题,这一切都交给了JVM来处理。对于Java对象来讲,如果说这个对象没有被其他对象所引用,那么该对象就是无用的,此对象就被称为垃圾,其占用的内存也就要被销毁。
回收算法:
标记-清除法:把需要回收的垃圾先进行标记,然后直接清除,会产生大量不连续的碎片。
标记-整理法:把需要回收的垃圾先进行标记,然后把存活对象向一端移动,再把标记的对象清理掉,提高了内存使用率。
复制法:把内存分为大小相同的块,每次使用其中的一块,当这块被使用完后,就把还存活的对象复制到另一块中,然后把该块的空间一次清理掉。
分代收集法:当前虚拟机的垃圾收集都采用分代收集算法,这种算法就是根据具体的情况选择具体的垃圾回收算法。一般将 java 堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。比如在新生代中,每次收集都会有大量对象死去,所以可以选择复制算法,只需要付出少量对象的复制成本就可以完成每次垃圾收集。而老年代的对象存活几率是比较高的,而且没有额外的空间对它进行分配担保,所以我们必须选择“标记-清除”或“标记-整理”算法进行垃圾收集。
说一下Spring中的两大核心?
spring是J2EE应用程序框架,是轻量级的IoC和AOP的容器框架。
IOC控制权反转(把对象的控制权交给spring管理):就是配置文件+反射(工厂也可以)+容器(map)
AOP(面向切面编程):使用动态代理的设计模式在执行方法前后或出现异常做加入相关逻辑
在这里也简单介绍一下DI。DI是依赖注入,@Value:简单属性值注入,@Automated:复杂类型的注入,@Reference:远程注入
什么是ORM?
对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简单的方案是采用硬编码方式(jdbc操作sql方式),为每一种可能的数据库访问操作提供单独的方法。
接口与抽象类的区别?
1)抽象类作为父类存在,抽取公有的属性和方法,而接口是抽取特有的属性和方法;
2)抽象类中可以有抽象方法和非抽象方法,接口中只能有抽象方法;
3)抽象类中的抽象方法必须被子类重写,只能是单继承、多层继承,而接口中的抽象方法可以多继承、多实现;
4)接口中的方法和属性有默认的修饰符(方法public abstract,属性public static final),而抽象类中没有;
5)抽象类中可以有构造方法,而接口中没有。
接口是否可以继承接口?接口是否可以实现接口?抽象类是否可以继承实体类?
接口可以继承接口:实现关系的传递(接口不是抽象类);
接口不能实现接口:实现接口必须重写接方法,接口中不能有方法体;
抽象类可以继承实体类:抽象类中可以有非抽象方法。
值传递与引用传递的区别?
值传递:在方法调用时,传递的参数是按值的拷贝进行传递,传递的是值的拷贝。实参与形参互不影响,主要是基本数据类型和String
引用传递:在方法调用时,传递的参数是按引用进行传递,传递的是引用的地址。形参发现变化,那么实参也跟着变化,主要是引用数据类型(String除外)
下面是通过实例进行说明:
打印结果:
String类型传递时,传递前后的值互不影响【值传递】;而list类型传递时传递前后的值跟着变化【引用传递】
2.数据库
事务隔离级别及其四大特征
事务是数据库操作的最小工作单元,如果一个包含多个步骤的业务操作,被事务管理,要么同时成功,要么同时失败。
问题:
1)脏读:一个事务,读取到另一个事务中没有提交的数据
2)幻读:一个事务操作数据表中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改
3)不可重复读:在同一个事务中,两次读取到的数据不一样。
隔离级别:
read uncommitted:读未提交。产生的问题:脏读、不可重复读、幻读
read committed:读已提交 (Oracle)。产生的问题:不可重复读、幻读
repeatable read:可重复读 (MySQL默认。 产生的问题:幻读
serializable:串行化。可以解决所有的问题
隔离级别从小到大安全性越来越高,但是效率越来越低
特征:
1)原子性(Atomicity):事务是不可分割的最小操作单位,要么同时成功,要么同时失败
2)一致性(Consistemcy):事务操作前后,数据总量保持不变
3)持久性(Isolation):当事务提交或回滚后,数据库持久化的保存数据
4)隔离性(Durability):多个事务之间相互独立,互不影响
数据库的分类及常用的数据库?
数据库分为:关系型数据库和非关系型数据库
关系型:mysql oracle sqlserver等
非关系型:redis,memcache,mogodb,hadoop等
mysql复制表到新表
方式一:
复制表结构及数据到新表
create table 新表 select * from 旧表
只复制表结构(让where条件不成立即可)
create table 新表 select * from 旧表 where 1=2
方式二:
复制表结构
create table 新表 like 旧表
复制表数据(两个表结构一样)
insert into 新表 select * from 旧表
复制表数据(两个表结构不一样)
insert into 新表(字段1,字段2,…….) select 字段1,字段2,…… from 旧表
数据库的三大范式
第一范式(1NF):每一列都是不可分割的原子数据项。
第二范式(2NF):在1NF的基础上,非码属性必须完全依赖于码。(在1NF基础上消除非主属性对主码的部分函数依赖)
1)函数依赖:A-->B,如果通过A的属性或属性组的值,可以唯一确定B属性的值,则称B依赖于A。
例如:学号-->姓名
2)完全函数依赖:A-->B,如果A是一个属性组,则B属性值的确定要依赖于A属性组的所有属性值。
例如:(学号,课程名)-->成绩
3)部分函数依赖:A-->B,如果A是一个属性组,则B属性值的确定要依赖于A属性组的部分属性值即可。
例如:(学号,课程名)-->姓名
4)传递函数依赖:A-->B,B-->C。如果通过A的属性或属性组的值,可以唯一确定B属性的值,通过B属性或属性组的值,又可以唯一确定C属性的值,则称C传递函数依赖于A.
例如:学号-->系名,系名-->系主任
5)码:在一张表中,如果一个属性或属性组,被其他所有的属性完全依赖,则称这个属性是这个表的码。
例如:该表的码为(学号,课程名称)
主属性:码属性组中的所有属性
非主属性:除了码属性组以外的属性
第三范式(3NF):在2NF基础上,任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖)
jdbc连接数据库的步骤?
注册驱动 --》获取连接 --》获取操作对象 --》操作数据库 --》释放资源
Jdbc与mybatis的优缺点?
jdbc的缺点:不仅需要频繁的创建数据库连接,而且涉及到的增删改查等功能需要在各个java文件中编写大量代码。
mybatis优点:封装了jdbc对数据库的各种操作,减少代码增加了连接池、缓存。
Mysql与Oracle的优缺点?
在类型方面,Oracle是大型数据库而Mysql是中小型数据库,Mysql是开源的而Oracle价格非常高Oracle。
在主键方面,Mysql一般使用自动增长类型,在创建表时只要指定表的主键为auto_increment,Oracle没有自动增长类型,主键一般使用的序列。
在分页方面,mysql采用limit方式,而Oracle采用结果集的ROWNUM来指定位置进行分页。
在单引号处理方面,MYSQL里可以用双引号包起字符串,ORACLE里只可以用单引号包起字符串。
SQL基础知识梳理
select * from table where 条件 group by 字段 #分组 having 条件 #聚合函数中使用,相当于where order by 字段 #排序 limit index,size #分页,起始索引,每页条数
组函数:去重 distinct() 统计总数sum() 计算个数count() 平均数avg() 最大值max() 最小数min()
多表连接:内连接join on,左连接left join on,右连接right join on
模糊查询:like '%'、
MySQL索引
常见的面试sql语句
数据的创建请直接下载:https://pan.baidu.com/s/1TyMmujfnqyFANFi0DORHMg 提取码:b8ht
1)查询学生基本信息
查询姓“猴”的学生信息
select * from student where 姓名 like '猴%'
查询姓名最后一个字是“猴”的学生信息
select * from student where 姓名 like '%猴'
查询姓名中包含“猴”的学生信息
select * from student where 姓名 like '%猴%'
查询姓“孟”的老师的个数
select count(教师号) from teacher where 教师姓名 like '孟%'
2)汇总查询
查询课程编号为0002的课程总成绩
select sum(成绩) from score where 课程号='0002'
查询选了课程的学生人数
select count(distinct 学号) from score
3)分组与排序查询
查询各科成绩最高和最低的分, 以如下的形式显示:课程号,最高分,最低分
select 课程号,max(成绩) 最高分,min(成绩) 最低分 from score group by 课程号
查询每门课程被选修的学生数
select 课程号,count(学号) from score group by 课程号
查询男生、女生各有多少人
select 性别,count(*) from student group by 性别
查询平均成绩大于60分学生的学号和平均成绩
select 学号,avg(成绩) from score group by 学号 having avg(成绩)>60
查询至少选修两门课程的学生学号
select 学号,count(课程号) from score group by 学号 having count(课程号)>=2
查询同名学生名单并统计同名人数
select 姓名,count(*) from student group by 姓名,性别 having count(*)>=2
查询不及格的课程并按课程号从大到小排列
select 课程号,成绩 from score where 成绩<60 order by 课程号 desc
查询每门课程的平均成绩,结果按平均成绩升序排序,平均成绩相同时,按课程号降序排列
select 课程号,avg(成绩) from score group by 课程号 order by avg(成绩),课程号 desc
检索课程编号为“0002”且分数小于60的学生学号,结果按按分数降序排列
select 学号,成绩 from score where 课程号='0002' and 成绩<60 order by 成绩 desc
统计每门课程的学生选修人数(超过2人的课程才统计)。要求输出课程号和选修人数,查询结果按人数降序排序,若人数相同,按课程号升序排序
select 课程号,count(学号) from score group by 课程号 having count(学号)>2 order by count(学号) desc,课程号
查询两门以上不及格课程的同学的学号及其平均成绩
select 学号,avg(成绩) from score where 成绩<60 group by 学号 having count(课程号)>=2
4)复杂查询
查询所有课程成绩小于60分学生的学号、姓名
select 学号,姓名 from student where 学号 in ( select 学号 from score where 成绩<60 )
查询没有学全所有课的学生的学号、姓名
select 学号,姓名 from student where 学号 in ( select 学号 from score group by 学号 having count(课程号)<( select count(课程号) from course ) )
查找1990年出生的学生信息
select * from student where year(出生日期)=1990
5)多表查询
查询所有学生的学号、姓名、选课数、总成绩
select a.学号,a.姓名,count(b.课程号) 课程数,sum(b.成绩) 总成绩 from student a left join score b on a.学号=b.学号 group by a.学号
查询平均成绩大于85的所有学生的学号、姓名和平均成绩
select a.学号,a.姓名,avg(b.成绩) from student a left join score b on a.学号=b.学号 group by a.学号 having avg(b.成绩)>85
查询学生的选课情况:学号,姓名,课程号,课程名称
select a.学号,a.姓名,b.课程号,b.课程名称 from student a left join score c on a.学号=c.学号 left join course b on b.课程号=c.课程号
查询出每门课程的及格人数和不及格人数
select 课程号,sum( case when 成绩>=60 then 1 else 0 end ) 及格人数,sum( case when 成绩<60 then 1 else 0 end ) 不及格人数 from score group by 课程号
使用分段[100-85],[85-70],[70-60],[<60]来统计各科成绩,分别统计:各分数段人数,课程号和课程名称
select a.课程号,b.课程名称,sum( case when 成绩 between 85 and 100 then 1 else 0 end ) '[100-85]',sum( case when 成绩 between 70 and 85 then 1 else 0 end ) '[85-70]',sum( case when 成绩 between 60 and 70 then 1 else 0 end ) '[70-60]', sum( case when 成绩<60 then 1 else 0 end ) '[<60]' from score a left join course b on a.课程号=b.课程号 group by a.课程号
内连接与外连接的区别
内连接是取出两张表中匹配到的数据,匹配不到的不保留。
外连接是取出连接表中匹配到的数据,匹配不到的会保留,其值为NULL。
左外连接是以左表为主,查询左表所有数据以及其与右表的交集部分;(左表是小表,右边是大表,【先查找小表中匹配的数据,然后再到大表中查找相应的数据】)
右外连接是以左表为主,查询右表所有数据以及其与左表的交集部分。(左表是大表,右边是小表)
索引的优缺点
索引相当于书的目录,是一种数据结构,能够帮助我们快速的检索数据库中的数据。我们使用的是InnoDB引擎,默认的是B+树。
获取它本身及子孙节点
select * from att_dept start with id= 12 connect by PRIOR id = parentid
mybatis批量执行sql,可以使用begin/end。最语句前面加begin,在最后面加end;,语句之间用;分割
Mybayis的大于小于怎么写?
大于使用>,小于使用<,不能直接使用>或<。
in和exist的区别?
in先把括号里面的条件查询出来放到临时表,然后遍历临时表,在外表中按临时表的每一行筛选数据;
exist先筛选外表,把查询的结果带入内查询进行判断,当里面的条件为真时返回外表记录,否则不返回。
in适用于外大内小,exist适用于外小内大。也就是说子表大时选择exist,外表大时选择in。
redis的持久化是如何做的?
redis的持久化有两种方式,RDB和AOF。
RDB叫做Redis数据快照,简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,恢复数据。、
AOF是一种追加文件。对于redis的每一个写命令都会记录在AOF文件中,相当于命令日志文件。
redis的应用场景
1)缓存
2)分布式锁:redis自带的setnx、redisson
redis缓存穿透、缓存击穿、缓存雪崩、数据过期策略请点击连接查看。
redis集群有哪些方案?
redis一共有三种集群方案:主从复制、哨兵模式、分片集群。
1)主从复制:通过主从集群的模式,提高redis的高并发能力,从而实现读写分离。主节点进行写操作同时同步到从节点,从节点进行读操作。主从同步分为全量同步和增量同步,
全量同步:
- 从节点请求主节点同步数据 (replication id、 offset)
- 主节点判断是否是第一次请求,是第一次就与从节点同步版本信息 (replication id和offset)
- 主节点执行bgsave,生成rdb文件后,发送给从节点去执行4.在rdb生成执行期间,主节点会以命令的方式记录到缓冲区(一个日志文件)
- 把生成之后的命令日志文件发送给从节点进行同步
增量同步:
- 从节点请求主节点同步数据,主节点判断不是第一次请求,不是第一次就获取从节点的offset值
- 主节点从命令日志中获取offset值之后的数据,发送给从节点进行数据同步
备注:
replid是数据集的标记,id一致则说明是同一数据集。每一个master都有唯一的replidslave则会继承master节点的replid
offset叫偏移量,随着记录在repl baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的ofset如果slave的offset小于master的offset,说明slave数据落后于master,需要更新。
2)哨兵模式:主要作用是实现主从集群的自动故障恢复。
- 监控:不断的检查主从节点是否工作正常。sentinel基于心跳机制检测服务状态,没1秒都向集群的各个实例发送ping请求,判断是否响应。如果sentinel节点发现某实例未在规定时间内相应,则视为主观下线;如果超过指定数量的sentinel节点都认为该实例主观下线,则该实例视为客观下线。
- 自动故障恢复:当主节点故障时,自动将一个从节点升为主节点。
- 通知:当集群发送故障转移时,会通知redis客户端。
3)分片集群
集群中有多个个master,每个master存储不同的数据,彼此间相互检测监控状态。
redis是单线程的,为什么这么快?
redis是基于内存的操作,读取数据很快;采用的是I/O多路复用模型,而且单线程更加完全。
3.数据结构
算法排序
1)冒泡排序:相邻两个进行比较,大的放在后面
2)选择排序:每次选择其中最小的与前面的数字换位置。
3)快速排序:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
4.javaEE
对servlet的理解?或者servlet是什么?
Servlet全称Java Servlet, 是用Java编写的服务器端程序,而这些Sevlet都要实现Servlet这个接口。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。
JSP和Servlet有哪些相同点和不同点?
JSP是Servlet技术的扩展,所有的jsp文件都会被翻译为一个继承HttpServlet的类。也就是jsp最终也是一个Servlet,这个Servlet对外提供服务。
Servlet和JSP最主要的不同点在于JSP侧重于视图,Servlet主要用于控制逻辑。
servlet、监听器、过滤器、拦截器的区别和执行顺序?
定义上:
1)Servlet是运行服务器端的java应用程序,可以动态的生成web页面。
2)监听器listener可以监听服务器执行某一动作,并根据需求做出相应的响应。
3)过滤器filter是对资源进行拦截,做一些处理后再交给下一个过滤器或servlet处理
生命周期上:
Servlet
1)装入:启动服务器时加载servlet的实例
2)初始化:web服务器接收到请求时调用init()方法;
3)调用:从第一次到以后的多次访问,调用doget()或dopost()方法
4)销毁:关闭服务器时调用destory()方法
Filter
1) 加载:启动服务器时加载过滤器的实例,并调用init()方法;
2) 调用:每次请求时只调用dofilter()方法
3) 销毁:服务器关闭前调用destory()方法
web.xml执行顺序:listener->filter->servlet
执行顺序
服务器启动:listener的init()-->filter的init(),有请求后调用servlet的init()方法
服务器关闭:servlet的destory()-->filter的destory()-->lister的destory()
拦截器Interceptor与过滤器的区别
过滤器可以简单理解为“取你所想取”,忽视掉那些你不想要的东西;拦截器可以简单理解为“拒你所想拒”,关心你想要拒绝掉哪些东西,比如一个BBS论坛上拦截掉敏感词汇。
1.拦截器是基于java反射机制的,而过滤器是基于函数回调的。
2.拦截器不依赖于servlet容器,而过滤器依赖于servlet容器。
3.拦截器只对action起作用,而过滤器几乎可以对所有请求起作用。
4.拦截器可以访问action上下文、值栈里的对象,而过滤器不能。
5.在action的生命周期里,拦截器可以多起调用,而过滤器只能在容器初始化时调用一次。
TCP与UDP的区别
tcp是面向连接的,udp是无连接的;
tcp提供可靠的服务,即通过tcp传输的数据不会丢失,没有重复,按顺序到达。udp无可靠性;
tcp是面向字节流的,udp是面向报文的;
tcp是全双工的可靠信道,udp是不可靠信道。
tcp的长连接与短链接的区别
长连接:建立连接——数据传输...(保持连接)...数据传输——关闭连接
短连接:建立连接——数据传输——关闭连接...建立连接——数据传输——关闭连接
优缺点:长连接可以省去较多的TCP建立和关闭的操作,减少浪费,节约时间。对于频繁请求资源的客户来说,较适用长连接。短连接对于服务器来说管理较为简单,存在的连接都是有用的连接,不需要额外的控制手段。
TCP长/短连接的应用场景:数据库的连接用长连接,WEB网站的http服务一般都用短链接。
在浏览器输入一个url回车后直到浏览器显示页面的过程中发生了什么?
域名解析 -> 建立tcp连接 -> 向服务器发送http请求 -> 服务器处理HTTP请求返回响应 -> 浏览器接受数据 -> 显示html页面
get请求与post请求的区别?
get请求把数据拼接在地址栏中,post请求把数据封装在请求体中;
get请求是不安全的,post请求是安全的;
get请求只能携带少量的数据,post请求数据大小无限制。
请求转发(forward)与重定向(Redirect)的区别?
请求转发地址栏不发生变化,重定向地址栏发生改变;
请求转发是一次请求(请求前后是同一个对象,转发之后会对转发之前的对象进行转换,变成ApplicationHttpRequest,但内容完全一致),重定向是两次请求;
请求转发可以共享数据,重定向不能共享数据。
浏览器的状态码?
200 - 确定。客户端请求已成功
302 - 对象已移动
400 - 错误的请求
404 - 没有找到文件或目录
500 - 内部服务器错误
cookie,session,application的区别?
cookie存放在用户浏览器,默认存活时间是一次会话(打开浏览器到关闭浏览器),数据又大小限制,大小为4k,最多有20个cookie。
session存放在服务器端,默认存活时间是30分组,数据没有大小限制,session是基于cookie的,sessionID存在cookie中。
application存放在服务器端,默认存活时间是整个应用的生命周期内。
session钝化:当服务器正常关闭时会把session对象全部保存在文件中。
session活化:当服务器启动时会把文件中的session加载到内存中。
jsp有哪些内置对象?四大作用域?
9个内置的对象:
request 用户端请求,此请求会包含来自GET/POST请求的参数
response 网页传回用户端的回应
pageContext 网页的属性是在这里管理
session 与请求有关的会话期
application servlet正在执行的内
out 用来传送回应的输出
config servlet的构架部件
page JSP网页本身
exception 针对错误网页,未捕捉的例外
四大作用域:pageContext:只在本jsp页面有效,
request:一次请求有效,
session:一次会话有效,
application:整个应用有效。
简单介绍一下Ajax?
ajax是异步的javascript和xml的组合,
在不重新加载整个网页的情况下,通过AJAX与服务器进行数据交换,对网页的某部分进行更新
简单讲一下webservice使用的场景?
webservice是一个SOA(面向服务的编程)的架构,它是不依赖于语言,不依赖于平台,可以实现不同的语言间的相互调用,通过Internet进行基于Http协议的网络应用间的交互。
天气预报:可以通过实现webservice客户端调用远程天气服务实现的。
单点登录:一个服务是所有系统的登录。
什么是MyBatis?
MyBatis的前身是iBatis,是对jdbc的封装。
#{ }是占位符,可以防止sql注入
${ }字符串拼接,简单类型必须是value.
MyBatis与Hibernate的区别?
MyBatis注重的是sql的封装,是轻量级的半自动框架,原理是反射,适用于敏捷开发;
Hibernate注重映射,是重量级的全自动框架。
MyBatis动态代理开发方式?
namespace与mapper接口的全路径名相同;
mapper.xml中的id与接口中的方法名要相同;
输入参数相同,输出参数相同。
MyBatis的延迟加载与缓存是什么?
延迟加载:一条sql的查询结果作为另一条sql查询的条件。先执行一条查询语句,然后再去查询另一条语句。
一级缓存:执行两条相同的查询语句时,只会查询一次,结果存在map中,是session级别的缓存,增删改会清除缓存,是默认的缓存级别。
二级缓存:是mapper级别的缓存,默认是开启的,提交或关闭session时提交结果到二级缓存中,增删改会清空缓存。必须让实体类实现serializable接口。
springmvc的执行原理?
1、 用户发送请求至前端控制器DispatcherServlet
2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、 DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
5、 执行处理器(Controller,也叫后端控制器)。
6、 Controller执行完成返回ModelAndView
7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器
9、 ViewReslover解析后返回具体View
10、 DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。
11、 DispatcherServlet响应用户
@RequestParam:取别名
@RequestBody:将请求体中的json格式的数据封装到对象中
@ResponseBody:将返回的java对象转换成json输出
springboot自动配置原理
在主启动类上一个注解@SpringBoootApplication,这个注解是一个复合注解。在这个注解中有一个注解是@SpringBootConfiguration,指明这个类是配置类;另一注解是@EnableAutoConfiguration表示开启自动配置。
@EnableAutoConfiguration中有一个注解是@Import,其导入的AutoConfigurationImportSelector的selectImports()方法通过SpringFactoriesLoader.loadFactoryNames()扫描所有具有META-INF/spring.factories的jar包。另一注解是@AutoConfigurationPackage,自动配置包扫描的路径,扫描的是启动类所在的包。
spring-boot-autoconfigure-x.x.x.x.jar里就有一个这样的spring.factories文件。这个spring.factories文件是一组一组的key=value的形式,其中一个key是EnableAutoConfiguration类的全类名,而它的value是一个xxxxAutoConfiguration的类名的列表,这些类名以逗号分隔。
@EnableAutoConfiguration注解通过@SpringBootApplication被间接的标记在了Spring Boot的启动类上。在启动类执行run方法时会执行selectImports()方法,找到所有JavaConfig自动配置类的全限定名对应的class,然后将所有自动配置类加载到Spring容器中。
@AutoConfigurationPackage和@ComponentScan的区别??
可以看到,其实在注解@SpringBoootApplication中不仅包含了@ComponentScan,还包含了@AutoConfigurationPackage,既然都是包扫描,那么它们有什么区别呢?
1)扫描方式:@ComponentScan 扫描通过 ClassPathBeanDefinitionScanner 类实现扫描;@AutoConfigurationPackage通过注册一个特殊的 BasePackagesBeanDefinition bean 定义来实现,该 bean 存储了需要扫描的基础包名
2)使用场景:@ComponentScan 适用于寻找和注册自定义的 Spring 组件,如带有 @Component、@Service、@Repository、@Controller 等注解的类;@AutoConfigurationPackage适用于 Spring Boot 自动配置过程,用于控制自动配置时需要扫描的基础包
webSocket的场景应用
webSocket是一种在单个TCP连接上进行全双工通信的协议,它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话。服务器与客户端只需要一次握手就可建立永久性的连接,进行双向数据传输。
应用场景:服务器更新,前端页面也进行局部刷新,更新服务器端返回的信息。
MVC的各个部分都有那些技术来实现?
M(Model) 模型:javabean
V(View) 视图:html, jsp, freemaker
C(Control) 控制器:Servlet,Action