Java资料整理

Java资料整理

原创 2017年08月25日 17:20:44
 1、LocalThread的应用场景,数据传输适合用LocalThread么
2、linux的基本命令
   软链接、更改用户组和名、查看磁盘IO、查看内存、查看磁盘大小
3、网络安全(攻防有哪几种类型)
4、JVM的包括哪几种,画图表示,JVM的垃圾回收算法有哪几种
5、年轻代、持久代、老年代
6、session和cookie的区别,在分布式环境中,如何保持session共享,例如两台tomcat中,其中一台挂了,剩下的如何保持会话。
7、HashMap的数据结构,画图, ConcurrentHashMap做了哪些并发控制。
 
 
1、异常的种类,哪种必须要捕获,不捕获会怎么样
2、html的渲染顺序是什么
3、sql如何优化,(字段顺序属于老的优化方法)
4、抽象类和接口的区别
5、struct2的实现原理
6、spring的实现原理
7、索引如何使用
8、hashmap和hashtable的区别
9、常见的排序方法有哪些,讲讲如何实现的
10、注解有哪几种,如何使用
11、hibernate和Mybatis的区别
12、hadoop的实现机制
13、新生代、老年代存放的模式、画图说明
14、性能优化,java代码编写过程中的优化、sql优化、页面优化、内存优化、jvm调优
15、死锁的原因和解决方案
16、Hadoop中的map/reduce来处理这种海量数据
17、分而治之的思想
18、面向对象的算法思想
19、创建对象,除了直接new还有什么其他方法。
20、JSP的内置对象是什么
21、redis的数据类型有哪几种
22、StringBulider 和StringBuffer区别
23、设计模式,为什么要用单例模式
24、List、Set、Map包括哪些
25、用过的NoSQL数据库有哪些,主要应用在什么地方
26、IO的底层实现,读文件使用了什么方式,除了POI还有什么可以替代的么
27、private\public\-\protector类的访问权限是什么
28、数据结构有哪些
29、反射
 
 
答案:
1、LocalThread的应用场景,数据传输适合用LocalThread么
ThreadLocal存取的数据, 在ThreadLocal类中有一个Map,用于存储每一个线程的变量的副本。对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,
而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,
而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。
 
 

什么情况下使用Thread Local呢?

  • 一般来说,当某些数据以线程为作用域并且不同线程具有不同的数据副本时,就考虑用它了

  • 典型的例子是:Handler要获取当前线程的Looper,Looper的作用域为线程,每个线程具有不同的Looper.
最常见的ThreadLocal使用场景为 用来解决 数据库连接、Session管理等。
 
      private static void testThreadLocal(){
            new Thread(new Runnable(){
                  ThreadLocal<String> mLocal=new ThreadLocal<String>();
                  public void run() {
                        mLocal.set("balabala  ");
                        String s=mLocal.get();
                  System.out.println(s);  
                  }     
            }).start();
      }
      
      
      private static void testThreadLocal2(){
            final ThreadLocal<String>  local=new InheritableThreadLocal<>();
            local.set("balabala");
            new Thread(new Runnable(){
                  public void run() {
                        System.out.println(local.get());    
                  }     
            }).start();
      }
 
 
 
2、linux的基本命令
chgrp命令
该命令用于改变文件所属用户组
chgrp users -R ./dir # 递归地把dir目录下中的所有文件和子目录下所有文件的用户组修改为users
 
chown命令
该命令用于改变文件的所有者,与chgrp命令的使用方法相同,只是修改的文件属性不同
 
创建软链接     ln -s 源文件 目标文件。
硬链接ln src  dst,没有参数-s, 它会在你选定的位置上生成一个和源文件大小相同的文件,无论是软链接还是硬链接,文件都保持同步变化。
 top、cpu 信息观察
 
vmstat
  vmstat 命令报告关于线程、虚拟内存、磁盘、陷阱和 CPU 活动的统计信息
 
iostat -dx 显示磁盘扩展信息
df -lh   查看磁盘l大小
 
3、网络安全(攻防有哪几种类型)
1、读取攻击:嗅探攻击、侦察攻击(数据整理攻击、拨号式扫描/移位式扫描攻击、探测/扫描攻击)、直接进入攻击。
2、操作攻击:网络操纵攻击、应用程序操纵攻击(缓冲区溢出攻击、WEB应用程序攻击)
3、欺骗攻击:MAC欺骗攻击、IP欺骗攻击、传输欺骗攻击(TCP欺骗攻击、UDP欺骗攻击)、身份欺骗攻击、无赖设备攻击
4、泛洪攻击:MAC泛洪攻击、TCP SYN泛洪攻击、网络泛洪攻击(DDOS攻击、Smurf攻击:利用ICMP进行ping攻击)、应用程序泛洪攻击。
5、重定向攻击:IP重定向攻击、L2重定向攻击、传输重定向攻击
 
防火墙()、防毒墙、入侵防御(IPS)、统一威胁安全网关
 
 
4、JVM虚拟机运行时的内存模型、画图表示,JVM的垃圾回收算法有哪几种
 
 
引用计数法:
     对象每被引用一次,引用计数器就+1,对象引用释放,引用计算器-1,知道对象的引用计数微0,对象就被释放。但是但A和B循环引用的时候,就都不会被回收了。
