Java数组与堆栈相关知识总结

一、数组创建

1.1 声明并赋值

int[] a = {1,2,3};

1.2 声明数组名开辟空间并且赋值

int[] a;
a = new int[]{1,2,3};

1.3 声明数组时指定元素个数然后赋值

int[] a= new int[3];

这里Java会默认数组元素值为0

1.4 在以上的基础上创建多维数组

int[][] a = {{1,2,3},{4,5,6},{7,8,9}}; //每个子数组元素个数不要求均相同
int[][] a = new int[m][n]; //其中n可以省略,在创建的时候可以指定
int[][][] a = new int[m][n][q]; //同样其中n、q可以省略

同样的,在new一个数组时,如不初始化,Java会默认数组元素值为0。

二、数据类型

Java中的数据类型有两种:

2.1 八种基本数据类型

  • int
  • short
  • long
  • byte
  • float
  • double
  • boolean
  • char

这种类型的定义是通过诸如int a = 3; long b = 255L;的形式来定义的,称为自动变量。
自动变量存的是字面值,这些字面值固定定义在某个程序块里面,程序块退出后,字段值就消失了,出于追求速度的原因,就存在于栈中。

2.2 包装类数据

包装类的数据是如 Integer, String, Double等将相应的基本数据类型包装起来的类。这些类数据全部存在于堆中,Java用new()语句来显式地告诉编译器,在运行时才根据需要动态创建,因此比较灵活,但缺点是要占用更多的时间。
String是一个特殊的包装类数据。即可以用String str = "abc";的形式来创建,也可以用String str = new String("abc");的形式来创建。String str = "abc";中,并没有通过new()来创建实例,因为String str = "abc"; 是存储在字符串常量池中。 字符串常量池则存在于方法区。
JVM为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化。

1.为字符串开辟一个字符串常量池,类似于缓存区。

2.创建字符串常量时,首先坚持字符串常量池是否存在该字符串。存在该字符串,

3.返回引用实例,不存在,实例化该字符串并放入池中。

String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true

可以看到结果是true,结果说明,JVM创建了两个引用str1和str2,但只创建了一个对象,而且两个引用都指向了这个对象。

String str1 = "abc";
String str2 = "abc";
str1 = "bcd";
System.out.println(str1 + "," + str2); //bcd, abc
System.out.println(str1==str2); //false

参考上面的代码可以知道,赋值的变化导致了类对象引用的变化,str1指向了另外一个新对象!而str2仍旧指向原来的对象。上例中,当我们将str1的值改为"bcd"时,JVM发现在栈中没有存放该值的地址,便开辟了这个地址,并创建了一个新的对象,其字符串的值指向这个地址。
事实上,String类被设计成为不可改变(immutable)的类。如果你要改变其值,可以,但JVM在运行时根据新值悄悄创建了一个新对象,然后将这个对象的地址返回给原来类的引用。这个创建过程虽说是完全自动进行的,但它毕竟占用了更多的时间。在对时间要求比较敏感的环境中,会带有一定的不良影响。
因此,并没有与String是不可变的相矛盾。
继续修改代码:

String str1 = "abc";
String str2 = "abc";
str1 = "bcd";
String str3 = str1;
System.out.println(str3); //bcd
String str4 = "bcd";
System.out.println(str1 == str4); //true

可以看出,str3 这个对象的引用直接指向str1所指向的对象(注意,str3并没有创建新对象)。当str1改完其值后,再创建一个String的引用str4,并指向因str1修改值而创建的新的对象。可以发现,这回str4也没有创建新的对象,从而再次实现栈中数据的共享。
继续修改代码:

String str1 = new String("abc");
String str2 = "abc";
System.out.println(str1==str2); //false

可以发现此时返回false,这是因为通过new出来的放在了中,而第二个存于栈中,所以不相等。
另外:数据类型包装类的值不可修改。不仅仅是String类的值不可修改,所有的数据类型包装类都不能更改其内部的值。

