
这么多容器都是java帮助我们实现好的方法,在实际上我们就不用再去自己实现这么多数据结构来帮助我们完成任务,java里面就封装好了。
目录
[2.1 Stack的成员变量](#2.1 Stack的成员变量)
[2.2 构造方法](#2.2 构造方法)
[2.3 添加方法(push)](#2.3 添加方法(push))
[2.3 删除方法(pop)](#2.3 删除方法(pop))
[2.4 获取栈顶元素(peek)](#2.4 获取栈顶元素(peek))
[2.5 判断栈是否为空(empty)](#2.5 判断栈是否为空(empty))
[2.6 判断栈里面是否有该元素(search)](#2.6 判断栈里面是否有该元素(search))
一、关于栈(Stack)
首先就是使用Stack命名的这个接口的栈,因为这个命名风格直接就是一个栈。但是他是有线程安全的,就是里面的方法都加入了 synchronized 线程锁,此时在项目中使用就有可能因为线程阻塞等待而导致程序的运行效率的问题,但是这个问题又不是你的代码的效率问题,而是因为这个线程阻塞等待引起的效率降低,所以不建议使用这个Stack来使用栈。
1.1.1导入包+创建对象
下面就不演示使用,简单的看一下源代码中是否被synchronized修饰。
java
import java.util.Stack;
public class Test01 {
public static void main(String[] args) {
Stack t = new Stack();
}
}
1.1.2 总体概括
一共是有六个方法,下面会详细的看待源代码来解析。

二、java源代码的详细解析
2.1 Stack的成员变量
在java源代码中,Stack并没有成员变量,因为Stack继承了Vector 这个类对象,所以Stack 是Vector 的子类,因为变长数组Vector 的成员变量可以完美的实现栈Stack 这个数据结构,所以成员变量的定义都在父类里面,可以理解为Stack 的功能只是Vector 的缩水版本。

2.2 构造方法
是的,java中Stack的构造方法是一个空的,目的就是为了防止编译器自动编译生成,那我Stack 创建出对象但是没有真正 的给里面分配内存空间 ,只是拿到了这个Stack 的壳子,那我添加元素该怎么办呢?那就是push的工作了,下面看push。
java
public Stack() {
}
2.3 添加方法(push)
java里面,Stack 把这个添加元素这个方法调用的是父类的,所以给Stack创建空间就是在addElement 这个函数里面,虽然Stack里面的push函数没有被synchoronized 修饰,那push这个函数就是一个线程不安全 的函数吗?
答案在push这里面看不出来,我们去看push调用的这个addElement 函数,发现过去它是Vector 这个父类中的函数,但是这个函数却是被synchronized 修饰的函数,所以线程也是安全的。具体的添加方法的简单实现在下面再写一个简短的代码。

2.3 删除方法(pop)
在这里它删除之前要先获取当前栈里面的元素,然后使用removeElementAt这个函数来让元素的size--;
但是它获取了元素,那栈里面是空的怎么办?
那栈是空的,我获取一个null的引用,然后返回这个空的引用,程序没问题吧。
那栈中元素减少一,你都是空的了,怎么减少?
在减少操作中是removeElementAt 这个函数来实现这个操作的,这个函数也是Vector类里面的函数,这里的只是调用了这个函数。那pop函数里面为空会不会抛异常呢,答案是会的,当我们栈的里面的元素是空的的时候,在len - 1 这里传递的下表就是 -1,在removeElementAt 这个函数中,下表不合法会抛出 ArrayIndexOutOfBoundsException这个异常。
具体实现看下面的图。他已经帮我们考虑好了。细节逻辑这里就不展开了。

2.4 获取栈顶元素(peek)
为什么是获取 len - 1 元素呢?
因为基础的栈的指向都是指向栈顶元素的下一个位置 ,也可以理解为下一个元素需要放置的位置。
但是这里如果栈为空 ,你还想要获取栈顶元素 ,这里就会抛出异常 ,直接让程序终止 。那pop函数 里面没有直接抛出异常 ,但是抛出异常的操 作是在removeElementAt 这个函数里面抛出 ArrayIndexOutOfBoundsException这个异常的。
所以栈为空的时候不管是 pop,还是peek都会抛出异常,让这个程序异常终止,除非我们去捕获异常来提前处理。

2.5 判断栈是否为空(empty)
判断是否为空就是非常简单了,下面的代码一看就了解,这里就不展开了。
总的来说还是去调用父类Vector 里面实现好的函数,实现了函数的复用。栈里面没有元素,那size() 获取到的就是 0,此时 0 == 0 返回 "true "。如果有元素 就返回了 false;

2.6 判断栈里面是否有该元素(search)
这里也可以理解为在栈里面查找元素并返回下标)
这里也是直接调用父类Vector里面已经实现好的查找函数,直接找到改下标,如果找到了,就返回>= 0 的值,如果没找到就返回 -1,因为它的底层还是数组,下标不会有负数的。所以负数就代表没有这个元素,也就没找到。
