黑马程序员技术交流社区

标题: 数组定义 [打印本页]

作者: 王春祥    时间: 2012-3-12 20:45
标题: 数组定义
本帖最后由 王春祥 于 2012-3-12 20:50 编辑

int[] a=new int []{1,2,3,4};和int[] a={1,2,3,4}没区别吗,第二句没有new也数组也创建了吗
声明,定义,创建之间什么关系
作者: 赵英坤    时间: 2012-3-12 21:04
没区别,都是在堆中创建了一个数组

下面那个什么关系我也是在没看懂你想说什么,把我积累的数组的资料跟你分享下吧

Java语法总结 - 数组

数组(array)是相同类型变量的集合,可以使用共同的名字引用它。数组可被定义为任何类型,可以是一维或多维。数组中的一个特别要素是通过下标来访问它。数组提供了一种将有联系的信息分组的便利方法。注意:如果你熟悉C/C++,请注意, Java数组的工作原理与它们不同。

1、数组不是集合,它只能保存同种类型的多个原始类型或者对象的引用。数组保存的仅仅是对象的引用,而不是对象本身。

2、数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。

3、数组声明的两种形式:一、int[] arr; 二、int arr[];  推荐使用前者,这符合Sun的命名规范,而且容易了解到关键点,这是一个int数组对象,而不是一个int原始类型。

4、在数组声明中包含数组长度永远是不合法的!如:int[5] arr; 。因为,声明的时候并没有实例化任何对象,只有在实例化数组对象时,JVM才分配空间,这时才与长度有关。

5、在数组构造的时候必须指定长度,因为JVM要知道需要在堆上分配多少空间。反例:int[] arr = new int[];

6、多维数组的声明。int[][][] arr; 是三维int型数组。

7、一维数组的构造。形如:String[] sa = new String[5]; 或者分成两句:String[] sa;  sa = new String[5];

8、原始类型数组元素的默认值。对于原始类型数组,在用new构造完成而没有初始化时,JVM自动对其进行初始化。默认值:byte、short、 int、long--0  float--0.0f double--0.0  boolean--false  char--'"u0000'。(无论该数组是成员变量还是局部变量)

9、对象类型数组中的引用被默认初始化为null。如:Car[] myCar = new Car[10]; 相当于从myCar[0]到myCar[9]都这样被自动初始化为myCar[i] = null;

10、对象类型的数组虽然被默认初始化了,但是并没有调用其构造函数。也就是说:Car[] myCar = new Car[10];只创建了一个myCar数组对象!并没有创建Car对象的任何实例!

11、多维数组的构造。float[][] ratings = new float[9][]; 第一维的长度必须给出,其余的可以不写,因为JVM只需要知道赋给变量ratings的对象的长度。

12、数组索引的范围。数组中各个元素的索引是从0开始的,到length-1。每个数组对象都有一个length属性,它保存了该数组对象的长度。(注意和String对象的length()方法区分开来,这两者没有统一起来是很遗憾的。)

13、Java有数组下标检查,当访问超出索引范围时,将产生ArrayIndexOutOfBoundsException运行时异常。注意,这种下标检查不是在编译时刻进行的,而是在运行时!也就是说int[] arr = new int[10];  arr[100] = 100; 这么明显的错误可以通过编译,但在运行时抛出!Java的数组下标检查是需要额外开销的,但是出于安全的权衡还是值得的,因为很多语言在使用数组时是不安全的,可以任意访问自身内存块外的数组,编译运行都不会报错,产生难以预料的后果!
作者: 冯林    时间: 2012-3-12 21:10
String s1=new String("ab");
String s2="ab";

他们的区别是什么?第一个语句有2个对象,第2个语句只有一个对象。数组和String都是引用类型。按此推算,不知道对不对?
作者: 赵英坤    时间: 2012-3-12 21:17
冯林 发表于 2012-3-12 21:10
String s1=new String("ab");
String s2="ab";

String是很特殊的,你写的这两句诗很不一样的,第一句是在堆中建的,第二句是在栈中的,我一两句也说不明白,照例贴上我的学习总结,希望对你有用


