目录
38.Mysql: Every derived table must have its own alias (每个派生出来的表都必须有一个自己的别名)
46.System.out.println(2/3); 0 System.out.println(3/2); 1
47.http get和post请求的区别 与head请求有什么区别
53.hashMap的put、get的原理 (数组和链表的结合体,底层是一个数组结构,数组的每一项又是一个链表)
57.@Autowired (srping的)与@Resource(j2ee)
1.集合类
Conllection:单列集合
Collection 是最基本的集合接口,一个 Collection 代表一组 Object,即 Collection 的元素, Java不提供直接继承自Collection的类,只提供继承于的子接口(如List和set)。
Collection 接口存储一组不唯一,无序的对象。
List接口是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的下标)来访问List中的元素,第一个元素的索引为 0,而且允许有相同的元素。
List 接口存储一组不唯一,有序(插入顺序)的对象。
LinkedList该类实现了List接口,允许有null(空)元素。主要用于创建链表数据结构,该类没有同步方法,如果多个线程同时访问一个List,则必须自己实现访问同步,解决方法就是在创建List时候构造一个同步的List。例如:
Listlist=Collections.synchronizedList(newLinkedList(...));
LinkedList 查找效率低。
ArrayList该类也是实现了List的接口,实现了可变大小的数组,随机访问和遍历元素时,提供更好的性能。该类也是非同步的,在多线程的情况下不要使用。ArrayList 增长当前长度的50%,插入删除效率低。
Vector 该类和ArrayList非常相似,但是该类是同步的,可以用在多线程的情况,该类允许设置默认的增长长度,默认扩容方式为原来的2倍。
Set 具有与 Collection 完全一样的接口,只是行为上不同,Set 不保存重复的元素。
Set 接口存储一组唯一,无序的对象。
HashSet该类实现了Set接口,不允许出现重复元素,不保证集合中元素的顺序,允许包含值为null的元素,但最多只能一个。
LinkedHashSet具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。
TreeSet该类实现了Set接口,可以实现排序等功能。
SortedSet 继承于Set保存有序的集合。
Map:双列集合
Map 接口存储一组键值对象,提供key(键)到value(值)的映射。
HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
该类实现了Map接口,根据键的HashCode值存储数据,具有很快的访问速度,最多允许一条记录的键为null,不支持线程同步
TreeMap 继承了AbstractMap,并且使用一颗树。
LinkedHashMap 继承于HashMap,使用元素的自然顺序对元素进行排序.
高度注意 Map 类集合 K/V 能不能存储 null 值的情况,如下表格:
集合类 | key | Value | Super | 说明 |
Hashtable | 不允许为 null | 不允许为 null | Dictionary | 线程安全 |
ConcurrentHashMap | 不允许为 null | 不允许为 null | AbstractMap | 锁分段技术(JDK8:CAS) |
TreeMap | 不允许为 null | 允许为 null | AbstractMap | 线程不安全 |
HashMap | 允许为 null | 允许为 null | AbstractMap | 线程不安全 |
Map遍历的几种方式:
public class Test{
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("1", "value1");
map.put("2", "value2");
map.put("3", "value3");
//第一种:普遍使用,二次取值
System.out.println("通过Map.keySet遍历key和value:");
for (String key : map.keySet()) {
System.out.println("key= "+ key + " and value= " + map.get(key));
}
//第二种
System.out.println("通过Map.entrySet使用iterator遍历key和value:");
Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}
//第三种:推荐,尤其是容量大时
System.out.println("通过Map.entrySet遍历key和value");
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}
//第四种
System.out.println("通过Map.values()遍历所有的value,但不能遍历key");
for (String v : map.values()) {
System.out.println("value= " + v);
}
}
}
Set和List的区别
1. Set 接口实例存储的是无序的,不重复的数据。List 接口实例存储的是有序的,可以重复的元素。
2. Set检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变 <实现类有HashSet,TreeSet>。
3. List和数组类似,可以动态增长,根据实际存储的数据的长度自动增长List的长度。查找元素效率高,插入删除效率低, 因为会引起其他元素位置改变 <实现类有ArrayList,LinkedList,Vector> 。
2.HashMap和HashTable区别
两者都是实现Map接口
HapMap可以允许key和value都可以为null
HashTable的key或者value不能为null
HashTable为线程安全的
在hashMap的基础上,ConcurrentHashMap将数据分为多个segment,默认16个(concurrency level),
然后每次操作对一个segment加锁,避免多线程锁得几率,提高并发效率。
新版本jdk更改设计,变为cas无锁算法
HashMap:哈希表((Hash table)既满足了数据的查找方便,同时不占用太多的内容空间,使用也十分方便。哈希表也有好多种实现,最常用的一种方法---拉链法:可以理解为链表的数组(链表+数组)。
解决hash冲突的方法
- 开放定址法(线性探测再散列,二次探测再散列,伪随机探测再散列)
- 再哈希法
- 链地址法
- 建立一个公共溢出区
Java中hashmap的解决办法就是采用的链地址法
3.线程和进程概念
进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。比如在Windows系统中,一个运行的exe就是一个进程。
线程是指进程中的一个执行流程,一个进程中可以运行多个线程。比如java.exe进程中可以运行很多线程。线程总是属于某个进程,进程中的多个线程共享进程的内存。
在线程的Thread对象上调用start()方法,而不是run()或者别的方法。在调用start()方法之前:线程处于新状态中,新状态指有一个Thread对象,但还没有一个真正的线程。在调用start()方法之后:发生了一系列复杂的事情,启动新的执行线程(具有新的调用栈);该线程从新状态转移到可运行状态;当该线程获得机会执行时,其目标run()方法将运行。
线程状态总的可分为五大状态:分别是就绪(Runable)、运行(Running)、等待/阻塞/睡眠(Waiting/Blocked/Sleeping)、死亡(Dead)
1、新状态:线程对象已经创建,还没有在其上调用start()方法。
2、可运行状态:当线程有资格运行,但调度程序还没有把它选定为运行线程时线程所处的状态。当start()方法调用时,线程首先进入可运行状态。在线程运行之后或者从阻塞、等待或睡眠状态回来后,也返回到可运行状态。
3、运行状态:线程调度程序从可运行池中选择一个线程作为当前线程时线程所处的状态。这也是线程进入运行状态的唯一一种方式。
4、等待/阻塞/睡眠状态:这是线程有资格运行时它所处的状态。实际上这个三状态组合为一种,其共同点是:线程仍旧是活的,但是当前没有条件运行。换句话说,它是可运行的,但是如果某件事件出现,他可能返回到可运行状态。
5、死亡态:当线程的run()方法完成时就认为它死去。这个线程对象也许是活的,但是,它已经不是一个单独执行的线程。线程一旦死亡,就不能复生。如果在一个死去的线程上调用start()方法,会抛出java.lang.IllegalThreadStateException异常。
4.创建线程
实现Runable 继承Thread 实现Callable(有返回值)
5.接口和抽象类的区别
接口的访问修饰符都是public的 抽象类的可以是public private protecte
接口是绝对抽象 不能被实例化 抽象类也不能被实例化
接口中声明的成员变量是fianl修饰的 抽象类修饰的不是fianl的
类实现接口,必须实现所有的接口中方法
类实现抽象类,如不全部实现所有方法 类必须也是抽象类
接口中的方法隐含的都是抽象的
抽象类中的方法可以是抽象的也可以是非抽象的
类可以实现多个接口 只能继承一抽象类
6.基本类型
Java语言提供了八种基本类型。六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型。
①. byte 数据类型是8位、有符号的,以二进制补码表示的整数;
byte 类型用在大型数组中节约空间,主要代替整数,因为 byte 变量占用的空间只有 int 类型的四分之一;
最小值是 -128(-2^7);
最大值是 127(2^7-1);
默认值是 0;
②short 数据类型是 16 位、有符号的以二进制补码表示的整数
Short 数据类型也可以像 byte 那样节省空间。一个short变量是int型变量所占空间的二分之一;
最小值是 -32768(-2^15);
最大值是 32767(2^15 - 1);
默认值是 0;
③int 数据类型是32位、有符号的以二进制补码表示的整数;一般地整型变量默认为 int 类型;
最小值是 -2,147,483,648(-2^31);
最大值是 2,147,483,647(2^31 - 1);
默认值是 0;
④long 数据类型是 64 位、有符号的以二进制补码表示的整数;
最小值是 -9,223,372,036,854,775,808(-2^63);
最大值是 9,223,372,036,854,775,807(2^63 -1);
默认值是 0L;
"L"理论上不分大小写,但是若写成"l"容易与数字"1"混淆,不容易分辩。所以最好大写。
⑤float 数据类型是单精度、32位、符合IEEE 754标准的浮点数;
float 在储存大型浮点数组的时候可节省内存空间;浮点数不能用来表示精确的值
默认值是 0.0f;
⑥double 数据类型是双精度、64 位、符合IEEE 754标准的浮点数;
默认值是 0.0d;
⑦boolean数据类型表示一位的信息;
只有两个取值:true 和 false;
这种类型只作为一种标志来记录 true/false 情况;
默认值是 false;
⑧char类型是一个单一的 16 位 Unicode 字符;
最小值是 \u0000(即为0);
最大值是 \uffff(即为65,535);
char 数据类型可以储存任何字符;
7.List
Array可以包含基本类型或对象类型 ArrayList只能包含对象类型
Array是不可变的 ArrayList的大小是可变的
ArrayList的查询速度快 添加删除慢 添加需要计算索引值
LinkedList的查询速度慢
存储内容比较:
- Array数组可以包含基本类型和对象类型,
- ArrayList却只能包含对象类型。
但是需要注意的是:Array数组在存放的时候一定是同种类型的元素。ArrayList就不一定了,因为ArrayList可以存储Object。
Array和ArrayList空间大小比较:
- 它的空间大小是固定的,空间不够时也不能再次申请,所以需要事前确定合适的空间大小。
- ArrayList的空间是动态增长的,如果空间不够,它会创建一个空间比原空间大一倍的新数组,然后将所有元素复制到新数组中,接着抛弃旧数组。而且,每次添加新的元素的时候都会检查内部数组的空间是否足够。
8.异常处理完成后,Execption对象会发生什么变化
下一个垃圾回收时会被回收掉
9.修饰符权限
public protected default private
当前类 当前包 子孙类 其他包
public都可以 protect 除了其他包 default 当前类,当前包 private 当前类
10.final、finally
final修饰的类的不能被继承 修饰的方法不能被重写 修饰的变量不能被修改
finally try catch异常代码块
11.单例模式---双重校验锁(饿汉模式:不安全)
public class Singleton(){
private Singleton(){}
private static Singleton singele = null;
private static synchronized Singleton getSingleton(){
if(singleton == null)
singleton = new Singleton();
return singleton;
}
}
//双重判断
publiic class Singleton()
{
private Singleton(){}
private static volatile Singleton singleton = null;
public static Singleton getSingleton()
{
if(null == singleton)
{
synchronized(Singleton.class)
{
if(null == singleton)
{
singleton = new Singleton();
}
}
}
return singleton;
}
}
12.连接数据库
①.在开发环境中加载指定数据库的驱动程序。
②.在Java程序中加载驱动程序。
③.创建数据连接对象:根据数据库的URL、用户名和密码,创建一个JDBC Connection 对象。
④.创建Statement对象:Statement 类的主要是用于执行静态 SQL 语句并返回它所生成结果的对象。
⑤.调用Statement对象的相关方法执行相对应的 SQL 语句:通过execuUpdate()方法用来数据的更新,包括插入和删除等操作,
通过调用Statement对象的executeQuery()方法进行数据的查询,而查询结果会得到 ResulSet对象,ResulSet表示执行查询数据库后返回的数据的集合,ResulSet对象具有可以指向当前数据行的指针。通过该对象的next()方法,使得指针指向下一行,然后将数据以列号或者字段名取出。如果当next()方法返回null,则表示下一行中没有数据存在。
⑥.关闭数据库连接:使用完数据库或者不需要访问数据库时,通过Connection的close() 方法及时关闭数据连接。
13.找错
public class Thing(){
void Ting(){
final String s = "";
int len = s.length();
}
}
局部变量不能被final修饰
14.找错
abstract class Something {
private abstract String doSomething ();
}
方法的修饰符不能为private 因为抽象类是让子类来实现的
15.找错
abstract class Something {
public int add(final int a){
return ++a;
}
}
final 修饰的变量不能被修改
16.找错
class Something {
int i;
public void doSomething() {
System.out.println("i = " + i);
}
}
int 的默认值为0 所以没有错
假如在int前面加final
17.找错
public class Something {
public static void main(String[] args) {
Something s = new (Something);
System.out.println("s.doSomething() returns " + doSomething());
//不直接调用doSomething()方法
//因为当前的main方法是static的,不能直接调用非静态方法()
}
public String doSomething() {
return "Do something ...";
}
}
18.找错
当前文件类名 Thing.java
class Something {
private static void main(String[] something_to_do) {
System.out.println("Do something ...");
}
}
Java的Class名字不一定和其文件名相同。但public class的名字必须和文件
名相同。
19.&和&& 区别 &是位运算符。&&是布尔逻辑运算符。
对于:& -- > 只要左右两边有一个为false,则为false;只有全部都为true的时候,结果为true
对于:&& -- > 只要符号左边为false,则结果为false;当左边为true,同时右边也为true,则结果为true
20.error和exception的区别
error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。
exception 表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况。
21. i++ 和 ++i 区别
{int i=0; int j=i++;}
{int i=0; int z=++i;}
运算过后,j=0;表明i++是指先把i赋值给j然后再自身加1;
运算过后,z=1;表明++i是指先自身加1后赋值给z;
22.Java程序的种类有:
(a)内嵌于Web文件中,由浏览器来观看的_Applet
(b)可独立运行的 Application
(c)服务器端的 Servlets
23.Servlet的生命周期
Servlet被服务器实例化之后,容器运行其init方法,请求到达是运行service方法,service方法会自动派遣运行于请求的doget或dopost,当服务器决定将实例销毁的时候调用destroy方法
24.java的设计模式 23
分为三大类别
创建型 5 工厂方法 静态方法 建造者 原型 单例
结构型 7 装饰器 适配器 组合 代理 享元 外观 桥接
行为型 11 迭代子 状态 模板 备忘录 解释器 责任链 观察者 命令 访问者 中介者 策略
25.线程池
Executor接口表示线程池,它的execute(Runable task)方法用来执行Runable类型的任务
Executor的子接口ExecutorService声明了管理线程池的一些方法
Executors类包含了一些静态方法,它负责生成各种类型的线程池ExecutorService的实例
Executors类生成的ExecutorService实例的静态方法
①newCachedThreadPool() 在有任务时才创建新线程,空闲线程被保留60秒
②newFixedThreadpool(int nThread) 线程池中包含固定的线程数目,,空闲线程一直会保留
③newScheduledThreadPool(int corePoolSize) 线程池能按照时间计划来执行任务,允许用户设定计划任务的时间,
参数为线程池的最小数量,当任务较多,线程池可能会创建更多的工作线程来执行任务
④newSingleThreadExecutor() 线程池创建一个工作线程,依次执行每个任务
⑤newSingleThreadScheduleExecutor() 线程池创建一个工作线程,它能按照时间计划来执行任务
ExecutorThreadPool下参数的默认队列为BlockingQueue
它的实现类有ArrayBlockingQueue、DelayQueue、LinkedBlockingQueue、SynchronousQueue等6个
具有给定(固定)容量的 LinkedBlockingQueue----②newFixedThreadpool
创建一个具有给定的(固定)容量和指定访问策略的 ArrayBlockingQueue,它最初包含给定 collection 的元素,并以 collection 迭代器的遍历顺序添加元素。
创建一个具有指定公平策略的 SynchronousQueue
26.单例模式
懒汉、饿汉、登记式、枚举、静态内部类、双重校验锁
27.六原则一法则
单一职责:高内聚低耦合
开闭原则:对扩展开放,对修改关闭
里氏代换原则:所有引用基类的地方必须能透明的使用其子类的对象
注意:1.子类的所有方法必须在父类中声明,或子类必须实现父类声明的所有方法
2.尽量把基类设计成抽象类或接口,让子类继承父类或实现父接口
里氏代换原则是开闭原则实现的重要方式之一
依赖倒置原则:抽象不应该依赖于细节,细节应当依赖于抽象(即:要针对接口变成,而不是针对实现编程)
接口隔离原则:使用多个专门的接口,而不使用单独的总接口,即客户端不应该依赖那些它不需要的接口
合成聚合复用原则:优先使用聚合或合成关系复用代码
迪米特法则:一个软件实体尽量可能少的与其他实体发生相互作用
28.jvm的内存分布
堆(java head)、栈(stack)、程序计数器(program counter register)、方法区(method area)、本地方法栈(native method stack)
29.工厂模式:将对象的创建和使用分开
30.redis和memcached区别
reids是单线程的 memached是多线程的
在redis中,并不是所有的数据都一直存储在内存中,这个和memcached相别一个最大的区别。redis只会缓存所有的key的信息,
如果redis发现内存的使用量超过了某一个阀值,Redis根据“swappability = age*log(size_in_memory)”计 算出哪些key对应的value需要swap到磁盘。
然后再将这些key对应的value持久化到磁盘中,同时在内存中清除。
1.redis不止支持简单的key/valuel类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
2.redis支持数据备份,即master-slave模式的数据备份。
3.redis支持数据持久化,可以将内存中的数据保存到磁盘中,重启的时候可以再次加载进行使用。
4.Memcached基本只支持简单的key-value存储,不支持枚举,不支持持久化和复制等功能
31.redis
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。
Redis 提供了两种持久化方式:
RDB(默认):
rdb是Redis DataBase缩写,功能核心函数rdbSave(生成RDB文件)和rdbLoad(从文件加载内存)两个函数
AOF :
Aof是Append-only file缩写,每当执行服务器(定时)任务或者函数时flushAppendOnlyFile 函数都会被调用, 这个函数执行以下两个工作
aof写入保存:
WRITE:根据条件,将 aof_buf 中的缓存写入到 AOF 文件
SAVE:根据条件,调用 fsync 或 fdatasync 函数,将 AOF 文件保存到磁盘中。
比较:
1、aof文件比rdb更新频率高,优先使用aof还原数据。
2、aof比rdb更安全也更大
3、rdb性能比aof好
4、如果两个都配了优先加载AOF
Redis分布式锁:先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。
set指令有非常复杂的参数,应该同时把setnx和expire合成一条指令来用的,避免执行expire之前进程意外crash或者要重启
Redis做异步队:一般使用list结构作为队列,rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会再重试。缺点是在消费者下线的情况下,生产的消息会丢失。
缓存穿透
一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就应该去后端系统查找(比如DB)。一些恶意的请求会故意查询不存在的key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。
如何避免?
1:对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对应的数据insert了之后清理缓存。
2:对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该bitmap过滤。
缓存雪崩
当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,会给后端系统带来很大压力。导致系统崩溃。
如何避免?
1:在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
2:做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期
3:不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。
32.成员量和局部变量的区别
局部变量:
局部变量声明在方法、构造方法或者语句块中;
局部变量在方法、构造方法、或者语句块被执行的时候创建,当它们执行完成后,变量将会被销毁;
访问修饰符不能用于局部变量;
局部变量只在声明它的方法、构造方法或者语句块中可见;
局部变量是在栈上分配的。
局部变量没有默认值,所以局部变量被声明后,必须经过初始化,才可以使用。
实例变量:
实例变量声明在一个类中,但在方法、构造方法和语句块之外;
当一个对象被实例化之后,每个实例变量的值就跟着确定;
实例变量在对象创建的时候创建,在对象被销毁的时候销毁;
实例变量的值应该至少被一个方法、构造方法或者语句块引用,使得外部能够通过这些方式获取实例变量信息;
实例变量可以声明在使用前或者使用后;
访问修饰符可以修饰实例变量;
实例变量对于类中的方法、构造方法或者语句块是可见的。一般情况下应该把实例变量设为私有。通过使用访问修饰符可以使实例变量对子类可见;
实例变量具有默认值。数值型变量的默认值是0,布尔型变量的默认值是false,引用类型变量的默认值是null。变量的值可以在声明时指定,也可以在构造方法中指定;
实例变量可以直接通过变量名访问。但在静态方法以及其他类中,就应该使用完全限定名:ObejectReference.VariableName。
区别:
1.成员变量定义在类中,局部变量定义在方法中
2.成员变量在当前类有效,局部变量在当前方法体中有效
3.成员变量存储在堆中,局部变量存在栈中
33.构造函数和一般函数的区别
构造函数和类名相同,在对象创建时就被调用,用于初始化,初始化只执行一次
一般函数,对象创建后需要调用才能执行,可以被调用多次
34.成员变量和静态变量的区别
1.成员变量属于对象,也成实例变量
2.静态变量属于类,也可以称类变量
3.成员变量存在堆中,静态变量存在方法区中
4.成员变量随着对象创建而存在,回收之后消失
5.静态变量类初始化而存在,随着类消失而消失
6.成员变量只能对象调用,静态变量可以被类或对象所调用
35.final特点: 可以修饰变量、方法、类
修饰的变量初是一个常量,只能赋值一次
修饰的方法不能被覆盖
修饰的类不能被继承
36.java异常处理
三种类型的异常:
检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
Java中的异常类都继承Throwable,Throwable对象可以分为两组。一组是unchecked异常,一组是checked异常
Exception 类是 Throwable 类的子类。除了Exception类外,Throwable还有一个子类Error 。
Java 程序通常不捕获错误。错误一般发生在严重故障时,它们在Java程序处理的范畴之外。
Error 用来指示运行时环境发生的错误,通常是指Java的内部错误以及资源耗尽错误,我们不能在编程层面上解决Error
例如,JVM 内存溢出。一般地,程序不会从错误中恢复。
37.多线程
可以并存于同一进程空间,在JVM的进程空间,一个stack代表了方法调用的次序。对于多线程来说,进程空间需要多个stack
用来记录不同线程的调用次序,多个stack互不影响,但所有的线程将共享堆(heap)中的对象
38.Mysql: Every derived table must have its own alias (每个派生出来的表都必须有一个自己的别名)
进行嵌套查询的时候的子查询的结果是作为一个派生类来进行上一级查询,应该在子查询的结果来加一个别名
update t_ticket_info set ticket_type = 1
WHERE ticket_no =
(select minno from (select min(ticket_no) as minno from t_ticket_info where ticket_type = 0) as a)
加入不在sql最后的那个子查询 as a ,就会 出现这个错误
39.JVM
栈(stack)是运行时的单位,堆是存储的单元
栈解决程序的运行问题,即程序如何执行,或如何处理数据(栈代表处理逻辑,栈中存储的都是基本数据类型或对象的引用)
堆解决的是数据存储问题,即数据怎么放,放在那(堆代表数据)
40.创建视图
create view user_view as select * from t_user_info
desc user_view
41.sql优化基本常识
在where查询,=左边进行函数、运算符或表达式运算
在where中避免出现!=和<>
在where中避免对字段进行null值判断
模糊查询尽量不要前置百分号
使用exists来代替in和not in
41.数据库事务的隔离级别和特性
MYSQL
① Serializable (串行化):可避免脏读、不可重复读、幻读的发生。
② Repeatable read (可重复读):可避免脏读、不可重复读的发生。
③ Read committed (读已提交):可避免脏读的发生。
④ Read uncommitted (读未提交):最低级别,任何情况都无法保证。
ORACLE
①③
特性:ACID 原子性 一致性 隔离性 持久性
42.springmvc原理
1、客户端发出一个http请求给web服务器,web服务器对http请求进行解析,如果匹配DispatcherServlet的请求映射路径(在web.xml中指定),web容器将请求转交给DispatcherServlet.
2、DipatcherServlet接收到这个请求之后将根据请求的信息(包括URL、Http方法、请求报文头和请求参数Cookie等)以及HandlerMapping的配置找到处理请求的处理器(Handler)。
3-4、DispatcherServlet根据HandlerMapping找到对应的Handler,将处理权交给Handler(Handler将具体的处理进行封装),再由具体的HandlerAdapter对Handler进行具体的调用。
5、Handler对数据处理完成以后将返回一个ModelAndView()对象给DispatcherServlet。
6、Handler返回的ModelAndView()只是一个逻辑视图并不是一个正式的视图,DispatcherSevlet通过ViewResolver将逻辑视图转化为真正的视图View。
7、Dispatcher通过model解析出ModelAndView()中的参数进行解析最终展现出完整的view并返回给客户端。
43.aop ioc
控制反转
控制权由对象转交给容器
容器根据配置文件来创建实例和各个实例之间的依赖关系
核心:BeanFactory,工厂创建的实例称作bean
面向切面编程
代理:动态代理和静态代理
静态代理:针对每个具体类来编写代理类
针对一个接口来编写一个代理类
44.mybatis
MyBatis应用程序根据XML配置文件创建SqlSessionFactory,
SqlSessionFactory在根据配置,配置来源于两个地方,一处是配置文件,一处是Java代码的注解,
获取一个SqlSession。SqlSession包含了执行sql所需要的所有方法,可以通过SqlSession实例直接运行映射的sql语句,
完成对数据的增删改查和事务提交等,用完之后关闭SqlSession。
45.String、StringBuffer 和 StringBuilder 类
String 类是不可改变的
StringBuffer 和 StringBuilder 类
和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。
StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。
由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。
String类为什么是final修饰的主要是为了“效率” 和 “安全性” 的缘故。若 String允许被继承, 由于它的高度被使用率, 可能会降低程序的性能,所以String被定义成final。
46.System.out.println(2/3); 0 System.out.println(3/2); 1
47.http get和post请求的区别 与head请求有什么区别
get提交:请求的通过地址栏传递参数,传参数的大小长度受浏览器限制,所传参数可见不安全
POST提交:不是通过url传递参数,是提交的是表单,把提交的数据放置在是HTTP包的包体中
48.httpsession什么时候被销毁
可以通过web.xml文件配置session的失效时间,单位为分钟
<seesion-config> <session-timeout>10</session-timeout></seesion-config>
可以通过session.invalidate()方法来销毁session对象。
49.MD5加密
任意长度的数据,算出的MD5值长度都是固定的。
目前没有软件能有效地破解 MD5。大多数时候只是把常见字符串的 MD5 存了起来为彩虹表,然后直接反查。
50.什么是sql注入
就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令
参数化查询
51.排序
String source[] = { "dad", "bood", "bada", "Admin", "Aa ", "A ", "Good", "aete", "cc", "Ko", "Beta", "Could" };
List<String> list = Arrays.asList(source);
Collections.sort(list, String.CASE_INSENSITIVE_ORDER);
System.out.println(list);
System.out.println("-------------------------------");
sort(source);
System.out.println(Arrays.toString(source));
52.关于高并发的秒杀问题
Redis 可以应对高并发场景,是因为它的读写请求均是单线程机制,不存在并发问题。而且 Redis 是基于内存的,读写速度也比 MySQL 快得多
53.hashMap的put、get的原理 (数组和链表的结合体,底层是一个数组结构,数组的每一项又是一个链表)
get:
先对key检查是否为null,为null放将到table数组的第一个位置
对key进行hashcode运算计算hash值
indexFor(hash,table.lenth)用来计算Entry对象在table数组中的精确位置,方法参数的hash就是根据key的hashcode方法计算出来的hash
获取table数组的索引,会得迭代链表,通过equals方法检查key是否有相等的
- HashMap有一个叫做Entry的内部类,它用来存储key-value对。
- 上面的Entry对象是存储在一个叫做table的Entry数组中。
- table的索引在逻辑上叫做“桶”(bucket),它存储了链表的第一个元素。
- key的hashcode()方法用来找到Entry对象所在的桶。
- 如果两个key有相同的hash值,他们会被放在table数组的同一个桶里面。
- key的equals()方法用来确保key的唯一性。
- value对象的equals()和hashcode()方法根本一点用也没有。
54.votile
1.防止重排序
2.实现可见性
可见性问题主要是一个线程修改了共享变量,而另一个线程却看不到。
可见性的问题的主要原因是每个线程都拥有自己的一个高速缓存区-----线程工作内存
votile 修饰i 多线程 每次i++ 100次循环 最后输出一定是小于等于100的
i++ 复合操作 包括三部
①读取i的值
②对i加1
③将i的值写回内存
volatile是无法保证这三个操作是具有原子性的,可以通过Automiclnteger或Synchronized来保证i++的
原子性
55.原子类
1)AutomicBoolean
2)AutomicInteger
3) AutomicLong
原子类自增1
public class Demo{
private static AtomicInteger count = new AtomicInteger(0);
public static void increment() {
count.getAndIncrement();
}
Synchronized 自增1
public class Demo(){
private static int i = 0;
public synchronized static int getInc(){
i++;
}
}
56.双亲委托模型
Java中ClassLoader的加载采用了双亲委托机制,采用双亲委托机制加载类的时候采用如下的几个步骤:
1. 当前ClassLoader首先从自己已经加载的类中查询是否此类已经加载,如果已经加载则直接返回原来已经加载的类。
每个类加载器都有自己的加载缓存,当一个类被加载了以后就会放入缓存,等下次加载的时候就可以直接返回了。
2. 当前classLoader的缓存中没有找到被加载的类的时候,委托父类加载器去加载,父类加载器采用同样的策略,首先查看自己的缓存,然后委托父类的父类去加载,一直到bootstrp ClassLoader.
3. 当所有的父类加载器都没有加载的时候,再由当前的类加载器加载,并将其放入它自己的缓存中,以便下次有加载请求的时候直接返回。
57.@Autowired (srping的)与@Resource(j2ee)
都可以用来装配bean. 都可以写在字段上,或写在setter方法上。
@autowired默认按照类型装配的,
默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:
@Autowired(required=false) ,如果我们想使用名称装配可以结合@Qualifier注解进行使用,如下:
Java代码
@Autowired() @Qualifier("dao")
private Dao dao;