root搜索算法:
     定义几个root,也就是这几个对象是不会被jvm虚拟机回收的,所以这些对象引用的对象都是在使用中的对象, 如果对象能够达到root,就不会被回收,如果对象不能够达到root,就会被回收。
 
root对象有;
被启动类(bootstrap加载器)加载类和创建的对象
jvm运行时方法区类静态变量引用的对象
jvm运行时方法区常量池引用的对象
jvm当前运行线程中虚拟机栈变量表引用的对象
本地方法栈中jni引用的对象
 
这种算法就算互相引用,但是无法访问根,所以还是会被回收。
 
强引用关系,就是通过new方式创建的对象,并且显示关联的对象。
 

Java里面有四种应用关系,从强到弱分别为:

Strong Reference(强引用) –>Weak Reference (弱引用) -> Soft Reference(软引用) – > Phantom Reference(引用)

 

Strong Reference : 只有在引用对象root不可达的情况下才会标识为可回收,垃圾回收才可能进行回收

Weak Reference :即使在root算法中 其引用的对象root可达到,但是如果jvm堆内存 不够的时候,还是会被回收。

Soft Reference : 无论其引用的对象是否root可达,在响应内存需要时,由垃圾回收判断是否需要回收。

Phantom Reference :在回收器确定其指示对象可另外回收之后,被加入垃圾回收队列.
 
 
标记-清除法:把标记出来的需要回收的对象直接进行回收, 标记和清除阶段的效率不高,而且清除后回产生大量的不连续空间,这样当程序需要分配大内存对象时,可能无法找到足够的连续空间。
标记-清除-压缩:这个算法是在标记-清除的算法之上进行一下压缩空间,重新移动对象的过程。因为标记清除算法会导致很多的留下来的内存空间碎片,随着碎片的增多,严重影响内存读写的性能,所以在标记-清除之后,会对内存的碎片进行整理。最简单的整理就是把对象压缩到一边,留出另一边的空间。由于压缩空间需要一定的时间,会影响垃圾收集的时间。
适合在收集对象存活时间较长的老年代。
 
 
标记-清除-复制:把内存分配微两个空间,有个空间用来负责装载正常的对象信息,有个是用来垃圾回收用的。
对内存要求比较高,适用于短生存期对象, 用复制方法收集新生代,由于新生代中大部分对象(98%)都是朝生夕死的,所以两块内存的比例不是1:1(大概是8:1)。
 
 
并行标记清除:作为有个线程进行, 并行的进行标记和清除。比如把需要标记的对象平均分配到多个线程之后,当标记完成之后,多个线程进行清除。
并发标记清除:应用程序和垃圾回收同时执行,
 
 
5、年轻代、老年代、持久代
 
年轻代;所有新生成的对象都是先放在年轻代中的,
 
 
 
在GC开始的时候,对象只会存在于Eden区和名为“From”的Survivor区,Survivor区“To”是空的。紧接着进行GC,Eden区中所有存活的对象都会被复制到“To”,而在“From”区中,仍存活的对象会根据他们的年龄值来决定去向。年龄达到一定值(年龄阈值,可以通过-XX:MaxTenuringThreshold来设置)的对象会被移动到年老代中,没有达到阈值的对象会被复制到“To”区域。经过这次GC后,Eden区和From区已经被清空。这个时候,“From”和“To”会交换他们的角色,也就是新的“To”就是上次GC前的“From”,新的“From”就是上次GC前的“To”。不管怎样,都会保证名为To的Survivor区域是空的。Minor GC会一直重复这样的过程,直到“To”区被填满,“To”区被填满之后,会将所有对象移动到年老代中。
 
 
老年代:在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。
持久代:
用于存放静态文件,如今Java类、方法等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些class,
例如Hibernate等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。
持久代大小通过-XX:MaxPermSize=<N>进行设置。
 
 
 
6、session和cookie的区别,在分布式环境中,如何保持session共享,例如两台tomcat中,其中一台挂了,剩下的如何保持会话。
1、cookie数据存放在客户的浏览器上,session数据放在服务器上
2、cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑安全应该使用session
3、session会在一定时间保存在服务器上,当访问增多,会比较占用服务器的性能,考虑到服务器减负性能方面,应当使用cookie
4、单个cookie保存的数据不能超过4K,很多浏览器会限制有个站点最多保存20个cookie
 
session是通过cookie来工作的,通过$_COOKIE['session']来联系的,通过$_COOKIE['PHPSESSID']可以知道session的id,
从而获取到其他的信息。
 
在购物网站中通常将用户加入购物车的商品连同session_id记录到数据库中,当用户再次访问时,通过sessionid就可以查找到用户上次加入购物车的商品。因为sessionid是唯一的,记录到数据库中就可以根据这个查找了。
 
 
session共享的问题:
1、粘性session
      粘性Session是指将用户锁定到某一个服务器上,比如上面说的例子,用户第一次请求时,负载均衡器将用户的请求转发到了A服务器上,如果负载均衡器设置了粘性Session的话,那么用户以后的每次请求都会转发到A服务器上,相当于把用户和A服务器粘到了一块,这就是粘性Session机制。
 
实现方式:以Nginx为例,在upstream模块配置ip_hash属性即可实现粘性Session。
 
