面试笔记整理

javaEE:

jvm:

JDK,JRE,JVM的区别

JDK(Java Development Kit) 是整个JAVA的核心,包括了Java运行环境(Java Runtime Envirnment),一堆Java工具(javac/java/jdb等)和Java基础的类库(即Java API 包括rt.jar)。
JDK是java开发工具包,基本上每个学java的人都会先在机器 上装一个JDK,那他都包含哪几部分呢?在目录下面有 六个文件夹、一个src类库源码压缩包、和其他几个声明文件。其中,真正在运行java时起作用的 是以下四个文件夹:bin、include、lib、 jre。有这样一个关系,JDK包含JRE,而JRE包 含JVM。

总的来说JDK是用于java程序的开发,而jre则是只能运行class而没有编译的功能。

JRE(Java Runtime Environment,Java运行环境),包含JVM标准实现及Java核心类库。JRE是Java运行环境,并不是一个开发环境,所以没有包含任何开发工具(如编译器和调试器)
JRE是指java运行环境。光有JVM还不能成class的 执行,因为在解释class的时候JVM需要调用解释所需要的类库lib。 (jre里有运行.class的java.exe)
JRE ( Java Runtime Environment ),是运行 Java 程序必不可少的(除非用其他一些编译环境编译成.exe可执行文件……),JRE的 地位就象一台PC机一样,我们写好的Win64应用程序需要操作系统帮 我们运行,同样的,我们编写的Java程序也必须要JRE才能运行。

JVM(Java Virtual Machine),即java虚拟机, java运行时的环境,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。针对java用户,也就是拥有可运行的.class文件包(jar或者war)的用户。里面主要包含了jvm和java运行时基本类库(rt.jar)。rt.jar可以简单粗暴地理解为:它就是java源码编译成的jar包。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。这就是Java的能够“一次编译,到处运行”的原因。

JDK、JRE、JVM三者的联系与区别

1.三者联系:
JVM不能单独搞定class的执行,解释class的时候JVM需要调用解释所需要的类库lib。在JDK下面的的jre目录里面有两个文件夹bin和lib,在这里可以认为bin里的就是jvm,lib中则是jvm工作所需要的类库,而jvm和 lib和起来就称为jre。JVM+Lib=JRE。总体来说就是,我们利用JDK(调用JAVA API)开发了属于我们自己的JAVA程序后,通过JDK中的编译程序(javac)将我们的文本java文件编译成JAVA字节码,在JRE上运行这些JAVA字节码,JVM解析这些字节码,映射到CPU指令集或OS的系统调用。

2.三者区别:
a.JDK和JRE区别:在bin文件夹下会发现,JDK有javac.exe而JRE里面没有,javac指令是用来将java文件编译成class文件的,这是开发者需要的,而用户(只需要运行的人)是不需要的。JDK还有jar.exe, javadoc.exe等等用于开发的可执行指令文件。这也证实了一个是开发环境,一个是运行环境。
b.JRE和JVM区别:JVM并不代表就可以执行class了,JVM执行.class还需要JRE下的lib类库的支持,尤其是rt.jar。

基本语法:

1.java.lang.Object类的六个常用方法:

(1)public boolean equals(java.lang.Object)比较对象的地址值是否相等,如果子类重写,则比较对象的内容是否相等

(2)public native int hashCode()获取哈希码

