Java摘抄面试题

java.lang.Object类是所有类的父类(又叫根类,超类,基类),它里面写了所有子类应该具有的共同功能,为了让所有类都可以使用这些共同功能,所有类都直接或者间接的继承Object类(能够说出Object类的特点)

根据JDK源代码及Object类的API文档,Object类当中包含的方法有11个。

public String toString():(对象在内存中看不见摸不着,所以提供方法,)把对象变成带有地址值的字符串

public boolean equals(Object obj):比较两个对象的地址值是否相等,相等返回true,否则返回false

StringBuilder

API中对String类有这样的描述:字符串是常量,它们的值在创建后不能被更改

StringBuilder/StringBuffer是个字符串的缓冲区(暂时存放数据的地方),即它是一个容器,容器中可以装很多字符串

它的内部拥有一个数组用来存放字符串内容,进行字符串拼接时,直接在数组中加入新内容。StringBuilder会自动维护数组的扩容。原理如下图所示:(默认16字符空间,超过自动扩充)

StringBuilder常用的方法有3个:

public StringBuilder append(...):添加任意类型数据的字符串形式,并返回当前对象自身。

public String toString():将当前StringBuilder对象转换为String对象。

public StringBuilder reverse():将当前StringBuilder对象里面的内容进行反转,如abc反转后变成cba

基本类型与对应的包装类(引用数据类型)对象之间,来回转换的过程称为”装箱“与”拆箱“:

装箱:把基本类型转换为对应的包装类对象。//对象new出来开辟空间,看起来像个箱子,装箱

拆箱:把包装类对象转换为对应的基本类型。

自动装箱与自动拆箱,基本数据类型和其对应的引用数据类型互相转换,系统自动完成,jdk1.5开始支持,把基本数据类型自动变成其对应的引用数据类型叫做自动装箱,反过来就是自动拆箱

Collection:单列集合类的根接口,用于存储一系列符合某种规则(抽象方法)的元素,

它有两个重要的子接口,分别是java.util.List和java.util.Set。

List的特点是元素有序、元素可重复,有索引相反的是,Set的特点是元素无序,而且不可重复,无索引。

List接口的主要实现类有java.util.ArrayList和java.util.LinkedList,Set接口的主要实现类有java.util.HashSet和java.util.TreeSet。


java.util.Iterator。Iterator接口也是Java集合中的一员,但它与Collection、Map接口有所不同,Collection接口与Map接口主要用于存储元素,而Iterator主要用于迭代访问(即遍历)Collection中的元素,因此Iterator对象也被称为迭代器。

迭代器的实现原理

在调用Iterator的next方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next方法后,迭代器的索引会向后移动一位,指向第一个元素并将该元素返回,当再次调用next方法时,迭代器的索引会指向第二个元素并将该元素返回,依此类推,直到hasNext方法返回false,表示到达了集合的末尾,终止对元素的遍历。

泛型可以在类或方法中预先地使用未知的类型。

List集合

List接口特点:(能够说出List集合特点,有序,有索引,可以存储重复元素)

数据存储的常用结构有:栈、队列、数组、链表和红黑树。


栈:stack,又称堆栈,它是运算受限的线性表,其限制是仅允许在表的一端进行插入和删除操作,不允许在其他任何位置进行添加、查找、删除等操作。

简单的说:采用该结构的集合,对元素的存取有如下的特点

先进后出(即,存进去的元素,要在后它后面的元素依次取出后,才能取出该元素)。例如,子弹压进弹夹,先压进去的子弹在下面,后压进去的子弹在上面,当开枪时,先弹出上面的子弹,然后才能弹出下面的子弹。

栈的入口、出口的都是栈的顶端位置。

这里两个名词需要注意:

压栈:就是存元素。即,把元素存储到栈的顶端位置,栈中已有元素依次向栈底方向移动一个位置。

弹栈:就是取元素。即,把栈的顶端位置元素取出,栈中已有元素依次向栈顶方向移动一个位置。

队列

队列queue,简称队,它同堆栈一样,也是一种运算受限的线性表,其限制是仅允许在表的一端进行插入,而在表的另一端进行删除。

简单的说,采用该结构的集合,对元素的存取有如下的特点:

先进先出(即,存进去的元素,要在后它前面的元素依次取出后,才能取出该元素)。例如,小火车过山洞,车头先进去,车尾后进去;车头先出来,车尾后出来。

队列的入口、出口各占一侧。例如,下图中的左侧为入口,右侧为出口。

数组//特点:查找快因为有索引,增删慢,因为数组的长度的是固定死了的,要增删要创建一个新的数组,然后给数组拷贝元素,消耗时间,相对慢

数组:Array,是有序的元素序列,数组是在内存中开辟一段连续的空间,并在此空间存放元素。就像是一排出租屋,有100个房间,从001到100每个房间都有固定编号,通过编号就可以快速找到租房子的人。

简单的说,采用该结构的集合,对元素的存取有如下的特点:

查找元素快:通过索引,可以快速访问指定位置的元素

增删元素慢

指定索引位置增加元素:需要创建一个新数组,将指定新元素存储在指定索引位置,再把原数组元素根据索引,复制到新数组对应索引的位置。

指定索引位置删除元素:需要创建一个新数组,把原数组元素根据索引,复制到新数组对应索引的位置,原数组中指定索引位置元素不复制到新数组中。