upstream mycluster{
    #这里添加的是上面启动好的两台Tomcat服务器
    ip_hash;#粘性Session
     server 192.168.22.229:8080 weight=1;
     server 192.168.22.230:8080 weight=1;
}
 
2、服务器session复制
     任何有个服务器上的session发生改变,该节点会把这个session的所有内容序列化,然后广播给其他的节点,
不管其他服务器需不需要session。
缺点:会对网络负荷造成一定压力,如果session量大的话可能会造成网络堵塞,拖慢服务器性能。
 
实现方式:
 
① 设置tomcat ,server.xml 开启tomcat集群功能
② 在应用里增加信息:通知应用当前处于集群环境中,支持分布式
在web.xml中添加选项
 
3、session共享机制
     使用分布式缓存方案比如memcached、Redis,但是要求Memcached或redis必须是集群。
 
① 粘性session处理方式
 
原理:不同的 tomcat指定访问不同的主memcached。多个Memcached之间信息是同步的,能主从备份和高可用。用户访问时首先在tomcat中创建session,然后将session复制一份放到它对应的memcahed上。memcache只起备份作用,读写都在tomcat上。当某一个tomcat挂掉后,集群将用户的访问定位到备tomcat上,然后根据cookie中存储的SessionId找session,找不到时,再去相应的memcached上去session,找到之后将其复制到备tomcat上。
 

② 非粘性session处理方式

原理:memcached做主从复制,写入session都往从memcached服务上写,读取都从主memcached读取,tomcat本身不存储session
实现方式:用开源的msm插件解决tomcat之间的session共享:Memcached_Session_Manager(MSM)
 
 
4、session持久化到数据库
     ,拿出一个数据库,专门用来存储session信息。保证session的持久化。
 
优点:服务器出现问题,session不会丢失
 
缺点:如果网站的访问量很大,把session存储到数据库中,会对数据库造成很大压力,还需要增加额外的开销维护数据库。
 
5、terracotta实现session复制
 
原理:Terracotta的基本原理是对于集群间共享的数据,当在一个节点发生变化的时候,Terracotta只把变化的部分发送给Terracotta服务器,然后由服务器把它转发给真正需要这个数据的节点。可以看成是对第二种方案的优化。
 
Terracotta作为一个JVM级的开源群集框架,不仅提供HTTP Session复制,它还能做分布式缓存,POJO群集,跨越群集的JVM来实现分布式应用程序协调等,
 
7、HashMap的数据结构,画图, ConcurrentHashMap做了哪些并发控制。
 
HashMap基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。它是线程不安全的。
HashMap采取数组加链表的存储方式来实现。亦即数组(散列桶)中的每一个元素都是链表,如下图:
HashMap 的实例有两个参数影响其性能:初始容量和负载因子。容量是哈希表中桶的数量,初始容量只是哈希表在创建时的容量。负载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。
 
通常,默认加载因子 (0.75) 在时间和空间成本上寻求一种折衷。加载因子过高虽然减少了空间开销,但同时也增加了查询成本(在大多数HashMap 类的操作中,包括get 和put 操作,都反映了这一点)。在设置初始容量时应该考虑到映射中所需的条目数及其加载因子,以便最大限度地减少rehash 操作次数。如果初始容量大于最大条目数除以加载因子,则不会发生rehash 操作。
 
hashtable是线程安全的,
 
ConcurrentHashMap的锁分段机制:
首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。     
 
 
由Segment数组结构和HashEntry数组结构组成,
 
 
 
1、异常的种类,哪种必须要捕获,不捕获会怎么样
 
Throwable 是所有 Java 程序中错误处理的父类 ,有两种资类: Error 和 Exception 。
   Error :表示由 JVM 所侦测到的无法预期的错误,由于这是属于 JVM 层次的严重错误 ,导致 JVM 无法继续执行,因此,这是不可捕捉到的,无法采取任何恢复的操作,顶多只能显示错误信息。
Exception :表示可恢复的例外,这是可捕捉到的。
 
runtime exception ,也称运行时异常,我们可以不处理
 
异常
try、catch、finally、throw、throws、exception、error。
产生异常的原因:
    1、系统资源不可用:如内存分配失败,文件打开失败、数据库连接失败等
    2、程序控制不当:如被零除,负数开方,数组下标越界等
 
异常Throable
    1、不可用解决的:Error
    2、可以解决的:Exception
        1、运行时异常:RuntimeException及其之类(非受检异常:不需要try catch)
            不必在编译时捕获或申明,.NullPointerException,ClassCastException
        2、非运行时异常:除RuntimeException及其之类以外的异常(受检异常)
            必须在编译时捕获或申明
    3、异常其实也就是看开发者的预判能力
 
finally:
    1、最后都会执行
    2、只有当finally之前有System.exit();的时候不会执行
 
多个异常时执行顺序:
    1、有异常时,异常类型与catch的异常类型从上向下匹配,小异常(异常类型范围小的)放最前面,大异常放后面。
    2、匹配类型只会匹配最先找到的一个,从上向下匹配的第一个。
try的存在:
    1、try不能独立存在,必须与catch或finally或三者一起存在。
throw:
    1、throw用来抛出异常,自己不处理,给别人处理
    2、throws用来申明异常,告诉别人有异常
    3、try catch自已处理异常