三、栈、栈、方法区

是一种连续储存的数据结构,具有先进后出的性质。
是一种非连续的树形储存数据结构,每个节点有一个值,整棵树是经过排序的。特点是根结点的值最小(或最大),且根结点的两个子树也是一个堆。常用来实现优先队列,存取随意。
(stack)与(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。

3.1 栈

1.每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象)。

2.每个栈中的数据(原始类型和对象引用)都是私有的。

3.栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)

4.数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会自动消失。

通常的操作有入栈(压栈),出栈和栈顶元素。想要读取栈中的某个元素,就是将其之间的所有元素出栈才能完成。

栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。
另外,栈数据可以共享
类似于int a = 3;等都是存放于栈中,当新创建值时Java会判断栈中是否已存在,若存在则引用该地址,不存在则创建。例如:

 int a = 3; int b = 3;

编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找有没有字面值为3的地址,没找到,就开辟一个存放3这个字面值的地址,然后将a指向3的地址。接着处理int b = 3;在创建完b的引用变量后,由于在栈中已经有3这个字面值,便将b直接指向3的地址。这样,就出现了a与b同时均指向3的情况。
特别注意的是,这种字面值的引用与类对象的引用不同。假定两个类对象的引用同时指向一个对象,如果一个对象引用变量修改了这个对象的内部状态,那么另一个对象引用变量也即刻反映出这个变化。相反,通过字面值的引用来修改其值,不会导致另一个指向此字面值的引用的值也跟着改变的情况。如上例,我们定义完a与 b的值后,再令a=4;那么,b不会等于4,还是等于3。在编译器内部,遇到a=4;时,它就会重新搜索栈中是否有4的字面值,如果没有,重新开辟地址存放4的值;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。

3.2 堆

的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。

1.存储的是对象,每个对象都包含一个与之对应的class。

2.JVM只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身。

3.对象的由垃圾回收器负责回收,因此大小和生命周期不需要确定。

3.3 方法区

1.静态区,跟堆一样,被所有的线程共享。

2.方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量

字符串常量池则存在于方法区

 字

符串对象的创建 面试题

面试题:String str4 = new String(“abc”) 创建多少个对象?

1、在常量池中查找是否有“abc”对象。

1)有则返回对应的引用实例;

2)没有则创建对应的实例对象。

2、在堆中 new 一个 String(“abc”) 对象。

3、将对象地址赋值给str4,创建一个引用。

所以,常量池中没有“abc”字面量则创建两个对象,否则创建一个对象,以及创建一个引用。

