在编程中,我们常常需要引用多个相同的对象,但在解决特定问题时往往不知道需要生成多少个对象?它们需要存储多久?该如何存储这些对象?
在大多数数语言中都可以通过数组类型来实现这一需求,这类数组通常被称作为容器(也被成为集合)。容器自身会进行扩充,编程者不必在意会有多少个对象需要存储,只需要创建容器对象,然后让其帮你处理所有细节。
JAVA中常见的容器分为三类:
1.List
List用于存储序列,常见的导出类为ArrayList和LinkedList,它们都实现了List的接口。在ArrayList中,随机访问元素花费的时间是固定的,但往中间插入元素,开销会比LinkedList大;LinkedList随机访问元素的代价高昂,但随机插入元素的性能优异。
2.Map
Map被称为关联数组,用过存储键值对的形式,来建立对象之间的关联。
3.Set
存储的对象不会重复,常用于去重的场景。
除此之外还有队列、树、堆栈等构件,适用于不同的存储场景。
JAVA容器中存储的对象默认为Object类型,因其为单根继承结构,故所有对象都可以向上转型为Object对象,可以存储Object的容器便可以存储任意对象。
但对象向上转型,会使它丢失身份,当我们从容器中取回对象时,就获取了一个对Object类型的引用,这时就需要一个接口在获取对象时能够转为具体引用对象,这里需要用到向下转型,将需要获取的对象指定为泛型,用一对尖括号表示。
List<Shape> shapeList = new ArrayList<>();
向下转型通常是不安全的(如:正方形可以向上转型为几何形,但几何形向下转型不一定为正方形,它还有可能是圆形),故向下转型时需要程序员付出更多心血去思考,避免程序出错。
这里顺带一提JAVA的异常处理机制,异常处理依赖于程序员的警惕性,异常是一种对象,它从出错地点被“抛出”,并被相应的异常处理器“捕获”。异常处理就像是程序在正常路径发生错误时,执行另一条路径,从而不影响后续程序的正常运行。
在对象的使用中,我们还有一个不可忽视的问题:对象的生成与销毁。
每个对象为了生存都需要占用内存资源,当我们不再需要一个对象时,它必须被清理掉,使其被占用的资源被释放,否则易发生内存泄露。
在C++中,对象的生命周期是由程序员直接控制,这种方式将存储空间的分配和释放置于优先考虑的位置,必须在编写程序时知道对象的确切数量、生命周期和类型,这会使得问题变得复杂,牺牲了灵活性,但这也是为了追求最大的执行速度做出的牺牲。
JAVA采用动态内存分配方式,每当创建新对象时,就使用new关键字来进行构建,这种方式直到运行时才知道需要多少对象,对象在堆中创建,存储空间在运行时被动态管理,程序员不必关心对象会在何时会被释放,JAVA中的“垃圾回收器”可以自动发现不在使用的对象,并将其销毁,减少了编程时需要考虑的问题,可以避免暗藏的内存泄露,这也得益于JAVA对象都是源于Object的单根继承结构,简化了“垃圾回收器”的实现。
本次分享至此结束,希望本文对你有所帮助,若能点亮下方的点赞按钮,在下感激不尽,谢谢您的【精神支持】。
若有任何疑问,也欢迎与我交流,若存在不足之处,也欢迎各位指正!