早抛出、晚捕获
 
 
 
2、html的渲染顺序是什么
1、浏览器加载html页面的Dom结构,是从上到下一行一行的下载和渲染的。
 
2、html页面所有渲染完的部分都是已经下载完的。
 
3、如果有js文件或者css样式文件,那么浏览器会启用单独的线程单独下载。
 
4、当所有样式表都下载完成以后页面才开始一起解析css文件开始渲染文件。
 
5、因为浏览器的加载是从上到下一行一行的加载的,所以如果页面同时定义了两个相同命名的js函数,后面的函数会覆盖前面的函数。
 
6、js函数只能操作js函数定义位置之前的Dom元素。
 
 
3、sql如何优化,(字段顺序属于老的优化方法)
1.对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
 
 
2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:
 
select id from t where num is null
最好不要给数据库留NULL,尽可能的使用 NOT NULL填充数据库.
 
备注、描述、评论之类的可以设置为 NULL,其他的,最好不要使用NULL。
 
不要以为 NULL 不需要空间,比如:char(100) 型,在字段建立时,空间就固定了, 不管是否插入值(NULL也包含在内),都是占用 100个字符的空间的,如果是varchar这样的变长字段, null 不占用空间。
 
 
可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:
 
select id from t where num = 0
 
3.应尽量避免在 where 子句中使用 != 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫描。
 
4.应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描,如:
 
select id from t where num=10 or Name = 'admin'
可以这样查询:
 
select id from t where num = 10
union all
select id from t where Name = 'admin'
 
5.in 和 not in 也要慎用,否则会导致全表扫描,如:
 
select id from t where num in(1,2,3)
对于连续的数值,能用 between 就不要用 in 了:
 
select id from t where num between 1 and 3
很多时候用 exists 代替 in 是一个好的选择:
 
select num from a where num in(select num from b)
用下面的语句替换:
 
select num from a where exists(select 1 from b where num=a.num)
 
 
6.下面的查询也将导致全表扫描:
 
select id from t where name like ‘%abc%’
若要提高效率,可以考虑全文检索。
 
7.如果在 where 子句中使用参数,也会导致全表扫描。因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然 而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描:
 
select id from t where num = @num
可以改为强制查询使用索引:
 
select id from t with(index(索引名)) where num = @num
.应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:
 
select id from t where num/2 = 100
应改为:
 
select id from t where num = 100*2
 
9.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如:
 
select id from t where substring(name,1,3) = ’abc’       -–name以abc开头的id
select id from t where datediff(day,createdate,’2005-11-30′) = 0    -–‘2005-11-30’    --生成的id
应改为:
 
select id from t where name like 'abc%'
select id from t where createdate >= '2005-11-30' and createdate < '2005-12-1'
 
10.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
 
11.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。
 
12.不要写一些没有意义的查询,如需要生成一个空表结构:
 
select col1,col2 into #t from t where 1=0
这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样:
create table #t(…)
 
13.Update 语句,如果只更改1、2个字段,不要Update全部字段,否则频繁调用会引起明显的性能消耗,同时带来大量日志。
 
14.对于多张大数据量(这里几百条就算大了)的表JOIN,要先分页再JOIN,否则逻辑读会很高,性能很差。
 
15.select count(*) from table;这样不带任何条件的count会引起全表扫描,并且没有任何业务意义,是一定要杜绝的。
 
 
16.索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有 必要。
 
17.应尽可能的避免更新 clustered 索引数据列,因为 clustered 索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将导致整个表记录的顺序的调整,会耗费相当大的资源。若应用系统需要频繁更新 clustered 索引数据列,那么需要考虑是否应将该索引建为 clustered 索引。
 
18.尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连 接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。
 
19.尽可能的使用 varchar/nvarchar 代替 char/nchar ,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。
 
20.任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。
 
21.尽量使用表变量来代替临时表。如果表变量包含大量数据,请注意索引非常有限(只有主键索引)。
 
22. 避免频繁创建和删除临时表,以减少系统表资源的消耗。临时表并不是不可使用,适当地使用它们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事件, 最好使用导出表。
 
23.在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。
 
24.如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。
 
25.尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。
 
26.使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。
 
27.与临时表一样,游标并不是不可使用。对小型数据集使用 FAST_FORWARD 游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括“合计”的例程通常要比使用游标执行的速度快。如果开发时 间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。
 
28.在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF 。无需在执行存储过程和触发器的每个语句后向客户端发送 DONE_IN_PROC 消息。
 
29.尽量避免大事务操作,提高系统并发能力。
 
30.尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。
 
 
 
4、抽象类和接口的区别
1、抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。
 
2、抽象类要被子类继承,接口要被类实现。
 
3、接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现
 
4、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
 
5、抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。
 
6、抽象方法只能申明,不能实现。abstract void abc();不能写成abstract void abc(){}。
 
7、抽象类里可以没有抽象方法
 
8、如果一个类里有抽象方法,那么这个类只能是抽象类
 
9、抽象方法要被实现,所以不能是静态的,也不能是私有的。
 
10、接口可继承接口,并可多继承接口,但类只能单根继承。
 
5、struct2的实现原理
 