链表//特点跟数组刚好相反,Node接口,节点

链表:linked list,由一系列结点node(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。我们常说的链表结构有单向链表与双向链表,这里先给大家介绍的是单向链表


简单的说,采用该结构的集合,对元素的存取有如下的特点:

多个结点之间,通过地址进行连接。例如,多个人手拉手,每个人使用自己的右手拉住下个人的左手,依次类推,这样多个人就连在一起了。


查找元素慢:想查找某个元素,需要通过连接的节点,依次向后查找指定元素

增删元素快

增加元素:只需要修改连接下个元素的地址即可。


删除元素:只需要修改连接下个元素的地址即可。


红黑树//特点:为了提高搜索,查找的效率,每个结点只能有两个结点

二叉树binary tree ,是每个结点不超过2的有序树(tree)

简单的理解,就是一种类似于我们生活中树的结构,只不过每个结点上都最多只能有两个子结点。

二叉树是每个节点最多有两个子树的树结构。顶上的叫根结点,两边被称作“左子树”和“右子树”。

我们要说的是二叉树的一种比较有意思的叫做红黑树,红黑树本身就是一颗二叉查找树,将节点插入后,该树仍然是一颗二叉查找树。也就意味着,树的键值仍然是有序的。我们只要红黑树是为了提高搜索效率的就行了。

List的子类

java.util.ArrayList集合数据存储的结构是数组结构。元素增删慢,查找快,由于日常开发中使用最多的功能为查询数据、遍历数据,所以ArrayList是最常用的集合。

java.util.LinkedList<E>集合数据存储的结构是链表结构。方便元素添加、删除的集合。

LinkedList是一个双向链表


Set接口

Set接口中元素无序,并且都会以某种规则保证存入的元素不出现重复

HashSet是根据对象的哈希值,来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。底层的实现,其实是一个java.util.HashMap支持。

HashSet是根据对象的哈希值,来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。保证元素唯一性的方式依赖于:hashCode与equals方法。

HashSet集合存储数据的结构

什么是哈希表呢?

JDK1.8之前,哈希表底层采用数组+链表实现,即使用链表处理哈希冲突,同一hash值的链表都存储在一个链表里。但是当位于一个中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。

而在JDK1.8中,哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。


HashSet下面有一个子类java.util.LinkedHashSet,它是链表和哈希表组合的一个数据存储结构。保证有序

Comparable可比较接口和Comparator比较器接口的区别?

Comparable:强行对实现它的每个类的对象,进行整体排序。类内部实现比较器,默认规则**

Comparator:也强行对某个对象,进行整体排序。外比较器,类的外部自己写规则**

不管是内比较器还是外比较器,只要排序都要实现这两个接口之一,

如果两个接口都实现,优先考虑的外比较器Comparator

Map双列集合

Map集合是双列集合存一对对数据,特点是无序,通过键找到值,要求键是唯一的

HashMap<K,V>:存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。

LinkedHashMap<K,V>:HashMap下有个子类LinkedHashMap,存储数据采用了哈希表结构+链表结构。

Map集合(得到键和得到值)遍历键找值方式

获取Map中所有的键,由于键是唯一的,所以返回一个Set集合存储所有的键。方法提示:keyset()

Set<String> keys = map.keySet();

// 遍历键集 得到 每一个键

        for (String key : keys) {

String value = map.get(key);

}

在Map集合中也提供了获取所有Entry键值对对象的方法:

public Set<Map.Entry<K,V>> entrySet(): 键值对对象的集合,获取到Map集合中所有的键值对对象的集合(Set集合)。

异常指的是程序在执行( 编译和运行)过程中,出现的非正常的情况,最终会导致JVM的非正常停止(中断)

在Java等面向对象的编程语言中,异常本身是一个类(模拟一类事物),产生异常就是创建异常对象并抛出了一个异常对象Java虚拟机默认处理异常的方式是中断处理,把程序中断,停止,并告诉你异常问题的名字,原因,代码位置

try{//尝试,试验,检测,需要时间,越少越好

    编写可能会出现异常的代码

}catch(异常类型  e){//e=对象;//如果上面出现问题,立马catch块抓住它,进行捕获

    处理异常的代码

    //记录日志/打印异常信息/继续抛出异常

}

finally代码块,跟try或者trycatch组合用的,不能单独使用,finally:有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。

进程:进行中的程序

线程:进程中的执行路径(执行路径,能做事情的地方,通道,路径)

多线程:进程中有多条执行路径,我就可以做多个事情(一条执行路径,可以执行或者说做一个事情)

并行:指两个或多个事件在同一时刻发生(同时发生)。

并发:指两个或多个事件在同一个时间段内发生。

进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个线程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。

线程:进程内部的一个独立执行单元(路径);一个进程可以同时并发的运行多个线程,可以理解为一个进程便相当于一个单 CPU 操作系统,而线程便是这个系统中运行的多个任务。

进程与线程的区别

进程:有独立的内存空间,进程中的数据存放空间(堆空间和栈空间)是独立的,至少有一个线程。

线程:堆空间是共享的,栈空间是独立的,线程消耗的资源比进程小的多。

Java中通过继承Thread类来创建并启动多线程


通过实现Runnable接口,使得该类有了多线程类的特征。


**实现Runnable接口比继承Thread类所具有的优势:

适合多个相同的程序代码的线程去共享同一个资源。

可以避免java中的单继承的局限性。//

增加程序的健壮性,实现解耦(耦合:类与类之间关系)操作,代码可以被多个线程共享,代码和线程独立。

线程池只能放入实现Runable或Callable接口线程,不能直接放入继承Thread的类。


线程同步,同步技术,解决线程的安全性问题:

同步就可以让cpu在某段时间内只让一个线程进来做事情,其他线程不能进来,等你做完了才能一个一个进来(理解为排队一个个来不会有问题),同步技术包括,同步代码块,同步方法,Lock锁

同步代码块:synchronized关键字可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。

同步方法:使用synchronized修饰的方法,就叫做同步方法,保证A线程执行该方法的时候,其他线程只能在方法外等着。

同步锁:

对象的同步锁只是一个概念,可以想象为在对象上标记了一个锁.

锁对象 可以是任意类型。

多个线程对象  要使用同一把锁。


Lock锁也称同步锁,加锁与释放锁方法化了,如下:

public void lock():加同步锁。

public void unlock():释放同步锁。

线程状态:NEW(新建)   Runnable(可运行)     Blocked(锁阻塞,暂时等待)    Waiting(无限等待)    Timed Waiting(计时等待)    Terminated(被终止)



在一个线程进行了规定操作后,就进入等待状态(wait()), 等待其他线程执行完他们的指定代码过后,再将其唤醒

(notify());在有多个线程进行等待时, 如果需要,可以使用( notifyAll())来唤醒所有的等待线程。


线程池:其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,从而无需反复创建线程而消耗过多资源。

合理利用线程池能够带来三个好处:

1. 降低资源消耗。

2. 提高响应速度。

3. 提高线程的可管理性。


使用Executors类,来创建线程池对象。

public static ExecutorService newFixedThreadPool(int nThreads) :返回线程池对象。

使用线程池中线程对象的步骤:

1. 创建线程池对象。

2. 创建Runnable接口子类对象。(task)

3. 提交Runnable接口子类对象。(take task)

4. 关闭线程池(一般不做)。



Lambda表达式的标准格式为:(参数类型 参数名称) -> { 代码语句 }

Lambda的语法非常简洁,完全没有面向对象复杂的束缚。但是使用时有几个问题需要特别注意://记忆

1. 使用Lambda必须具有接口,且要求接口中有且仅有一个抽象方法(函数式接口)。 无论是JDK内置的

Runnable 、 Comparator 接口还是自定义的接口,只有当接口中的抽象方法存在且唯一时,才可以使用

Lambda。

2. 使用Lambda必须具有上下文推断。 也就是方法的参数或局部变量类型,必须为Lambda对应的接口类型,才能

使用Lambda作为该接口的实例

java.io.File 类是文件和目录(文件夹)路径名的抽象表示,主要用于文件和目录的创建、查找和删除等操作。

绝对路径:从盘符开始的路径,这是一个完整的路径。如"D:\a.png";

相对路径:相对于某个东西而言的路径,这是一个便捷的路径,开发中经常使用。

递归:指在当前方法内,方法自己调用自己的这种现象。(回看day8)


字节输入流FileInputStream读一个字节read()和读一个字节数组read(byte[] arr)方法,

有数组读取到的内容存到数组,方法的返回值表示读取到的有效字节个数,

没数组读取到的内容存到read方法的返回值,

但是只要读不到都返回-1,就可以定义变量接收read方法的返回值,循环赋值判断不等于-1就可以一直读

套路:

int ch;

while(()!=-1){//()当成一个整体,不要漏掉里面的()括号!!!记忆!!!

}

字节输入流一个读一个字节和一个读一个字节数组的代码总结如下:(能够理解读取数据read(byte[])方法)

java.util.Properties 继承于Hashtable ,来表示一个持久的属性集。它使用键值结构存储数据,每个键及其对应值都是一个字符串。该类也被许多Java类使用,比如获取系统属性时,System.getProperties 方法就是返回一个Properties对象。

字节缓冲流:BufferedInputStream,BufferedOutputStream

字符缓冲流:BufferedReader,BufferedWriter

字符集 Charset:是一个系统,支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等。


Java 提供了一种对象序列化的机制。用一个字节序列,可以表示一个对象,该字节序列包含该对象的数据、对象的类型和对象中存储的数据等信息。字节序列,写出到文件之后,相当于,文件中持久保存了一个对象的信息。

反之,该字节序列,还可以从文件中读取回来,重构对象,对它进行反序列化


序列化操作

一个对象要想序列化,必须满足两个条件:

该类必须实现java.io.Serializable 接口,Serializable 是一个标记接口,读作序列化接口,不实现此接口的类,将不会使任何状态,序列化或反序列化,会抛出NotSerializableException 。

该类的所有属性必须是可序列化的。如果有一个属性不需要序列化的,则该属性必须注明是瞬态的,使用transient 关键字修饰。//


对于JVM来说,可以反序列化的对象,它必须是,能够找到class文件的类。

如果找不到该类的class文件,则抛出一个 ClassNotFoundException 异常。 

**另外,当JVM反序列化对象时,能找到class文件,但是class文件,在序列化对象(属性)之后发生了修改,那么反序列化操作也会失败,抛出一个InvalidClassException异常。**

网络通信协议

网络通信协议:通信协议是计算机必须遵守的规则,只有遵守这些规则,计算机之间才能进行通信。协议中对数据的传输格式、传输速率、传输步骤等做了统一的规定,通信双方都必须同时遵守,最终完成双方的数据交换。

TCP/IP协议: 传输控制协议/因特网互联协议( Transmission Control Protocol/Internet Protocol),是Internet最基本、最广泛的协议。


TCP:传输控制协议 (Transmission Control Protocol)。TCP协议是面向连接的通信协议,即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输

三次握手:TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠。

第一次握手,客户端向服务器端发出连接请求,等待服务器确认。

第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求。

第三次握手,客户端再次向服务器端发送确认信息,确认连接。

UDP:用户数据报协议(User Datagram Protocol)。UDP协议是一个面向无连接的协议。传输数据时,不需要建立连接,不管对方端服务是否启动,直接将数据、数据源和目的地都封装在数据包中,直接发送。每个数据包的大小限制在64k以内。它是不可靠协议,因为无连接,所以传输速度快,但是容易丢失数据。日常应用中,例如视频会议、QQ聊天等。

IP地址:指互联网协议地址(Internet Protocol Address),俗称IP。IP地址用来给一个网络中的计算机设备做唯一的编号标识(身份证)

如果说IP地址可以唯一标识网络中的设备,那么端口号就可以唯一标识设备中的进程(应用程序)了。

端口号:用两个字节表示的整数,它的取值范围是0~65535(刚好是char类型的范围)。其中,0~1023之间的端口号,用于一些知名的网络服务和应用,普通的应用程序,需要使用1024以上的端口号。如果端口号被另外一个服务或应用所占用,会导致当前程序启动失败。

利用协议+IP地址+端口号 三元组合,就可以标识网络中的进程了,那么进程间的通信,就可以利用这个标识与其它进程进行交互。

在Java中,提供了两个类,用于实现,TCP通信程序:

客户端:java.net.Socket 类表示。创建Socket对象,向服务端发出连接请求,服务端响应请求,两者建立连接开始通信。

服务端:java.net.ServerSocket 类表示。创建ServerSocket对象,相当于开启一个服务,并等待客户端的连接。

Socket 类:该类实现客户端套接字,套接字,指的是两台设备之间 通讯 的端点。通过调用io流来实现设备间的通信,数据交换,网络中通信,其实是套接字之间的通信,底层用的是io流。

ServerSocket类:这个类,实现了服务器套接字,该对象,等待通过网络的请求。

简单的TCP网络程序


函数式接口在Java中是指:有且只有一个抽象方法的接口

======================================================================

MySQL


所有的字段名都写出来INSERT INTO 表名 (字段名1, 字段名2, 字段名3…) VALUES (值1, 值2, 值3);


CREATE TABLE student2 LIKE student;

INSERT INTO student2 SELECT * FROM student;


不带条件修改数据UPDATE 表名 SET 字段名=值;

带条件修改数据UPDATE 表名 SET 字段名=值 WHERE 字段名=值;


查询指定列的数据,多个列之间以逗号分隔SELECT 字段名1, 字段名2... FROM 表名;


使用别名的好处是方便观看和处理查询到的数据

SELECT 字段名1 AS 别名, 字段名2 AS 别名... FROM 表名;

SELECT 字段名1 AS 别名, 字段名2 AS 别名... FROM 表名 AS 表别名;

需要到多表查询的时候才能体现出好处


查询指定列并且结果不出现重复数据

SELECT DISTINCT 字段名 FROM 表名;


某列数据和固定值运算SELECT 列名1 + 固定值 FROM 表名;

某列数据和其他列数据参与运算SELECT 列名1 + 列名2 FROM 表名;


in关键字,在()范围里面,可以理解为是或者的优化,或者集合

语法格式:SELECT 字段名 FROM 表名 WHERE 字段 in (数据1, 数据2...);

in里面的每个数据都会作为一次条件,只要满足条件的就会显示

SELECT * FROM student4 WHERE id IN (1,3,5);


LIKE表示模糊查询

SELECT * FROM 表名 WHERE 字段名 LIKE '通配符字符串';


单列排序

`SELECT 字段名 FROM 表名 WHERE 字段=值 ORDER BY 字段名 [ASC|DESC];`

SELECT * FROM student3 ORDER BY age DESC;

组合排序

`SELECT 字段名 FROM 表名 WHERE 字段=值 ORDER BY 字段名1 [ASC|DESC], 字段名2 [ASC|DESC];`

SELECT * FROM student3 ORDER BY age DESC, math DESC;


五个聚合函数:

count: 统计指定列记录数,记录为NULL的不统计

sum: 计算指定列的数值和,如果不是数值类型,那么计算结果为0

max: 计算指定列的最大值min: 计算指定列的最小值

avg: 计算指定列的平均值,如果不是数值类型,那么计算结果为0

聚合函数的使用:写在 SQL语句SELECT后 字段名的地方

SELECT 字段名... FROM 表名;

SELECT COUNT(age) FROM 表名;

利用IFNULL()函数,如果记录为NULL,给个默认值,这样统计的数据就不会遗漏

SELECT COUNT(IFNULL(english,0)) FROM student3;


GROUP BY怎么分组的?将分组字段结果中相同内容作为一组

SELECT * FROM student3 GROUP BY sex;

GROUP BY将分组字段结果中相同内容作为一组,并且返回每组的第一条数据,所以单独分组没什么用处。分组的目的就是为了统计,一般分组会跟聚合函数一起使用。

分组后聚合函数的作用?不是操作所有数据,而是操作一组数据。

SELECT SUM(math), sex FROM student3 GROUP BY sex;


having与where的区别:(巧记,bye(by having),后面再聚!!!)

having是在分组后对数据进行过滤

where是在分组前对数据进行过滤

having后面可以使用聚合函数

where后面不可以使用聚合函数


LIMIT的使用场景:分页

每页显示5条

-- 第一页: LIMIT 0,5; 跳过0条,显示5条

-- 第二页: LIMIT 5,5;  跳过5条,显示5条

-- 第三页: LIMIT 10,5; 跳过10条,显示5条,5每页显示条数固定死了


数据库约束

PRIMARY KEY: 主键,非空,唯一

UNIQUE: 唯一,表示使用了这个约束的字段不能重复

NOT NULL: 非空,表示使用了这个约束的字段不能为null

DEFAULT: 默认,表示如果这个字段没有插入值的话,会赋一个默认值

FOREIGN KEY: 外键(难点)


MySQL索引的类型

1. 普通索引

2. 唯一索引,索引列的值必须唯一,但允许有空值(注意和主键不同)。

CREATE UNIQUE INDEX index Name ON table(column(length))

3. 全文索引(FULLTEXT)

MySQL从3.23.23版开始支持全文索引和全文检索,FULLTEXT索引仅可用于 MyISAM 表;

4. 单列索引、多列索引

多个单列索引与单个多列索引的查询效果不同,因为执行查询时,MySQL只能使用一个索引,会从多个索引中选择一个限制最为严格的索引。

5. 组合索引(最左前缀)就是只从最左面的开始组合。

并不是只要包含这两列的查询都会用到该组合索引,

使用到上面的索引

SELECT*FROM article WHREE title='测试'AND time=1234567890;

SELECT*FROM article WHREE utitle='测试';

–不使用上面的索引SELECT*FROM article WHREE time=1234567890;

MySQL索引的优化

1. 何时使用聚集索引或非聚集索引?

2. 索引不会包含有NULL值的列

只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。

3. 使用短索引

对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个CHAR(255)的列,如果在前10个或20个字符内,多数值是惟一的,那么就不要对整个列进行索引。

4. 索引列排序

MySQL查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引

5. like语句操作

般情况下不鼓励使用like操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引而like “aaa%”可以使用索引。

6. 不要在列上进行运算

表关系

一对多建表原则: 在从表(多方)创建一个字段,字段作为外键指向主表(一方)的主键

多对多关系建表原则: 需要创建第三张表,中间表中至少两个字段,这两个字段分别作为外键指向各自一方的主键。


范式是指:设计数据库表的规则(Normal Form) 好的数据库设计对数据的存储性能和后期的程序开发,都会产生重要的影响。建立科学的,规范的数据库就需要满足一些规则来优化数据的设计和存储

第一范式,每一列都是不可分割的原子数据项,而不能是集合、数组、记录等非原子数据项。


第二范式(2NF)要求实体的属性完全依赖于主关键字。





总结内连接查询步骤:

确定查询哪些表

确定表连接条件

确定查询字段


左外连接:使用LEFT OUTER JOIN ... ON,OUTER可以省略

SELECT 字段名 FROM 左表 LEFT OUTER JOIN 右表 ON 条件;

在内连接的基础上保证左表的数据全部显示


右外连接:使用RIGHT OUTER JOIN ... ON,OUTER可以省略

SELECT 字段名 FROM 左表 RIGHT OUTER JOIN 右表 ON 条件;

在内连接的基础上保证右表的数据全部显示




子查询结果只要是多列,肯定在FROM后面作为表

SELECT 查询字段 FROM (子查询) 表别名 WHERE 条件;

子查询作为表需要取别名,否则这张表没用名称无法访问表中的字段

子查询总结

子查询结果只要是单列,肯定在WHERE后面作为条件SELECT 查询字段 FROM 表 WHERE 字段=(子查询);

子查询结果只要是多列,肯定在FROM后面作为表SELECT 查询字段 FROM (子查询) 表别名 WHERE 条件;


多表查询






type:查询级别

type=ALL 全表扫描,

 type=index 索引全扫描,遍历整个索引来查询匹配的行

type=range 索引范围扫描,常见于 <,<=,>,>=,between,in等操作符。

  例 

    explain select * from adminlog where id>0 , 

    explain select * from adminlog where id>0 and id<=100

    explain select * from adminlog where id in (1,2) 


type=ref  使用非唯一索引或唯一索引的前缀扫描,返回匹配某个单独值的记录行。ref还经常出现在JOIN操作中

type=eq_ref 类似于ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中有一条记录匹配;简单来说,说是多表连接中使用 主建或唯一健作为关联条件

 type=const/system 单表中最多有一个匹配行。主要用于比较primary key [主键索引]或者unique[唯一]索引,因为数据都是唯一的,所以性能最优。条件使用=。 

type=NULL 不用访问表或者索引,直接就能够得到结果


==================================================================================

接口一般来说有两种,一种是程序内部的接口,一种是系统对外的接口。

系统对外的接口:比如你要从别的网站或服务器上获取资源或信息,别人肯定不会把数据库共享给你,他只能给你提供一个他们写好的方法来获取数据,你引用他提供的接口就能使用他写好的方法,从而达到数据共享的目的,比如说咱们用的app、网址这些它在进行数据处理的时候都是通过接口来进行调用的。

程序内部的接口:方法与方法之间,模块与模块之间的交互,程序内部抛出的接口,比如bbs系统,有登录模块、发帖模块等等,那你要发帖就必须先登录,要发帖就得登录,那么这两个模块就得有交互,它就会抛出一个接口,供内部系统进行调用。


什么是JDBC:Java Data Base Connectivity(Java数据库连接) JDBC是Java访问数据库的标准规范

JDBC的作用:JDBC是用于执行SQL语句的Java API(Java语言通过JDBC可以操作数据库)

JDBC四个核心对象这几个类都是在java.sql包中

DriverManager: 用于注册驱动、以及获取Connection连接对象

Connection: 表示与数据库创建的连接

Statement: 执行SQL语句的对象、将SQL语句发送到mysql服务器进行执行。

ResultSet: 结果集或一张虚拟表,查询数据的时候查询到的所有结果全部在ResultSet对象中


ResultSet的原理:

ResultSet内部有一个指针,刚开始记录开始位置

调用next方法, ResultSet内部指针会移动到下一行数据

我们可以通过ResultSet得到一行数据 getXxx得到某列数据


使用JDBC查询数据库中的数据的步骤

注册驱动

获取连接

获取到Statement

使用Statement执行SQL

ResultSet处理结果

关闭资源


JDBC事务

注册驱动

获取连接

获取到Statement

开启事务

使用Statement执行SQL

提交或回滚事务

关闭资源


什么是SQL注入?

SQL注入(SQLi)是一种注入攻击,,可以执行恶意SQL语句。

prepareStatement()会先将SQL语句发送给数据库预编译。

PreparedSatement使用步骤

编写SQL语句,未知内容使用?占位:"SELECT * FROM user WHERE name=? AND password=?;";

获得PreparedStatement对象

设置实际参数

执行参数化SQL语句

关闭资源


连接池的概念: 连接池是创建和管理数据库连接的缓冲池技术。连接池就是一个容器,连接池中保存了一些数据库连接,这些连接是可以重复使用的。

数据库连接池相关API​ Java为数据库连接池提供了公共的接口: javax.sql.DataSource,各个厂商需要让自己的连接池实现这个接口。这样应用程序可以方便的切换不同厂商的连接池。

常见的连接池: C3P0、Druid、DBCP等


代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户和目标对象之间起到中介的作用。

静态代理

概念:由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。

动态代理

概念:动态代理与静态代理模式原理是一样的,只是动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。代理者和委托者的关系是在程序运行时确定。

java.lang.reflect.Proxy:这是 Java 动态代理机制生成的所有动态代理类的父类,它提供了一组静态方法来为一组接口动态地生成代理对象。

Proxy.newProxyInstance(loader,interfaces,invacationHandler)


com.mchange.v2.c3p0.ComboPooledDataSource类表示C3P0的连接池对象,常用2种创建连接池的方式:1.无参构造,使用默认配置,2.有参构造,使用命名配置


Druid是阿里巴巴开发的号称为监控而生的数据库连接池,Druid是目前最好的数据库连接池。

com.alibaba.druid.pool.DruidDataSourceFactory类有创建连接池的方法

使用步骤

在src目录下创建一个properties文件,并设置对应参数

加载properties文件的内容到Properties对象中

创建DRUID连接池,使用配置文件中的参数

从DRUID连接池中取出连接

执行SQL语句

关闭资源


元数据的概述

包含了数据库、表、列的定义信息,关于数据库的整体综合信息。

JdbcTemplate处理了资源的建立和释放。

在JdbcTemplate中执行SQL语句的方法大致分为3类:

execute:可以执行所有SQL语句,一般用于执行DDL语句。(了解)

update:用于执行INSERT、UPDATE、DELETE等DML语句。

queryXxx:用于DQL数据查询语句。


反射是一种机制,利用该机制可以在程序运行过程中对类进行解剖并操作类中的方法,属性,构造方法等成员。

我们在使用这些IDE写代码也无时无刻的使用着反射机制,一个常用反射机制的地方就是当我们通过对象调用方法或访问属性时,开发工具都会以列表的形式显示出该对象所有的方法或属性,以供方便我们选择使用,

使用反射机制解剖类的前提

必须先要获取到该类的字节码文件对象,即Class类型对象

获取Class对象的三种方式

方式1:通过类名.class获取

方式2:对像名调用getClass()方法获取


方式3:通过Class.forName("全限定类名")方法获取



Constructor是构造方法类,类中的每一个构造方法都是Constructor的对象,通过Constructor对象可以实例化对象。


Method是方法类,类中的每一个方法都是Method的对象,通过Method对象可以调用方法。


Field是属性类,类中的每一个属性(成员变量)都是Field的对象,通过Field对象可以给对应的成员变量赋值和取值。



BeanUtils是Apache commons组件的成员之一,主要用于简化JavaBean封装数据的操作

常用的操作有以下三个:

对JavaBean的属性进行赋值和取值。

将一个JavaBean所有属性赋值给另一个JavaBean对象中。

将一个Map集合的数据封装到一个JavaBean对象中。





Tomcat

自动化部署?

Jenkins自动化部署



设置日志级别以及输出位置

1.让所有文件都输出到同一个文件中

打开Tomcat目录conf\logging.properties,修改如下,所有日志输出到tomcat开头的文件中

1catalina.org.apache.juli.FileHandler.level = FINE

2.打开访问日志

编辑 ${catalina}/conf/server.xml 文件. 注 :${catalina} 是 tomcat 的安装目录

3.修改tomcat日志级别

Tomcat 日志分为下面5类:

catalina 、 localhost 、 manager 、 admin 、 host-manager

每类日志的级别分为如下 7 种:

SEVERE (highest value) > WARNING > INFO > CONFIG > FINE > FINER > FINEST (lowest value)


servlet运行原理

1. Servlet对象是由服务器创建

2. request与response对象也是由tomcat服务器创建

3. request对象封装了浏览器过来的所有请求信息,response对象代表了服务器的响应信息。


HttpServletResponse对象封装了向客户端发送数据、发送响应头,发送响应状态码的方法。开发人员必须学会使用HttpServletResponse,才能给浏览器发送数据。

响应的组成部分:

响应行(协议版本、响应状态码)

响应头(键值对)

响应体(显示在页面上的内容、下载的内容)


Response的小结

response的概念:服务器发送给客户端的响应内容,我们通过response对象的方法,设置响应内容,然后由服务器将其发送给客户端

setStatus(状态码)方法,设置响应状态码(重要)

setHeader(name,value),设置响应头

常见的响应头:Refresh,location,Content-Type,Content-Disposation

发起重定向:response.SendRedirect("路径")(重要)

解决响应的中文乱码问题:response.setContentType("text/html;charset=UTF-8")(重要)

获取响应的字符输出流:response.getWriter()(重要)

获取响应的字节输出流:response.getOutputStream()(下载的时候使用)


ServletContext是一个容器(域对象)可以存储键值对数据(String key,Object value),保存在ServletContext中的数据不仅可以提供给所有的servlet使用,而且可以在整个项目范围内使用(后期的过滤器、监听器也可以使用ServletContext)。

什么是HttpServletRequest?

HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息。

通过Request对象进行的常用操作:

获取客户机信息

获取请求头信息

获取请求参数

利用请求域传递对象

请求转发和重定向的区别



​ cookie就是服务器存放在浏览器(客户端)的一小份数据(只能是字符串,并且不超过4kb),以后浏览器(客户端)每次访问这个服务器都会将cookie携带过来。



​ 什么时候Session会销毁:

session过期,闲置30分钟

服务器关闭

session手动调用invalidate()方法


MVC是一种软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller),即为MVC。

