跳到主要内容

· 23 分钟阅读
CheverJohn

Java是一种面向对象编程(OOP)的语言。 掌握Java需要付出的代价就是,思考对象的时候,需要采用 形象思维(一种抽象思维),而不是程序化的思维。 特别是在尝试创建可重复使用(可再生) 的对象的时候,我们都会面临着一项痛苦的抉择。 事实上,正是由于这样的特性,很难有人能够设计出完美的东西,只有一些Java的编程专家才能编写出可以让大多数人使用的代码,而我江某人学习编程的目的就在于此,成为编程专家。

初章主要是描述了Java的多项设计思想,并从概念上解释面向对象的程序设计。

抽象概念的由来

抽象方法是怎么出现的呢?

​ 起因是我们在解决实际问题的时候发现每一类问题都有其自己的特征。而我们在C或一切其他语言中学到的都只是根据一类问题设计一套方法来解决它。以至于当超出这个问题的时候,方法就会显得特别笨拙。 ​ 面向对象的程序设计就是在以上基础跨出一大步。我们利用一些概念去描述表达实际问题中的元素。我们利用“对象”这个概念建立起实际问题和方法之间的联系。如果一些问题在后期出现了更多的问题,我们就可以相应的在代码中加入其它对象 通过添加新的对象类型,程序可以灵活的进行调整。与特定的问题打配合。从而达到解决问题的目的。 ​ 毫无疑问,面向对象程序设计语言是一门灵活、强大的语言抽象方法。它允许我们根据问题来描述问题,而不是单纯地根据方案。

OOP面向对象程序设计的特征

通过上面讲述的这些特征,我们可以理解“纯粹”的面向对象程序设计方法是什么样子的: (1) 所有东西都是对象。可以将对象想象成一种新型变量;它保存着数据,但可要求它对它自身进行一些操作,比如说增加点方法,增加点变量。理论上来讲,我们可以从问题中找出所有概念性的东西,然后在我们的程序中将其表达为一个对象。

(2) 程序将会是一大堆对象的组合;通过对象与对象之间的消息传递(传参),各个对象都知道自己该干什么,不该干什么。为了向另外一个对象发出请求,就需要向那个对象发送消息。具体来讲,我们可以将消息想象为一个调用请求,它调用的是从属于目标对象的一个子例程或函数。

(3) 每个对象都有自己的存储空间,可以容纳其他对象。或者是通过封装现有对象,进而制造出新的对象。所以尽管先前我们讲的对象看起来很简单,其实在每一个程序中,这些概念都能上升到一个任意高的复杂程度。

(4) 每个对象都有一种类型。根据Java的基本语法,每个对象都是某一个“类”的一个“实例”。而不同类与类之间的区别是什么呢?我抽象地讲,是“能将什么消息发给它?

(5) 同一类的所有对象都能接收相同的消息。举例子举例子,这边有圆(Circle)、形状(Shape)两个类。由于圆其实也是形状嘛,我可以这样说,圆(Circle)的一个对象也属于类型为形状(Shape)的一个对象,所以一个圆能够完全接收来自形状(Shape)的任意消息。这就意味着我们可以让程序代码统一指挥形状(Shape),令其自动控制所有符合形状(Shape)描述的对象,其中自然包括圆(Circle)类的那个对象。这一特性叫做对象的”可替换性“,是OOP最重要的概念之一。

对象的接口

上头我已经为大家引入了类与对象的概念,其实很好理解。类就相当于一样东西,比如说程序员就是一类。而对象呢,按照程序员类来说,这边的对象就是具体的一个程序员,比如说我江某人,就是一个程序员类的对象。

​ 每一个对象都隶属于一个特定的“类”,那个类具有自己的通用特征与行为。

​ 我们该如何让对象完成真正有用的工作呢?比如说让我江某人程序员对象完成一个C++的代码工作。我们可以在类中定义“接口”,对象的“类”就规定了它的接口形式。“类”和“接口”的等价或对应关系就是面向对象程序设计的基础。

​ 下面来一个图解

接口的讲解.jpg

在上面这个图解中,,类的名字叫做Light,我们可以向Light对象发出的请求包括有打开(on)、关闭(off)、变得更明亮(brighten)、变得更黯淡(dim)。我们可以简单地声明一个名字(lt),我们为Light对象创建了一个“句柄”(就是名字,咱们对象的名字,在这边名字就叫做lt),这里边lt,也就是咱们的句柄,指向了刚刚新建的对象。然后我们用new关键字新建类型为Light的一个对象。再用等号将其赋值给句柄。

​ 为了向对象发送一条消息,我们使用下面的格式来将句柄名、句点符号、和消息名称(on、off之类的)连接起来:

lt.on();

实现方案的隐藏

这部分我将谈谈我们为什么要隐藏我们的类成员,类中的方法

​ 首先我想就程序员的分类来讲,目前使用面向对象程序设计语言的程序员主要是分为两类的,一类是类的创建者,一类是类的使用者。前者制造出了包含各种使用的类包,后者会用前者的类包,解决各种问题。

​ 这个时候,我们就需要考虑一个问题了,类创建者创建的类包里不能所有东西都能被使用者调用呀。如果任何人都能使用一个类的所有成员,那么使用者就可以对那个类做出任何事情。即使是一些不能够给使用者使用的类内包含的一些成员。如若不能进行控制的话,就没有办法组织这一情况的发生。

为啥要控制类中成员的访问权限呢?

综上,我们有两方面的原因促使我们需要对类中成员的访问权限进行控制。 原因一:防止使用者程序员接触他们不该接触的东西——通常是一些内部数据类型的设计思想。若只是为了使用类包解决问题,用户只需要操作接口就行了,不需要明白这些信息。我们向用户提供的实际是一种服务。 原因二:允许类包设计人员修改内部结构,不用担心它对使用者程序员造成影响。假如我们(类设计程序员)最开始写了一个简单的类包,以便简化开发。以后又决定进行改写,使其更快地运行。若接口与实现方法早已经隔离开了,并分别受到保护,就可以放心做到这一点。

Java如何实现控制呢?

Java采用三个显式(明确)关键字以及一个隐式(暗示)关键字来设置类边界:public、private、protected 以及暗示性的friendly。若未明确指定其他关键字,则默认为后者。

解释这些关键字:

public(公共):意味着后续的定义,任何人均可使用。 private(私有):意味着除您自己、类型的创建者以及那个类型的内部函数成员之外,其他任何人都不能访问后续的定义信息。private在类创建者和类使用者之间竖起了一堵墙。若有人试图调用,便会在编译期报错。 friendly(友好的)涉及“包装”或“封装”(Package)的概念——即Java用来构建库的方法。若某样东西是“友好的”,意味着它只能在这个包装的范围内使用(所以这一访问级别有时也叫做“包装访问”) protected(受保护的):与“private”相似,只是一个继承的类就可以访问咱们的受保护成员,但是依旧不能访问私有成员。

方案的重复使用

创建并测试好一个类后,这个好不容易创建好的类其实往往有很多缺点。只有较多经验以及洞察力的人才能 设计出一个好的方案。

​ 为了重复使用一个类,最简单的方法就是仅直接使用那个类的对象。同时也将那个类的一个对象植入一个新类中。我们把这叫做“创建一个成员对象”。新类可以由任意数量和类型的其他对象构成。这个概念叫做“组织”——在现有类的基础上组织一个新类。有时组织也称为“包含”关系,比如“一辆车包含了一个变速箱”

​ 对象的组织具有极大的灵活性。新类的“成员对象”通常设为“私有”,使用这个类的使用者程序员不能访问它们。

继承:重新使用接口

当我们费尽心思做出一种数据类型之后,加入不得不又新建一种类型,令其实现大致相同的功能,那会是一件很麻烦的事情。但是若能利用已有的数据类型,对其进行“克隆模仿”,再根据实际情况进行添加或修改,那情况就会好多了。“继承”正是针对这个目标而设计的。但是继承并不完全等价于克隆。在继承的过程中,如果父类发生了变化,子类(继承后产生的新类)也会反映出这种变化。

在Java中继承是通过extends关键字实现的。使用继承时,相当于创建了一个新类。这个新类不仅包含了现有类型的所有成员(除了不能被访问的private成员)。其中最最重要的是它还复制了父类的接口。也就是说,能向父类发送的消息,亦可原样发给子类的对象。

由于父类和子类拥有相同的接口了,但是我们的子类不能一模一样呀,那样还跟父类有什么区别?为了做出区分,所以那个接口也必须进行特殊的设计。下面讲一下两种区分父类和子类的方法:

区分父类子类的方法

方法一:为子类添加新函数(功能)。这些新函数并非父类接口的一部分。为什么会有这种方法的出现呢?一般是因为我们发现父类原有的功能已经不能满足我们的需求了,于是我们就要添加更多的函数。这是一种最简单最基本的继承用法。

方法二:近看extends关键字看上去是让我们要为接口“扩展”新功能,但实情并非肯定得照办。为了区分我们的新类,第二个办法就是改变父类,“改善”父类。

改善父类