一个请求在Struts2框架中的处理大概分为以下几个步骤 
    1、客户端初始化一个指向Servlet容器(例如Tomcat)的请求
    2、这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin) 
    3、接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请是否需要调用某个Action 
      4、如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy 
    5、ActionProxy通过ConfigurationManager询问框架的配置文件,找到需要调用的Action类 ,这里,我们一般是从struts.xml配置中读取。
    6、ActionProxy创建一个ActionInvocation的实例。
    7、ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
8、一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2 框架中继承的标签。在这个过程中需要涉及到ActionMapper
 
在上述过程中所有的对象(Action,Results,Interceptors,等)都是通过ObjectFactory来创建的。
6、spring的实现原理
 
 
 
7、索引如何使用
 
当一个新表被创建之时,系统将在磁盘中分配一段以8K为单位的连续空间,当字段的值从内存写入磁盘时,就在这一既定空间随机保存,当一个8K用完的时候,SQLS指针会自动分配一个8K的空间。这里,每个8K空间被称为一个数据页(Page),又名页面或数据页面,并分配从0-7的页号,每个文件的第0页记录引导信息,叫文件头(File header);每8个数据页(64K)的组合形成扩展区(Extent),称为扩展。全部数据页的组合形成堆(Heap)。
SQLS规定行不能跨越数据页,所以,每行记录的最大数据量只能为8K。这就是char和varchar这两种字符串类型容量要限制在8K以内的原因,存储超过8K的数据应使用text类型,实际上,text类型的字段值不能直接录入和保存,它只是存储一个指针,指向由若干8K的文本数据页所组成的扩展区,真正的数据正是放在这些数据页中。
页面有空间页面和数据页面之分。
当一个扩展区的8个数据页中既包含了空间页面又包括了数据或索引页面时,称为混合扩展(Mixed Extent),每张表都以混合扩展开始;反之,称为一致扩展(Uniform Extent),专门保存数据及索引信息。
表被创建之时,SQLS在混合扩展中为其分配至少一个数据页面,随着数据量的增长,SQLS可即时在混合扩展中分配出7个页面,当数据超过8个页面时,则从一致扩展中分配数据页面。
空间页面专门负责数据空间的分配和管理,包括:PFS页面(Page free space):记录一个页面是否已分配、位于混合扩展还是一致扩展以及页面上还有多少可用空间等信息;GAM页面(Global allocation map)和SGAM页面(Secodary global allocation map):用来记录空闲的扩展或含有空闲页面的混合扩展的位置。SQLS综合利用这三种类型的页面文件在必要时为数据表创建新空间;
 
索引分为聚簇索引和非聚簇索引两种,聚簇索引是按照数据存放的物理位置为顺序的,而非聚簇索引就不一样了;聚簇索引能提高多行检索的速度,而非聚簇索引对于单行的检索很快。
 
1. 普通索引

–直接创建索引
02 CREATE INDEX index_name ON table(column(length))
03 –修改表结构的方式添加索引
04 ALTER TABLE table_name ADD INDEX index_name ON (column(length))
05 –创建表的时候同时创建索引
06 CREATE TABLE `table` (
07 `id` int(11) NOT NULL AUTO_INCREMENT ,
08 `title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
09 `content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL ,
10 `timeint(10) NULL DEFAULT NULL ,
11 PRIMARY KEY (`id`),
12 INDEX index_name (title(length))
13 )
14 –删除索引
15 DROP INDEX index_name ON table
 
2.唯一索引。
它与前面的"普通索引"类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:
(1)创建索引:CREATE UNIQUE INDEX indexName ON tableName(tableColumns(length))
(2)修改表结构:ALTER tableName ADD UNIQUE [indexName] ON (tableColumns(length))
(3)创建表的时候直接指定:CREATE TABLE tableName ( [...], UNIQUE [indexName] (tableColumns(length));
 
3、全文索引

–创建表的适合添加全文索引
02 CREATE TABLE `table` (
03 `id` int(11) NOT NULL AUTO_INCREMENT ,
04 `title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
05 `content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL ,
06 `timeint(10) NULL DEFAULT NULL ,
07 PRIMARY KEY (`id`),
08 FULLTEXT (content)
09 );
10 –修改表结构添加全文索引
11 ALTER TABLE article ADD FULLTEXT index_content(content)
12 –直接创建索引
13 CREATE FULLTEXT INDEX index_content ON article(content)
 
 
ALTER TABLE `table_name` ADD FULLTEXT ( `column` )
 
 
4. 单列索引、多列索引
 
多个单列索引与单个多列索引的查询效果不同,因为执行查询时,MySQL只能使用一个索引,会从多个索引中选择一个限制最为严格的索引。
5. 组合索引(最左前缀)
 
平时用的SQL查询语句一般都有比较多的限制条件,所以为了进一步榨取MySQL的效率,就要考虑建立组合索引。例如上表中针对title和time建立一个组合索引:ALTER TABLE article ADD INDEX index_titme_time (title(50),time(10))。建立这样的组合索引,其实是相当于分别建立了下面两组组合索引:
 
–title,time
 
–title
 
为什么没有time这样的组合索引呢?这是因为MySQL组合索引“最左前缀”的结果。简单的理解就是只从最左面的开始组合。并不是只要包含这两列的查询都会用到该组合索引,如下面的几个SQL所示:
 
