1、数据库中表的别名不能用as;
2、ORACLE中左连接的sql语法:
SELECT a.id,a.name from 表名 a left join 表名 b where a.id = b.id;
3、多表查询并求平均值
select ix.id,ix.xmmc,ip.* from INFO_XMXX ix left join (select xmid,avg(PFFZ) PJZ from INFO_PFXX group by xmid) ip on ix.id = ip.xmid;
4、JDK源码中对于String中的equals的理解;
重写了Object的equals的方法,先判断两个对象内存地址是否相等,再判断两个值是否相等
public boolean equals(Object anObject){
if(this == anObject){
return true;
}
if(anObject instanceOf String){
String anotherString = (String)anObject;
int n = value.length;
if(n = anotherString.value.length){
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while(n-- != 0){
if(v1[i] != v2[i]){
return false;
i ++;
}
return true;
}
}
}
return false;
}
instanceOf通过返回一个boolean值来指出,这个对象是否是这个特定类或其子类的一个实例
5、java compareTo()方法(指定的数与参数必须是同一类型)
public int compareTo(UnmberSubClass refenceName);
refenceName参数的类型是Byte、Double、Integer、Folat、Long或short类型的参数
若指定的数与参数相等则返回0;
若指定的数小于参数则返回-1;
若指定的数大于参数则返回1;
1 public class Test{ 2 Integer a = 6; 3 System.out.println(a.compareTo(6)); //0 4 System.out.println(a.compareTo(3)); //-1 5 System.out.println(a.compareTo(9)); //1 6 }
6、关于Arrays.copyOfRange()方法
Arrays.copyOfRange(T[] original,int form int to)
将一个原始数组original,从下标form开始复制,一直到下标to,生成一个新的数组
注:该新的数组包括form的下标但不包括to的下标
7、split(String regex)和split(String regex,int limit)的区别
limit > 0 则pattern(模式)应用n-1次
String str = "a,b,c": String[] c1 = str.split(",",2); System.out.println(c1.length); //2 System.out.println(Arrays.toString(c1)); //{"a","b,c"}
limit = 0 则pattern(模式)应用无限次并且省略末尾的空字符串
String str = "a,b,c,,"; String[] c2 = str.split(",",0); System.out.println(c2.lengtg); //3 System.out.println(Arrays.toString(c2)); //{"a","b","c"}
limit < 0 则pattern(模式)应用无限次
String str = "a,b,c,,"; String c3 = str.split(",",-1); System.out.println(c3.length); //5 System.out.println(Arrays.toString(c3)); //{"a","b","c","",""}
8、数据库设计三大范式
<1> 第一范式(每一列的属性都是不可再分的属性值,确保每一列的原子性)
当关系模式R的所有属性都不能再分解为更基本的数据单位时,称R是满足第一范式的,简记为INF,满足第一范式是关系模式规范化的第一要求,否则,将有很多基本操作在这样的关系模式中实现不了。
<2>第二范式(每一行的数据都只能与其中一列相关,即一行数据只做一件事,表中的所有列都必须依赖于主键,而不能有任何一列与主键没有关系)
如果关系模式R满足第一范式,并且R的所有主非属性都完全依赖于R的每一个候选关键属性,称R满足第二范式,简记为2NF。
<3>第三范式(数据不能存在传递关系,即每个属性都与主键有直接关系而不是间接关系)
称R是一个满足第一范式条件的关系模式,X是R的任意属性集,如果X非传递依赖于R的任意一个候选关键字,称R满足第三范式,简记为3NF。
9、char类型可以存放两个汉字吗?
可以。因为char类型是16位,一个汉字是2个字节,一个字节是8位,所以char类型刚好可以存放两个汉字。
10、java基本数据类型
byte | Boolean | char | int | short | float | double | long |
8位 | 1位 | 16位 | 32位 | 16位 | 32位 | 64位 |
64位 |
11、在Oracle SQL Developer中如何设置给表ID自增:
1>建序列
数据库名——>序列——>新建序列——>
2>创建触发器
该序列名与上面创建时的序列名一致;
3>启动触发器
12、ArrayList和LinkedList的区别:
对比1:
1>ArrayList与LinkedLIst的比较:
1、ArrayList是实现了基于数组的动态数据结构,因为地址连续,一旦存储好了,查询的效率会非常高(在内存中是连着放的)。
2、因为地址连续,插入和删除时ArrayList需要移动数据,所以插入和删除效率低。
3、LinkedList是基于链表的数据结构,地址是任意的,所以在开辟内存空间的时候不需要等一个连续的地址,对于新增和删除操作,LinkedList效率较高。
4、因为linkedList要移动指针,所以查询效率较低。
2>适用场景分析:
当需要对数据进行访问的时候用ArrayList的效率比较高,当对数据进行新增和删除的操作时,用LinkedList效率比较高。
对比二:
1>ArrayList与Vector的比较:
1、Vector的方法是同步的,都是线程安全的,而ArrayList不是,所以ArrayList的性能比Vector好。
2、当Vector或ArrayList中的元素超过它的初始大小时,Vector扩容是原来的一倍,而ArrayList则是原来的50%,所以ArrayList比Vector节约空间。
3、大多数情况不使用Vector,因为其性能不好,但其支持线程同步。
4、Vector可以设置增长因子,而ArrayList不可以。
2>使用场景
1、Vector是线程同步,所以是线程安全的,而ArrayList是线程异步的,在不考虑线程同步的情况下,建议使用ArrayList。
2、如果集合中的元素数目大于目前集合数组的长度时,在集合中使用数据量比较大的数据,Vector的优势更大一些。
对比三:
1>HashSet与TreeSet的比较:
1、TreeSet是二叉树实现的,其中的数据都是排好序的,所以不允许放入null值。
2、HashSet是哈希表实现的,其中的数据是无序的,可以放入null值,但只能放入一个null值,且HashSet与TreeSet中的值都不能重复。
3、HashSet要求放入的对象必须实现HashCode()方法,因为放入的对象,是以HashCode码作为标示的,而具有相同内容的String对象,其HashCode是一样的,所以放入的内容不能重复,但同一个类的对象可以放入不同的实例。
2>适用场景:
HashSet是基于Hash算法实现的,其性能通常由于TreeSet,所以我们通常都适用HashSet,但在做排序功能时,TreeSet的优势大于HashSet.
对比四:
1>HashMap与concurrentHashMap的比较:
1、HashMap不是线程安全的,而concurrentHashMap是线程安全的。
2、concurrentHashMap采用锁分段技术,将整个Hash桶进行了分段segment,也就是将这个大的数组分成了几个小的片段segment,而且每个小的片段segment上面都有锁存在,那么在插入元素的时候就需要先找到应该插入到哪一个分段segment,然后再在这个分段上面进行插入,而且这里还需要获得segment锁。
3、concurrentHashMap让锁的力度更精细一些,并发性能更好。
对比五:
1>HashTable与concurrentHashMap的比较:
他们都可以用于多线程的环境,但是当HashTable增加到一定的时候,性能就会急剧下降,因为迭代时需要被锁定很长时间。而concurrentHashMap引入了分割(segmentation),无论它变得多么大,仅仅需要锁定map的某个部分,而其他线程不需要等到迭代完成才能访问map,性能会比HashTable好。
对比六:
1>String、StringBuffer、StringBuilder的区别:
1、运行速度对比:StringBuilder>StringBuffer>String.
2、线程安全上,StringBuffer是线程安全的,StringBuilder是线程不安全的。
2>适用场景:
1、String:适用于少量字符串操作的情况。
2、StringBuffer:适用于多线程下在字符串缓冲区进行大量操作的情况。
3、StringBuffer:适用于单线程下在字符串缓冲区进行大量操作的情况。
对比七:
1>sleep与wait的区别:
1、sleep()方法属于Thread类,而wait()方法属于Object类。
2、sleep()方法导致了程序直通执行指定的时间,让出cpu给其他线程,但是它的监控状态依然保持着,当指定的时间到了又会自动恢复运行状态。所以在调用sleep()方法的过程中,线程不会释放对象锁。
3、调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()后本线程才进入对象锁定池准备获取对象锁进入运行状态,
13、JVM的内存结构:
根据JVM规范,JVM内存共分为虚拟机栈、堆、方法区、程序计数器、本地方法栈五个部分。
1、java虚拟机栈:
线程私有;每个方法在执行的时候创新一个栈帧,存储了局部变量表,操作数栈,动态连接,方法返回地址等;每个方法从调用到执行完毕,对应每一个栈帧在虚拟机栈中的入栈和出栈。
2、堆:
线程共享;被所有线程共享的一块内存区域;在虚拟机启动时创建,用于存放对象实例。
3、方法区:
线程共享;被所有线程共享的一块内存区域;用于存储已被虚拟机加载的类消息,常亮,静态变量等。
4、程序计数器:
线程私有;是当前线程所执行的字节码的行号的指示器,每条线程都有一个独立的程序计数器,这类内存也成为"线程私有"的内存。
5、本地方法栈:
线程私有;主要为虚拟机使用到的native方法服务。
14、强引用、弱引用和软引用的区别:
1>强引用:
只有这个对象被释放之后,对象才会被释放掉,只要引用存在,垃圾回收器永远不会回收,这是常见的new出来的对象。
2>软引用:
内存溢出之前通过代码回收的引用。软引用主要是用户实现类似缓存的功能,在内存足够的情况下直接通过软引用取值,无需从繁忙的真实来源查询数据,提升速度;当内存不足时,自动删除这部分缓存数据,从真正的来源查询数据。
3>弱引用:
第二次垃圾回收是回收的引用,短时间内通过弱引用取对应的数据,可以取到,当执行过第二次垃圾回收时,将返回null。弱引用主要用于监控对象是否已经被垃圾回收器标记为即将回收的垃圾,可以通过弱引用的isEnQueued方法返回对象是否被垃圾回收器标记。
15、GIT与SVN的区别:
1>GIT是分布式的,SVN不是。
2>GIT把内容按元数据方式储存,SVN是按文件方式存储。
3>GIT的分支和SVN分支不同。
4>GIT没有一个全局的版本号,而SVN有。
5>GIT的内容完整性要优于SVN。
16、栈溢出和堆溢出的代码:
递归调用可以导致栈溢出;
不断创建对象可以导致堆溢出;
1 public class Test{ 2 public void testHeap(){ 3 for(;;){ 4 ArrayList list = new ArrayList(20000); 5 } 6 } 7 int num = 1; 8 public void testStack(){ 9 num ++; 10 this.testStack(); 11 } 12 public static void main(String[] args){ 13 Test t = new Test(); 14 t.testHeap(); 15 t.testStack(); 16 } 17 }
17、BIO、NIO和AIO的区别:
Java BIO:同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器就会启动一个线程进行处理,如果这个连接不做任何事情就会造成不必要的线程开销,当然可以通过线程池机制改善。
Java NIO:同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。
Java AIO:异步非阻塞,服务器实现迷失为一个有效请求一个连接,客户端的I/O请求都是由OS先完成了再通知服务器应用启动线程进行处理。
NIO比BIO的改善之处是把一些无效的连接挡在了启动线程之前,减少了这部分资源的浪费(没创建一个线程,就要为这个线程分配一定的内存空间)
AIO比NIO的进一步改善之处是将一些暂时可能无效的连接挡在了启动线程之前,比如在NIO的处理方式中,当一个请求来的话,开启线程进行处理,但这个请求所需要的资源还没有就绪,此时必须等待后端的应用资源,这时线程就阻塞了。
使用场景分析:
BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序只管简单易理解,如之前在Apache中使用。
NIO方式适用于连接数目比较多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JK1.4开始支持,如在Nginx、Netty中使用。
AIO方式适用于链接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持,在成长中,Netty曾经使用过,后来放弃。
18、Java中的堆和栈
栈是一种具有后进先出的数据结构;
堆是一种经过排序的树形数据结构,每个节点都有一个值。通常我们所说的堆的数据结构,是指二叉堆。堆的特点是根节点的值是最小(或最大),且跟节点的两个子树也是一个堆。由于堆的这个特性,常用来实现优先队列,堆的存取是随意的。
为什么要划分堆和栈:
1>从软件设计的角度看,栈代表了处理逻辑,而堆代表了数据。这样分开,使得处理逻辑更为清晰。
2>堆与栈的分离,使得堆中的数据可以被多个栈共享,一方面这种共享提供了一种有效的数据交互方式(如:共享内存),另一方面,堆中的共享常量和缓存可以被所有栈访问,节省了空间。
3>栈因为运行时的需要,比如保存系统运行的上下文,需要进行地址段的划分。由于栈只能向上增长,因此就会限制住栈存储内容的能力。而堆不同,堆中的对象时可以根据需要动态增长的,因此栈和堆的拆分,使得动态增长成为可能,相应栈中只需记住堆中的一个地址即可。
4>体现了Java面向对象这一核心特点。
19、为什么要用线程池:
线程池是指在初始化一个多线程应用程序过程中创建的一个线程集合,然后在需要执行新的任何时重用这些线程而不是新建一个线程。
使用线程池的好处:
1>线程池改进了一个应用程序的响应时间。由于线程池中的线程已经准备好且等待被分配任务,应用程序可以直接拿来使用而不用新建一个线程。
2>线程池节省了CLR为每个短生命周期任务创建一个完整的线程的开销并可以在任务完成后回收资源。
3>线程池根据当前在系统中运行的进程来优化线程时间片。
4>线程池允许我们开启多个任务而不用我们为每个线程设置属性。
5>线程池允许我们为正在执行的任务的程序参数传递一个包含状态信息的对象引用。
6>线程池可以用来解决处理一个请求最大线程数量限制问题。
20、MySQL优化:
1>对查询进行优化,应尽量避免全表扫描,首先应考虑在where及order by涉及的列上建立索引。
2>应尽量避免在where子句中使用!=或<>操作符,否则引擎将放弃索引而使用全表扫描。
3>尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接会逐个比较字符串中的每一个字符,而对于数字型而言只需呀比较一次就够了。
4>任何地方都不要使用select * from t,用具体的字段列表代表"*",不要返回用不到的任何字段。
5>避免重复创建和删除临时表,以减少系统表资源的消耗。
21、乐观锁和悲观锁的区别以及实现方法:
悲观锁:一段执行逻辑加上悲观锁,不同线程同时执行时,只能有一个线程执行,其他线程在入口处等待,直到锁被释放。
乐观锁:一段执行逻辑加上乐观锁,不同线程同时执行时,可以同时进入执行,在最后更新数据时要检查这些数据是否被其他线程修改(版本和执行初是否相同),没有修改则进行更新,否则放弃本次操作。
22、sqls语句中的NVL用法
(1) NVL(表达式1,表达式2)
如果表达式1为空值,nvl返回值为表达式2的值,否则返回表达式1的值。表达式可以为字符型、数字型和日期型,但表达式1与表达式2的数值类型必须一致。
(2)NVL(表达式1,表达式2,表达式3)
如果表达式1为空值,则返回表达式3的值,如果表达式1不为空,则返回表达式2的值(有点类型3元表达式)