为了改善一个父类,我们无非就是改善父类中的函数(或者叫方法),那么我们相应的只需要在子类中的函数中建立一个新的定义就可以了。我们的目标是:”尽管使用的函数接口未变,但他的新版本具有不同的表现“,但是万物没有这么绝对,我们还有另外情况,这边引用两个概念:等价关系类似关系

等价关系:子类完全照搬父类的所有的东西 类似关系:我们在子类中新加入了新的东西,那是原来父类中没有的东西。新的子类依旧拥有旧的父类的接口,但也包含了其他一些新的东西。所以就变成了不是上面所说的那种“等价关系”。

举一个例子:假定我有一个房间,房间连好了用于制冷的各种控制装置,用程序员思维来看,就是说我们已经拥有了必要的“接口”来控制制冷。现在假设我们的制冷机坏掉了,于是我将它换成了一台新型的冷、热两用空调,冬天制热、夏天制冷嘛。冷热空调“类似“制冷机,但是能做更多的事情。但是呢,由于我们的房间只安装了控制制冷的设备”接口“,所以”接口“们只能同新机器的制冷部分打交道。新机器的接口已得到扩展,但现有的系统并不知情,也不能够接触除了原始接口以外的任何东西。

当我们明确了等价和类似两种概念之后,以后在面对情况的时候就可以合理选择了。

多形对象的互换使用

继承的结果往往会是创造了一系列的类,而这所有的类都是建立在统一的接口基础上的。如图

向上转型的形象描述.jpg

这边要讲一个很重要的概念了哈,我们一定要把子类的对象当做父类的对象来对待。这一点是非常重要的。这就意味着我们只需编写代码就行了,不需要注意类的特定细节,只与父类打交道。

根据图例我们可以看到通过集成,这边有三个子类。那么我们为三个子类新编写的代码也会像在父类中那样良好工作。所以说程序具备了“扩展能力”,具有扩展性。

假设我们新加了一个函数:

void doStuff(Shape s)}{
s.erase();
// 等等等等等
s.draw();
}

这样一个函数可以用途任何“几何形状”(Shape)通信,例如我这边又安排了一个代码:

Circle c = new Circle();
Triangle t = new Triangle();
Line l = new Line();
doStuff(c);
doStuff(t);
doStuff(l);

这边我就分析一下doStuff(c)这串代码的意思(事实就是:我确实后边安排了这个代码) 此时,一个Circle句柄传递给了一个本来期待Shape句柄的函数。但是由于咱们的圆也是一种几何形状,所以doStuff()能够正确地进行处理。也就是说,凡是doStuff()能发给一个Shape的消息,Circle也能接收。所以这样子写是正确的,不会有报错。

我们把这种生成子类的方法叫做向上转型。向上是因为继承的方向是从“上面”来的——即父类位于顶部,子类在下方展开。

注意了哦,doStuff()里面的代码,它并非是这样表达的:”如果你是一个Circle,就这样作;如果你是一个Square,就按照那样做;等等诸如此类“。若那样子写代码的话,得累死你,就需要检查Shape所有可能的类型,如圆、矩形、四边形等等等等。这显然是非常麻烦的,而且每次添加了一种新的Shape类型后,都要相应地进行修改,在这里,我们只需要这样做:”你是一种几何形状,我知道你能将自己删掉(即代码里面的erase()),请自己放手去干吧,并且自己去控制所有的细节吧。“

这边我写了三个代码有助于我们理解:

代码一(Shape父类):

package cn.mr8god.shape;

import static java.lang.System.*;

/**
* @author Mr8god
* @date 2020/4/1120:28
*/
public class Shape {
public void draw(){
out.println("我是父类中的draw()方法");
}

public void erase(){
out.println("我是父类中的erase()方法");
}

public void move(){
out.println("我是父类中的move()方法");
}

public void getColor(){
out.println("我是父类中的getColor()方法");
}

public void setColor(){
out.println("我是父类中的setColor()方法");
}

代码二(Circle继承类):

package cn.mr8god.shape;

import static java.lang.System.*;

/**
* @author Mr8god
* @date 2020/4/822:04
*/
public class Circle extends Shape{
void doStuff(Shape s){
s.erase();
out.println("我是来自子类Circle里边的doStuff方法。");
}

}

代码三(ShapeTest类):

package cn.mr8god.shape;


/**
* @ Mr8god
* @ 2020/4/11
*/
class ShapeTest {
public static void main(String[] args) {
Shape sh = new Shape();

sh.draw();
sh.erase();
sh.move();
sh.getColor();
sh.setColor();

Circle ci = new Circle();
ci.draw();
ci.erase();
ci.move();
ci.getColor();
ci.setColor();
ci.doStuff(ci);
}

}

自此输出:

向上转型代码的输出.jpg

如何实现控制访问

Java用三个关键字在类的内部设定边界:public、private、protected。这些访问指定词决定了紧跟其后被定义的东西可以被谁使用。

public:表示紧随其后的元素对任何人都是可用的

private:这个关键字表示除类型创建者和类型的内部方法之外的其他任何人都不能访问的元素。private就像你与使用类的程序员之间的一堵墙,如果有人试图访问private成员,就会在编译期间得到错误信息。

protected:这个关键字与private作用相当,差别仅在于继承的类可以访问protected成员,但是不能访问private成员。

· 13 分钟阅读
CheverJohn

Java内存区域

Java虚拟机运行时数据区.jpg

程序计数器

  1. 作用:当前线程所执行的字节码的行号指示器。
  2. 字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
  3. 存在的意义:Java虚拟机的多线程是通过线程轮流切换实现的,类似于操作系统的时间片算法来分配核心(处理器)的执行时间。所以,为了线程每一次切换后能够恢复到之前正确的执行位置,每个线程就需要各自独立的程序计数器。
  4. 如果线程此时正在执行的是一个Java方法,计数器记录的即是正在执行的虚拟机字节码指令的地址;如果正在执行的是Nativie方法,这个计数器即是空(Undefined)。

Java虚拟机栈(就是大家常说的栈内存)

虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧,用于存储局部变量表、操作栈、动态链接、方法出口等信息。

每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

大部分程序员把Java的内存区域划分为堆内存(Heap)和栈内存(Stack),事实上Java内存区域的划分远比这复杂。其中所指的“堆”在后边会聊到,而所指的“栈”就是现在讲的虚拟机栈,或者说是虚拟机栈中的局部变量表部分。

局部变量表

局部变量表存放了编译期可知的8种基本数据类型(int、char、byte、short、long、double、boolean、float)、对象引用和returnAddress类型

这边插一句关于对象引用类型的分析解释:字如其意,是一种引用,就是C中的指针嘛,我们来看一个例子

int[] arr = new int[4];

=左边的arr是变量部分,=右边的是一个对象。

右边只是一个指向对象起始地址的引用指针。

左边的arr是变量,所以被存放在栈内存中。右边的是对象, 所以被存放在堆内存中,两者靠指针来维系关系。上面这句话应该这么来理解。

continue!继续聊局部变量表,8种基本数据类型里64位长度的long和double类型的数据会占用2个局部变量空间,其余的数据类型只占用1个。

局部变量表所需的内存空间在编译期间就完成了分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是早就确定好的,而且我们在方法运行期间不会改变 局部变量表的大小。

continue!继续聊虚拟机栈,我们聊报错

报错

有两种:

  1. StackOverflowError异常:如果线程请求的栈深度大于虚拟机所允许的深度
  2. OutOfMemoryError异常:当我们使用的虚拟机栈的内存不够时就会出现这个报错

本地方法栈

与虚拟机栈作用相似 ,区别在于虚拟机栈是为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用的Native方法服务。

甚至于有的虚拟机(比如Sun HotSpot虚拟机)直接将本地方法栈和虚拟机栈合二为一。

与虚拟机栈一样,本地方法栈区域也会抛出两种报错StackOverflowError和OutOfMemoryError。

Java堆

是Java虚拟机所管理的内存中最大的一块。在虚拟机启动时就被创建了。

唯一目的就是存放对象实例,只要我们new的对象实例都在这边分配了内存。

Java对可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可。

当前主流的虚拟机都是按照可扩展来实现的(通过 -Xmx:最大多少内存空间,-Xms:最小多少内存空间 来控制)

如果堆中内存不够的话,将会抛出OutOfMemoryError异常,我称之为爆内存,并且在下面给出爆内存的具体例子:

public class 爆内存 {
public static void main(String[] args) {
int it = 20;
long[] arr = new long[100];
arr[99] = 33;
System.out.println(arr[99]);
}
}
//教你如何爆内存哈,在终端输入Java -Xmx256 爆内存

当然爆内存知识OutOfMemoryError异常三种情况中的一种,之后我也会仔细围绕这个好好讲讲,https://blog.csdn.net/z453588/article/details/83743837,可以先看看这个博客解解馋

方法区

与Java堆一样,是各个线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

可以和Java堆一样不需要连续的内存 和可以选择固定大小或者可扩展外

还可以选择不识闲垃圾回收。相对而言,垃圾收集行为在这个区域很少见。但是并非是说数据进入方法区就永久存在了。

这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载。

运行时常量池

是方法区的一部分。

Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。

运行时常量池相对于Class文件常量池的另外一个重要特征就是具备动态性

动态性:Java语言并不要求常量一定只能在编译期产生,运行期间也可能将新的常量放入池中。这种特性被开发人员用的较多的就是String类的intern()方法。

既然运行时常量池是方法区的一部分,自然会受到方法区内存的限制,当无法再申请到内存时会抛出OutOfMemoryError异常。

直接内存

直接内存不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域,但是这部分内存也被频繁地使用,而且也可能导致OutOfMemoryError异常出现。

JDK1.4中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用来进行操作。这样在一些场景中能显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。

既然是直接内存,那么这一部分内存是不会受到Java堆大小的限制的咯,

但是既然是内存,则肯定还是会受到本机总共内存的大小和处理器寻址空间的限制。

服务器管理员配置虚拟机参数时,一般会根据实际内存设置 -Xmx等参数信息,但经常会忽略掉直接内存,使得各个内存区域的总和大于物理内存限制(包括物理上的限制和操作系统级的限制),从而导致动态扩展时出现OutOfMemoryError异常。

对象访问

上面都是从Java虚拟机的运行时数据区来讨论的,这边在讨论一个话题:对象访问是如何进行的呢?

对象访问是Java中的常客,即使是最简答的访问,也会涉及到Java栈、Java堆、方法区这三个最重要内存区域之间的关联关系。举个例子说明:

Object obj = new Object();

等号左边的一部分会被保存在Java栈的本地变量表里,我之前也有所涉及,作为一个reference类型数据出现,一个引用类型嘛。

而右边的部分会被存储到Java堆中去。形成一块连在一起的结构化内存(类似于数组一样的结构)

另外在Java堆中还必须包含能查找到此对象类型数据(如对象类型、父类、实现的接口、方法等)的地址信息,这些类型数据则存储在方法区中。

对象访问的两种方法:使用句柄和直接指针

如果使用句柄访问方式,Java堆中将会划分出一块内存来作为句柄池,栈内存中存储的就是对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的具体地址信息。

通过句柄访问对象.jpg

如果使用直接指针访问方式,Java堆对象的布局就必须要考虑如何放置访问类型数据的相关信息,栈内存中直接存储的就是对象地址

通过直接指针访问对象.jpg

各有优势:

使用句柄访问方式的最大好处就是堆内存中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针就行了。

使用直接指针访问方式的最大好处是速度更快,它节省了一次指针定位的时间开销,由于对象的访问在Java中非常频繁,因此此类开销积少成多后会非常可观。

各种异常实战

明儿个再补充

· 2 分钟阅读
CheverJohn

391.jpg

从样本中提取有用的信息来研究总体的分布及各种特征数的过程叫做构造统计量

统计量:样本的不含任何位置参数的函数

392.jpg

常用统计量

基本概念

样本均值 样本方差 样本标准差 样本矩

样本均值和总体均值的区别

393.jpg

394.jpg

395.jpg

从上面的例子我们可以总结出这样的结论

样本均值的平均值等于总体均值 样本方差的平均值等于总体均值

当总体数字特征未知时,我们可以总结出以下的方法来求数字特征

  1. 用样本均值估计总体均值
  2. 用样本方差估计总体方差
  3. 用样本原点矩估计总体原点矩
  4. 用样本中心矩估计总体中心矩

统计量的分布被称为抽样分布

总体服从一般分布,如指数分布均匀,分布等要得出统计量的分布是很困难的 总体服从正态分布时统计量样本均值样本方差是可以计算的

直方图

方法:

  1. 求最大最小值,并求极差
  2. 分组定组距(一般数据个数n>=50,分成10组以上;小于的时候,一般分为5组)
  3. 定分点定区间
  4. 统计数据落入各组间的概率
  5. 画出直方图

作图反应数据特征

· 6 分钟阅读
CheverJohn

依概率收敛、切比雪夫不等式

依概率收敛

定义

依概率收敛.jpg

稍微解释一下哈,当存在一个任意值ε(大于0哈),当我们的n趋向于无穷大的时候,那么这个概率趋向于零。当然这么说就只是表面意思意思了,我们得详细地去了解一下呀。

这边需要举个例子了

依概率收敛的详细解释.jpg

江某人有话说:这里看到贝努利试验,我想大家肯定会松了一大口气,因为这个东西大家肯定都懂。像咱们抛一次硬币就算一次贝努利试验,但是我们抛了n次硬币。这就叫做n重贝努利试验。

扯回正题哈,当咱们对某一件事件进行观测的时候,若事件A(为了便于解释,就把某一件事件设为事件A了)在一次试验发生的概率为P。利用n次事件中出现了na次事件A,算出事件A出现的频率(n/na)。

注意了。图中的公式是错误的。也就是,当n越大的时候,并不意味这一次事件的概率与咱们算的频率相等。我们讲的频率“稳定于”概率应该从可能性角度来讲。

从可能性来讲概率收敛.jpg

得出概念,只有满足以下公式 $$ \lim_{n\rightarrow+\infty}P{|\frac{na}{n}-p|\geq ε}=0 $$ (楼上的公式打的不容易呀,害,真刺激!)

那么这种收敛就称为“依概率收敛”

依概率收敛的性质:

依概率收敛的性质.jpg

这边就由我江某人来给大家稍微讲解一下以助于理解哈:

首先前三行的意思是,当Xn依概率收敛到a,Yn依概率收敛到b,那么当n趋向于无穷是,且函数g(x,y)在点(a,b)上连续,那么g(Xn,Yn)依概率收敛到g(a,b)。

中间两行的意思是,Xn+Yn会依概率收敛到a+b,Xn/Yn会依概率收敛到a/b,XnxYn会依概率收敛到axb。

特别需要记住一点的是,最后两行,如果Xn依概率收敛到a,f(x)在a点连续,那么当n趋向于无穷的时候,f(Xn)依概率收敛到f(a)。

切比雪夫不等式(Chebyshev不等式)

设随机变量X具有数学期望,且它的数学期望E(X)=μ,方差D(X)=$σ^2$,则对于任意$ε>0$,都有: $$ P{|X-μ|\geq ε} \leq \frac{σ^2}{ε^2} $$ 定理的等价形式为: $$ P{|X-μ| < ε} \geq 1-\frac{σ^2}{ε^2} $$ // 此处明天补上证明过程。。。

X与它均值的偏差的绝对值大于等于ε的概率小于$$ \frac{σ^2}{ε^2} $$

适用范围广,但是结果相对来说比较粗糙。

// 此处后期补上例题解析

大数定律

频率的稳定值记为概率,这句话的意思,可以用一个公式来进行描述。 $$ \lim_{n\rightarrow+\infty}P{|\frac{na}{n}-p|\geq ε}=0 $$ 这个结论可以用“大数定律”来进行描述

定理1(贝努力大数定律)

记na为n重贝努利试验中事件A发生的次数,并记事件A在每次试验中发生的概率为p(0<p<1),则对于$&forall ε > 0$有 $$ \lim_{n\rightarrow+\infty}P{|\frac{na}{n}-p|\geq ε}=0 $$ 即$\frac{na}{n}$趋向于P,当n趋向于+$\infty$

这就说明了,频率是依概率收敛的事件发生的概率的!!!

证明:略,明天补上。。。

贝努力大数定律的重要意义:

  1. 提供了用大量重复独立试验中事件出现概率的极限值来确定概率的理论依据,使得概率的概念才有严格的意义。
  2. 提供了通过试验来确定事件概率的方法——可以通过做试验确定某事件发生的频率,并把它作为相应的概率估计,例如:想估计某产品的不合格品率p,可以随机抽取n(n较大)件,将n件产品的不合格品的比例作为p的估计。

大数定律(Laws of Large Numbers)

内容:设X1,X2,……,Xn,……是一列随机变量,则在一定条件下,随机变量序列Yn=$\frac{X1+……+Xn}{n} $,收敛到μ,当n趋向于$\infty$的时候。

这边需要帮助理解的几个点是:

  1. 随机变量序列Yn收敛到μ的含义是什么?答:依概率收敛
  2. μ是什么?答:当Xi期望相同时,μ = E(Xi)
  3. 一定条件是什么?答:不一样的条件会得到不同的大数定律

定理2(切比雪夫大数定律的推论)

定理3(辛钦大数定律)

辛钦大数定律的意义:

· 32 分钟阅读
CheverJohn

HTTP简介

HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。。

HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。

HTTP工作原理

HTTP协议工作于客户端-服务端架构上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。

Web服务器有:Apache服务器,IIS服务器(Internet Information Services)等。

Web服务器根据接收到的请求后,向客户端发送响应信息。

HTTP默认端口号为80,但是你也可以改为8080或者其他端口。

HTTP三点注意事项

  • HTTP是无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。

  • HTTP是媒体独立的:这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。客户端以及服务器指定使用适合的MIME-type内容类型。

    注释:MIME Type 是该资源的媒体类型,MIME Type 不是个人指定的,是经过互联网(IETF)组织协商,以 RFC(是一系列以编号排定的文件,几乎所有的互联网标准都有收录在其中) 的形式作为建议的标准发布在网上的,大多数的 Web 服务器和用户代理都会支持这个规范 (顺便说一句,Email 附件的类型也是通过 MIME Type 指定的)。