1    –使用到上面的索引
2    SELECT * FROM article WHREE title='测试' AND time=1234567890;
3    SELECT * FROM article WHREE utitle='测试';
4    –不使用上面的索引
5    SELECT * FROM article WHREE time=1234567890;
 
索引和优化:
1、选择索引的数据类型:   越小的数据类型、越简单的数据类型越好,尽量避免NULL
 
 
8、hashmap和hashtable的区别
 
hashtable是线程安全的,线程安全以及速度。仅在你需要完全的线程安全的时候使用Hashtable,而如果你使用Java 5或以上的话,请使用ConcurrentHashMap吧
Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。
 
HashMap可以通过下面的语句进行同步:
Map m = Collections.synchronizeMap(hashMap);
 
 
 
 
 
9、常见的排序方法有哪些,讲讲如何实现的
 
 
 
10、springmvc注解有哪几种,如何使用
@Service
@Repository
@Autowired
@Component
 
Controller   该类为Controller,用于标注一个类是Controller类,是处理请求逻辑的类,该类会被DispatcherServlet所识别,并完成相应的依赖注入。
RequestMapping  配置方法路径等信息,分为类和方法上两种,类上的该注解将表明该类处理的根URL
方法上的该注解将和类上的注解一起构成该方法要处理的URL路径
ResponseBody   返回值
PathVariable     获取Restful路径中的值 /company/{corpId}/dept/{deptId}
RequestParam  获取Request参数值如   xxx?from=index_nav
RequestBody:请求的body体的绑定(通过HttpMessageConverter进行类型转换);
 
 
 
11、hibernate和Mybatis的区别
 
Hibernate缓存
Hibernate一级缓存是Session缓存,利用好一级缓存就需要对Session的生命周期进行管理好。建议在一个Action操作中使用一个Session。一级缓存需要对Session进行严格管理。
 
Hibernate二级缓存是SessionFactory级的缓存。 SessionFactory的缓存分为内置缓存和外置缓存。内置缓存中存放的是SessionFactory对象的一些集合属性包含的数据(映射元素据及预定SQL语句等),对于应用程序来说,它是只读的。外置缓存中存放的是数据库数据的副本,其作用和一级缓存类似.二级缓存除了以内存作为存储介质外,还可以选用硬盘等外部存储设备。二级缓存称为进程级缓存或SessionFactory级缓存,它可以被所有session共享,它的生命周期伴随着SessionFactory的生命周期存在和消亡。
 
MyBatis缓存
MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。MyBatis 3 中的缓存实现的很多改进都已经实现了,使得它更加强大而且易于配置。
 
默认情况下是没有开启缓存的,除了局部的 session 缓存,可以增强变现而且处理循环 依赖也是必须的。要开启二级缓存,你需要在你的 SQL 映射文件中添加一行:  <cache/>
 
Hibernate的查询会将表中的所有字段查询出来,这一点会有性能消耗。
Hibernate也可以自己写SQL来指定需要查询的字段,但这样就破坏了Hibernate开发的简洁性。
 
Mybatis的SQL是手动编写的,所以可以按需求指定查询的字段。
hibernate往往还不适合(多表关联查询等).
 
 
 
12、hadoop的实现机制
HDFS: 
 
 
 
14、性能优化,java代码编写过程中的优化、sql优化、页面优化、内存优化、jvm调优
 
 
 
15、死锁的原因和解决方案
〈1〉互斥条件。即某个资源在一段时间内只能由一个进程占有,不能同时被两个或两个以上的进程占有。这种独占资源如CD-ROM驱动器,打印机等等,必须在占有该资源的进程主动释放它之后,其它进程才能占有该资源。这是由资源本身的属性所决定的。如独木桥就是一种独占资源,两方的人不能同时过桥。
 
 〈2〉不可抢占条件。进程所获得的资源在未使用完毕之前,资源申请者不能强行地从资源占有者手中夺取资源,而只能由该资源的占有者进程自行释放。如过独木桥的人不能强迫对方后退,也不能非法地将对方推下桥,必须是桥上的人自己过桥后空出桥面(即主动释放占有资源),对方的人才能过桥。
 
 〈3〉占有且申请条件。进程至少已经占有一个资源,但又申请新的资源;由于该资源已被另外进程占有,此时该进程阻塞;但是,它在等待新资源之时,仍继续占用已占有的资源。还以过独木桥为例,甲乙两人在桥上相遇。甲走过一段桥面(即占有了一些资源),还需要走其余的桥面(申请新的资源),但那部分桥面被乙占有(乙走过一段桥面)。甲过不去,前进不能,又不后退;乙也处于同样的状况。
 
  〈4〉循环等待条件。存在一个进程等待序列{P1,P2,...,Pn},其中P1等待P2所占有的某一资源,P2等待P3所占有的某一源,......,而Pn等待P1所占有的的某一资源,形成一个进程循环等待环。就像前面的过独木桥问题,甲等待乙占有的桥面,而乙又等待甲占有的桥面,从而彼此循环等待。
 
