Java 基础
JDK 和 JRE 有什么区别?
JDK是java的开发工具包,包含各种类库,并且包含了JRE,javac是在JDK中的;
JRE是java程序的运行环境,安装过程中自动添加PATH
== 和 equals 的区别是什么?
对于==,比较的是值是否相等,如果比较的是基本数据类型的变量,则直接比较其存储的值是否相等,
如果比较的是引用数据类型,则比较的是所指向的对象的地址值.
equals不能作用于基本数据类型,它比较的是是否是同一个对象
如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址值.
如String,Date等类对equals方法进行了重写,比较的则是所指向的对象的内容
两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?
首先,两个对象equals相等,hashcode一定相等;但是hashcode相等时,equals不一定相等.
其次,两个不同的对象,因为可能存在哈希碰撞,所以hashcode可能是相等的,但是显然equals不为true.
还有就是,在object类中,euqals方法还是用的==来判断的,==对于对象而言比较的是地址值,所以equals相等
hashcode一定一样,反之就不一定了.
final 在 java 中有什么作用?
final关键字可作用于类,类属性和方法;
作用于类上时,该类不能被继承
作用于属性时,该属性不能被重新复制
作用于方法时,该方法不能被重写
java 中的 Math.round(-1.5) 等于多少?
Math的round方法是四舍五入,如果参数是负数,则往大的数如,Math.round(-1.5)=-1
String 属于基础的数据类型吗?
不是,String是一个类,是引用数据类型.
java 中操作字符串都有哪些类?它们之间有什么区别?
有String,StringBuilder,StringBuffer
String是不可变的,每次对String的操作都会产生一个String对象
StringBuilder和StringBuffer是可变的,能够被多次修改,并不会产生新的对象.
StringBuilder是线程不安全的,StringBuffer是线程安全的.
StringBuilder的处理速度比StringBuffer要快
String str="i"与 String str=new String(“i”)一样吗?
他们的值相等,用equals得到true,但是他们是两个对象,如果用==判断返回false.
且str="i"是直接在常量池中引用字符串,而new String(“i”)是在堆中根据i再创建一个对象.
如何将字符串反转?
通过StringBuilder的reverse()方法可以直接反转
StringBuilder sb = new StringBuilder(“abc”);
sb.reverse().toString();
1
2
通过String的toCharArray方法可以获得字符串每一个字符并且转换为字符数组
然后循环从后往拼接即可
递归的方法反转(当只有一个字符时,返回原字符;当有两个以上的字符时,返回结果为第二个字符串开始的子串+第一个字符)
public String reverseString(String str) {
if ((null == str) || str.length()<2) {
return str;
}
return reverseString(str.subString(1)) +str.charAt(0);
}
1
2
3
4
5
6
String 类的常用方法都有那些?
charAt(int index)返回指定索引处的字符
length()返回字符串长度
split()根据给定的正则表达式拆分字符串
toString()返回此对象本身
抽象类必须要有抽象方法吗?
抽象类可以没有抽象方法,但是如果一个类已经声明为抽象类,那么它也不能再实例化,不能直接构造该类对象.
普通类和抽象类有哪些区别?
抽象类不能被实例化,普通类反之
抽象类的访问权限限于public和protected,如果为private的话,就不能被子类继承了.
如果一个类继承于抽象类,则它必须实现父类的抽象方法.如果不想实现,那么子类也必须是抽象类.
抽象类能使用 final 修饰吗?
不能,final修饰的类是不能被继承的,如果抽象类不能继承,就没有意义了.
接口和抽象类有什么区别?
抽象类可以有构造方法,接口不能有构造方法.
抽象类可以包含非抽象方法,接口则不能.
抽象类方法访问权限是public、protected,接口中只能是public.
只能单继承,但是可以多实现.
java 中 IO 流分为几种?
大的方面来说有两种:字节流和字符流
字节流继承于InputStream、OutputStream
字符流继承于Reader、Writer
BIO、NIO、AIO 有什么区别?
BIO表示同步阻塞式IO,交互方式是同步、阻塞方式,即客户端有连接请求时服务端就需要启动一个线程进行处理,
如果这个连接不做任何事情会造成不必要的开支.
NIO表示同步非阻塞IO,客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求
时才启动一个线程处理.
AIO表示异步非阻塞IO,客户端的I/O请求都是由操作系统先完成IO操作后再通知服务器应用来启动线程处理.
Files的常用方法都有哪些?
String getName():返回File对象所表示的文件名或文件路径
String getPath():返回File对象所对应的相对路径
boolean exists():判断File对象的文件或者目录是否存在
boolean isDirectory():判断File对象是否是目录
容器
java 容器都有哪些?
String,数组以及java.util下面的集合类
List:存放有序,列表存储,元素可重复
ArrayList LinkedList Vector
Set:无序,元素不可重复
HashSet TreeSet
Map:无序,元素可重复
HashMap TreeMap LinkedHashMap HashTable
Collection 和 Collections 有什么区别?
Collection是集合类的一个顶级接口,它提供了对集合对象进行基本操作的通用接口方法.
Collections是集合类的一个工具类,它提供了一系列的静态方法,用于对集合中元素进行排序,搜索以及线程同步等操作.
List、Set、Map 之间的区别是什么?
List: 可以允许重复的对象;
可以插入多个null元素;
有序,输入顺序就是输出顺序;
Set: 不允许重复对象;
无序,且只允许一个null对象;
Map: 存储键值对,只能有唯一的key,value可以重复
只能有一个null键
HashMap 和 Hashtable 有什么区别?
一. HashMap可以接受null键和值,HashTable不行
二. HashTable是线程安全的,通过synchronized来保证,而HashMap线程不安全
三. HashMap的迭代器是fail-fast迭代器,而HashTable的enumerator迭代器不是fail-fast.
如何决定使用 HashMap 还是 TreeMap?
HashMap基于散列表实现,适用于查询频繁的情况
TreeMap基于红黑树实现,适用于创建比较多的情况.且TreeMap存储数据是按照字母表的顺序存储的,
如果对顺序有要求也可以选用TreeMap.
说一下 HashMap 的实现原理?
数组+链表,初始16,75扩容,数据存在内部类Map.Entry中,其中包含key value hashcode和next.
说一下 HashSet 的实现原理?
HashSet基于HashMap实现,默认构造函数是构造一个初始容量为16的HashMap,所有放入HashSet
集合的元素实际上由HashMap的key来保存,而value则保存了一个PRESENT的静态Object对象,因为元素都保存在key
中,所以才能不重复.
ArrayList 和 LinkedList 的区别是什么?
ArrayList底层基于动态数组,LinkedList基于链表实现,底层是循环双向链表
对于随机访问get和set,ArrayList优于LinkedList.
对于新增add和删除remove,LinkedList比较快
如何实现数组和 List 之间的转换?
List转数组:toArray()方法.在方法参数中指定原集合的长度的数组即可.
数组转List:Arrays的asList()方法.
ArrayList 和 Vector 的区别是什么?
Vector的方法都是同步的,是线程安全的,ArrayList则不是.
在进行扩容的时候,Vector扩容至原来的一倍,ArrayList增加至原来的0.5倍.
Array 和 ArrayList 有何区别?
Array(数组)可以包含基本数据类型和对象类型,ArrayList只能包含对象类型.
ArrayList可以自动扩容,Array则不行.
在 Queue 中 poll()和 remove()有什么区别?
Queue中,add方法和offer方法都可以添加元素,而remove和poll都是删除队列的头元素,区别在于:
add方法在队列满的情况下抛异常,而offer方法则返回false.
remove方法在队列为空时抛异常,poll方法将返回null.
哪些集合类是线程安全的?
Vector HashTable ConcurrentHashMap
Stack
迭代器 Iterator 是什么?
Iterator是个接口,它提供了很多对元素进行迭代的方法.迭代器可以在迭代过程中删除
底层集合的元素,可以直接调用Iterator的remove()方法来删除.
因为在Conllection接口中定义了获取集合迭代器的方法,所以每一个集合都包括了可以返回迭代器实例的方法.
Iterator 怎么使用?有什么特点?
每个集合都可以用iterator()方法一个Iterator实例.
使用next()方法获取序列中的下一个元素,使用hasNext()方法检查序列中是否有元素
使用remove()方法将迭代器新返回的方法删除.
特点:Iterator将集合的遍历和其底层的结构分离.
Iterator 和 ListIterator 有什么区别?
ListIterator是Iterator的子接口,用于扩展Iterator.
在Iterator中,我们只能向前移动,无法操纵或者修改集合中的元素.ListIterator弥补了这种缺点
区别: 1.范围不同,Iterator适用于所有集合,而ListIterator只适用于List及其子类
2.ListIterator有add方法可以添加元素,Iterator则不行.
3.ListIterator可以实现双向遍历,Iterator则不行.
4.ListIterator可以实现对象的修改,Iterator不行
5.ListIterator可以获取集合中的所有,Iterator不行.
怎么确保一个集合不能被修改?
可以使用Collections或者Guava来快速实现.如Collections.unmodifiableMap(xxxMap);
多线程
并行和并发有什么区别?
并行是多个事件同时进行,并发是多个事件在某一时间段内间隔发生.
你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。
你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。
线程和进程的区别?
进程是操作系统资源分配的基本单位,线程是任务调度和执行的基本单位.
进程有独立的地址空间,一个进程崩溃后在保护模式下不会对其他进程产生影响,而线程只是一个进程中的
不同执行路径,线程有自己的堆栈和局部变量.在操作系统中能同时运行多个进程,而在同一个进程内有多个
线程同时执行.
守护线程是什么?
守护线程是服务其他线程的,在java中,线程有两种:守护线程和用户线程.
java中的jvm垃圾回收线程就是一个典型的守护线程.当用户线程全部执行完,包括main线程也执行完毕,那么
jvm会自动退出,此时守护线程也就停止了.
创建线程有哪几种方式?
三种: 1. 继承Thread类,重写run方法,用子类实例调用start()方法;
2. 实现Runnable接口并重写run方法,创建Thread实例并传入Runnable实例,代用Thread的start()方法
3. 创建Callable接口的实现类,重写call方法;
构造此实现类的实例,将其作为参数构造一个FutureTask类的实例;
以FutureTask的实例为参数构造一个Thread对象执行start()方法.
第三种方式可以允许有返回值,也可以声明抛出异常类.
说一下 runnable 和 callable 有什么区别?
runnable方式时,多个线程间可以共享实例变量,callable方式则不行
runnable方式没有返回值,callable有返回值
runnable方式run方法的异常只能在内部消化,callable的call()方法允许抛出异常
线程有哪些状态?
NEW 新建状态,此时线程还没有运行线程中的代码
RUNNABLE 就绪状态;处于就绪状态的线程并不一定立即运行run方法,必须还要和其他线程竞争CPU时间
RUNNING 运行状态;线程获得CPU时间后才进入运行状态,开始执行run方法
BLOCKED 阻塞状态;线程运行过程中会有各种原因来进入阻塞状态,如:调用sleep方法进入休眠;
在IO操作中被阻塞;试图得到一个锁,该锁正被其他线程持有;等待某个触发条件.
阻塞状态的线程此时没有结束,暂时让出CPU时间给其他线程.
DEAD 死亡状态;有两个原因导致线程死亡:第一是run方法正常退出自然死亡;第二是一个未捕获的
异常终止了run方法使线程死亡.
为了确定线程在当前是否存活着(就是要么是可运行的,要么是被阻塞了),需要使用isAlive方法,如果是可运行或被阻塞,这个方法返回true;如果线程仍旧是new状态且不是可运行的,或者线程死亡了,则返回false。
sleep() 和 wait() 有什么区别?
sleep方法使Thread类的,而wait方法使Object类中的
sleep方法使线程暂停指定的时间,让出CPU给其他线程,但是他的监控状态依然保持着,时间到了以后会自动恢复运行状态
在这个过程中,线程不会释放同步对象锁.
而调用wait方法,线程会放弃对象锁,进入等待队列,待调用notify/notifyAll方法后才会进入锁池,获取对象锁后才进入运行状态.
notify()和 notifyAll()有什么区别?
notify()方法随机唤醒一个wait线程到锁池中去竞争锁,而notifyAll方法唤醒所有wait线程到锁池.
notity()方法可能产生死锁,notifyAll则不会.
线程的 run()和 start()有什么区别?
run()方法只是定义了线程的执行单元并非直接开启了线程资源,只有start()方法被调用,才可以启动一个线程.
如果直接调用run方法,会被当成普通方法在main线程执行,并不会创建线程.
44.创建线程池有哪几种方式?
java中的Executors可以为我们创建现成的线程池,有以下几种:
newSingleThreadExecutor 创建一个单线程的线程池,它只有一个工作线程,操作无界工作队列,可以保证任务顺序
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待
newCachedThreadPool 创建一个可缓存线程池,有空闲线程时会回收,但是任务过多,会一直创建,消耗资源
newScheduledThreadPool 创建一个大小无线的线程池,此线程池支持定时以及周期性任务的需求.
45.线程池都有哪些状态?
RUNNING:一旦被创建,就处于此状态,可以接受新任务以及对已经添加的任务进行处理.
SHUTDOWN:此时不接收新任务,但是可以处理已添加的任务
STOP:此状态不接收新任务,不处理已添加任务,并且会中断正在处理的任务.
TIDYING:当所有的任务已终止,ctl记录的任务数变为0,线程池会变成tidying状态.当线程池变为TIDYING状态会执行terminated()方法.
当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN -> TIDYING。
当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP -> TIDYING。
TERMINATED:线程池彻底终止会变成这个状态.当在TIDYING状态,执行完terminated()函数后,就会由TIDYING状态变为TERMINATED状态.
线程池中 submit()和 execute()方法有什么区别?
接受参数不一样,execute()方法接收Runnable类型的参数;submit()可以接收runnable和callable类型的参数
submit方法有返回值,返回一个Future类型的对象,execute方法没有返回值.
submit方法方便处理Exception异常.
在 java 程序中怎么保证多线程的运行安全?
最简单的方式是加入synchronized关键字,在共享数据语句中加入该关键字可以在某一时段指挥让一个线程执行,其他线程不能执行.
使用锁Lock
redis?
多线程锁的升级原理是什么?
在java中,锁有三种状态,级别从低到高依次为:偏向锁、轻量级锁、重量级锁,这几个状态会随着竞争情况逐渐升级,但是不能降级.
先说为什么要有锁升级:因为synchronized是重量级锁,每次在进行锁请求时,如果当前资源被其他线程占有,就要将当前线程阻塞,加入到阻塞队列中然后
清空当前线程的缓存,等到锁释放时再通过notify或者notifyAll方法唤醒当前线程,让其处于就绪状态.在这个过程中是非常消耗资源的,而且有时候线程刚挂起,锁就释放了.
而java的线程是映射到操作系统的原生线程之上的,每次线程的阻塞和唤醒都要在用户态和核心态之间转换,十分浪费资源.所以jvm对syncronized进行了优化,分为三种锁.
当锁对象第一次被线程获取的时候,虚拟机会将对象头中的锁标志位设置成01,并将偏向锁标志设置为1,线程通过CAS的方式将自己的ID值放到对象头中.这样每次该线程每次
再进入锁对象的时候不用任何的同步操作,直接比较当前锁对象头中是不是该线程的ID,如果是就可以直接进入.当有其他线程来尝试获取锁的时候,发现偏向锁标示是1,说明
锁已经被占用,则会使用CAS将对象头的偏向锁指向当前线程.
需要注意的是,偏向锁使用一种等待竞争出现才会释放锁的机制,当有其他线程尝试获取锁的时候,才会释放锁.首先它会暂停拥有偏向锁的线程,然后检查持有偏向锁的线程
是否活着,如果不处于活动状态,则将对象头设置为无锁状态;如果活着,那么拥有偏向锁的栈会被执行,遍历偏向对象的锁记录,使之要么恢复到无锁要么标记对象不适合作为
偏向锁.最后唤醒暂停的线程.
假设线程1持有偏向锁,线程2来竞争偏向锁:
一. 首先线程2会检查偏向锁标记,如果是1,说明是偏向锁,那么JVM会找到线程1看其是否还活着.
二. 如果线程1已经执行完毕,那么先将偏向锁置为0,对象头设置为无锁的状态,用CAS的方式尝试将线程2的ID放入对象头,此时锁不升级,还是偏向锁.
三. 如果线程1还活着,先暂停线程1,将锁标志位变为00(轻量级锁),然后在线程1的栈帧中开辟出一块空间将对象头的Mark word置换到线程1的栈帧中,而对象头
中存储的是指向当前线程栈帧的指针.此时变为轻量级锁,线程1继续执行,线程2采用CAS的方式尝试获取锁.
轻量级锁是通过CAS的方式尝试获取锁对象,一旦失败会先检查对象头中存储的是否是指向当前线程栈帧的指针,如果是,就可以获取锁对象,如果不是说明存在竞争那么久
膨胀成为重量级锁.
一旦有两个以上的线程竞争锁,轻量级锁就会膨胀为重量级锁,锁的状态变为10,此时对象头中存储的就是指向重量级锁的栈帧的指针,而且其他等待所的线程要进入阻塞状态,
等待重量级锁释放后被唤醒然后去竞争.重量级锁是由操作系统来负责线程的调度,会消耗大量的系统资源.
什么是死锁?
死锁是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种相互等待的过程,如果没有外力作用,他们讲无法推进下去.
怎么防止死锁?
以确定的顺序获取锁
超时放弃.(Lock锁中就使用了这种方式)
银行家算法
ThreadLocal 是什么?有哪些使用场景?
也成为线程本地变量,ThreadLocal在每个线程中对一个变量创建了一个副本,且在线程内部任何地方都可以使用,线程间互不影响.
应用场景:spring的声明式事物管理.
说一下 synchronized 底层实现原理?
首先,每个对象都有一个监视器锁(monitor),当monitor被占用时就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor的所有权,过程如下:
如果monitor的进入数为0,则线程进入monitor,将进入数设置为1,该线程为monitor的所有者
如果线程已经占有monitor,只是重新进入,则进入数+1
如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获得所有权
执行monitorexit的线程必须是objectref所对应的monitor的所有者.指令执行时,monitor的进入数-1,如果减为0,那么线程退出monitor,不再是持有者.
在将synchronized代码块反编译以后,我们可以发现调用了monitorenter和monitorexit指令.
所以如果synchronized同步代码块,底层是调用monitor的两个指令来实现锁
如果synchronized同步方法,底层是读取运行时常量池的ACC_SYNCHRONIZED标志来实现的.
synchronized 和 volatile 的区别是什么?
volatile修饰的变量,jvm每次都从主内run读取,不会从工作内存读取
而synchronized是锁住当前变量,同一时刻只有一个线程能访问当前变量.
volatile只是作用于变量,synchronized可以用在变量,方法中
valatile仅能实现变量修改的可见性,无法保证原子性.
synchronized可以实现变量修改的可见性和原子性.
synchronized 和 Lock 有什么区别?
synchronized是java内置的关键字,Lock是个接口
synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁.
synchronized会自动释放锁,Lock需要手动释放
synchronized可重入(同一个类中两个同步方法,获取到锁后不用每次都去获取),不可中断,非公平;Lock可判断可公平.
synchronized获得锁的线程阻塞,其他线程都会无线等待,Lock不会
synchronized 和 ReentrantLock 区别是什么?
synchronized遇到异常不catch,锁会自动释放,ReentrantLock需要手动释放
synchronized是非公平锁,ReentrantLock可以实现公平锁.
前者无法获取锁的状态,后者可以tryLock()方法可以返回是否获得了锁.
说一下 atomic 的原理?
atomic包用中的类可以实现多线程环境下的变量操作,底层是调用CPU的CAS指令来进实现线程安全的.
CAS,比较并操作,每次在set前,对比一下当前值和预期值是否一样,一样则set,否则认为失败,循环对比直到成功.
反射
什么是反射?
在运行过程中,对任何一个类,都能知道这个类的所有属性和方法,对于任意一个对象,都能改变其属性.
什么是 java 序列化?什么情况下需要序列化?
序列化就是一种用来处理对象流的机制,简单来说,就是把对象存储在某一个地方,硬盘或者网络,即把对象的内容转变为字节序列.
当想把内存中的对象状态保存在一个文件或者数据库,或者在网络上传输的时候,就需要序列化,在java中需要实现Serializable接口.
动态代理是什么?有哪些应用?
动态代理是将对象中不同方法的调用重新定向到一个统一处理函数,做自定义的逻辑处理,但是调用者察觉不到.
应用: Spring的AOP,事物,权限,日志.RPC框架
怎么实现动态代理?
利用JDK的反射机制实现
使用CGLIB代理.
对象拷贝
为什么要使用克隆?
想要对一个对象进行处理,但是又想保留原有的数据,这时可以使用克隆.
如何实现对象克隆?
实现Cloneable接口并重写Object的clone()方法
实现Serializable接口,通过对象的序列化和反序列化实现深度克隆
深拷贝和浅拷贝区别是什么?
是否支持引用数据类型的成员变量的复制.
Java Web
jsp 和 servlet 有什么区别?
jsp擅长表现页面显示,servlet擅长逻辑控制
servlet没有内置对象,jsp有内置对象
servlet的应用逻辑在.java文件中,而jsp中,java和html组合为一个.jsp文件.
servlet在java代码中嵌入html代码,jsp是在html中嵌入java代码
jsp 有哪些内置对象?作用分别是什么?
jsp有9个内置对象:
request 用户端请求,此请求会包含来自GET/POST请求的参数
response 网页传回用户端的回应
pageContext 网页的属性是在这里管理
session 与请求有关的会话期
application servlet正在执行的内容
out 用来传送回应的输出
config servlet的构架部件
page JSP网页本身
exception 针对错误网页,未捕捉的例外
说一下 jsp 的 4 种作用域?
application:它的有效范围是整个应用。整个应用是指从应用启动.pplication里的变量可以被所有用户共用。如果用户甲的操作修改了application中的变量,用户乙访 问时得到的是修改后的值。
session:如果把变量放到session里,就说明它的作用域是session,它的有效范围是当前会话。所谓当前会话,就是指从用户打开浏览器开始,到用户关闭浏览器这中间 的过程。这个过程可能包含多个请求响应。也就是说,只要用户不关浏览器,服务器就有办法知道这些请求是一个人发起的,整个过程被称为一个会话(session)
request:就说明它的作用域是request,它的有效范围是当前请求周期。所谓请求周期,就是指从http请求发起,到服务器处理结束,返回响应的整个过程。在这个过 程中可能使用forward的方式跳转了多个jsp页面,在这些页面里你都可以使用这个变量。
page:代表变量只能在当前页面有效
session 和 cookie 有什么区别?
数据存放位置不同.session在服务器,cookie在客户端浏览器
安全程度不同,别人可以分析存放在本地的cookie进行cookie欺骗.
单个cookie保存的数据不能超过4k,而session是在服务器的,所以没有限制
cookie只能存储string类型的数据,session可以存储对象.
说一下 session 的工作原理?
当用户第一次访问一个服务器,服务器就会为该用户创建一个session,并生成一个和该session有关的session_id,
这个id是唯一的,不可重复.这个id将会在本次响应中返回,保存在客户端的cookie中,下次方法的时候,客户端浏览器
的cookie中含有session_id,服务器基于这个id就可以识别该用户.
如果客户端禁止 cookie 能实现 session 还能用吗?
可以,当cookie被禁用,我们可以使用"URL重写"来使session生效,简单来说就是将sessionid的信息作为请求地址的一部分
这样服务器就可以解析URL,得到该sessionid,进而识别用户.
spring mvc 和 struts 的区别是什么?
mvc的入口是一个servlet,struts2的入口是一个filter
mvc是单例的,struts2是多例的
mvc面向方法开发,struts2面向类开发.
struts2采用值栈存储请求和响应数据,mvc通过参数解析器将request请求解析.
如何避免 sql 注入?
采用预编译语句
使用正则过滤传入的参数.
屏蔽不安全的字符
什么是 XSS 攻击,如何避免?
XSS攻击,即跨站脚本攻击.是指攻击者在用户端注入恶意的可运行脚本,让其在用户浏览网页时运行,从而通过脚本来获得用户的信息.
避免: 对用户输入和URL参数进行过滤,过滤掉脚本相关的内容
对输出进行编码
什么是 CSRF 攻击,如何避免?
CSRF攻击也叫跨站请求伪造,攻击者通过伪造用户的浏览器请求,向用户自己曾经认证过的网站发送,使目标网站误以为
是用户的真实操作而去执行命令.
避免:1.令牌机制 2.token验证
异常
throw 和 throws 的区别?
throws:用来声明一个方法可能抛出的所有异常信息,不会处理异常,只是将异常向上传,交给调用者
throw:抛出一个具体的异常类型.
throws出现在方法声头,而throw出现在函数体
throws表示出现异常的可能,并不一定会发生,throw则是抛出了一个存在的异常实例.
final、finally、finalize 有什么区别?
final: 修饰类,表示该类不可继承
修饰方法,表示该方法不可重写
修饰变量,表示该变量不允许被修改
finally:是保证代码一定要被执行的一种机制.常用来关闭连接资源或者解锁等.
finalize:是Object的一个方法,它的目的是保证对象在被垃圾收集前完成特定资源的回收.1.9后已经过时.
try-catch-finally 中哪个部分可以省略?
catch可以省略
不管有没有捕获到异常,finally中的代码都会被执行;
finally是在return之后执行的,程序在执行完return之后,会将值保存起来,当执行完finally中的代码之后再将return值返回
如果finally中存在return,会导致最后返回的是finally中的值.
try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?
会执行,return的值会暂时保存.等到运行完finally中的代码块时才会返回return的值
常见的异常类有哪些?
空指针异常类型:NullPointerException
类型强制转换类型:ClassCastException
数组下标越界异常:ArrayIndexOutOfBoundsException
输入输出异常:IOException
网络
http 响应码 301 和 302 代表的是什么?有什么区别?
301和302都是HTTP请求的状态码,其中301代表永久性转移,302代表暂时性转移.
301代表转向前的网址不在了,就会把新的网址当做有效目标
302只是代表临时性重定向,旧的网址会保留.
forward 和 redirect 的区别?
forward:直接转发,客户端浏览器只发出一次请求,由第二个信息资源响应该请求,共享同一个request对象
redirect:间接转发,服务端响应第一次请求的时候,让浏览器去访问另外一个URL,从而达到转发的目的.本质上是两次HTTP请求.
forward地址栏不变,redirect地址栏改变
简述 tcp 和 udp的区别?
tcp基于连接,udp基于无连接
tcp对系统资源要求高,udp少
tcp基于字节流,udp基于数据报文
tcp复杂,udp简单
tcp 为什么要三次握手,两次不行吗?为什么?
为了实现可靠数据传输,TCP 协议的通信双方,都必须维护一个序列号以标识发送出去的数据包中哪些是已经被对方收到的。
三次握手的过程即是通信双方相互告知序列号起始值,并确认对方已经收到了序列号起始值的必经步骤
如果只是两次握手,至多只有连接发起方的起始序列号能被确认,另一方选择的序列号则得不到确认
说一下 tcp 粘包是怎么产生的?
TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。
产生原因:
发送方原因:TCP默认会使用Nagle算法。而Nagle算法主要做两件事:1)只有上一个分组得到确认,才会发送下一个分组;2)收集多个小分组,
在一个确认到来时一起发送。
接收方原因:TCP接收到分组时,并不会立刻送至应用层处理,或者说,应用层并不一定会立即处理;实际上,TCP将收到的分组保存至接收缓存里,
然后应用程序主动从缓存里读收到的分组。这样一来,如果TCP接收分组的速度大于应用程序读分组的速度,多个包就会被存至缓存,
应用程序读时,就会读到多个首尾相接粘到一起的包
OSI 的七层模型都有哪些?
1:物理层 2:数据链层 3:网络层 4:传输层 5:会话层 6:表示层 7:应用层
get 和 post 请求有哪些区别?
1.get产生一个TCP数据包,POST产生两个
2.get将数据放在url中可以看到,post会放在html header中提交
3.get数据大小有限制,最大1024字节,post没有限制
如何实现跨域?
1.JSONP技术
2.CORS规范
3.通过服务端实现
4.websocket
说一下 JSONP 实现原理?
JSONP原理是动态添加一个
设计模式
说一下你熟悉的设计模式?
单例模式,装饰者模式,代理模式,适配器模式,策略模式
简单工厂和抽象工厂有什么区别?
简单工厂只能生产同一等级结构中的任一产品
抽象工厂用来生产不同产品族中的全部产品
Spring/Spring MVC
为什么要使用 spring?
方便解耦,可以将对象间的依赖关系交给spring
spring支持aop编程,可以很方便的对程序进行监控,拦截
方便测试,支持junit
集成其他框架比较方便
声明式事务
解释一下什么是 aop?
aop即面向切面编程,在原有功能的基础上通过aop添加新的功能,而原有的功能并不知道新添加的功能.
简单来说,就是在某个类或者方法执行前后打个标记,声明在执行到这里之前要先执行什么,之后执行什么,插入了新的执行方法.
解释一下什么是 ioc?
ioc控制反转.即把创建对象和维护对象之间关系的权利交给spring容器去做,程序自己不再维护.
传统:自己使用new 或者getInstance直接或者间接创建一个对象(高耦合,不易测试)
spring:容器使用工厂模式为了创建了所需要的对象,我们不用自己创建,直接调用即可.
spring 有哪些主要模块?
spring core: core是spring的核心类库,它的所有功能都依赖于该类库,主要实现IOC功能.
AOP: spring aop提供了常用的拦截器供用户配置.
ORM: 该模块提供对常用的ORM框架的管理和辅助支持.spring自己不实现ORM,只是对常见的ORM进行封装管理
DAO: spring提供对jdbc的支持,统一管理jdbc事物,并不对其进行实现
WEB: 提供对常用框架,如struts2的支持,将spring的资源注入给这些框架,也能在这些框架的前后插入拦截器
Context: 提供框架式的bean访问方式,其他程序可以通过Context访问spring的bean资源
MVC: 提供一套轻量级的MVC实现,简单方便.
spring 常用的注入方式有哪些?
构造器注入:可以在xml中通过constructor-arg标签来注入一个对象到构造器中
setter方法注入: 首先要配置被注入的bean,在该bean对应的类中,应该有要注入的对象属性或者基本数据类型的属性。
例如:为UserBiz类注入UserDAO,同时为UserBiz注入基本数据类型String,那么这时,
就要为UserDAO对象和String类型设置setter方法.,用于进行依赖注入。
注解注入:基于注解在xml文件中开启注解扫描以后,就可以在filed上使用注解@Autowired或者@Rsource来注入对象.
spring 中的 bean 是线程安全的吗?
不是的,spring并没有对单例bean做多线程的封装.
spring 支持几种 bean 的作用域?
1.singleton: 单例,默认作用域,在spring容器中此种类型的bean只有一个
2.prototype: 原型,每次调用getBean方法就会产生一个新的实例.
3.request: 每次HTTP请求都会产生不同的bean实例.
4.session: 每次会话产生一个实例
5.global-session: 所有会话共享一个实例
spring 自动装配 bean 有哪些方式?
1.xml配置方式
2.注解扫描方式
spring 事务实现方式有哪些?
1.编程式事务 允许用户在代码中精确定义事务的边界
2.声明式事务 基于AOP,将操作和事务管理分离.
说一下 spring 的事务隔离?
隔离级别定义了一个事务可能受其他并发事务影响的程度。
spring设置了五种事务个例级别:
1.ISOLATION_DEFAULT: 使用数据库默认的隔离级别
2.ISOLATION_READ_UNCOMMITTED: 最低的隔离级别,允许读未提交的数据变更,可能会导致脏读,幻读或不可重复读.
3.ISOLATION_READ_COMMITTED: 允许读取已经提交的数据,可以阻止脏读,但是幻读和不可重复读有可能发生.
4.ISOLATION_REPEATABLE_READ: 保证了一个事务不能读取另一个未提交的数据.可以避免不可重复读和脏读
5.ISOLATION_SERIALIZABLE: 串行化,事务被处理为顺序执行,通过锁定事务相关的数据库来实现.
说一下 spring mvc 运行流程?
1.用户向服务器发送请求,被springMVC的前端控制器拦截(DispatcherServlet)
2.前端控制器对请求的URL进行解析,得到标识符URI,根据URI调用处理器映射器
3.处理器映射器与该Handler有关的对象和拦截器信息返回给DispatcherServlet
4.前端控制器根据获得的处理器信息,调用对应的处理器适配器HandlerAdapter处理数据
5.处理器适配器提取request中的模型数据,开始执行Handler,在此之前还可以做数据合适的转换和数据验证等.
处理完成后向DispatcherServlet返回一个ModelAndView对象
6.前端控制器根据ModelAndView选择合适的视图解析器ViewResolver处理数据
7.视图解析器根据model和view渲染视图,将结果返回给客户端
spring mvc 有哪些组件?
DispatcherServlet 前端控制器
HandlerMapping 请求派发,建立请求和处理器的映射
Controller 处理器
ModelAndView 封装模型和试图信息
ViewResolver 视图处理器,定位页面
@RequestMapping 的作用是什么?
映射请求,指定哪些URL可以被该处理器处理.
@Autowired 的作用是什么?
根绝类型从容器中取出对象进行注入
Spring Boot/Spring Cloud
什么是 spring boot?
可以认为是一个服务于框架的框架,简化了配置文件.整合了所有的框架
为什么要用 spring boot?
开发速度快
测试简单
配置简单
部署简单
可以基于springboot来构建springcloud生态
spring boot 核心配置文件是什么?
application和bootstrap,application配置文件主要用于SpringBoot项目的自动化配置.
bootstrap配置文件在使用spring cloud配置时使用
spring boot 配置文件有哪几种类型?它们有什么区别?
两种:properties和yml.区别是格式不同
spring boot 有哪些方式可以实现热部署?
两种方式:1: Spring Loaded
2: Spring-boot-devtools
jpa 和 hibernate 有什么区别?
jpa是一种规范,提供了一些列操作数据库的接口,本事不能直接使用
hibernate是jpa的一种实现,是可以直接使用操作数据库的ORM框架
什么是 spring cloud?
springcloud是一个微服务框架,提供全套的分布式系统解决方案,它为微服务架构开发提供配置管理、服务治理、熔断机制、智能路由
控制总线等一系列的管理操作.
spring cloud 断路器的作用是什么?
在微服务架构中,存在很多的微服务,彼此之间存在依赖关系,当某个单元出现故障时,就会因为依赖关系导致整个系统的瘫痪.
断路器的作用是当某个微服务发生故障时,通过断路器的故障监控,向调用方返回一个错误响应,使之不至于长时间等待,避免了故障在分布式系统中的蔓延
spring cloud 的核心组件有哪些?
服务发现: Netflix Eureka
客户端负载均衡: Netflix Ribbon
断路器: Netflix Hystrix
服务网关: Netflix Zuul
分布式配置: Spring cloud Config
Hibernate
为什么要使用 hibernate?
1.对JDBC访问数据库的代码做了大量的封装,简化开发
2.性能好,支持各种关系数据库.
什么是 ORM 框架?
ORM的意思是对象关系映射,它的作用是在关系型数据库和业务实体对象之间做映射
这样我们在操作具体业务对象的时候,就不需要去和具体的SQL语句打交道,只需要操作对象的属性和方法.
hibernate 中如何在控制台查看打印的 sql 语句?
在hibernate配置文件中配置hibernate.show_sql属性
hibernate 有几种查询方式?
三种:HQL查询 QBC查询(也叫Criteria查询) 本地SQL查询
hibernate 实体类可以被定义为 final 吗?
不能,因为hibernate使用代理方式在延迟加载的情况下提高性能,如果定义为final
就不能继承,也就无法实现代理.
在 hibernate 中使用 Integer 和 int 做映射有什么区别?
1.如果数据库返回字段值是null的话,int类型会报错,Integer则不会
hibernate 是如何工作的?
通过Configuration config = new Configuration().configure();解析配置文件
由hibernate.cfg.xml中的读取并解析映射信息
通过SessionFactory sf = config.buildSessionFactory();//创建SessionFactory
Session session = sf.openSession();//打开Sesssion
Transaction tx = session.beginTransaction();//创建并启动事务Transation
persistent operate操作数据,持久化操作
tx.commit();//提交事务
关闭session和sessionFactory
get()和 load()的区别?
get方式会直接触发sql语句查出对象,load方式会使用延迟加载的机制加载这个对象,此时是个代理对象
只保存实体对象的id值,只有用到其他属性的时候才会调用sql查出来.
如果对象不存在,get方式会抛出空指针异常,load方式会抛出ObjectNotFoundException
说一下 hibernate 的缓存机制?
hibernate为了降低对数据库访问的频率,加入了缓存机制.缓存内的数据是对物理数据库数据的复制,
应用程序在运行时,从缓存中读写数据.
Hibernate的缓存包括两大类:session一级缓存和sessionFactory二级缓存.一级缓存不可卸载.
当根据ID查询数据的时候,首先从session缓存中查,查不到,如果设置了二级缓存,那么从二级缓存中查,
如果都查不到,再查数据库.将查到的数据按照ID放入缓存中,在删除,更新,增加数据的时候更新缓存.
hibernate 对象有哪些状态?
Hibernate对象有三种状态
Transient 瞬时态, 此时对象刚new出来,还没有save()
Persistent 持久态, 调用了save方法或者游离态的对象调用了update方法后会变成持久态
如果对象是持久化对象时,那么对该对象的任何修改,都会在提交事务时才会与之进行比较
当调用了session.clear()方法,以后 对象就会变成游离态
在 hibernate 中 getCurrentSession 和 openSession 的区别是什么?
采用getCurrentSession()获得的session会绑定到当前线程,而openSession则不会
getCurrentSession()获得的session在commit或者rollback后会自动关闭,而openSession必须手动关闭
hibernate 实体类必须要有无参构造函数吗?为什么?
必须要有,以为hibernate是通过反射的方式来获得对象实例的,此时会调用默认的无参构造.
Mybatis
mybatis 中 #{}和 ${}的区别是什么?
前者会将传入的数据当成字符串,在之前加入双引号,后者是直接将数据显示在sql中
前者会当做占位符,防sql注入,后者不能
mybatis 有几种分页方式?
两种,一种是内存分页,一种是物理分页
内存分页: 一次性查询出所有满足条件的数据,临时保存在集合中,通过List的subList的方式获取分页数据.
物理分页: 借助sql进行分页或者利用拦截器分页
RowBounds 是一次性查询全部结果吗?为什么?
不是,因为mybatis是对JDBC的封装,在JDBC的驱动中有一个Fetch Size的配置,它规定了每次最多从数据库查询多少条数据.这样做可以防止内存溢出.
mybatis 逻辑分页和物理分页的区别是什么?
逻辑分页一次性查询很多数据,然后再结果中检索分页的数据,消耗内存.
物理分页是从数据库查询指定条数的数据.
mybatis 是否支持延迟加载?延迟加载的原理是什么?
支持,在配置文件的标签中设置就可以激活
原理: 在调用的时候出发加载,而不是在初始化的时候加载信息.如a.getB().getName(),如果a.getB()的值为null,会触发保存好的关联B对象的sql语句查询出B,然后再调用getName().
说一下 mybatis 的一级缓存和二级缓存?
一级缓存是SqlSession级别的,在一个sqlsession中,第一次查询缓存中是否有数据,没有就会查询数据库,并将数据保存在一级缓存中.第二次去查的时候会直接从缓存中查询.如果这中间sqlsession进行了commit操作则会清空缓存.
二级缓存是Mapper级别的,多个sqlsession共享,默认关闭.它基于Mapper文件的namespace,如果两个mapper的namespace相同,那么会共享缓存的数据.使用二级缓存要在配置文件中开启,并且序列化po类.
mybatis 和 hibernate 的区别有哪些?
mybatis灵活,可以写sql,hibernate学习困难
mybatis 有哪些执行器(Executor)?
SimpleExecutor:每执行一次 update 或 select 就开启一个 Statement 对象,用完立刻关闭 Statement 对象
ReuseExecutor:执行update或select以SQL作为key查找Statement对象,存在就使用,不存在就创建,用完后不关闭,可以重复使用
BatchExecutor:执行update(没有select,jdbc批处理不支持select)时,将所有SQL都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象.
mybatis 分页插件的实现原理是什么?
分页插件的基本原理是使用 MyBatis 提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的SQL,然后重写SQL,根据dialect方言,添加对应的物理分页语句和参数
mybatis 如何编写一个自定义插件?
只需实现Interceptor接口,并指定要拦截的方法签名
@Intercepts({
@Signature(
type=Executor.class,method=“update”,args={ MappedStatement.class,Object.class })})
public class ExamplePlugin implements Interceptor {
public Object intercept(Invocation invocation) throws Throwable {
//自定义实现
return invocation.proceed();
}
public Object plugin(Object target){
return Plugin.wrap(target,this)
}
public void setProperties(Properties properties){
//传入配置项
String size = properties.getProperty(“size”);
}
}