(3)public java.lang.String toString(把数据转变成字符串

(4)public final native java.lang.Class getClass()获取类结构信息

(5)protected void finalize() throws java.lang.Throwable垃圾回收前执行的方法

(6)protected native Object clone() throws java.lang.CloneNotSupportedException克隆

(7)public final void wait() throws java.lang.InterruptedException多线程中等待功能

(8)public final native void notify()多线程中唤醒功能

(9)public final native void notifyAll()多线程中唤醒所有等待线程的功能

2.==跟equals的区别:

==:1.如果两个基本类型变量,比较的是值

? 2.引用类型,比较的是地址值

? 3.不能比较两个没有父子关系的两个对象

equals:1.系统类一般重写了equals方法,比较的是内容

? 2.用户自定义的类如果没有覆盖equals方法的话,将调用父类 的equals(比如是Object),而Object的equals的比较是地 址(return(this==obj) )

:在Object中==和equals比较的都是地址,作用相同

下面的代码有啥不妥:

if(username.equals(“zxx”)){}

当username为null时,会报空指针异常

而if(“zxx”.equals(username)){}则不会报

前提username初始化赋值了,哪怕为null

3.java中的类型转换问题:

short s1 = 1;
s1 = s1 +1; 编译报错,+会提升为int类型 用short接收不了int类型
short s1 = 1;
s1 += 1;编译正常,+=编译器会进行特殊处理进行类型转换 s1=(short)s1+1

4.有效算出2^8的方法

2<<3

5.final修饰的变量,指的是引用指向不能变

用final修饰的变量,指的是引用类型的指向是不能变的,也就是指向的地址值只能赋值一次,但是对于地址值里面的内容是可以变化的

6.Math类中提供了三个与取整相关的方法:

ceil,floor,round

ceil表示向上取整

floor表示向下取整

round表示+0.5向下取整

7.super.getClass方法的调用

getClass方法是被final修饰的方法,不能被重写覆盖,返回的是当前类对象的信息

8.java.sql.Date和java.util.Date的联系跟区别:

java.sql.Date是java.util.Date的子类,是一个包装了毫秒值的瘦包装器,允许JDBC将毫秒值标识为SQLDATE值,毫秒值表示自1970年1月1日00:00:00GMT以来经过的毫秒数。简单点来说,java.sql.Date就是与数据库Date相对应的一个类型,而java.util.Date是纯java的Date

9.abstract class和interface有什么区别?

含有abstract修饰符的class即为抽象类,abstract 类不能创建的实例对象。含有abstract方法的类必须定义为abstract class,abstract class类中的方法不必是抽象的。abstract class类中定义抽象方法必须在具体(Concrete)子类中实现,所以,不能有抽象构造方法或抽象静态方法。如果的子类没有实现抽象父类中的所有抽象方法,那么子类也必须定义为abstract类型。

接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为public static final。

下面比较一下两者的语法区别:

1.抽象类可以有构造方法,接口中不能有构造方法。

2.抽象类中可以有普通成员变量,接口中没有普通成员变量

3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。

4.抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然

eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。

5.抽象类中可以包含静态方法,接口中不能包含静态方法

6.抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量 只能是public static final类型,并且默认即为public static final类型。

7.一个类可以实现多个接口,但只能继承一个抽象类

10.接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承具体类(concrete class)? 抽象类中是否可以有静态的main方法

接口可以继承接口。抽象类可以实现(implements)接口,抽象类可继承具体类。抽象类中可以有静态的main方法。

备注:只要明白了接口和抽象类的本质和作用,这些问题都很好回答,你想想,如果你是java语言的设计者,你是否会提供这样的支持,如果不提供的话,有什么理由吗?如果你没有道理不提供,那答案就是肯定的了。

只有记住抽象类与普通类的唯一区别就是不能创建实例对象和允许有abstract方法。

11.静态变量跟实例变量的区别

在语法上的区别:静态变量需要在变量名前面加static关键字,而实例变量前则不需要加

程序上运行的区别:静态变量可以直接类名.静态变量名调用,属于类共享变量,在类加载阶段就会被分配空间

实例变量则需要创建实例对象才能被调用

12.一个static方法内部是否可以调用非static方法

不可以,非static方法需要对象调用,而static方法不需要创建对象就能调用,当一个static方法被调用的时候,可能还没有创建任何实例对象

13.在java中,为什么基本类型不能做为hashMap的键值,而只能是引用类型,把引用类型做为HashMap的键值,需要注意哪些地方。

在Java中是使用泛型来约束HashMap中的key和value的类型的,即HashMap<K, V> ;而泛型在Java的规定中必须是

对象Object类型的,也就是说HashMap<K, V>可以理解为HashMap<Object,Object> ,很显然基本数据类型不是

Object类型的,因此不能作为键值,只能是引用类型。虽然我们在HashMap中可以这样添加数据 :“map.put(1,

“Java”);",但实际上是将其中的key值1进行了自动装箱操作,变为了Integer类型。

引用数据类型分为两类:系统提供的引用数据类型(如包装类、String等 )以及自定义引用数据类型。系统提供的引

用数据类型中已经重写了HashCode()和equals()两个方法,所以能够保证Map中key值的唯一性;但是自定义的引用

数据类型需要自己重写HashCode()和equals0这两个方法,以保证Map中key值的唯一性。

14.&和&&的区别

&是位运算符,表示按位与运算,不仅可以操作布尔型,而且还可以操作数值型

&&是逻辑运算符,表示逻辑运算与,只能操作布尔型,会发生短路现象

常用API:

java.lang.object类:

(1)public boolean equals(java.lang.Object)比较对象的地址值是否相等,如果子类重写,则比较对象的内容是否相等

(2)public native int hashCode()获取哈希码

(3)public java.lang.String toString()把数据转变成字符串 包名…类名 @内存地址值

(4)public final native java.lang.Class getClass()获取类结构信息

(5)protected void finalize() throws java.lang.Throwable垃圾回收前执行的方法

(6)protected native Object clone() throws java.lang.CloneNotSupportedException克隆

(7)public final void wait() throws java.lang.InterruptedException多线程中等待功能

(8)public final native void notify()多线程中唤醒功能

(9)public final native void notifyAll()多线程中唤醒所有等待线程的功能

java.lang.String类:

boolean equals(Object obj) 比较字符串是否相同

boolean contain(String str) 字符串对象是否包含给定字符串

int length()

String substring(int start)

String substring(int start,int end)

byte[] getBytes()

char[] toCharArray()

static String value(int i)

String toLowerCase()

String toUpperCase()

String concat(String str)

String replace(char old,char new)

String replace(String,String new)

String trim()

int compareTo(String str)

面向对象:

多态:

实现多态的三个条件:

1.继承的存在(多态只发生在继承的基础上)

2.子类重写父类的方法(多态会调用子类重写后的方法)

3.父类引用变量指向子类对象(涉及子类到父类的类型转换)

类型转换:

隐式转换:

用一个类的父类型接受子类型

Father f = new Father(); 

Son s = new Son();

f = s;
显示转换:
Object o = new Student();

Student s = (Student)o;

在编译期间,会检测,o是什么类型的变量,s和o有没有子父类关系

而在jvm运行期间,则会检测o具体是什么类型,是不是Student类型以及Student的子类型

例子:

Object o = "aaa";

String s = "bbb";

s  = (String) o;编译运行通过 

在编译期间 两个有父子关系,而在运行期间,o的实际指向类型为String类型,所以运行通过

Object oo = {"ccc","ddd"};

String ss = {"eee","fff"};

ss = (String[]) oo;编译通过

在编译期间,两个有父子关系,而在运行期间,oo实际指向类型为Object,不是Object的同类型或者子类型,所以运行不通过

重载和重写

public,protected,default,private作用域

作用域 当前类 同一package 子孙类 其他package

public √ √ √ √

protected √ √ √ ×

default√ √ × ×

private √ × × ×

重载只能在同一个类中,也称为编译时多态

重写发生在子类和父类间

修饰符返回值方法名参数抛出异常
重载无关相同相同不同无关
重写大于等于相同相同相同小于等于

OverLoad表示同一个类中可以有多个名称相同的方法,但是参数列表各不相同,当参数列表中没有指定类型时,会向上转型,不能向下转型,不然会丢失精度。

Override表示子类继承了父类中的某一个方法,重新定义了一遍,方法重写存在于子类和父类之间且发生在非静态方法上,父类中的静态方法不能被子类重写为非静态方法,而非静态方法也不能被子类重写为静态方法 ,对于父类的静态方法,子类可以继承,也可以定义一个名字一样的静态方法,但这不是重写,因为静态方法是属于类的,可以用类名直接直接调用,跟对象无关。

包装类:

基本数据类型包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

为什么为基本类型引入包装类

基本数据类型很方便,简单,高效

但是java中的基本类型不面向对象(没有属性,方法),这在实际应用时存在很多不便(比如集合的元素只能是Object)

jdk1.5以后提供了自动装箱和自动拆箱,此外包装类还实现了基本类型变量和字符串之间的转换

基本类型变量----String.valueOf()–>字符串

包装类类型变量<----WrapperClass.parseXxx(String)–字符串

Integer与int之间的区别

Integer是java为int提供的包装类,int的默认值为0,而Integer的默认值为null,在实际开发中会选用Integer而不是int,此外Integer还提供了很多操作整数的方法。

java的数据类型

数据类型分为八大基本数据类型和引用类型(class,interface,数组)

反射

反射的概念:

在程序运行期间,可以动态的加载一个只有名称的类,对于这个已经加载的类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能调用他的任意一个方法和属性。在加载完类初始化后,会在堆内存中产生一个Class类型的对象,这个对象中包含了这个类的结构信息,我们可以通过这个Class对象来看到类的结构,所以说这个Class对象就像一面镜子,透过镜子看见类中的结构,所以称之为反射。

创建对象的几种方式:

1.使用new语句创建对象(最常用)

2.运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()方法

3.调用对象的clone方法

4.通过反序列化手段,调用java.io.ObjectInputSteam对象的readObject()方法

获取对象对应的Class对象的方式:

1.使用类名.class来获取

Class c = Student.class;

2.使用这个类的对象来获取

Student stu = new Student();

Class c = stu.getClass();

3.使用Class中的静态方法forName来获取

String className = "com.xh.Student";

Class c  = Class.forName(className);

当使用多态的时候,上面两个方式获取的对象有所不同

Person p = new Student();

Class c1 = Person.class;//获取的是Person类型的class对象

Class c2  = p.getClass(); //获取的是p所指向对象的实际类型的class对象

使用反射动态的创建对象

String className = "com.xh.Student";
Class c = Class.forName(className);
Object o = c.newInstance();
	Constructor<?> constructor = 			 		c.getConstructor(int.class);
constructor.newInstance(1);
Method method =c.getMethod("init",String.class);
method.invoke(o,"test");

集合:

集合分为两个大的类型:Collection和Map

Collection接口:

由List接口和Set接口实现

其中List接口的实现类有:ArrayList,LinkedList,Vector

其中ArrayList是采用了数组方式来实现的

LinkedList采用的是链表结构来实现的

而Vector采取了synchronized关键字给方法中的代码进行加锁操作

List集合的特点:有序可重复

Set接口的实现类有:HashSet,TreeSet 而SortedSet只是Set的子接口,可以将集合中的元素进行排序

TreeSet集合默认将对象从小到大排序,因此我们可以改变排序规则,改变的方式有两种:

1.将要比较的对象的类实现Comparable接口,重写compare To方法

2.可以在TreeSet的构造器中传一个比较器,在同时实现接口跟比较器的情况下,比较器优先级更高

Set集合的特点:无序不可重复,根据对象的hashCode和equals来判断当前这个对象是否跟集合中其他对象相同

另外Collection继承了Iterable接口,很多集合都实现了这个接口,实现了这个接口后就可以实现迭代的功能了

Map接口:

实现类有HashMap,TreeMap,HashTable 而SortdMap是Map的子接口

Entry是Map接口的一个内部接口,Entry类型代表的就是Map中的一组键值对,可以通过map.entrySet()方法把键值对存入Set集合,再通过迭代的方式得到Entry,然后通过getKey()和getValue()方法得到键值对。

也可以通过map.KeySet方法把key值都存入Set集合,然后再通过迭代的方式得到key值,然后调用map.get(key)方法得到value值

而SortedMap可以对存放进来的key-value进行排序,估计key的值进行排序

HashMap是一个很重要的集合,甚至HashSet中很多方法都是借助于HashMap的功能来实现的,而TreeSet的大多数功能也是有TreeMap实现的

数组与集合的区别:

数组:只能存储同类型数据

? 长度固定了就不能发生改变

? 没啥可调用的方法

集合:能存储任意类型的对象

? 长度可以自增长

? 有很多操作集合数据的方法

泛型:

在声明一个类,接口,方法的时候,需要的涉及到一个问题:要给属性确定一个类型,或者给方法的返回值确定一个类型,或者给方法的参数确定一个类型

public class Student{

?	private Long id;

}

public class Student<T>{

?	private T id;

}

==号两边的所指定的泛型类型,一定是一样的,不可能出现两边是不同的泛型类型

//编译通过

Object o = new Integer(1);

//编译报错 ArrayList<Object>和ArrayList<Integer>是两个不同的类型,且没有子父类的关系

ArrayList<Object> list = new ArrayList<Integer>();

泛型的类型之间没有多态,所以等号的两边泛型类型必须一致

通配符:?

注意,使用?通配之后,就不能往集合中添加数据了

Collection<?> c = null;

c = new ArrayList<String>();

c.add("hello");//编译报错

但可以像集合中添加null,null是所有引用类型共有的一个值

泛型的擦除:

泛型信息只存在于编译期间的源码中,也可以说是假泛型,编译成class文件后,class文件中将会擦除掉所有的泛型类型相关的信息

所以,ArrayList 和 ArrayList 在编译期间是不同的类型(不兼容),因为编译器会根据泛型的信息做类型的安全检查,编程成class文件后,这个俩个和ArrayList表示的是同一种类型。

//注意,这里编译会报错
//List<String> List<Integer> 编译的时候虽然不同
//但是编译后泛型信息会被擦除
//List<String> List<Integer> 就变成相同的类型
//类中相当于有了俩个一模一样的方法,编译报错
例如:
	public void run(List<String> list){
	}

?	public void run(List<Integer> list){
?	}

例如:

		ArrayList<String> list1 = new ArrayList<String>();
		ArrayList<Integer> list2 = new ArrayList<Integer>();

		//判断list1所指向对象的实际类型 和 list2指向对象的实际类型
		//是否相等
		//结果输出为:true
		//原因:编译成class文件后,泛型信息被擦除
		System.out.println(list1.getClass() == list2.getClass());

IO:

对象流:一般项目中的bean对象都需要实现java.io.Serializable的接口,该接口其实时空的实现,但是jvm在用io流传输数据的时候,会检测该类有没有实现可序列化这个接口,java中的序列化指的是把java对象转化为字节序列过程

线程:

创建线程的两种方式:

继承Thread类,实现Runable接口

线程的五种状态:

new runable runing blocked dead

网络编程:

jsp:

九大内置对象:

**HttpServletRequest request:**一次请求

HttpServletResponse response:

**ServletContext application:**整个web环境

ServletConfig config:

**JspWriter out:**用于向浏览器输出内容的输出流

**Throwable exception:**这个对象其实我们并不能直接使用,需要相关设置后才能使用,这个可以算是一个隐藏对象.这个对象表示将来这个jsp页面运行出错的时候所抛出的异常对象

**PageContext pageContext:**页面范围(只能在同一个页面中起作用)

**Object page:**虽然名字叫page,但是这个并不是页面范围对象,它是Object类型的对象,表示当前这个页面本身。

其实page指的是jsp页面翻译成的java类,服务器使用这个java类所创建的对象

把page对象输出即可看到,所以说page对象代表jsp页面本身

**HttpSession session:**一次会话,session是保存在服务器端的一个对象,客户端是没有session的。cookie在客户端和服务器端都会有,但是存在的形式不一样,在客户端cookie是以本地文件(浏览器管理的文件)的形式存在的,在服务器端是以java对象的形式存在我们平时说的cookie都是指的客户端文件形式存在的cookie

session是在服务器保存用户的相关信息,cookie是在客户端保存相关信息。同时cookie还可以在客户端保存session的信息,例如session的id值,这id的全名叫做JSEESIONID

xml:

JDBC:

JDK8新特性:

数据库连接池:

数据库连接池的好处,当我们数据库创建连接并获取后,只要不关闭连接,这个连接就会一直被占用着,及时我们不使用这个连接去做任何事。但是数据库给我们的连接数量是有限的,一旦超过这个连接个数,就会报错。(Oracle最多十四个),这样显然是不合理的,当连接数不够时,应该等待连接的关闭然后再去获取,而数据库连接池就是如此,会给我们创建一个池子,当池子连接不够用时我们应该先等待连接

DruidDataSource dataSource = new DruidDataSource();

dataSource.setDriverClassName

dataSource.setUrl

dataSource.setUsername

dataSource.setPassword

dataSource.setInitialSize

dataSource.setMaxActive

idea快捷键:

Alt + 回车 导包 自动修正
Alt + Insert 生成代码 getset等等方法
ctrl + 空格 代码提示
ctrl + shift + 空格 自动补全代码
ctrl + d 复制行
ctrl + x 剪切,删除行
ctrl + / 注释
shift + f6 重构/重命名
ctrl + shift + up/down 光标跳到上一行或者下一行
shift + alt + up/down 代码向上或者向下移动

Oracle:

基本SQL语句:

创建/删除用户:

 create user  用户名  identified by 密码;
 drop user 用户名 cascade;

赋予权限:

grant resource,connect to 用户名;
grant create view to 用户名;   赋予视图权限

切换用户:

conn 用户名/密码

设置日期环境:脚本中包含了英文日期等

alter session set NLS_LANGUAGE='english';

插入语句:

insert into 表名(字段名,...) values('字段',...);

删除语句:

delete from 表名 where 字段名 = 条件;
delete from 表名;

更新语句:

update 表名 set 字段名 = 值,... where 字段名 = 条件;

创建/删除序列:

create sequence 序列名;
select 序列名.currval from dual; 查看当前值
select 序列名.nextval from dual; 查看序列下一个值
drop sequence 序列名;
insert into 表名 values(序列名.nextval,...);

视图:

创建视图:
	create or replace view 视图名字
	as
	sql语句;
删除视图:
	drop view 视图名字;
可以对视图进行crud操作

查询语句

查询当前用户下所有的表:select  table_name  from user_tables;
查询某张表中内容:select * from 表名;
把查询结果拼接:select id, '姓名:'|| last_name ||‘-’||first_name 				from 表名;
查询结果去重:select distinct 字段1,字段2 
			from 表名
(distinct只能放在select关键字后面)
查询结果排序:select 字段1,...
			from 表名
			order by 字段 [asc/desc] 默认desc降序
			select 字段1,...
			from 表名
			order by 1 [asc/desc]
null排序规则:
	升序排列,默认情况下,null值排后面
	降序排序,默认情况下,null值排前面
限制查询:select 字段1,...
		from 表名
		where ...
比较符: =  >  <  >=  <=  不等于有三个 !=  <>  ^=
逻辑比较符:between x and y 在[x,y]之内
		  in 在什么之中
		  Like 模糊查询 需要使用通配符
		  	   %:0到多个字符
		  	   _:当且仅当通配一个字符
		  	   \:默认\为转义字符,也可以指定 指定的时候用escape指明
		  is null 对于null值操作不能使用= 
逻辑操作符:and,or    注:and优先级更高
		  not 搭配使用 比如not like  not in  not between and
哑表:select 1+1 from dual; 主要用来校验select数据 只有一行一列

函数查询:

字符函数,数字函数,日期函数,转换函数,组函数

字符函数:
	LOWER 返回转换成小写的字符串
		select lower(字段名/'字符串') from 表名/dual;
	UPPER 返回转换为大写的字符串
		select upper(字段名/'字符串') from 表名/dual;
	INITCAP 返回首字母大写其余字母小写的字符串
		select initcap(字段名/'hEllO') from 表名/dual;
	CONCAT 字符串的拼接,类似于||
		select concat('hello','world') 别名 from dual;
		select 'hello'||'world' from dual;
	SUBSTR 字符串的截取 从第二个字符串开始(包含) 连续截取三个字符
		select substr('hello',2,3) from dual;
	LENGTH 返回字符串的长度
		select length('world') from dual;
   	NVL 转换为空值 
   		nvl(arg1,arg2) 如果参数为空,然后参数2
   			select nvl(null,1) from dual;
   		nvl2(arg1,arg2,arg3) 如果参数为空, 返回参数3, 空返回参数2
   			select nvl2(null,1,10) from dual;
   		nullif 如果参数1=参数2 那么就返回null 否则返回参数1
   			select nullif(1,1) from dual;
数字函数:
	ROUND 四舍五入
	round(arg1,arg2) 
		arg1表示要进行四舍五入的数字 
		arg2表示保留到哪一位
		select round(45.926,2) from dual;  45.93
		select round(45.923,-1) from dual; 50;
	TRUNC 截取到某一位 跟round用法一样但trunc只舍取不进位
		select trunc(45.929) from dual; 45.92
		select trunc(45.929) from dual; 40
	MOD 取余
	mod(arg1,arg2)
		select mod(10,3) from dual;  1
		注:任何数对0取余是其本身,对1取余是0
日期函数:
	查询当前日期:
		select sysdate from dual;
	查询明天这个时候:
		select sysdate + 1 from dual;
	查询一小时后:
		select sysdate + 1/24 from dual;
	MONTHS_BETWEEN 两个日期之间相差多少月
		select months_between(sysdate+30,sysdate) from 		   dual (如果不满一个月就返回小数)
	ADD_MONTHS 返回一个日期数据 在当前时间点往后退x月的日期
    	select add_months('01-2月-2016',2) from dual;
    NEXT_DAY 返回日期,表示下一个星期几在哪一天
    	离当前时间最近的下一个星期5是哪一个天
    	select next_day(sysdate,'星期五') from dual;
    	如果使用'FRIDAY',那么需要改语言环境为英文
    	alter session set nls_language=‘english’;
    LAST_DAY 返回指定时间的当前月份的最后一天
    	select last_day(sysdate) from dual;
    ROUND 对日期进行四舍五入
    	select round(sysdate,'Month') from dual;
    	select round(sysdate,'YEAR') from dual;
    	月份15不进 16进 年份6舍 7进
    TRUNC 对日期进行截取,只舍不进
    	select trunc(sysdate,'MONTH') from dual;
    	select trunc(sysdate,'YEAR') from dual;
转换函数:
	TO_CHAR 把日期转换为指定格式
		select to_char(sysdate,'yyyy-mm-DD') from dual;
	TO_NUMBER 把字符转换为数
		select to_char('0100') from dual;
	TO_DATE 把字符转换为日期
		select to_date('2016-1-1','yyyy-mm-dd') from 		 dual;
		英文环境下:
		select to_date('25-MAY-95','dd-MONTH-yy') from   	   dual;
	
格式说明
yyyy四位数的年份
rrrr四位数的年份
yy两位数的年份
rr两位数的年份
mm两位数的月份(数字)
D一周的星期几
DD一月的第几天
DDD一年的第几天
YEAR英文的年份
MONTH英文全称的月份
mon英文简写的月份
ddsp英文的第几天(一个月的)
ddspth英文序列数的第几天(一个月的)
DAY全英文的星期
DY简写的英文星期
hh[12|24]小时 默认 12 进制
mi分钟
ss
am上下午

组函数:

平均数avg
个数count
最大值max
最小值min
求和sum
标准差stddev
方差variance

group by :

? 先分组,然后在组内使用组函数

having:

? 先分组,再筛选,所以一定跟在group by后面

注: 当select/having出现组函数的时候,其他没有被组函数修饰的列必须出现在group by后面

不等值连接:

外连接:

第一种方式(oracle特有)

select e.last_name,d.name
from s_emp e, s_dept d
where e.dept_id(+) = d.id;

第二种方式:

select e.last_name,d.name
from s_emp e left outer join s_dept d on e.dept_id = 
d.id;

所谓左外连接,就是在等值连接的基础上,额外显示左表中多出来的数

右外连接,就是在等值连接的基础上,额外显示右表中多出来的数

全连接:

在等值连接的基础上,额外展示两张表多余的内容

select e.lastname,d.name
from s_emp e full outer join s_dept d on e.dept_id = d.id

自连接:

两张相同的表,进行连接,也就是自己和自己进行关联

select e.lastname,m.lastname 
from s_emp e, s_emp m
where e.manager.id = manager.id;

结果集:

union:获得两个结果集的并集

union all:两个结果集合在一起展示

minus:差集,第一个结果集减去第二个结果集和它相同的部分

intersect:两个结果集的交集

伪列:

rownum:oracle特有的,只能进行查询,根据返回结果为每一条数据生成序列化的数字,只能大于0或大于等于1,不是是其他数。也可以是小于或小于等于任何数,代表查询前x行数据。

select *
from s_emp
where rownum >= 1;

查询前五行数据

select *
from s_emp
where rownum < 6;

查询第五条到第七条数据

select *
from s_emp
where rownum <= 7
minus 
select *
from s_emp
where rownum < 5;

SQL语句类型:

  • DQL数据查询语言:select语句

  • DML数据管理语言:insert,delete,update

  • TCL事务控制语言:commit,rollback,savepoint

  • DDL数据定义语言:create,drop,alter,DDL也会提交事务,并且结束事务

  • DCL数据控制语言:grant,revoke

事务的四种特征(ACID):

  • 原子性:要么全部完成,要么全部不完成

  • 一致性:开始事务之前和结束之后,数据库数据的一致性约束没有被破坏,无论两个事务执行顺序如何,数据库都会达到统一的状态,比如转账,无论转了多少次,两个人账户的总和跟先前是一样的

  • 隔离性:多个用户并发访问一个数据库的时候,操作同一张表时,不能被干扰

  • 持久性:某个事物一旦被提交了一行,无论数据库崩溃还是其他未知情况,该事务的结果都能被持久化保存下来

问题:

  • 脏读:主要是update操作引起,当一条事务被提交,然后在数据库中被其他用户查询了,但是这条事务又进行了回滚。

  • 幻读:主要是insert/delete引起的,事务1查询筛选出了10条数据,但当事务1再次用相同的条件查询却得到了不同的数据,这是因为在事务1的两次查询期间事务2进行了插入操作

  • 不可重复读:主要是update操作引起,事务1在读完数据,而事务2立马修改了这条数据,并提交给了数据库,当事务1再次读取该数据的时候得到了不同的结果

事务的隔离级别:读未提交,读已提交,可重复读,串行化

Oracle跟mysql的区别:

1.主键自增长:Oracle的之间需要依赖于序列实现

而mysql的主键自增长只需要建表时指定就可以了

2.命令行工具:Oracle官方指定的是SQLPlus

而mysql的是mqsql

3.提交方式:Oracle默认手动提交

mysql默认是自动提交

4.事务的隔离性:Oracle支持serializable的隔离级别,每个session提交后其他session才能看到提交的更改

而mysql只支持只读的隔离级别,一个session读取数据时,其他session不能更改数据,但是可以在表最后插入数据

sql练习:

查询每个员工的名字及员工对应的管理者名字?(自连接)

select emp.name,manage.name
from s_emp emp,s_emp manage
where emp.manage_id = manage.id;

查询部门表中前7条记录?(伪列)

select *
from s_dept
where rownum <= 7;

查询部门表中第3条到第5条数据?

select *
from s_dept
where rownum <= 5 
minus
select *
from s_dept
where rownum <3;

查询所有员工的平均工资,最高工资,最低工资,工资总和,还有有多少个员工?

select avg(salary),max(salary),min(salary),sum(salary),count(*)
from s_emp;

查询每个部门的平均工资,对平均工资降序排序.平均工资大于1400

select dept_id,avg(salary)
from s_emp
group by dept_id
having avg(salary)>1400
order by avg(salary) desc;

查看各个部门的最高工资

select dept_id,max(salary)
from s_emp
group by dept_id;

查看各个部门的员工数

select dept_id,count(*)
from s_emp
group by dept_id;

查询各个部门的平均薪水和最大薪水,并且平均薪水大于2000的部门id。

select dept_id,avg(salary),max(salary)
from s_emp
group by dept_id
having avg(salary)>2000;

查询title中不包含vp字符串的每个职位的平均薪水,并对平均薪水进行降序排列,并且每个职位的总薪水大于5000。

select title,avg(salary)
from s_emp
where title not like '%vp%'
group by title
having sum(salary)>5000
order by avg(salary) desc;

查看每个区域部门数?

select region.id,region_name,count(*)
from s_emp emp,s_dept dept,s_region region
where emp.dept_id = dept.id and dept.region_id = region.id
group by region.id,region.name
order by region_id;

查询s_emp表中部门的平均工资大于等于1400的部门,同时按照部门编号进行排序

select dept_id,avg(salary)
from s_emp 
group by dept_id
having dept_id,avg(salary)>=1400
order by dept_id;

查看薪资大于Chang员工薪资的员工信息

select *
from s_emp
where salary > (
			select salary 
			from s_emp
			where name like 'Chang'
		);

查看薪资大于Chang员工薪资或者所在部门在3号区域下的员工的信息

select *
from s_emp
where salary > (
			select salary 
			from s_emp
			where name like 'Chang'
		) or dept_id in(
			select dept.id
			from s_dept dept,s_region region
			where dept_region = region.id and region.id=3
		);

查看和Ngao所在部门的区域id一样的所有员工id和名字

select emp.id,emp.name,dept.region_id
from s_emp emp,s_dept dept
where dept.region_id = (
	select dept.region_id
	from s_emp emp,s_dept dept
	where emp.last_name like 'Ngao' and emp.dept_id= 		dept.id
	) and dept.id = emp.dept_id;

查询每一个部门的员工小于该部门的平均工资的员工的信息?


查询平均工资比 41号部门的平均工资高的部门的平均工资

select avg(salary)
from s_emp
group by dept_id
having avg(salary) > (
	select avg(salary)
	from s_emp
    having emp.dept_id = 41
);

查看所有和Chang不同部门的员工信息

select *
from s_emp
from dept_id != (
	select dept_id
	from s_emp
	where name like 'Chang'
);

查询比Ngao所在部门平均工资高的部门的员工信息

select *
from s_emp
having dept_id in (
	select dept_id
	from s_emp
	group by dept_id
	having avg(salary) > (
		select avg(salary)
		from s_emp
		where dept_id=(
			select dept_id
			from s_emp
			where name like 'Ngao'
		)
	)
);

mysql:

Web:

1.http请求和响应

请求:

? 请求行:get/post url HTTP/1.1

? 请求头:key:value

? Appcet:application/json 浏览器要求接收的数据类型

? Content-type:application/json 针对post请求 发送后台设置请求体参数的类型 produces

? 空行

? 请求体:get 没有请求体 post

响应:

? 响应行

? 响应头

? 空行

? 响应体

Redis

1.五大基本数据类型

  • String:键值对的形式存储,最为常用的

  • list:它实际上是一个链表,可以进行进栈,也可以进行队列

    ? 不可重复

  • set:微博共同关注可以使用此数据类型 并集

    ? A用户的所有关注放在一个set集合中,他的粉丝也放在一个集合中

  • hash:hash变更的数据user name age,尤其用户信息 用来存储json对象

  • zset:相比于hash多了一个score 意味着我们可以进行权重排序,比如消息的优先级

2.三大特殊类型

Geospatial地理位置

Hyperloglog基数统计

Bitmap位图场景

3.redis的事务:

一次性,顺序性,排他性 实现悲观锁

4.redis集成springboot

5.redis的持久化

  • rdb:

  • aof:

6.订阅发布

7.主从复制:

集群服务

8.缓存的击穿,穿透以及雪崩

缓存穿透:

概念

用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是像持久层数据库查询,发现也没有,于是本次查询失败,当用户很多的时候,缓存没有命中,于是都去请求持久层数据库,这会给持久层数据库造成很多的压力,这时候就相当于出现了缓存穿透。

解决方案:
布隆过滤器:

布隆过滤器是一种数据结构,对所有可能查询到参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了从底层存储系统的查询压力。

缓存空对象:

当存储层不命中后,即使返回的空对象也将其缓存起来,同时回设置一个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端数据源。

但这会存在两个问题:

1.如果空值能被存储起来,这就意味着缓存需要更多的空间存储更多的键,因为当中可能会有很多的空值的键。

2.即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致,这对于需要保持一致性的业务会有影响。

缓存击穿:

概念

这里需要注意的是和缓存击穿的区别,缓存击穿,是指一个key非常热门,再不停的扛着大并发,大并发集中对着一个点进行访问,当这个key再失效的瞬间,持续的大并发就床破缓存,直接请求数据库,就像再一个屏障上凿开了一个洞。

解决方案:
设置热点永不过期

从缓存层面来看,没有设置过期时间,所以不会出现热点key国企后产生的问题。

加互斥锁

分布式锁:使用分布式锁,保证对于每个key同时只有一个线程取查询后端服务,其他线程没有获得分布式锁的权限,因此只需要等待即可。这种方法将高并发的压力转义到了分布式锁,因此对分布式锁的考验很大。

9.哨兵模式

Mybatis:

Spring:

1.什么是AOP

面向切面编程(AOP)完善spring的依赖注入(DI),面向切面编程在spring中主要表现为两个方面
1.面向切面编程提供声明式事务管理
2.spring支持用户自定义的切面

面向切面编程(aop)是对面向对象编程(oop)的补充,
面向对象编程将程序分解成各个层次的对象,面向切面编程将程序运行过程分解成各个切面。
AOP从程序运行角度考虑程序的结构,提取业务处理过程的切面,oop是静态的抽象,aop是动态的抽象,
是对应用执行过程中的步骤进行抽象,,从而获得步骤之间的逻辑划分。

aop框架具有的两个特征:
1.各个步骤之间的良好隔离性
2.源代码无关性

2.spring 的优点

1.降低了组件之间的耦合性 ,实现了软件各层之间的解耦
2.可以使用容易提供的众多服务,如事务管理,消息服务等
3.容器提供单例模式支持
4.容器提供了AOP技术,利用它很容易实现如权限拦截,运行期监控等功能
5.容器提供了众多的辅助类,能加快应用的开发
6.spring对于主流的应用框架提供了集成支持,如hibernate,JPA,Struts等
7.spring属于低侵入式设计,代码的污染极低
8.独立于各种应用服务器
9.spring的DI机制降低了业务对象替换的复杂性
10.Spring的高度开放性,并不强制应用完全依赖于Spring,开发者可以自由选择spring的部分或全部

3.什么是DI机制

依赖注入(Dependecy Injection)和控制反转(Inversion of Control)是同一个概念,具体的讲:当某个角色
需要另外一个角色协助的时候,在传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在spring中
创建被调用者的工作不再由调用者来完成,因此称为控制反转。创建被调用者的工作由spring来完成,然后注入调用者
因此也称为依赖注入。
spring以动态灵活的方式来管理对象 , 注入的两种方式,设置注入和构造注入。
设置注入的优点:直观,自然
构造注入的优点:可以在构造器中决定依赖关系的顺序。

4.常用注解:

1)用于注解bean对象注解