解决方案:
1〉打破互斥条件。即允许进程同时访问某些资源。但是,有的资源是不允许被同时访问的,像打印机等等,这是由资源本身的属性所决定的。所以,这种办法并无实用价值。
2〉打破不可抢占条件。即允许进程强行从占有者那里夺取某些资源。就是说,当一个进程已占有了某些资源,它又申请新的资源,但不能立即被满足时,它必须释放所占有的全部资源,以后再重新申请。它所释放的资源可以分配给其它进程。这就相当于该进程占有的资源被隐蔽地强占了。这种预防死锁的方法实现起来困难,会降低系统性能。
〈3〉打破占有且申请条件。可以实行资源预先分配策略。即进程在运行前一次性地向系统申请它所需要的全部资源。如果某个进程所需的全部资源得不到满足,则不分配任何资源,此进程暂不运行。只有当系统能够满足当前进程的全部资源需求时,才一次性地将所申请的资源全部分配给该进程。由于运行的进程已占有了它所需的全部资源,所以不会发生占有资源又申请资源的现象,因此不会发生死锁。
(4)打破循环等待条件,实行资源有序分配策略。采用这种策略,即把资源事先分类编号,按号分配,使进程在申请,占用资源时不会形成环路。所有进程对资源的请求必须严格按资源序号递增的顺序提出。进程占用了小号资源,才能申请大号资源,就不会产生环路,从而预防了死锁。这种策略与前面的策略相比,资源的利用率和系统吞吐量都有很大提高
 
 
安全序列、银行家算法。
 
 
16、Hadoop中的map/reduce来处理这种海量数据
17、分而治之的思想
18、面向对象的算法思想
19、创建对象,除了直接new还有什么其他方法
 
使用new关键字:这是我们最常见的也是最简单的创建对象的方式,通过这种方式我们还可以调用任意的够赞函数(无参的和有参的)。比如:Student student = new Student();
使用Class类的newInstance方法:我们也可以使用Class类的newInstance方法创建对象,这个newInstance方法调用无参的构造器创建对象,如:Student student2 = (Student)Class.forName("根路径.Student").newInstance(); 或者:Student stu = Student.class.newInstance();
使用Constructor类的newInstance方法:次方法和Class类的newInstance方法很像,java.lang.relect.Constructor类里也有一个newInstance方法可以创建对象。我们可以通过这个newInstance方法调用有参数的和私有的构造函数。如: Constructor<Student> constructor = Student.class.getInstance(); Student stu = constructor.newInstance(); 这两种newInstance的方法就是大家所说的反射,事实上Class的newInstance方法内部调用Constructor的newInstance方法。这也是众多框架Spring、Hibernate、Struts等使用后者的原因。
使用Clone的方法:无论何时我们调用一个对象的clone方法,JVM就会创建一个新的对象,将前面的对象的内容全部拷贝进去,用clone方法创建对象并不会调用任何构造函数。要使用clone方法,我们必须先实现Cloneable接口并实现其定义的clone方法。如:Student stu2 = <Student>stu.clone();这也是原型模式的应用。
使用反序列化:当我们序列化和反序列化一个对象,JVM会给我们创建一个单独的对象,在反序列化时,JVM创建对象并不会调用任何构造函数。为了反序列化一个对象,我们需要让我们的类实现Serializable接口。如:ObjectInputStream in = new ObjectInputStream (new FileInputStream("data.obj")); Student stu3 = (Student)in.readObject();
 
 
20、JSP的内置对象是什么
分别为:request、response、session、application、out、pagecontext、config、page、exception
 
21、redis的数据类型有哪几种
 
String(字符串)
Hash(哈希): Redis hash 是一个键名对集合、
List(列表) :Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
Set(集合) Redis的Set是string类型的无序集合。 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
zset(sorted set:有序集合)
Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
zset的成员是唯一的,但分数(score)却可以重复。
 
22、StringBulider 和StringBuffer区别
 
StringBuilder:线程非安全的
StringBuffer:线程安全的。
当我们在字符串缓冲去被多个线程使用是,JVM不能保证StringBuilder的操作是安全的,虽然他的速度最快,但是可以保证StringBuffer是可以正确操作的。当然大多数情况下就是我们是在单线程下进行的操作,所以大多数情况下是建议用StringBuilder而不用StringBuffer的,就是速度的原因。
 
23、设计模式,为什么要用单例模式
 
 
 
 
24、List、Set、Map包括哪些
List特点:元素有放入顺序,元素可重复 
Map特点:元素按键值对存储,无放入顺序 
Set特点:元素无放入顺序,元素不可重复(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的) 
List接口有三个实现类:LinkedList,ArrayList,Vector 
LinkedList:底层基于链表实现,链表内存是散乱的,每一个元素存储本身内存地址的同时还存储下一个元素的地址。链表增删快,查找慢 
ArrayList和Vector的区别:ArrayList是非线程安全的,效率高;Vector是基于线程安全的,效率低 
Set接口有两个实现类:HashSet(底层由HashMap实现),LinkedHashSet 
SortedSet接口有一个实现类:TreeSet(底层由平衡二叉树实现) 
Query接口有一个实现类:LinkList 
Map接口有三个实现类:HashMap,HashTable,LinkeHashMap 
HashMap非线程安全,高效,支持null;HashTable线程安全,低效,不支持null 
SortedMap有一个实现类:TreeMap 
其实最主要的是,list是用来处理序列的,而set是用来处理集的。Map是知道的,存储的是键值对 
set 一般无序不重复.map kv 结构 list 有序 。
25、用过的NoSQL数据库有哪些,主要应用在什么地方
 