到此这篇关于Java数组与堆栈相关知识总结的文章就介绍到这了,更多相关Java数组与堆栈内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • java自带的工具Jstack截取进程中的堆栈信息

    在Java软件的使用过程中,有时会莫名的出现奇怪的问题.而这些问题常常无法使用日志信息定位,这时我们就需要通过查看进程内部线程的堆栈调用关系来分析问题出在哪里. 举个例子,当我们在做某个操作时,莫名的会弹出多个警告框,其中有些信息是正常的,有些则不是.对于这些错误的警告信息,我们该如何定位是哪个位置的代码出现了错误弹出的框呢? 我们就需要在弹框以后,去查看软件的各个线程,去查找究竟是哪个线程导致了该问题.可是有时因为环境.时间等问题,我们根本不能拿着IDE去调试, 只能通过工具软件拍下内存快照,

  • 详解Java线程堆栈

    写在前面: 线程堆栈应该是多线程类应用程序非功能问题定位的最有效手段,可以说是杀手锏.线程堆栈最擅长与分析如下类型问题: 系统无缘无故CPU过高. 系统挂起,无响应. 系统运行越来越慢. 性能瓶颈(如无法充分利用CPU等) 线程死锁.死循环,饿死等. 由于线程数量太多导致系统失败(如无法创建线程等). 如何解读线程堆栈 如下面一段Java源代码程序: package org.ccgogoing.study.stacktrace; /** * @Author: LuoChong400 * @Des

  • Java基础语法之二维数组详解

    一.二维数组 进入正题之前.首先为了便于大家理解,我画了一个图: xx枪战游戏中, 我是一个刚刚注册账号的小白,系统送了我两把枪,此时,我的武器库只有这么一层(可以理解为一位数组,枪就是对应的数组中对应的元素) 经过艰苦卓绝的战斗,终于有了一笔钱,现在我打算配置好的游戏装备,我现在有了一个枪柜,它可以存放三层的枪械,每一层都可以放多把武器(这个就是二维数组,有多层,每层都是一个一维数组) 随着游戏时长和我的高超技术,获取游戏装备的效率越来越高了,一个枪柜已经存不下了,于是,我就有了多个枪柜(这个

  • 浅谈Java数组的一些使用方法及堆栈存储

    数组 用于存储一组同一数据类型数据的容器 数组会对放入其中的数据自动编号,编号是从0开始的---下标 定义格式 数据类型[] 数组名 = new 数据类型[数组的大小];---可以先声明再初始化 int[] arr = new int[5];---定义了一个最多能存储5的整数的数组 arr[3] = 4; arr[3]---通过数组名[下标]的形式来获取数组元素或者给对应的位置赋值 数据类型[] 数组名 = new 数据类型[]{元素1,元素2--}; int[] arr = new int[]

  • Java实现二维数组和稀疏数组之间的转换

    前言 用Java实现二维数据和稀疏数组之间的转换 1. 需求和思路分析 1.1 以二维数组的格式模拟棋盘.地图等类似的二维结构为基础,与稀疏数组之间进行转化. 1.2 思路分析 二维数组转化为稀疏数组 遍历原始的二维数组,得到有效数据个数 sum 根据sum就可以创建稀疏数组sparseArr int[sunm+1][3] 将二维数组的有效数据存入到稀疏数组 稀疏数组转为二维数组 先读取稀疏数组的第一行,根据第一行的数据,创建原始的二维数组 再读取稀疏数组后几行的数据,并赋给原始的二维数组即可.

  • 输出java进程的jstack信息示例分享 通过线程堆栈信息分析java线程

    复制代码 代码如下: #!/bin/shpro_name=java #process namekeys=`ps -ef |grep "$pro_name" |grep -v "grep" | awk '{print $2}'`nowdate=`date +%Y%m%d%H%M%S` jstackpath="/usr/java/jdk1.6.0_07/bin/jstack"cpulogpath="/home/" for key

  • Java数组与堆栈相关知识总结

    一.数组创建 1.1 声明并赋值 int[] a = {1,2,3}; 1.2 声明数组名开辟空间并且赋值 int[] a; a = new int[]{1,2,3}; 1.3 声明数组时指定元素个数然后赋值 int[] a= new int[3]; 这里Java会默认数组元素值为0 1.4 在以上的基础上创建多维数组 int[][] a = {{1,2,3},{4,5,6},{7,8,9}}; //每个子数组元素个数不要求均相同 int[][] a = new int[m][n]; //其中n

  • Java基础之引用相关知识总结

    一.引用的定义 在JDK 1.2以前,Java中的引用定义很传统:如果reference类型的数据存储的数值代表的是另外一块内存的起始地址,就称这块内存代表着一个引用. 二.问题 当描述这样的一类对象:当内存空间还足够时,则能保留在内存之中,如果内存空间在进行垃圾收集后还是非常紧张,则可以抛弃这些对象.此时的引用就显得过于狭隘.因此在JDK 1.2之后,Java堆引用的概念进行了扩充. 三.引用的分类 回收时机 强引用 Strong Reference 类似Object obj = new Ob

  • Java基础之并发相关知识总结

    一.Java并发是什么? 用学术定义来说就是 并发:同一时间段,多个任务都在执行 (单位时间内不一定同时执行): 简单来说就是,同一个时间段,让计算机同时做多个事情. 说到并发,不得不提就是并行: 并行:单位时间内,多个任务同时执行. 两者大眼一看很像,仔细一想却并不相同,因为并行强调某个时间点多个任务同时执行,而并发强调的是一个时间段内多个任务都在执行. 二.怎么做? 大部分并发问题,最终都可以抽象成三类问题分工.同步和互斥.而且针对不同的问题有着不同的方式来解决,具体如下图所示: 三.分工

  • Java数据结构之链表相关知识总结

    一.链表 1.1 概述 链表是真正动态的数据结构,最简单的动态数据结构,基本用于辅助组成其他数据结构. 数据存储在"节点"(Node)中 优点:真正的动态,不需要处理固定容量的问题 缺点:丧失了随机访问的能力 1.2 链表使用的基本功能 定义Node节点 private class Node{ public E e; public Node next; public Node(E e, Node next){ this.e = e; this.next = next; } public

  • 详解Java中的数组与字符串相关知识

    Java数组的定义和使用 如果希望保存一组有相同类型的数据,可以使用数组. 数组的定义和内存分配 Java 中定义数组的语法有两种: type arrayName[]; type[] arrayName; type 为Java中的任意数据类型,包括基本类型和组合类型,arrayName为数组名,必须是一个合法的标识符,[ ] 指明该变量是一个数组类型变量.例如: int demoArray[]; int[] demoArray; 这两种形式没有区别,使用效果完全一样,读者可根据自己的编程习惯选择

  • 总结一下Java回调机制的相关知识

    一.回调 回调分为同步回调和异步回调, 假如以买彩票的场景来模拟, 我买彩票, 调用彩票网,给我返回的结果确定是否中奖,同步回调就是,我买了彩票之后, 需要等待彩票网给我返回的结果, 这个时候我不能做其他事情, 我必须等待这个结果, 这就叫同步回调, 同步, 就意味着等待, 我不能去做其他事情, 必须等待, 异步回调就是, 我买了彩票之后, 可以去做其他事情, 然后当彩票网有了结果和消息, 再给我返回消息, 其中最明显的方式就是在得到彩票结果的函数之中, 添加一个其他的方法, 如果我的其他方法可

  • 关于Java数组查询的相关问题及实例 原创

    在做数组查询的过程中,我们有时候会遇到一些问题,下面就跟随作者一起解答这些问题. Arrays 类的 binarySearch() 方法,可使用二分搜索法来搜寻指定数组,以获得指定对象.该方法返回要搜索元素的索引值. binarySearch()方法提供了多种重载形式,用于满足各种类型数组的查找需要. binarySearch()方法有两种参数类型. (1)binarySearch(Object[] a.Object key) 其中a 代表要所搜的数组,key 表示要搜索的值.如果key 包含在

  • Java基于socket编程相关知识解析

    一.网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输. 在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可以唯一地确定Internet上的一台主机. 而TCP层则提供面向应用的可靠(tcp)的或非可靠(UDP)的数据传输机制,这是网络编程的主要对象,一般不需要关心IP层是如何处理数据的. 目前较为流行的网络编程模型是客户机/服务器(C/S)结构.即通信双方一方作为服务器等待客户提出请求并予以响应.客户则

  • 深入学习JAVA GC日志的相关知识

    GC环境模拟 首先我们给出如下代码用来触发GC public static void main(String[] args) { // 每100毫秒创建100线程,每个线程创建一个1M的对象,即每100ms申请100M堆空间 Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> { for (int i = 0; i < 100; i++) { new Thread(() -> { try { // 申请1M byte

  • java中数组的相关知识小结(推荐)

    1. 2.数组的命名方法 1)int[]ages=new int[5]; 2) int[]ages; ages=new int[5]; 3)int[]ags={1,2,3,4,5}; 4)int[]ags; ags=new int{1,2,3,4}; 或者 int[]ags=new int{1,2,3,4}; 3.java不支持不同类型的重名数组 4.java中数组的循环赋值 package dierge; public class Shuzu { public static void main

随机推荐