    媒体类型通常通过HTTP协议,由web服务器告知浏览器的,更准确地说,是通过Content-Type来表示的。例如:

    Content-Type:text/HTML

    通常只有一些互联网上获得广泛应用的格式才会获得一个 MIME Type,如果是某个客户端自己定义的格式,一般只能以 application/x- 开头

  • HTTP是无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

下图表展示了HTTP协议通信流程:

cgiarch_1_.gif

HTTP消息结构

HTTP是基于客户端/服务端(C/S)的架构模型,通过一个可靠的链接来交换信息,是一个无状态的请求/响应协议。

一个HTTP"客户端"是一个应用程序(Web浏览器或其他任何客户端),通过连接到服务器达到向服务器发送一个或多个HTTP的请求的目的。

一个HTTP"服务器"同样也是一个应用程序(通常是一个Web服务,如Apache Web服务器或IIS服务器等),通过接收客户端的请求并向客户端发送HTTP响应数据。

HTTP使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接。

一旦建立连接后,数据消息就通过类似Internet邮件所使用的格式[RFC5322]和多用途Internet邮件扩展(MIME)[RFC2045]来传送。

HTTP协议的8种请求类型介绍

HTTP协议中共定义了八种方法或者叫“动作”来表明对Request-URI指定的资源的不同操作方式,具体介绍如下:

  • OPTIONS:返回服务器针对特定资源所支持的HTTP请求方法。也可以利用向web服务器发送'*'的请求来测试服务器的功能性。
  • HEAD:向服务器所要与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息
  • GET:向特定的资源发出请求
  • POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的创建和/或已有资源的修改。
  • PUT:向指定资源位置上传其最新内容。
  • DELETE:请求服务器删除Request-URI所标识的资源。
  • TRACE:回显服务器收到的请求,主要用于测试或诊断。
  • CONNECT:HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。

虽然HTTP的请求方式有8种,但是我们在实际应用中最常用的也就是GETPOST,其他请求方式也都可以通过这两种方式间接的来实现。

客户端请求消息

客户端发送一个HTTP请求到服务器的请求消息包括以下格式:请求行(request line)、请求头部(header)、空行和请求数据四个部分组成,下图给出了请求报文的一般格式。

2012072810301161_1_.png

服务器响应消息

HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。

httpmessage_1_.jpg

实例

下面实例是一点典型的使用GET来传递数据的实例:

客户端请求:

GET /hello.txt HTTP/1.1
User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
Host: www.example.com
Accept-Language: en, mi

服务端响应:

HTTP/1.1 200 OK
Date: Mon, 27 Jul 2009 12:28:53 GMT
Server: Apache
Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
ETag: "34aa387-d-1568eb00"
Accept-Ranges: bytes
Content-Length: 51
Vary: Accept-Encoding
Content-Type: text/plain

输出结果:

Hello World! My payload includes a trailing CRLF.

HTTP请求方式

根据HTTP标准,HTTP请求可以使用多种请求方法。

HTTP1.0定义了三种请求方法:GET,POST和HEAD方法。

HTTP1.1新增了六种请求方法OPTIONS,PUT,PATCH,DELETE,TRACE和CONNECT方法。

序号方法描述
1GET请求指定的页面信息,并返回实体主体。
2HEAD类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头
3POST向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。
4PUT从客户端向服务器传送的数据取代指定的文档的内容。
5DELETE请求服务器删除指定的页面。
6CONNECTHTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。
7OPTIONS允许客户端查看服务器的性能。
8TRACE回显服务器收到的请求,主要用于测试或诊断。
9PATCH是对 PUT 方法的补充,用来对已知资源进行局部更新 。

HTTP响应头信息

HTTP请求头提供了关于请求,响应或者其他的发送实体的信息。

在本章节中我们将具体来介绍HTTP响应头信息。

应答头说明
Allow服务器支持哪些请求方法(如GET、POST等)。
Content-Encoding文档的编码(Encode)方法。只有在解码之后才可以得到Content-Type头指定的内容类型。利用gzip压缩文档能够显著地减少HTML文档的下载时间。Java的GZIPOutputStream可以很方便地进行gzip压缩,但只有Unix上的Netscape和Windows上的IE 4、IE 5才支持它。因此,Servlet应该通过查看Accept-Encoding头(即request.getHeader("Accept-Encoding"))检查浏览器是否支持gzip,为支持gzip的浏览器返回经gzip压缩的HTML页面,为其他浏览器返回普通页面。
Content-Length表示内容长度。只有当浏览器使用持久HTTP连接时才需要这个数据。如果你想要利用持久连接的优势,可以把输出文档写入 ByteArrayOutputStream,完成后查看其大小,然后把该值放入Content-Length头,最后通过byteArrayStream.writeTo(response.getOutputStream()发送内容。
Content-Type表示后面的文档属于什么MIME类型。Servlet默认为text/plain,但通常需要显式地指定为text/html。由于经常要设置Content-Type,因此HttpServletResponse提供了一个专用的方法setContentType。
Date当前的GMT时间。你可以用setDateHeader来设置这个头以避免转换时间格式的麻烦。
Expires应该在什么时候认为文档已经过期,从而不再缓存它?
Last-Modified文档的最后改动时间。客户可以通过If-Modified-Since请求头提供一个日期,该请求将被视为一个条件GET,只有改动时间迟于指定时间的文档才会返回,否则返回一个304(Not Modified)状态。Last-Modified也可用setDateHeader方法来设置。
Location表示客户应当到哪里去提取文档。Location通常不是直接设置的,而是通过HttpServletResponse的sendRedirect方法,该方法同时设置状态代码为302。
Refresh表示浏览器应该在多少时间之后刷新文档,以秒计。除了刷新当前文档之外,你还可以通过setHeader("Refresh", "5; URL=http://host/path")让浏览器读取指定的页面。 注意这种功能通常是通过设置HTML页面HEAD区的<META HTTP-EQUIV="Refresh" CONTENT="5;URL=http://host/path">实现,这是因为,自动刷新或重定向对于那些不能使用CGI或Servlet的HTML编写者十分重要。但是,对于Servlet来说,直接设置Refresh头更加方便。 注意Refresh的意义是"N秒之后刷新本页面或访问指定页面",而不是"每隔N秒刷新本页面或访问指定页面"。因此,连续刷新要求每次都发送一个Refresh头,而发送204状态代码则可以阻止浏览器继续刷新,不管是使用Refresh头还是<META HTTP-EQUIV="Refresh" ...>。 注意Refresh头不属于HTTP 1.1正式规范的一部分,而是一个扩展,但Netscape和IE都支持它。
Server服务器名字。Servlet一般不设置这个值,而是由Web服务器自己设置。
Set-Cookie设置和页面关联的Cookie。Servlet不应使用response.setHeader("Set-Cookie", ...),而是应使用HttpServletResponse提供的专用方法addCookie。参见下文有关Cookie设置的讨论。
WWW-Authenticate客户应该在Authorization头中提供什么类型的授权信息?在包含401(Unauthorized)状态行的应答中这个头是必需的。例如,response.setHeader("WWW-Authenticate", "BASIC realm=\"executives\"")。 注意Servlet一般不进行这方面的处理,而是让Web服务器的专门机制来控制受密码保护页面的访问(例如.htaccess)。

HTTP状态码

当浏览者访问一个网页时,浏览者的浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前,此网页所在的服务器会返回一个包含HTTP状态码的信息头(server header)用以响应浏览器的请求。

HTTP状态码的英文为HTTP Status Code。

下面是常见的HTTP状态码:

  • 200 - 请求成功
  • 301 - 资源(网页等)被永久转移到其它URL
  • 404 - 请求的资源(网页等)不存在
  • 500 - 内部服务器错误

HTTP状态码分类

HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。HTTP状态码共分为5种类型:

分类分类描述
1**信息,服务器收到请求,需要请求者继续执行操作
2**成功,操作被成功接收并处理
3**重定向,需要进一步的操作以完成请求
4**客户端错误,请求包含语法错误或无法完成请求
5**服务器错误,服务器在处理请求的过程中发生了错误

HTTP状态码列表

状态码状态码英文名称中文描述
100Continue继续。客户端应继续其请求
101Switching Protocols切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议
200OK请求成功。一般用于GET与POST请求
201Created已创建。成功请求并创建了新的资源
202Accepted已接受。已经接受请求,但未处理完成
203Non-Authoritative Information非授权信息。请求成功。但返回的meta信息不在原始的服务器,而是一个副本
204No Content无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档
205Reset Content重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域
206Partial Content部分内容。服务器成功处理了部分GET请求
300Multiple Choices多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择
301Moved Permanently永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
302Found临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
303See Other查看其它地址。与301类似。使用GET和POST请求查看
304Not Modified未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
305Use Proxy使用代理。所请求的资源必须通过代理访问
306Unused已经被废弃的HTTP状态码
307Temporary Redirect临时重定向。与302类似。使用GET请求重定向
400Bad Request客户端请求的语法错误,服务器无法理解
401Unauthorized请求要求用户的身份认证
402Payment Required保留,将来使用
403Forbidden服务器理解请求客户端的请求,但是拒绝执行此请求
404Not Found服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面
405Method Not Allowed客户端请求中的方法被禁止
406Not Acceptable服务器无法根据客户端请求的内容特性完成请求
407Proxy Authentication Required请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权
408Request Time-out服务器等待客户端发送的请求时间过长,超时
409Conflict服务器完成客户端的 PUT 请求时可能返回此代码,服务器处理请求时发生了冲突
410Gone客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置
411Length Required服务器无法处理客户端发送的不带Content-Length的请求信息
412Precondition Failed客户端请求信息的先决条件错误
413Request Entity Too Large由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息
414Request-URI Too Large请求的URI过长(URI通常为网址),服务器无法处理
415Unsupported Media Type服务器无法处理请求附带的媒体格式
416Requested range not satisfiable客户端请求的范围无效
417Expectation Failed服务器无法满足Expect的请求头信息
500Internal Server Error服务器内部错误,无法完成请求
501Not Implemented服务器不支持请求的功能,无法完成请求
502Bad Gateway作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应
503Service Unavailable由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中
504Gateway Time-out充当网关或代理的服务器,未及时从远端服务器获取请求
505HTTP Version not supported服务器不支持请求的HTTP协议的版本,无法完成处理

HTTP content-type

Content-Type(内容类型),一般是指网页中存在的Content-Type,用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件,这就是经常看到一些PHP网页点击的结果却是下载一个文件或一张图片的原因。

Content-Type标头告诉客户端实际返回的内容的内容类型。

语法格式:

Content-Type: text/html; charset=utf-8
Content-Type: multipart/form-data; boundary=something

实例:

F7E193D6-3C08-4B97-BAF2-FF340DAA5C6E_1_.jpg

常见的媒体格式类型如下:

  • text/html : HTML格式
  • text/plain :纯文本格式
  • text/xml : XML格式
  • image/gif :gif图片格式
  • image/jpeg :jpg图片格式
  • image/png:png图片格式

以application开头的媒体格式类型:

  • application/xhtml+xml:XHTML格式
  • application/xml: XML数据格式
  • application/atom+xml :Atom XML聚合格式
  • application/json: JSON数据格式
  • application/pdf:pdf格式
  • application/msword : Word文档格式
  • application/octet-stream : 二进制流数据(如常见的文件下载)
  • application/x-www-form-urlencoded : <__form encType="">中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)

另外一种常见的媒体格式是上传文件之时使用的:

  • multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式

HTTP content-type对照表

文件扩展名Content-Type(Mime-Type)文件扩展名Content-Type(Mime-Type)
.*( 二进制流,不知道下载文件类型)application/octet-stream.tifimage/tiff
.001application/x-001.301application/x-301
.323text/h323.906application/x-906
.907drawing/907.a11application/x-a11
.acpaudio/x-mei-aac.aiapplication/postscript
.aifaudio/aiff.aifcaudio/aiff
.aiffaudio/aiff.anvapplication/x-anv
.asatext/asa.asfvideo/x-ms-asf
.asptext/asp.asxvideo/x-ms-asf
.auaudio/basic.avivideo/avi
.awfapplication/vnd.adobe.workflow.biztext/xml
.bmpapplication/x-bmp.botapplication/x-bot
.c4tapplication/x-c4t.c90application/x-c90
.calapplication/x-cals.catapplication/vnd.ms-pki.seccat
.cdfapplication/x-netcdf.cdrapplication/x-cdr
.celapplication/x-cel.cerapplication/x-x509-ca-cert
.cg4application/x-g4.cgmapplication/x-cgm
.citapplication/x-cit.classjava/*
.cmltext/xml.cmpapplication/x-cmp
.cmxapplication/x-cmx.cotapplication/x-cot
.crlapplication/pkix-crl.crtapplication/x-x509-ca-cert
.csiapplication/x-csi.csstext/css
.cutapplication/x-cut.dbfapplication/x-dbf
.dbmapplication/x-dbm.dbxapplication/x-dbx
.dcdtext/xml.dcxapplication/x-dcx
.derapplication/x-x509-ca-cert.dgnapplication/x-dgn
.dibapplication/x-dib.dllapplication/x-msdownload
.docapplication/msword.dotapplication/msword
.drwapplication/x-drw.dtdtext/xml
.dwfModel/vnd.dwf.dwfapplication/x-dwf
.dwgapplication/x-dwg.dxbapplication/x-dxb
.dxfapplication/x-dxf.ednapplication/vnd.adobe.edn
.emfapplication/x-emf.emlmessage/rfc822
.enttext/xml.epiapplication/x-epi
.epsapplication/x-ps.epsapplication/postscript
.etdapplication/x-ebx.exeapplication/x-msdownload
.faximage/fax.fdfapplication/vnd.fdf
.fifapplication/fractals.fotext/xml
.frmapplication/x-frm.g4application/x-g4
.gbrapplication/x-gbr.application/x-
.gifimage/gif.gl2application/x-gl2
.gp4application/x-gp4.hglapplication/x-hgl
.hmrapplication/x-hmr.hpgapplication/x-hpgl
.hplapplication/x-hpl.hqxapplication/mac-binhex40
.hrfapplication/x-hrf.htaapplication/hta
.htctext/x-component.htmtext/html
.htmltext/html.htttext/webviewhtml
.htxtext/html.icbapplication/x-icb
.icoimage/x-icon.icoapplication/x-ico
.iffapplication/x-iff.ig4application/x-g4
.igsapplication/x-igs.iiiapplication/x-iphone
.imgapplication/x-img.insapplication/x-internet-signup
.ispapplication/x-internet-signup.IVFvideo/x-ivf
.javajava/*.jfifimage/jpeg
.jpeimage/jpeg.jpeapplication/x-jpe
.jpegimage/jpeg.jpgimage/jpeg
.jpgapplication/x-jpg.jsapplication/x-javascript
.jsptext/html.la1audio/x-liquid-file
.larapplication/x-laplayer-reg.latexapplication/x-latex
.lavsaudio/x-liquid-secure.lbmapplication/x-lbm
.lmsffaudio/x-la-lms.lsapplication/x-javascript
.ltrapplication/x-ltr.m1vvideo/x-mpeg
.m2vvideo/x-mpeg.m3uaudio/mpegurl
.m4evideo/mpeg4.macapplication/x-mac
.manapplication/x-troff-man.mathtext/xml
.mdbapplication/msaccess.mdbapplication/x-mdb
.mfpapplication/x-shockwave-flash.mhtmessage/rfc822
.mhtmlmessage/rfc822.miapplication/x-mi
.midaudio/mid.midiaudio/mid
.milapplication/x-mil.mmltext/xml
.mndaudio/x-musicnet-download.mnsaudio/x-musicnet-stream
.mochaapplication/x-javascript.movievideo/x-sgi-movie
.mp1audio/mp1.mp2audio/mp2
.mp2vvideo/mpeg.mp3audio/mp3
.mp4video/mpeg4.mpavideo/x-mpg
.mpdapplication/vnd.ms-project.mpevideo/x-mpeg
.mpegvideo/mpg.mpgvideo/mpg
.mpgaaudio/rn-mpeg.mppapplication/vnd.ms-project
.mpsvideo/x-mpeg.mptapplication/vnd.ms-project
.mpvvideo/mpg.mpv2video/mpeg
.mpwapplication/vnd.ms-project.mpxapplication/vnd.ms-project
.mtxtext/xml.mxpapplication/x-mmxp
.netimage/pnetvue.nrfapplication/x-nrf
.nwsmessage/rfc822.odctext/x-ms-odc
.outapplication/x-out.p10application/pkcs10
.p12application/x-pkcs12.p7bapplication/x-pkcs7-certificates
.p7capplication/pkcs7-mime.p7mapplication/pkcs7-mime
.p7rapplication/x-pkcs7-certreqresp.p7sapplication/pkcs7-signature
.pc5application/x-pc5.pciapplication/x-pci
.pclapplication/x-pcl.pcxapplication/x-pcx
.pdfapplication/pdf.pdfapplication/pdf
.pdxapplication/vnd.adobe.pdx.pfxapplication/x-pkcs12
.pglapplication/x-pgl.picapplication/x-pic
.pkoapplication/vnd.ms-pki.pko.plapplication/x-perl
.plgtext/html.plsaudio/scpls
.pltapplication/x-plt.pngimage/png
.pngapplication/x-png.potapplication/vnd.ms-powerpoint
.ppaapplication/vnd.ms-powerpoint.ppmapplication/x-ppm
.ppsapplication/vnd.ms-powerpoint.pptapplication/vnd.ms-powerpoint
.pptapplication/x-ppt.prapplication/x-pr
.prfapplication/pics-rules.prnapplication/x-prn
.prtapplication/x-prt.psapplication/x-ps
.psapplication/postscript.ptnapplication/x-ptn
.pwzapplication/vnd.ms-powerpoint.r3ttext/vnd.rn-realtext3d
.raaudio/vnd.rn-realaudio.ramaudio/x-pn-realaudio
.rasapplication/x-ras.ratapplication/rat-file
.rdftext/xml.recapplication/vnd.rn-recording
.redapplication/x-red.rgbapplication/x-rgb
.rjsapplication/vnd.rn-realsystem-rjs.rjtapplication/vnd.rn-realsystem-rjt
.rlcapplication/x-rlc.rleapplication/x-rle
.rmapplication/vnd.rn-realmedia.rmfapplication/vnd.adobe.rmf
.rmiaudio/mid.rmjapplication/vnd.rn-realsystem-rmj
.rmmaudio/x-pn-realaudio.rmpapplication/vnd.rn-rn_music_package
.rmsapplication/vnd.rn-realmedia-secure.rmvbapplication/vnd.rn-realmedia-vbr
.rmxapplication/vnd.rn-realsystem-rmx.rnxapplication/vnd.rn-realplayer
.rpimage/vnd.rn-realpix.rpmaudio/x-pn-realaudio-plugin
.rsmlapplication/vnd.rn-rsml.rttext/vnd.rn-realtext
.rtfapplication/msword.rtfapplication/x-rtf
.rvvideo/vnd.rn-realvideo.samapplication/x-sam
.satapplication/x-sat.sdpapplication/sdp
.sdwapplication/x-sdw.sitapplication/x-stuffit
.slbapplication/x-slb.sldapplication/x-sld
.slkdrawing/x-slk.smiapplication/smil
.smilapplication/smil.smkapplication/x-smk
.sndaudio/basic.soltext/plain
.sortext/plain.spcapplication/x-pkcs7-certificates
.splapplication/futuresplash.spptext/xml
.ssmapplication/streamingmedia.sstapplication/vnd.ms-pki.certstore
.stlapplication/vnd.ms-pki.stl.stmtext/html
.styapplication/x-sty.svgtext/xml
.swfapplication/x-shockwave-flash.tdfapplication/x-tdf
.tg4application/x-tg4.tgaapplication/x-tga
.tifimage/tiff.tifapplication/x-tif
.tiffimage/tiff.tldtext/xml
.topdrawing/x-top.torrentapplication/x-bittorrent
.tsdtext/xml.txttext/plain
.uinapplication/x-icq.ulstext/iuls
.vcftext/x-vcard.vdaapplication/x-vda
.vdxapplication/vnd.visio.vmltext/xml
.vpgapplication/x-vpeg005.vsdapplication/vnd.visio
.vsdapplication/x-vsd.vssapplication/vnd.visio
.vstapplication/vnd.visio.vstapplication/x-vst
.vswapplication/vnd.visio.vsxapplication/vnd.visio
.vtxapplication/vnd.visio.vxmltext/xml
.wavaudio/wav.waxaudio/x-ms-wax
.wb1application/x-wb1.wb2application/x-wb2
.wb3application/x-wb3.wbmpimage/vnd.wap.wbmp
.wizapplication/msword.wk3application/x-wk3
.wk4application/x-wk4.wkqapplication/x-wkq
.wksapplication/x-wks.wmvideo/x-ms-wm
.wmaaudio/x-ms-wma.wmdapplication/x-ms-wmd
.wmfapplication/x-wmf.wmltext/vnd.wap.wml
.wmvvideo/x-ms-wmv.wmxvideo/x-ms-wmx
.wmzapplication/x-ms-wmz.wp6application/x-wp6
.wpdapplication/x-wpd.wpgapplication/x-wpg
.wplapplication/vnd.ms-wpl.wq1application/x-wq1
.wr1application/x-wr1.wriapplication/x-wri
.wrkapplication/x-wrk.wsapplication/x-ws
.ws2application/x-ws.wsctext/scriptlet
.wsdltext/xml.wvxvideo/x-ms-wvx
.xdpapplication/vnd.adobe.xdp.xdrtext/xml
.xfdapplication/vnd.adobe.xfd.xfdfapplication/vnd.adobe.xfdf
.xhtmltext/html.xlsapplication/vnd.ms-excel
.xlsapplication/x-xls.xlwapplication/x-xlw
.xmltext/xml.xplaudio/scpls
.xqtext/xml.xqltext/xml
.xquerytext/xml.xsdtext/xml
.xsltext/xml.xslttext/xml
.xwdapplication/x-xwd.x_bapplication/x-x_b
.sisapplication/vnd.symbian.install.sisxapplication/vnd.symbian.install
.x_tapplication/x-x_t.ipaapplication/vnd.iphone
.apkapplication/vnd.android.package-archive.xapapplication/x-silverlight-app

· 4 分钟阅读
CheverJohn

URI(Uniform Resource Identifier)

采用一种特定语法标识一个资源的字符串

格式:

模式:模式特定部分(模式特定部分的语法取决于所用的模式)

模式包括:

由小写字母、数字和加号、点及连号符组成

data链接中直接包含的Base64编码数据

file本地磁盘的文件

ftp FTP服务器

HTTP使用超文本传输协议的国际互联网服务器

mailto电子邮件地址

magnet可以通过对等网络下载的资源

Telnet与基于Telnet的服务连接

模式特定部分包扩:

//authority/path?query(//授权机构/路径?查询字符串)

由ASCII字母数字符号组成,还可以使用标点符号-、_、·、!、~

定界符(/、?、&、=)可以有其预定义用途

所有其他字符及内容中需用到的定界符也应用%转义(空格%20/%2F)

authority:负责解析该URI其余部分的授权机构 授权机构是Internet主机,还可提供可选的用户名和端口 如:ftp://mp3:mp3@ci43198-a.ashvill.nc.home.com:33/VanHalen-Jump.mp3

path:授权机构用来确定所标识资源的字符串

URL最常见的URI

两者区别:URI表示资源是什么,URL表示资源的具体位置,URI是URL的抽象。Java中URL对象对应网络获取的应用层协议的一个表示,而URI对象纯粹用于解析和处理字符串。

绝对URL

protocol://userInfo@host.port/path?query#fragment

host 提供所需资源服务区的名字(主机/服务器ip地址)

userInfo 可选,服务器登录信息

port 可选,服务在其默认端口运行,无需此部分

path 指定服务器上的一个特定目录文件系统,路径相对于服务器的文档跟目录,向公众开放的服务器不会将其整个文件系统展示给客户端,而只是展示指定目录中的内容

query 向服务器提供附加参数,一般只在http URL中使用,其中包含表单数据,作为输入提供给服务端的运行程序

fragment 指向远程资源的某个特定部分 HTML 锚 XML XPointer 段 ref 片段标识符在HTML文档中用id属性创建

包含片段标识符的是URL引用,不是URL

相对URL继承了 父文档部分信息的URL

在相对URL中,缺少的各部分都与所在文档的URL中对应的部分相同

例如浏览http://www.ibiblio.org/java/faq/javatutoial.html时

若无"/"开头 例如<__a href="javafaq.html">

相当于http://www.ibiblio.org/java/faq/javafaq.html

若以"/"开头 如<__a href="/projects/ipv61">

则相当于http://www.ibiblio.org/projects/ipv61

相对URL允许用多种协议来提供一个文档树,且相对URL允许将整个文档树从一个网站移动或复制到另一个网站,而不会破坏所有的内部连接。

· 8 分钟阅读
CheverJohn

首先

我们了解浏览器是如何处理内容的 。在浏览器中显示的内容有 HTML、有 XML、有 GIF、还有 Flash ……那么,浏览器是如何区分它们,决定什么内容用什么形式来显示呢?答案是 MIME Type,也就是该资源的媒体类型。

媒体类型通常是通过HTTP协议,由web服务器告知浏览器的,更准确地说 ,是通过Content-Type来表示的,例如:

Content-type:text/HTML

表示内容是 text/HTML 类型,也就是超文本文件。为什么是“text/HTML”而不是“HTML/text”或者别的什么?MIME Type 不是个人指定的,是经过 ietf 组织协商,以 RFC 的形式作为建议的标准发布在网上的,大多数的 Web 服务器和用户代理都会支持这个规范 (顺便说一句,Email 附件的类型也是通过 MIME Type 指定的)。

通常只有一些在互联网上获得广泛应用的格式才会获得一个 MIME Type,如果是某个客户端自己定义的格式,一般只能以 application/x- 开头。

XHTML 正是一个获得广泛应用的格式,因此,在 RFC 3236 中,说明了 XHTML 格式文件的 MIME Type 应该是 application/xHTML+XML。

当然,处理本地的文件,在没有人告诉浏览器某个文件的 MIME Type 的情况下,浏览器也会做一些默认的处理,这可能和你在操作系统中给文件配置的 MIME Type 有关。比如在 Windows 下,打开注册表的“HKEY_LOCAL_MACHINESOFTWAREClassesMIMEDatabaseContent Type”主键,你可以看到所有 MIME Type 的配置信息。

然后

在把输出结果传送到浏览器上的时候,浏览器必须启动适当的应用程序来处理这个输出文档。这可以通过多种类型MIME(多功能网际邮件扩充协议)来完成。在HTTP中,MIME类型被定义在Content-Type header中。

例如,架设你要传送一个Microsoft Excel文件到客户端。那么这时的MIME类型就是“application/vnd.ms-excel”。在大多数实际情况中,这个文件然后将传送给Execl来处理(假设我们设定Execl为处理特殊MIME类型的应用程序)。在ASP中,设定MIME类型的方法是通过Response对象的ContentType属性。

多媒体文件格式MIME

最早的HTTP协议中,并没有附加的数据类型信息,所有传送的数据都被客户程序解释为超文本标记语言HTML 文档,而为了支持多媒体数据类型,HTTP协议中就使用了附加在文档之前的MIME数据类型信息来标识数据类型。

MIME意为多目Internet邮件扩展,它设计的最初目的是为了在发送电子邮件时附加多媒体数据,让邮件客户程序能根据其类型进行处理。然而当它被HTTP协议支持之后,它的意义就更为显著了。它使得HTTP传输的不仅是普通的文本,而变得丰富多彩。

每个MIME类型由两部分组成,前面是数据的大类别,例如声音audio、图像image等,后面定义具体的种类。

常见的MIME类型有

超文本标记语言文本 .html,.html text/html 普通文本 .txt text/plain RTF文本 .rtf application/rtf GIF图形 .gif image/gif JPEG图形 .ipeg,.jpg image/jpeg au声音文件 .au audio/basic MIDI音乐文件 mid,.midi audio/midi,audio/x-midi RealAudio音乐文件 .ra, .ram audio/x-pn-realaudio MPEG文件 .mpg,.mpeg video/mpeg AVI文件 .avi video/x-msvideo GZIP文件 .gz application/x-gzip TAR文件 .tar application/x-tar

Internet中有一个专门组织IANA来确认标准的MIME类型,但Internet发展的太快,很多应用程序等不及IANA来确认他们使用的MIME类型为标准类型。因此他们使用在类别中以x-开头的方法标识这个类别还没有成为标准,例如:x-gzip,x-tar等。事实上这些类型运用的很广泛,已经成为了事实标准。只要客户机和服务器共同承认这个MIME类型,即使它是不标准的类型也没有关系,客户程序就能根据MIME类型,采用具体的处理手段来处理数据。而Web服务器和浏览器(包括操作系统)中,缺省都设置了标准的和常见的MIME类型,只有对于不常见的 MIME类型,才需要同时设置服务器和客户浏览器,以进行识别。

由于MIME类型与文档的后缀相关,因此服务器使用文档的后缀来区分不同文件的MIME类型,服务器中必须定义文档后缀和MIME类型之间的对应关系。而客户程序从服务器上接收数据的时候,它只是从服务器接受数据流,并不了解文档的名字,因此服务器必须使用附加信息来告诉客户程序数据的MIME类型。服务器在发送真正的数据之前,就要先发送标志数据的MIME类型的信息,这个信息使用Content-type关键字进行定义,例如对于HTML文档,服务器将首先发送以下两行MIME标识信息,这个标识并不是真正的数据文件的一部分。

Content-type:text/html

注意,第二行为一个空行,这是必须的 ,使用这个空行 的目的是将MIME信息与真正的数据内容分隔开。

MIME (Multipurpose Internet Mail Extensions) 是描述消息内容类型的因特网标准。 MIME 消息能包含文本、图像、音频、视频以及其他应用程序专用的数据。 官方的 MIME 信息是由 Internet Engineering Task Force (IETF) 在下面的文档中提供的: RFC-822 Standard for ARPA Internet text messages

RFC-2045 MIME Part 1: Format of Internet Message Bodies

RFC-2046 MIME Part 2: Media Types

RFC-2047 MIME Part 3: Header Extensions for Non-ASCII Text

RFC-2048 MIME Part 4: Registration Procedures

RFC-2049 MIME Part 5: Conformance Criteria and Examples

不同的应用程序支持不同的 MIME 类型。

· 11 分钟阅读
CheverJohn

第一章:随机事件及其概率(1)

第一部分

样本空间,随机事件

来自百度百科
样本空间

####### 随机事件E的所有基本结果组成的集合为E的样本空间。样本空间的元素称为样本点或基本事件

####### 举个例子:设随机试验E是"抛一颗骰子,观察出现的点数"。那么E的样本空间就是S:{1,2,3,4,5,6,}。

####### 有些实验有两个或多个可能的样本空间。

######## 举个例子:从52张扑克牌中随机抽出一张,一个可能的样本空间是数字(A到K),另外一个可能的样本空间是花色(黑桃,红桃,梅花,方块)。 如果要完整地描述一张牌,就需要同时给出数字和花色,这时的样本空间可以通过构建上述两个样本空间的笛卡尔乘积来得到。

随机事件

####### 子主题 4

######## 随机事件是指在随机试验中,可能出现也可能不出现,而在大量重复试验中具有某种规律性的事件叫做随机事件(简称事件)

######## 随机试验中的每一个可能出现的试验结果称为这个试验的一个样本点,全体样本点组成的集合称为这个试验的样本空间。

######## 仅含一个样本点的随机事件称为基本事件 含有多个样本点的随机事件称为复合事件

#######

####### 特点

######## 1、可以在相同的条件下重复进行

######## 2、每个试验的可能结果不止一个,并且能实现预测试验的所有可能结果

######## 3、进行一次试验之前不能确定哪一个结果会出现

####### 特殊事件

######## 必然事件

######### 必然事件记作Ω,样本空间Ω也是其自身的一个子集,Ω也是一个"随机"事件,每次试验中必定有Ω中的一个样本点出现,必然发生。

######## 不可能事件

######### 不可能事件记作Φ,空集Φ也是样本空间的一个子集,Φ也是一个特殊的"随机"事件,不包含任何样本点,不可能发生。

####### 事件关系

######## 事件A是事件B的子事件,事件A发生必然导致事件B发生,事件A的样本点都是事件B的样本点,记作A⊂B。

######## 若A⊂B且B⊂A,那么A=B,称A和B为相等事件,事件A与事件B含有相同的样本点。

######## 和事件发生,即事件A发生或事件B发生,事件A与事件B至少一个发生,由事件A与事件B所有样本点组成,记作A∪B。

######## 积事件发生,即事件A和事件B同时发生,由事件A与事件B的公共样本点组成,记作AB或A∩B。

####### 事件种类

######## 互斥事件

######### 互斥事件(互不相容事件)事件A与事件B,AB=Φ,事件A与事件B不能同时发生,事件A与事件B没有公共的样本点。

######## 对立事件

######### 事件A的对立事件,事件A不发生,事件A的对立事件是由不属于事件A的样本点组成,记作ā。

######## 差事件

######### 差事件发生,即事件A发生且事件B不发生,是由属于事件A但不属于事件B的样本点组成,记作A-B。

来自维基百科
1.例子

####### 假设我们有一堆52张的扑克牌,并闭着眼睛在这堆牌中抽取一张牌,那么用概率论的术语来说,我们实际上是在做一个随机试验。这时,我们的样本空间是一个有着52个元素的集合,因为任意一张牌都是一个可能的结果。而一个随机事件,则是这个样本空间的任意一个子集(这个任意子集包括空集,一个元素的集合及多个元素的集合)。运用组合知识可以知道,随机事件一共有2\^52种。当这个事件仅仅包括样本空间的一个元素(或者说它是一个单元素集合)的时候,称这个事件为一个基本事件。比如说事件"抽到的牌是黑桃7"。当事件是空集时,称这个事件为不可能事件。当事件是全集时,则称事件是必然事件。其它还有各种各样的事件,比如: "抽到的牌是小丑"(也是不可能事件) "抽到的牌是红桃3"(基本事件) "抽到的牌数字是9"(包含4个元素) "抽到的牌是方块"(包含13个元素) "抽到的牌是红颜色的并且数字小于等于10"(包含20个元素) "抽到的牌不是红桃3"(包含51个元素) 由于事件是样本空间的子集,所以也可以写成集合的形式。有时候写成集合的形式可能会很困难。有时候也可以用文氏图来表示事件,这时可以用事件所代表图形的面积来按比例显示事件的概率。

事件的相互关系及运算

频率

概率

第二部分

等可能概型(古典概型)

基本描述
定义:古典概型也叫传统概率,其定义是由法国数学家拉普拉斯 (Laplace ) 提出的。如果一个随机试验所包含的单位事件是有限的,且每个单位事件发生的可能性均相等,则这个随机试验叫做拉普拉斯试验,这种条件下的概率模型就叫古典概型。
在这个模型下,随机实验所有可能的结果是有限的,并且每个基本结果发生的概率是相同的。古典概型是概率论中最直观和最简单的模型,概率的许多运算规则,也首先是在这种模型下得到的。
定义
(1) 试验中所有可能出现的基本事件只有有限个;

####### 有限性

(2) 试验中每个基本事件出现的可能性相等。

####### 等可能性

具有以上两个特点的概率模型是大量存在的,这种概率模型称为古典概率模型,简称古典概型,也叫等可能概型。
古典概型的判断
一个试验是否为古典概型,在于这个试验是否具有古典概型的两个特征------有限性和等可能性,只有同时具备这两个特点的概型才是古典概型。
概率公式
P(A)= m/n =A包含的基本事件的个数m/基本事件的总数n
如果一次实验中可能出现的结果有n个,而且所有结果出现的可能性都相等,那么每一个基本事件的概率都是 1/n ; 如果某个事件A包含的结果有m个,那么事件A的概率为P(A)= m/n =A包含的基本事件的个数m/基本事件的总数n

条件概率

全概率公式与贝叶斯公式

事件独立性

第二章:随机变量及其分布(1)

第一部分

随机变量

离散型随机变量

分布函数

第二部分

连续型随机变量及其概率密度

均匀分布与指数分布

正态分布

随机变量函数的分布

第三部分

二元随机变量,离散型随机变量分布律

二元离散型随机变量边际分布律与条件分布律

不用看

二元随机变量分布函数、边际分布函数及条件分布函数

了解一下边缘分布函数即可

二元连续性随机变量,联合概率密度

自个笔记
子主题 1

第四部分

二元连续型随机变量边际概率密度

二元连续型随机变量条件概率密度

不用看

二元均匀分布,二元正态分布

随机变量的独立性

第五部分

二元随机变量函数的分布

Z=X+Y的分布

max(X,Y)和min(X,Y)的分布

第三章:随机变量的数字特征

第一部分

随机变量的数学期望

随机变量函数的数学期望

数学期望的性质

方差定义和计算公式

第二部分

方差的性质

协方差与相关系数

不相关与独立

矩,协方差矩阵,多元正态分布的性质

· 13 分钟阅读
CheverJohn

一、首先说一下什么是递归

  1. 递归的本质是,某个方法调用了本身,本质还是调用一个方法,只是这个方法它恰好就是本身而已

  2. 递归因为是在自身中调用自身,所以会有下面三个较为显著的特点:

    1. 调用的是同一个方法

    2. 因为1,所以只需要写一个方法,就可以让你轻松调用无数次,所以调用的方法可大可小,具体取决于你的实际案例

    3. 在自身中调用自身,是嵌套调用(栈帧无法回收,开销巨大)

  3. 结合以上2和3的两个特点,所以递归调用最大的诟病就是开销巨大,栈帧和堆有时候会一起爆掉,俗称内存溢出

  4. 既然会导致内存溢出的话,我们就提出了尾递归这样一种解决思路

二、尾递归优化

  1. 尾递归优化是利用上面的第一个特点“调用同一个方法”来进行优化的

  2. 尾递归优化其实包括两个东西:1)尾递归的形式;2)编译器对尾递归的优化

    1. 尾递归的形式:
      1. 尾递归其实只是一种对递归的特殊写法,这种写法原本并不会带来跟递归不一样的影响,它只是写法不一样而已,写成这样不会有任何优化效果,该爆的栈和帧都还会爆
      2. 那么具体的不一样体现在哪里呢
        1. 前面说了,递归的本质是某个方法调用了自身,尾递归这种形式就要求:某个方法调用自身这件事,一定是该方法做的最后一件事(所以当有需要返回值的时候会是return f(n),没有返回的话就直接是f(n)了)
      3. 要求很简单,就是只有一条,但是有一些常见的误区
        1. 这个f(n)外不能加其他东西,因为这就不是最后一件事了,值返回来后还要再干点其他的活,变量空间还需要保留
          1. 比如如果有返回值的,你不能:乘个常数 return 3f(n);乘个n return n*f(n);甚至是 f(n)+f(n-1)
      4. 另外,使用return的尾递归还跟函数式编程有一点关系
  3. 为什么写成尾递归的形式,编译器就能优化了?或者说【编译器对尾递归的优化】的一些深层思想

    1. 说是深层思想,其实也是因为正好编译器其实在这里没做什么复杂的事,所以很简单
    2. 由于这两方面的原因,尾递归优化得以实现,而且效果很好
      1. 因为在递归调用自身的时候,这一层函数已经没有要做的事情了,虽然被递归调用的函数是在当前的函数里,但是他们之间的关系已经在传参的时候了断了,也就是这一层函数的所有变量什么的都不会再被用到了,所以当前函数虽然没有执行完,不能弹出栈,但它确实已经可以出栈了,这是一方面
      2. 另一方面,正因为调用的是自身,所以需要的存储空间是一毛一样的,那干脆重新刷新这些空间给下一层利用就好了,不用销毁再另开空间
    3. 有人对写成尾递归形式的说法是【为了告诉编译器这块要尾递归】,这种说法可能会导致误解,因为不是只告诉编译器就行,而是你需要做优化的前半部分,之后编译器做后半部分
  4. 所以总结:为了解决递归的开销大问题,使用尾递归优化,具体分两步:1)你把递归调用的形式写成尾递归的形式;2)编译器碰到尾递归,自动按照某种特定的方式进行优化编译

  5. 举例:

    (no尾递归)

    def recsum(x):
    if x == 1:
    return x
    else:
    return x + recsum(x - 1)

    (使用尾递归)

    def tailrecsum(x, running_total=0):
    if x == 0:
    return running_total
    else:
    return tailrecsum(x - 1, running_total + x)

但不是所有语言的编译器都做了尾递归优化。比如C实现了,JAVA没有去实现

说到这里你很容易联想到JAVA中的自动垃圾回收机制,同是处理内存问题的机制,尾递归优化跟垃圾回收是不是有什么关系,这是不是就是JAVA不实现尾递归优化的原因?

三、所以下面要讲一下垃圾回收(GC)

  1. 首先我们需要谈一下内存机制,这里我们需要了解内存机制的两个部分:栈和堆。下面虽然是在说JAVA,但是C也是差不多的
    1. 在Java中, JVM中的栈记录了线程的方法调用。每个线程拥有一个栈。在某个线程的运行过程中, 如果有新的方法调用,那么该线程对应的栈就会增加一个存储单元,即栈帧 (frame)。在frame 中,保存有该方法调用的参数、局部变量和返回地址
    2. Java的参数和局部变量只能是 基本类型 的变量(比如 int),或者对象的引用(reference) 。因此,在栈中,只保存有基本类型的变量和对象引用。而引用所指向的对象保存在堆中。
  2. 然后由栈和堆的空间管理方式的不同,引出垃圾回收的概念
    1. 当被调用方法运行结束时,该方法对应的帧将被删除,参数和局部变量所占据的空间也随之释放。线程回到原方法,继续执行。当所有的栈都清空时,程序也随之运行结束。
    2. 如上所述,栈 (stack)可以自己照顾自己。但堆必须要小心对待。堆是 JVM中一块可自由分配给对象的区域。当我们谈论垃圾回收 (garbage collection) 时,我们主要回收堆(heap)的空间
    3. Java的普通对象存活在堆中。与栈不同,堆的空间不会随着方法调用结束而清空(即使它在栈上的引用已经被清空了)(也不知道为什么不直接同步清空)。因此,在某个方法中创建的对象,可以在方法调用结束之后,继续存在于堆中。这带来的一个问题是,如果我们不断的创建新的对象,内存空间将最终消耗殆尽。
    4. 如果没有垃圾回收机制的话,你就需要手动地显式分配及释放内存,如果你忘了去释放内存,那么这块内存就无法重用了(不管是什么局部变量还是其他的什么)。这块内存被占有了却没被使用,这种场景被称之为内存泄露
  3. 所以不管是C还是JAVA,最原始的情况,都是需要手动释放堆中的对象,C到现在也是这样,所以你经常需要考虑对象的生存周期,但是JAVA则引入了一个自动垃圾回收的机制,它能智能地释放那些被判定已经没有用的对象

四、现在我们就可以比较一下尾递归优化和垃圾回收了

  1. 富士达他们最本质的区别是,尾递归优化解决的是内存溢出的问题,而垃圾回收解决的是内存泄露的问题

    1. 内存泄露:指程序中动态分配内存给一些临时对象,但是对象不会被GC所回收,它始终占用内存。即被分配的对象可达但已无用。
    2. 内存溢出:指程序运行过程中无法申请到足够的内存而导致的一种错误。内存溢出通常发生于OLD段或Perm段垃圾回收后,仍然无内存空间容纳新的Java对象的情况。
    3. 从定义上可以看出内存泄露是内存溢出的一种诱因,不是唯一因素。
  2. 自动垃圾回收机制的特点是:

    1. 解决了所有情况下的内存泄露的问题,但还可以由于其他原因内存溢出
    2. 针对内存中的堆空间
    3. 正在运行的方法中的堆中的对象是不会被管理的,因为还有引用(栈帧没有被清空)
      1. 一般简单的自动垃圾回收机制是采用 引用计数 (reference counting)的机制。每个对象包含一个计数器。当有新的指向该对象的引用时,计数器加 1。当引用移除时,计数器减 1,当计数器为0时,认为该对象可以进行垃圾回收
  3. 与之相对,尾递归优化的特点是:

    1. 优化了递归调用时的内存溢出问题

    2. 针对内存中的堆空间和栈空间

    3. 只在递归调用的时候使用,而且只能对于写成尾递归形式的递归进行优化

    4. 正在运行的方法的堆和栈空间正是优化的目标

最后可以解答一下前头提出的问题

  1. 通过比较可以发现尾递归和GC是完全不一样的,JAVA不会是因为有GC所以不需要尾递归优化。那为什么呢,我看到有的说法是:JAVA编写组不实现尾递归优化是觉得麻烦又没有太大的必要,就懒得实现了(原话是:在日程表上,但是非常靠后),官方的建议是不使用递归,而是使用while循环,迭代,递推