数据存档、存储商品分类信息
 
26、IO的底层实现,读文件使用了什么方式,除了POI还有什么可以替代的么
1) 缓冲区操作。2) 内核空间与用户空间。3) 虚拟内存。4) 分页技术。
 
一般IO缓冲区操作:
1) 用户进程使用read()系统调用,要求其用户空间的缓冲区被填满。
2) 内核向磁盘控制器硬件发命令,要求从磁盘读入数据。
3) 磁盘控制器以DMA方式(数据不经过CPU)把数据复制到内核缓冲区。
4) 内核将数据从内核缓冲区复制到用户进程发起read()调用时指定的用户缓冲区。
 
从上图可以看出:磁盘中的数据是先读取到内核的缓冲区中。然后再从内核的缓冲区复制到用户的缓冲区。为什么会这样呢?
因为用户空间的进程是不能直接硬件的(操作磁盘控制器)。磁盘是基于块存储的硬件设备,它一次操作固定大小的块,而用户请求请求的可能是任意大小的数据块。因此,将数据从磁盘传递到用户空间,由内核负责数据的分解、再组合。
 
内存映射IO:就是复用一个以上的虚拟地址可以指向同一个物理内存地址。将内核空间的缓冲区地址(内核地址空间)映射到物理内存地址区域,将用户空间的缓冲区地址(用户地址空间)也映射到相同的物理内存地址区域。从而数据不需要从内核缓冲区映射的物理内存地址移动到用户缓冲区映射的物理内存地址了。
要求:①用户缓冲区与内核缓冲区必须使用相同的页大小对齐。②缓冲区的大小必须是磁盘控制器块大小(512字节磁盘扇区)的倍数---因为磁盘是基于块存储的硬件设备,一次只能操作固定大小的数据块。
用户缓冲区按页对齐,会提高IO的效率---这也是为什么在Java中new 一个字节数组时,指定的大小为2的倍数(4096)的原因吧。
 
JAVA中的IO,本质上是把数据移进或者移出缓冲区。
 
 
NIO
Buffer
Channel
Selector

为了实现Selector管理多个SocketChannel,必须将多个具体的SocketChannel对象注册到Selector对象,并声明需要监听的事件,目前有4种类型的事件:
 
connect:客户端连接服务端事件,对应值为SelectionKey.OP_CONNECT(8)
accept:服务端接收客户端连接事件,对应值为SelectionKey.OP_ACCEPT(16)
read:读事件,对应值为SelectionKey.OP_READ(1)
write:写事件,对应值为SelectionKey.OP_WRITE(4)
 
当SocketChannel有对应的事件发生时,Selector能够觉察到并进行相应的处理。
 
 
 
 
27、private\public\-\protector类的访问权限是什么
 
protected:受保护,父子权限:本类及其子类都可以访问,同一个包中的其他类也可以访问,不同包的子类可以访问。
    ——:默认权限,只有相同包的才可以访问
 
28、数据结构有哪些
 
数组(Array): 一个数组可以分解为多个数组元素,这些数组元素可以是基本数据类型或是构造类型。因此按数组元素的类型不同,数组又可分为数值数组、字符数组、指针数组、结构数组等各种类别。
栈(Stack):是只能在某一端插入和删除的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。
队列(Queue):一种特殊的线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为队空。
链表(Linked List):是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
树(Tree):是包含n(n>0)个结点的有穷集合K,且在K中定义了一个关系N,N满足以下条件:
1)有且仅有一个结点K0,他对于关系N来说没有前驱,称K0为树的根结点。简称为根(root)。
 
2)除K0外,K中的每个结点,对于关系N来说有且仅有一个前驱。
3)K 中各结点,对关系N来说可以有m个后继(m>=0)。
图(Graph):图是由结点的有穷集合V和边的集合E组成。其中,为了与树形结构加以区别,在图结构中常常将结点称为顶点,边是顶点的有序偶对,若两个顶点之间存在一条边,就表示这两个顶点具有相邻关系。
堆(Head):在计算机科学中,堆是一种特殊的树形数据结构,每个结点都有一个值。通常我们所说的堆的数据结构,是指二叉堆。堆的特点是根结点的值最小(或最大),且根结点的两个子树也是一个堆。
散列表(Hash):若结构中存在关键字和K相等的记录,则该记录必定在f(K)的存储位置上。由此,不需比较便可直接取得所查记录。称这个对应关系f为散列函数(Hash function),按这个思想建立的表为散列表。
 
29、反射
反射机制的作用:
1,反编译:.class-->.java
 2,通过反射机制访问java啊啊啊  的属性,方法,构造方法等;
             这样好像更容易理解一些,下边我们具体看怎么实现这些功能。
 
//第一种方式:  
Classc1 = Class.forName("Employee");  
//第二种方式:  
//java中每个类型都有class 属性.  
Classc2 = Employee.class;  
 
//第三种方式:  
//java语言中任何一个java对象都有getClass 方法  
Employeee = new Employee();  
Classc3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee)
posted on 2017-12-09 17:53  曹明  阅读(319)  评论(0编辑  收藏  举报