过滤器和拦截器的区别?

(1)使用范围不同:Filter是Servlet规范规定的,只能用于web程序中。而拦截器既可以用于web程序,也可以用于Application、swing程序中。

(2)规范不同:Filter是在servlet规范中定义的,是Servlet容器支持的,而拦截器是在spring容器内的,是spring框架支持的。

(3)使用的资源不同:同其他的代码块一样,拦截器也是一个spring的组件,归spring管理,配置在spring文件中,因此能使用spring里的任何资源,独享。例如service对象、数据源、事务管理等,通过IOC注入到拦截器即可;而Filter不能。

(4)深度不同:Filter只在Servlet前后起作用。而拦截器能深入到方法前后、异常抛出前后等。因此拦截器的使用灵活性更大。所以在Spring为基础的构架的程序中,优先使用拦截器。


Ajax 即"Asynchronous Javascript And XML"(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。


sudo,可以理解为超级管理员执行的操作,通常是系统级别的指令。


Nginx还是一种高性能的HTTP和反向代理服务器,同时也是一个代理邮件服务器。

Nginx上可以:

可以发布网站(静态资源)

可以实现负载均衡

可以作为邮件服务器实现收发邮件等功能

可以作为反向代理服务器





Redis支持的键值数据类型

字符串类型 string(掌握)

散列类型 hash

列表类型 list

集合类型 set

有序集合类型 sortedset


redis的应用场景


字符串类型string概述

字符串类型是Redis中最为基础的数据存储类型,它在Redis中是二进制安全的,这便意味着该类型存入和获取的数据相同。在Redis中字符串类型的Value最多可以容纳的数据长度是512M。

**set key value**

**get key**


Redis中的Hash类型可以看成具有String Key和String Value的map容器。所以该类型非常适合于存储值对象的信息。如Username、Password和Age等。如果Hash中包含很少的字段,那么该类型的数据也将仅占用很少的磁盘空间。每一个Hash可以存储4294967295个键值对。

**hset key field value**

**hget key field**



在Redis中,List类型是按照插入顺序排序的字符串链表。和数据结构中的普通链表一样,我们可以在其头部(left)和尾部(right)添加新的元素。在插入时,如果该键并不存在,Redis将为该键创建一个新的链表。与此相反,如果链表中所有的元素均被移除,那么该键也将会被从数据库中删除。List中可以包含的最大元素数量是4294967295

**lpush key values[value1 value2…]**


lpop key

返回并弹出指定的key关联的链表中的第一个元素,即头部元素。如果该key不存在,返回nil;若key存在,则返回链表的头部元素。


rpop key

从尾部弹出元素。


在Redis中,我们可以将Set类型看作为没有排序的字符集合,和List类型一样,我们也可以在该类型的数据值上执行添加、删除或判断某一元素是否存在等操作。需要说明的是,这些操作的时间复杂度为O(1),即常量时间内完成次操作。Set可包含的最大元素数量是4294967295,和List类型不同的是,Set集合中不允许出现重复的元素。

第五种数据类型叫做sortedSet,有序集合。

在set的基础上,有序了。给每一个元素指定一个score(分数)


RDB持久化(默认支持,无需配置)

该机制是指在指定的时间间隔内将内存中的数据集快照写入磁盘。

AOF持久化

该机制将以日志的形式记录服务器所处理的每一个写操作,在Redis服务器启动之初会读取该文件来重新构建数据库,以保证启动后数据库中的数据是完整的。

Jedis的基本使用

官方网站里列一些Java的客户端,有Jedis、Redisson、Jredis、JDBC-Redis、等其中官方推荐使用Jedis和Redisson。


Redis的分布式锁?

分布式锁是控制分布式系统或不同系统之间共同访问共享资源的一种锁实现,如果不同的系统或同一个系统的不同主机之间共享了某个资源时,往往需要互斥来防止彼此干扰来保证一致性。

Redis(setnx命令)

https://www.cnblogs.com/fixzd/p/9479970.html


Maven的作用

maven对项目的第三方构件(jar包)进行统一管理。向工程中加入jar包不要手工从其它地方拷贝,通过maven定义jar包的坐标,自动从maven仓库中去下载到工程中。(很重要)

maven提供一套对项目生命周期管理的标准,开发人员、和测试人员统一使用maven进行项目构建。项目生命周期管理:编译、测试、打包、部署、运行。

maven对工程分模块构建,提高开发效率。

Maven的概念模型

项目对象模型 (Project Object Model)。POM对象模型,每个maven工程中都有一个pom.xml文件,定义工程所依赖的jar包、本工程的坐标、打包运行方式。

依赖管理系统(基础核心 )。maven通过坐标对项目工程所依赖的jar包统一规范管理。

maven定义一套项目生命周期。清理、初始化、编译、测试、报告 、打包、部署、站点生成。

一组标准集合。maven工程有自己标准的工程目录结构、定义坐标有标准。

maven 管理项目生命周期过程都是基于插件完成的,例如:开发中使用插件。


Maven的坐标

groupId:定义当前Maven组织的名称

artifactId:定义项目模块

version:定义当前项目的当前版本


maven的命令的总结

clean命令,可以清理项目,将编译后的文件清除掉

compile命令,它可以编译maven项目中的java文件(test不会编译),执行compile,必然先会将项目清理

test命令,它会编译和运行项目中的单元测试用例

package命令,将项目进行打包。执行package命令必然会先进行编译

install命令,将项目打包并且安装到本地仓库。执行install命令必然先会进行打包


========================================================================

RESTful架构是目前最流行的一种互联网软件架构

是所有Web应用都应该遵守的架构设计指导原则

​ 7个HTTP方法:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS

幂等性:不论你请求多少次,资源的状态是一样的。


MongoDB是一个基于分布式文件存储的数据库。

MongoDB 的逻辑结构是一种层次结构。主要由:文档(document)、集合(collection)、数据库(database)这三部分组成的。逻辑结构是面向用户的,用户使用 MongoDB 开发应用程序使用的就是逻辑结构。


mongodb-driver是mongo官方推出的java连接mongoDB的驱动包,相当于JDBC驱动。我们现在来使用mongodb-driver完成对Mongodb的操作。

即时通信(Instant Messaging,简称IM)是一个允许两人或多人使用网络实时的传递文字消息、文件、语音与视频交流。 即时通讯技术应用于需要实时收发消息的业务场景。


WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。




接口加密方式

加密方式

摘要算法

消息摘要是把任意长度的输入揉和而产生长度固定的信息。

​ 消息摘要算法的主要特征是加密过程不需要密钥,并且经过加密的数据无法被解密,只有输入相同的明文数据经过相同的消息摘要算法才能得到相同的密文。消息摘要算法不存在密钥的管理与分发问题,适合于分布式网络上使用。

常见的摘要算法:CRC、MD5、SHA等


对称加密的特点:

速度快,通常在消息发送方需要加密大量数据时使用。

密钥是控制加密及解密过程的指令。

算法是一组规则,规定如何进行加密和解密。


非对称加密算法是一种密钥的保密方法,加密和解密使用两个不同的密钥,公开密钥(publickey:简称公钥)和私有密钥(privatekey:简称私钥)。公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密。


数字签名(又称公钥数字签名)是一种类似写在纸上的普通的物理签名,是使用了公钥加密领域的技术实现,用于鉴别数字信息的方法。

​ 数字签名通常使用私钥生成签名,使用公钥验证签名。

推荐阅读更多精彩内容