@Component

@Repository

@Service

@Controller

作用:调用无参构造器创建一个bean对象,并把对象存入spring的IOC容器进行管理,相当于在xml中配置一个bean
属性:指定bean的id,如果不指定value属性,默认bean的id时当前类的类名首字母小写

@Bean

作用:用于把当前方法的返回值作为bean对象存入spring的ioc容器中
属性:name用于指定bean的id,不写时默认值为当前方法的名称

2)用于依赖注入的注解

@Autowired

作用:@Autowire和@Resource都是Spring支持的注解形式动态装配bean的方式。Autowire默认按照类型(byType)装配,如果想要按照名称(byName)装配,需要结合@Qualifier注解使用
属性:required:@Autowire注解默认情况下要求依赖对象必须存在。如果不存在,则在注入的时候会抛出异常。如果允许依赖对象为null,需设置required属性为false
@Autowire
@Qualifier("userService")
private UserService userService;

@Qualifier

作用:在自动按照类型注入的基础上,在按照bean的id注入。在给字段注入时不能独立使用,必须和@Autowire一起使用,但是给方法参数注入时,可以独立使用
属性:value用于指定要注入的bean的id,可省略不写

@Resource

作用:@Autowire和@Resource都是Spring支持的注解形式动态装配bean的方式。@Resource默认按照名称(byName)装配,名称可以通过name属性指定,如果没有指定name,则注解在字段上时,默认取(name=字段名称)装配。如果注解中sertter方法上时,默认取(name=属性名称)装配
属性:name:用于指定要注入的bean的id
type:用于指定要注入的bean的type
@Resource(name="userServie")
//@Resource(type="userService")
//@Resource(name="userService",type="UserService")
private UserService userService;