解析Java中的String对象的数据类型
  1. 首先String不属于8种基本数据类型,String是一个对象。
  因为对象的默认值是null,所以String的默认值也是null;但它又是一种特殊的对象,有其它对象没有的一些特性。
  2. new String()和new String(“”)都是申明一个新的空字符串,是空串不是null;
  3. String str=”kvill”;
   String str=new String (“kvill”);的区别:
  在这里,我们不谈堆,也不谈栈,只先简单引入常量池这个简单的概念。
  常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。
  看例1:
  String s0=”kvill”;
  String s1=”kvill”;
  String s2=”kv” + “ill”;
  System.out.println( s0==s1 );
  System.out.println( s0==s2 );
  结果为:
  true
  true
  首先,我们要知结果为道Java会确保一个字符串常量只有一个拷贝。
  因为例子中的s0和s1中的”kvill”都是字符串常量,它们在编译期就被确定了,所以s0==s1为true;而”kv”和”ill”也都是字符串常量,当一个字符串由多个字符串常量连接而成时,它自己肯定也是字符串常量,所以s2也同样在编译期就被解析为一个字符串常量,所以s2也是常量池中”kvill”的一个引用。
  所以我们得出s0==s1==s2;
  用new String() 创建的字符串不是常量,不能在编译期就确定,所以new String() 创建的字符串不放入常量池中,它们有自己的地址空间。
  看例2:
  String s0=”kvill”;
  String s1=new String(”kvill”);
  String s2=”kv” + new String(“ill”);
  System.out.println( s0==s1 );
  System.out.println( s0==s2 );
  System.out.println( s1==s2 );
  结果为:
  false
  false
  false
  例2中s0还是常量池中”kvill”的应用,s1因为无法在编译期确定,所以是运行时创建的新对象”kvill”的引用,s2因为有后半部分new String(“ill”)所以也无法在编译期确定,所以也是一个新创建对象”kvill”的应用;明白了这些也就知道为何得出此结果了。
  4. String.intern():
  再补充介绍一点:存在于.class文件中的常量池,在运行期被JVM装载,并且可以扩充。String的intern()方法就是扩充常量池的一个方法;当一个String实例str调用intern()方法时,Java查找常量池中是否有相同Unicode的字符串常量,如果有,则返回其的引用,如果没有,则在常量池中增加一个Unicode等于str的字符串并返回它的引用;看例3就清楚了
  例3:
  String s0= “kvill”;
  String s1=new String(”kvill”);
  
  String s2=new String(“kvill”);
  System.out.println( s0==s1 );
  System.out.println( “**********” );
  s1.intern();
  s2=s2.intern(); //把常量池中“kvill”的引用赋给s2
  System.out.println( s0==s1);
  System.out.println( s0==s1.intern() );
  System.out.println( s0==s2 );
  结果为:
  false
  **********
  false //虽然执行了s1.intern(),但它的返回值没有赋给s1
  true //说明s1.intern()返回的是常量池中”kvill”的引用
  true
  最后我再破除一个错误的理解:
  有人说,“使用String.intern()方法则可以将一个String类的保存到一个全局String表中,如果具有相同值的 Unicode字符串已经在这个表中,那么该方法返回表中已有字符串的地址,如果在表中没有相同值的字符串,则将自己的地址注册到表中“如果我把他说的这个全局的String表理解为常量池的话,他的最后一句话,“如果在表中没有相同值的字符串,则将自己的地址注册到表中”是错的:
  看例4:
  String s1=new String("kvill");
  String s2=s1.intern();
  System.out.println( s1==s1.intern() );
  System.out.println( s1+" "+s2 );
  System.out.println( s2==s1.intern() );
  结果:
  false
  kvill kvill
  true
  在这个类中我们没有声名一个”kvill”常量,所以常量池中一开始是没有”kvill”的,当我们调用s1.intern()后就在常量池中新添加了一个”kvill”常量,原来的不在常量池中的”kvill”仍然存在,也就不是“将自己的地址注册到常量池中”了。
  s1==s1.intern()为false说明原来的“kvill”仍然存在;
  s2现在为常量池中“kvill”的地址,所以有s2==s1.intern()为true。
  5. 关于equals()和==:
  这个对于String简单来说就是比较两字符串的Unicode序列是否相当,如果相等返回true;而==是比较两字符串的地址是否相同,也就是是否是同一个字符串的引用。
  6. 关于String是不可变的
  这一说又要说很多,大家只要知道String的实例一旦生成就不会再改变了,比如说:String str=”kv”+”ill”+” “+”ans”;

  就是有4个字符串常量,首先”kv”和”ill”生成了”kvill”存在内存中,然后”kvill”又和” “ 生成 ”kvill “存在内存中,最后又和生成了”kvill ans”;并把这个字符串的地址赋给了str,就是因为String的“不可变”产生了很多临时变量,这也就是为什么建议用StringBuffer的原因了,因为StringBuffer是可改变的
作者: 赵英坤    时间: 2012-3-12 21:21
本帖最后由 赵英坤 于 2012-3-12 21:24 编辑
冯林 发表于 2012-3-12 21:10
String s1=new String("ab");
String s2="ab";


额,网速不好,多点了几次。。。莫怪
作者: 潘许超    时间: 2012-3-12 23:19
数组的定义

就是同一种类型数据的集合,数组就是一个 容器。

好处:可以自动给数组中的元素从0开始编号,方便操作这些元素

格式:元素类型[] 数组名=new 元素类型(元素个数或数组长度);int[] num=new int(3); x[0]=59;

new 是用来在内存中产生一个容器内存实体。数组是一个引用数据类型

元素类型[] 数组名= new 元素类型[] {元素1,元素2}这是一种静态初始化方式

java在内存中开辟了5个内存分配空间:栈和堆以及以后要讲的三个方法区,本地方法区,寄存器

作者: 冯建鹏    时间: 2012-3-13 00:31
看毕老师的视频,两者的区别应该就是产生对象的个数问题吧,int[] a=new int []{1,2,3,4};产生两个对象
int[] a={1,2,3,4}产生一个对象。
作者: 刘_浩    时间: 2012-3-13 00:38
没有区别。用到new是在堆中开辟了一个存储空间,如果没有赋值的话,将是默认值。而你刚写的int[] a=new int []{1,2,3,4};和int[] a={1,2,3,4}都已经存在实实在在的元素,所以开辟和存储都做了。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2