标签:
1. Java的GC的理解
Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代码,对内存泄露和溢出的问题,也不需要像C程序员那样战战兢兢。这是因为在Java虚拟机中,存在自动内存管理和垃圾清扫机制。概括地说,该机制对 JVM(Java Virtual Machine)中的内存进行标记,并确定哪些内存需要回收,根据一定的回收策略,自动的回收内存,永不停息(Nerver Stop)的保证JVM中的内存空间,防止出现内存泄露和溢出问题。
Java GC机制主要完成3件事:确定哪些内存需要回收,确定什么时候需要执行GC,如何执行GC。然而,如果我们从事较大型的应用软件开发,曾经出现过内存优化的需求,就必定要研究 Java GC机制。学习Java GC机制,可以帮助我们在日常工作中排查各种内存溢出或泄露问题,解决性能瓶颈,达到更高的并发量,写出更高效的程序。
我们将从4个方面学习Java GC机制,
1,内存是如何分配的;2,如何保证内存不被错误回收(即:哪些内存需要回收);3,在什么情况下执行GC以及执行GC的方式;4,如何监控和优化GC机制。
Java程序的具体执行过程
首先Java源代码文件(.java后缀)会被Java编译器编译为字节码文件(.class后缀),然后由JVM中的类加载器加载各个类的字节码文件,加载完毕之后,交由JVM执行引擎执行。在整个程序执行过程中,JVM会用一段空间来存储程序执行期间需要用到的数据和相关信息,这段空间一般被称作为Runtime Data Area(运行时数据区),也就是我们常说的JVM内存(虚拟机内存)。因此,在Java中我们常常说到的内存管理就是针对这段空间进行管理(如何分配和回收内存空间)。
RDA(运行时数据区) 通常包括这几个部分:
程序计数器(Program CounterRegister):是一个比较小的内存区域,用于指示当前线程所执行的字节码执行到了第几行,可以理解为当前线程的行号指示器。字节码解释器在工作时,会通过改变这个计数器的值来取下一条语句指令。
JVM栈(VM Stack):一个线程的每个方法在执行的同时会创建一个栈帧,每个栈帧对应一个被调用的方法,在栈帧中包括局部变量表(Local Variables)、操作数栈(OperandStack)、指向当前方法所属的类的运行时常量池(运行时常量池的概念在方法区部分会谈到)的引用(Referenceto runtime constant pool)、方法返回地址(ReturnAddress)和一些额外的附加信息。当线程执行一个方法时,就会随之创建一个对应的栈帧,并将建立的栈帧压栈。当方法执行完毕之后,便会将栈帧出栈。因此可知,线程当前执行的方法所对应的栈帧必定位于Java栈的顶部。讲到这里,大家就应该会明白为什么 在 使用 递归方法的时候容易导致栈内存溢出的现象了以及为什么栈区的空间不用程序员去管理了(当然在Java中,程序员基本不用关系到内存分配和释放的事情,因为Java有自己的垃圾回收机制),这部分空间的分配和释放都是由系统自动实施的。对于所有的程序设计语言来说,栈这部分空间对程序员来说是不透明的。下图表示了一个Java栈的模型:
本地方法栈(Native MethodStack) : 本地方法栈与Java栈的作用和原理非常相似。区别只不过是Java栈是为执行Java方法服务的,而本地方法栈则是为执行本地方法(Native Method)服务的。在JVM规范中,并没有对本地方发展的具体实现方法以及数据结构作强制规定,虚拟机可以自由实现它。在HotSopt虚拟机中直接就把本地方法栈和Java栈合二为一。
方法区(Method Area) :在Java虚拟机规范中,将方法区作为堆的一个逻辑部分来对待,但事实 上,方法区并不是堆(Non-Heap);另外,不少人的博客中,将Java GC的分代收集机制分为3个代:青年代,老年代,永久代,这些作者将方法区定义为“永久代”,这是因为,对于之前的HotSpot Java虚拟机的实现方式中,将分代收集的思想扩展到了方法区,并将方法区设计成了永久代。不过,除HotSpot之外的多数虚拟机,并不将方法区当做永 久代,HotSpot本身,也计划取消永久代。本文中,由于笔者主要使用Oracle JDK6.0,因此仍将使用永久代一词。
方法区是各个线程共享的区域,用于存储已经被虚拟机加载的类信息(即加载类时需要加载的信息,包括版本、field、方法、接口等信息)、final常量、静态变量、编译器即时编译的代码等。
方法区在物理上也不需要是连续的,可以选择固定大小或可扩展大小,并且方法区比堆还多了一个限制:可以选择是否执行垃圾收集。一般的,方法区上 执行的垃圾收集是很少的,这也是方法区被称为永久代的原因之一(HotSpot),但这也不代表着在方法区上完全没有垃圾收集,其上的垃圾收集主要是针对 常量池的内存回收和对已加载类的卸载。
在方法区上进行垃圾收集,条件苛刻而且相当困难,效果也不令人满意,所以一般不做太多考虑,可以留作以后进一步深入研究时使用。
在方法区上定义了OutOfMemoryError:PermGen space异常,在内存不足时抛出。
运行时常量池(Runtime ConstantPool)是方法区的一部分,用于存储编译期就生成的字面常量、符号引用、翻译出来的直接引用(符号引用就是编码是用字符串表示某个变量、接口的位置,直接引用就是根据符号引用翻译出来的地址,将在类链接阶段完成翻译);运行时常量池除了存储编译期常量外,也可以存储在运行时间产生的常量(比如String类的intern()方法,作用是String维护了一个常量池,如果调用的字符“abc”已经在常量池中,则返回池中的字符串地址,否则,新建一个常量加入池中,并返回地址)。
堆(Heap):Java中的堆是用来存储对象本身的以及数组(当然,数组引用是存放在Java栈中的)。只不过和C语言中的不同,在Java中,程序员基本不用去关心空间释放的问题,Java的垃圾回收机制会自动进行处理。因此这部分空间也是Java垃圾收集器管理的主要区域。另外,堆是被所有线程共享的,在JVM中只有一个堆。
补充:直接内存并不是JVM管理的内存,可以这样理解,直接内存,就是 JVM以外的机器内存,比如,你有4G的内存,JVM占用了1G,则其余的3G就是直接内存,JDK中有一种基于通道(Channel)和缓冲区 (Buffer)的内存分配方式,将由C语言实现的native函数库分配在直接内存中,用存储在JVM堆中的DirectByteBuffer来引用。 由于直接内存收到本机器内存的限制,所以也可能出现OutOfMemoryError的异常。
2. Java的弱应用和强引用的理解
强引用是和垃圾回收机制相关的。
一般的,如果一个对象可以通过一系列的强引用引用到,那么就说明它是不会被垃圾回收机制(Garbage Collection)回收的。
因为垃圾回收是不会回收你正在使用的对象的。
3. Java是多继承还是单继承
类是单继承接口是实现是多继承的。
4. 抽象类和接口的比较
概述:Java接口(interface)和Java抽象类(abstract class)代表的就是抽象类型,就是我们需要提出的抽象层的具体表现。OOP面向对象的编程,如果要提高程序的复用率,增加程序的可维护性,可扩展性,就必须是面向接口的编程,面向抽象的编程,正确地使用接口、抽象类这些有用的抽象类型作为你结构层次上的顶层。
【1】Java接口和Java抽象类最大的一个区别,就在于Java抽象类可以提供某些方法的部分实现,而Java接口不可以(就是interface中只能定义方法,而不能有方法的实现,而在abstract class中则可以既有方法的具体实现,又有没有具体实现的抽象方法),这大概就是Java抽象类唯一的优点吧,但这个优点非常有用。如果向一个抽象类里加入一个新的具体方法时,那么它所有的子类都一下子都得到了这个新方法,而Java接口做不到这一点,如果向一个Java接口里加入一个 新方法,所有实现这个接口的类就无法成功通过编译了,因为你必须让每一个类都再实现这个方法才行,这显然是Java接口的缺点。这个在我的另外一篇博客mapreduce 新旧API 区别中有提到类似的问题,在新的mapreduce api中更倾向于使用抽象类,而不是接口,因为这更容易扩展。原因就是上面划线部分所说的。
【2】一个抽象类的实现只能由这个抽象类的子类给出,也就是说,这个实现处在抽象类所定义出的继承的等级结构中,而由于Java语言的单继承性,所以抽象类作为类型定义工具的效能大打折扣。在这一点上,Java接口的优势就出来了,任何一个实现了一个Java接口所规定的方法的类都可以具有这个接口的类型,而一个类可以实现任意多个Java接口,从而这个类就有了多种类型。(使用抽象类,那么继承这个抽象类的子类类型就比较单一,因为子类只能单继承抽象类;而子类能够同时实现多个接口,因为类型就比较多。接口和抽象类都可以定义对象,但是只能用他们的具体实现类来进行实例化。)
【3】从第2点不难看出,Java接口是定义混合类型的理想工具,混合类表明一个类不仅仅具有某个主类型的行为,而且具有其他的次要行为。
【4】结合1、2点中抽象类和Java接口的各自优势,具精典的设计模式就出来了:声明类型的工作仍然由Java接口承担,但是同时给出一个Java 抽象类,且实现了这个接口,而其他同属于这个抽象类型的具体类可以选择实现这个Java接口,也可以选择继承这个抽象类,也就是说在层次结构中,Java 接口在最上面,然后紧跟着抽象类,这下两个的最大优点都能发挥到极至了。这个模式就是“缺省适配模式”。在Java语言API中用了这种模式,而且全都遵循一定的命名规范:Abstract +接口名。(A extends AbstractB implementsinterfaceC,那么A即可以选择实现(@Override)接口interfaceC中的方法,也可以选择不实现;A即可以选择实现(@Override)抽象类AbstractB中的方法,也可以选择不实现)
5. SDK测试了解
什么是SDK:SDK就是一个程序,提供一些方法,调用这些方法,可以实现一些功能。如:调用银行提供的SDK,可以实现在线支付的功能。
目前主要接手的SDK有JS SDK 和android SDK。JS SDK就是给你一个js文件,里面提供一些调用的方法。Android SDK就是提供一个jar包,引用jar包后根据说明文档,调用里面的方法。
SDK怎么测:
1、入参和出参:一般SDK说明文档会提供接口的入参和出参,以及入参的类型、是否必填、边界值
是否必选:如果文档里写的参数是必选的,可以用null,“” 写用例
边界值:一般写入操作,都会有他的边界值,这个文档里应该详细有写。如果参数为1-99 int类型。那用例就是0,1,99,100来写用例。如果参数的类型为string 长度为 1-50,就是长度为0,1,50,51来写用例
引用类型和引用类型:如果参数是引用类型,需要测试null 和“”。如果是值类型可以对正数、负数、0以及最大值最小值。这个看需求。
特殊字符:可以测一下键盘能打出来的特殊字符,如~@#¥%……&*()——+{}P|:"<>?还有中文的特殊字符。
特殊情况:像一些查询类接口,可以针对*%这种通配符写用例
注意出参细节:很多时候,很多出参往往被大家忽视。以为只要有参数就对了。比如发送图片接口,返回的width、height、和大小。这些都可能被忽视,以及返回的图片地址是不是能打开,大小是否正确。以及图片被压缩后是不是符合要求。
注意出参格式:比如有时候客户端和服务端交互的时候是用xml,但是出参的格式是json。有时候开发忘记解析了,就变成xml,所以这也是一个bug。
注意出参的返回顺序:如果出参是一个列表,还要看列表的返回顺序是否正确。
2、不同的场景调用
未登录和已登录
网速不好的情况
如果设计到ip电话,可以测wifi 4G 3G 2G,电话中 wifi切换4G,wifi切换3G 等等
用户被后台删除的情况
不走寻常路,可能会发现意外的bug:比如之前测试加好友/同意/拒绝这三个接口。如果这三个接口分开测,一点问题都没有。但是这个场景(A给B发出加好友申请,A再调用同意接口同意B,然后A和B就互为好友。其实应该B同意A才会互为好友)。
3、兼容性测试:
androidSDK的话,最好多找几个不同的手机多做一下自由测试。
web SDK的话,最好多找几个浏览器和不同浏览器版本多做一下自由测试。
4、反复测试:
有些静态变量,在退出后没有初始化,可能会导致一些问题。比如之前测webSDK,登录退出登录退出后,请求的地址就变成http://xxx/Login/Login,原因就是在登录的时候,请求的地址就是url=url+/Login。退出后,没有对url初始化,所以多次登录后,url后面就会有很多/Login
5、注意用例的大小写以及特殊符号的中英文:比如之前有个同事搜索用户昵称接口,用户昵称包含英文的(,但是他的入参为中文的(,搜了半天没搜到,还以为是开发的问题呢。还要后来自己发现了,不然找开发的话,开发会不高兴了。
6、考虑全面:比如测试QQ的历史消息,不要觉得,发送一条消息然后能获取到就行了。其实我们应该想好历史消息的类型,如(文本、表情(ios的表情等等)、图片、语音、文件 等等)消息类型必须全面。其次,应该考虑QQ的客户端,看一下web端、android端、ios端、windows客户端 等等 发送的消息是否没个端都能获取历史消息。然后再细测 历史消息的时间昵称这些是否正确、以及图片是否能打开 保存的文件地址是否正确。还有一些特殊的场景,比如改QQ名称前的历史消息和改名以后的历史消 。还有其他的等等 就靠大家多想啦。
目前问题总结
边界值。比如用户名的最大长度为50的情况下:不能创建会议、不能收到离线消息、等等
特殊字符:用户昵称含特殊字符不能收到短信。发短信借口,短信内容为特殊字符,会收不到短信以及短信内容为空。
错误提示不正确。
6. Python自动化测试
7. Tomcat默认端口号:8080
8. 函数覆盖和函数重载的区别
重载和覆盖的异同点:
*相同【1】都要求方法同名【2】都可以用于抽象方法和非抽象方法
*不同:覆盖要求参数一致,而重载要求参数必须不一致;覆盖要求返回类型必须一直,重载对此不做限制;覆盖只能用于子类覆盖父类方法,重载应用于同一个类中;覆盖对方法的访问权限和异常有特殊要求,重载没有限制;父类的一个方法只能被子类覆盖一次,而一个方法可以重载多次。
方法覆盖的问题:【1】子类的方法名称、参数名和返回类型必须与父类的方法的名称、参数名和返回类型一致【2】子类的方法不能够缩小父类方法的访问权限3】子类方法不能抛出比父类方法更多的异常。子类抛出的异常必须和父类相同或者是父类异常的子类。【4】方法覆盖仅仅是存在于子类和父类【5】父类的静态方法不能被子类覆盖为非静态方法6】子类和父类的静态方法可以重名,以便在子类中隐藏父类的方法。在编译的时候,子类定义的静态方法也必须满足与方法覆盖类似的约束;方法的参数名一致,返回类型一致,不能缩小父类的方法的权限,不能够抛出更多的异常。【7】父类的非静态方法不能够被子类覆盖为静态方法【8】父类的私有方法不能够被子类覆盖【9】父类的抽象方法可以被子类通过两种途径来覆盖:一种是实现抽象方法;另一种是重新声明父类的
9. 安卓的权限控制文件
AndroidManifest.xml
10. 进程和线程的区别
[1]一个程序至少有一个进程,一个进程至少有一个线程。线程的划分尺度小于进程,使得多线程程序的并发性高。
[2]进程在执行过程中拥有独立的内存单元,而多个线程是共享内存的,从而极大的提高了程序的运行效率。
[3]线程在执行过程中和进程是有区别的。每个独立的线程有一个程序运行的入口、程序顺序执行和程序运行的出口。但是线程不能够独立的执行,必须依存在应用程序中。
[4]从逻辑的角度讲,多线程的意义在于一个应用程序中有多个执行部分可以同时执行。操作系统并没有将线程看作多个独立的应用,来实现进程的调度和管理,以及资源分配。这就是线程和进程的区别。
[5]进程是具有一定独立功能的程序关于某个数据集合上面的一次运行活动,进程是系统进行资源分配和调度的单位。
[6]线程是一个进程的实体,是cpu调度和分派的基本单位,它是比进程更小的能够独立运行的基本单位。线程本上基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(程序计数器、一组寄存器和栈),但是它与同属一个进程的其他线程共享进程拥有的全部资源。
[7]一个线程可以创建和撤销另一个进程,同一个进程中的多个线程可以并发执行。
总结:线程和进程的主要差别在于,它们是不同操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃之后,在保护模式下不会对其他的进程产生影响,而线程只是进程中的一个不同的执行路径。线程有自己的堆栈和执行变量,单线程之间没有单独的地址空间,一个线程的死掉会等于整个进程死掉,所以多进程的程序比多线程的程序健壮,但是在进程进行切换的时候,消耗资源较大,效率差一些。但是对于一些要求同时进行又需要共享某些变量的并发操作,只能用线程,不能用进程。
11. 进程和线程的状态
创建-》就绪-》运行-》阻塞或者等待、睡眠-》死亡状态
1. 新建状态(New):新创建了一个线程对象。
2. 就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
3. 运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
4. 阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5. 死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
12. 内部类
内部类不是很好理解,但说白了其实也就是一个类中还包含着另外一个类:如同一个人是由大脑、肢体、器官等身体结果组成,而内部类相当于其中的某个器官之一,例如心脏:它也有自己的属性和行为(血液、跳动).
显然,此处不能单方面用属性或者方法表示一个心脏,而需要一个类.
Out.In in = new Out().new In()可以用来生成内部类的对象,这种方法存在两个小知识点需要注意
? 开头的Out是为了标明需要生成的内部类对象在哪个外部类当中
? 必须先有外部类的对象才能生成内部类的对象,因为内部类的作用就是为了访问外部类中的成员变量
? 内部类在没有同名成员变量和局部变量的情况下,内部类会直接访问外部类的成员变量,而无需指定Out.this.属性名.否则,内部类中的局部变量会覆盖外部类的成员变量而访问内部类本身的成员变量可用this.属性名,访问外部类的成员变量需要使用Out.this.属性名.
? 如果用static 将内部内静态化,那么内部类就只能访问外部类的静态成员变量,具有局限性.其次,因为内部类被静态化,因此Out.In可以当做一个整体看,可以直接new 出内部类的对象(通过类名访问static,生不生成外部类对象都没关系)
? 如果一个内部类只希望被外部类中的方法操作,那么可以使用private声明内部类上面的代码中,我们必须在Out类里面生成In类的对象进行操作,而无法再使用Out.In in = new Out().new In() 生成内部类的对象.也就是说,此时的内部类只有外部类可控制.如同是,我的心脏只能由我的身体控制,其他人无法直接访问它
? 内部类移到了外部类的方法中,然后在外部类的方法中再生成一个内部类对象去调用内部类方法.如果此时我们需要往外部类的方法中传入参数,那么外部类的方法形参必须使用final定义,至于final在这里并没有特殊含义,只是一种表示形式而已. 而心脏又在人体当中,正如同是内部类在外部内当中.
? 匿名内部类 接口 抽象类都可以使用匿名内部类来实现。
13. 设计模式: http://www.cnblogs.com/beijiguangyong/archive/2010/11/15/2302807.html
创建型
1. Factory Method(工厂方法):一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method 使一个类的实例化延迟到其子类。
2. Abstract Factory(抽象工厂): 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
3. Builder(建造者): 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
4. Prototype(原型): 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
5. Singleton(单例): 保证一个类仅有一个实例,并提供一个访问它的全局访问点。
结构型
6. Adapter Class/Object(适配器):将一个类的接口转换成客户希望的另外一个接口。Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
7. Bridge(桥接): 将抽象部分与它的实现部分分离,使它们都可以独立地变化。
8. Composite(组合): 将对象组合成树形结构以表示“部分-整体”的层次结构。C o m p o s i t e 使得用户对单个对象和组合对象的使用具有一致性。
9. Decorator(装饰): 动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator 模式相比生成子类更为灵活。
10. Facade(外观): 为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
11. Flyweight(享元): 运用共享技术有效地支持大量细粒度的对象。
12. Proxy(代理): 为其他对象提供一种代理以控制对这个对象的访问。
行为型
13. Interpreter(解释器): 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
14. Template Method(模板方法): 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。TemplateMethod 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
15. Chain of Responsibility(责任链): 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
16. Command(命令): 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。
17. Iterator(迭代器): 提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。
18. Mediator(中介者): 用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
19. Memento(备忘录): 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
20. Observer(观察者): 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。
21. State(状态): 允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
22. Strategy(策略): 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
23. Visitor(访问者): 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。TemplateMethod 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
14. Http的方法
关于http协议涉及方法的两个名词解释:safe型方法和Idempotent型方法。
safe型方法通常是指不影响服务器端资源的行为,它的操作结果仅仅是读取信息,GET和HEAD多数情况下被认为具有“safe”的特性。
Idempotent型方法正如Idempotent这个词的意思一样,如果一个方法,n次调用与一个独立请求所产生的资源消耗相同,即没有边际损耗,则我们可以认为这类方法是idempotent型方法,get、head、put、delete、options和trace都具有这样的特性。
http协议通常包括的方法有很多,以下我只列出我在http/1.1协议定义中看到的方法:get、post、head、options、put、delete、trace、connect。
get方法用于获取URI资源,是最为常用的一种方法。
post方法用于向指定URI提交内容,服务器端响应其行为,该方法也极为常用。
head方法向URI发送请求,仅仅只需要获得响应的协议头。
put方法用于向URI发送请求,若URI不存在,则要求服务器端根据请求创建资源。当URI存在时,服务器端必须接受请求内容,将其作为URI资源的修改后版本。
delete方法用于删除URI标识的指定资源。
trace方法用于激活服务器端对请求的循环反馈,反馈作为http响应的正文内容被传输回客户端。
connect方法通常被用于使用代理连接。
对于上面提到的这些方法,相信大家如果肯花时间,自然可以在http协议的标准中看到更加详细的内容。但有一点是我需要说明的,以上提到的方法,除了get、post和head可以通过浏览器应用外,其它的方法例如put和delete使用起来有些问题。但ajax的出现为我们提供了一种解决的方式,ajax使用xmlhttprequest进行操作时,在发送请求之前,可以通过设置request type的方式来完成对请求方法的设定。
诸位如果作为servlet开发的人可以尝试一下直接在servlet中实现doPut、doDelete等方法,并在客户端使用ajax对相同的URI使用不同的方法进行请求。
15. TCP的详解http://www.cnblogs.com/feitian629/archive/2012/11/16/2774065.html
在传输层叫做段(segment),在网络层叫做数据报(datagram),在链路层叫做帧(frame)。数据封装成帧后发到传输介质上,到达目的主机后每层协议再剥掉相应的首部,最后将应用层数据交给应用程序处理。
TCP建立连接的过程:
【1】. 客户端发出段1,SYN 位表示连接请求。序号是1000,这个序号在网络通讯中用作临时的地址,每发一个数据字节,这个序号要加1,这样在接收端可以根据序号排出数据包的正确顺序,也可以发现丢包的情况,另外,规定SYN 位和FIN 位也要占一个序号,这次虽然没发数据,但是由于发了SYN 位,因此下次再发送应该用序号1001。mss表示最大段尺寸,如果一个段太大,封装成帧后超过了链路层的最大帧长度,就必须在IP 层分片,为了避免这种情况,客户端声明自己的最大段尺寸,建议服务器端发来的段不要超过这个长度。
【2】 服务器发出段2,也带有SYN 位,同时置ACK 位表示确认,确认序号是1001,表示“我接收到序号1000 及其以前所有的段,请你下次发送序号为1001 的段”,也就是应答了客户端的连接请求,同时也给客户端发出一个连接请求,同时声明最大尺寸为1024。
【3】 客户端发出段3,对服务器的连接请求进行应答,确认序号是8001。
在这个过程中,客户端和服务器分别给对方发了连接请求,也应答了对方的连接请求,其中服务器的请求和应答在一个段中发出,因此一共有三个段用于建立连接,称为‘‘‘三方握手(three-way-handshake)‘‘‘。在建立连接的同时,双方协商了一些信息,例如双方发送序号的初始值、最大段尺寸等。
(4)TCP数据传输过程
【1】 客户端发出段4,包含从序号1001 开始的20 个字节数据。
【2】 服务器发出段5,确认序号为1021,对序号为1001-1020 的数据表示确认收到,同时请求发送序号1021 开始的数据,服务器在应答的同时也向客户端发送从序号8001 开始的10 个字节数据,这称为piggyback。
【3】 客户端发出段6,对服务器发来的序号为8001-8010 的数据表示确认收到,请求发送序号8011 开始的数据。
在数据传输过程中,ACK 和确认序号是非常重要的,应用程序交给TCP 协议发送的数据会暂存在TCP 层的发送缓冲区中,发出数据包给对方之后,只有收到对方应答的ACK 段才知道该数据包确实发到了对方,可以从发送缓冲区中释放掉了,如果因为网络故障丢失了数据包或者丢失了对方发回的ACK 段,经过等待超时后TCP 协议自动将发送缓冲区中的数据包重发。
(5)TCP连接的关闭
【1】 客户端发出段7,FIN 位表示关闭连接的请求。
【2】 服务器发出段8,应答客户端的关闭连接请求。
【3】 服务器发出段9,其中也包含FIN 位,向客户端发送关闭连接请求。
【4】 客户端发出段10,应答服务器的关闭连接请求。
建立连接的过程是三方握手,而关闭连接通常需要4 个段(四次握手),服务器的应答和关闭连接请求通常不合并在一个段中,因为有连接半关闭的情况,这种情况下客户端关闭连接之后就不能再发送数据给服务器了,但是服务器还可以发送数据给客户端,直到服务器也关闭连接为止,稍后会看到这样的例子
16. Java反射和动态代理
Java反射:
【1】通过一个对象获得完整的包名和类名
【2】实例化Class类对象demo1=Class.forName("Reflect.Demo");
【3】通过Class实例化其他类的对象per=(Person)demo.newInstance();Class实例化其他类的对象的时候,一定要自己定义无参的构造函数。
http://www.cnblogs.com/xiaoluo501395377/p/3383130.html
动态代理:动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实。代理一般会实现它所表示的实际对象的接口。代理可以访问实际对象,但是延迟实现实际对象的部分功能,实际对象实现系统的实际功能,代理对象对客户隐藏了实际对象。客户不知道它是与代理打交道还是与实际对象打交道。
目前Java开发包中包含了对动态代理的支持,但是其实现只支持对接口的的实现。其实现主要通过java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。
Proxy类主要用来获取动态代理对象,InvocationHandler接口用来约束调用者实现.
17. Java泛型的理解
1、泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。
2、同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。
3、泛型的类型参数可以有多个。
4、泛型的参数类型可以使用extends语句,例如<T extendssuperclass>。习惯上称为“有界类型”。get extends和putsuper原则
List<?extends E>不能添加元素,但是由于其中的元素都有一个共性--有共同的父类,因此我们在获取元素时可以将他们统一强制转换为E类型,我们称之为get原则。
List<?super E>其list中存放的都是E的父类型元素(包括E),集合中的元素都是E的父类型(包括E),其中的元素类型众多,在获取元素时我们无法判断是哪一种类型,故设计成不能获取元素,我们称之为put原则。
5、泛型的参数类型还可以是通配符类型。例如
Class<?>classType = Class.forName(java.lang.String);
18. Java容器
Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│└Stack
└Set
Map
├Hashtable
├HashMap
└WeakHashMap
Iterator是迭代器类,而Iterable是接口。
好多类都实现了Iterable接口,这样对象就可以调用iterator()方法。
一般都是结合着用,比如
HashMap类就实现了Iterable接口,而要访问或打印出Map中所有内容时,就可以这样:HashMap
hashMap;
Iterator iter = hashMap.iterator();
while(iter.hashNext()) {
String s = iter.next();
}
标签:
原文地址:http://blog.csdn.net/zhangyifei521/article/details/51751159