@Value

作用:通过@Value可以将外部的值动态注入到bean中,可以为基本类型数据和String类型数据的变量注入数据
@Value("tom")
private String name;
@Value("18")
private Integer age;

从properties中读取数据
jabc.driver \= com.mysql.jdbc.Driver
@Value("${jdbc.driver}")
private String driver;

3)用于改变bean作用范围的注解

@Scope

作用:指定bean的作用范围
属性:value:1)singleton:单例
			2)prototype:多例
			3)request:
			4)session:
			5)globalsession:

4)生命周期相关的注解

@PostConstruct

作用:指定初始化方法

@PreDestory

作用:指定销毁方法

5)配置类相关的注解

@Configurtion

@Import

@ComponentScan

SpringMVC:

SpringMVC采用Model-view-Controller形式

Model:模型,处理应用程序中数据逻辑部分

View:视图,是数据显示部分

Controller:控制器,是处理用户交互部分,负责从视图中读取数据并向模型发送数据等

springmvc生命周期:
在这里插入图片描述

Springboot:

1)常用注解:

@RequestMapping

@PostMapping

@ResponseBody

@RestController

热部署

swagger

SpringCloud:

SpringData:

数据结构:

restful

软件设计模式

程序设计六大原则

1、开闭原则(Open Close Principle)

开闭原则的意思是:对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。

2、里氏代换原则(Liskov Substitution Principle)

里氏代换原则是面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。LSP 是继承复用的基石,只有当派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。里氏代换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。

3、依赖倒转原则(Dependence Inversion Principle)

这个原则是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。

4、接口隔离原则(Interface Segregation Principle)

这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。它还有另外一个意思是:降低类之间的耦合度。由此可见,其实设计模式就是从大型软件架构出发、便于升级和维护的软件设计思想,它强调降低依赖,降低耦合。

5、迪米特法则,又称最少知道原则(Demeter Principle)

最少知道原则是指:一个实体应当尽量少地与其他实体之间发生相互作用,使得系统功能模块相对独立。

6、合成复用原则(Composite Reuse Principle)

合成复用原则是指:尽量使用合成/聚合的方式,而不是使用继承

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值