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

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

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

  数组初始化可以在声明是进行,int[] arr = {1,2,3}或者int[] arr = new int[3]{1,2,3}。

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的数组下标检查是需要额外开销的,但是出于安全的权衡还是值得的,因为很多语言在使用数组时是不安全的,可以任意访问自身内存块外的数组,编译运行都不会报错,产生难以预料的后果!

使用reflict.Array创建Array实例

import java.util.*;
import java.lang.reflect.*; public class ArrayTest {
public static void main(String...args) {
int[] arr = (int[])Array.newInstance(Integer.TYPE, 10);
Random r = new Random(100);
for(int i =0; i<arr.length; i++) {
arr[i] = r.nextInt(100);
}
System.out.println(Arrays.toString(arr));
}
}

1、 不能用“==”比较两个字符串内容相等。

2、 对list做foreach循环时,循环代码中不能修改list的结构。

java foreach只能用于只读的情况.如果需要删除操作,请用迭代器或者直接遍历List.

3、 空指针异常。

4、 数组下标越界。

// 获取一个数组对象

String[] cIds = ContentService.queryByName(name);

if(null != cIds)

{

// 只是考虑到cids有可能为null的情况,但是cids完全有可能是个0长度的数组,因此cIds[0]有可能数组下标越界

5、 将字符串转换为数字时没有捕获NumberFormatException异常。

6、 对文件、IO、数据库等资源进行操作后没有及时、正确进行释放。

7、 循环体编码时不考虑性能,循环体中包含不需要的重复逻辑。

8、 数据类没有重载toString()方法。

9、 嵌套使用try-catch,或者try-catch后面没有必要的finally操作。

10、 equals操作时没有将常量放在equals操作符的左边。

java低级错误

  1. Calendar的错误使用

Calendar从星期日开始到星期六为一个周期,数字表示依次为:1,2,3……7;MONTH的表示是从数字0开始,所以月份应该是该数字+1。所以我们在使用的时候一定要仔细的阅读API文档,避免类似的陷阱。

  1. 序列化类的多版本问题

Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。当实现java.io.Serializable接口的实体(类)没有显式地定义serialVersionUID时,Java序列化机制会根据编译的class自动生成一个serialVersionUID作序列化版本比较用,这种情况下,只有同一次编译生成的 class才会生成相同的serialVersionUID

---解决方法:可以在程序一生成一个

serialVersionUID属性,这样运行

就不会出错。

  1. 正确定义hashcode
  2. 解读

类A覆写了hashCode方法,并采用A的属性value来生成A的hashCode。使用HashSet作为集合对象,把类A的一个对象a加入到HashSet中后,如果对象a的属性value发生了变化,则a的hashCode()方法返回的值也就发生变化,则无法将对象a从HashSet中删除。

预防措施如下:

1、如果覆写了equals方法,必须同时覆写hashCode方法。

2、equals方法和hashCode方法应避免使用易变的属性,避免该对象的hashCode频繁变化。

3、当对象被加入到HashSet(或作为Key加入到HashMap)后,应该避免该对象的hashCode发生变化。

4.正确理解Java的浅clone和深clone

浅clone和深clone都是clone,它们本质区别是对象内部的成员属性(非原生类型属性,如int等)在clone时是否处理为引用。如果仍然保留为引用,则称为浅clone,反之称为深clone。浅clone方式得到clone对象即可,深clone方式在得到clone对象后,还需要对引用的成员属性进行“clone”处理。使用Vector等容器的clone方法一定要注意:对于不变属性可以直接拷贝,对于可变属性需要手动写方法实现深层拷贝防止引用调用。深拷贝要深到什么程度,答案就是一直深到你想要的程度,包括深到不能再深的程度。

  1. 为什么定义equals方法的同时也要定义hashCode方法

equals方法用于实现对象之间逻辑上是否相等的判断,而不是判断两个引用是否指向同一个对象,hashCode用于返回对象的哈希码(也有翻译成散列码的),逻辑上相等(equals比较相等)的两个不同对象它们返回的hashCode值肯定不相等。 Java规范中规定:如果两个对象根据equals(Object)方法是相等的,那么调用这两个对象中任一个对象的hashCode方法必须产生同样的整数结果,所以定义equals的同时一定要定义hashCode,并且要保证equals比较相等的对象,hashCode返回值也必须相同。

如果定义了equals方法,没有定义hashCode,两个对象的hashCode却不同,Map查找对象的时候会首先比较hashCode值,然后再使用equals比较,造成Map无法找到期望的对象。

  1. 大小写转换的正确处理

String提供有大小写转换方法:String.toUpperCase()和String.toLowerCase(),另外还有带Locale参数的大小写转换方法:String.toUpperCase(Locale locale)和String.toLowerCase(Locale locale)。 String.toUpperCase(Locale locale)和String.toLowerCase(Locale locale)之所以要带Locale参数,就是希望你指定使用的是哪种语言,不带参数的String.toUpperCase()和String.toLowerCase()使用的是系统缺省的语言,例如操作系统的当前语言。有些语言的大小写转换使用了较特殊的规则,甚至不是1:1的字符对应关系,也就是说转换前和转换后的字符串长度不一定相等。

---如果在Eclipse的run对话框中显示告诉VM我用的是Turkish,那最后输出的结果已经不是我预期的大写的I了,而是另外一个字符(İ)。

这个例子充分说明,大小写转换因语言环境的不同,转换结果可能并非如你所预期的。

如果大小写转换之后你是要用于字符串比较(这样的转换纯粹是为了比较的方便),也就是在我们的26个字母通常大小写转换预期内,则强烈建议你显示指定“英文”的Locale(Local.US)。

如果你的大小写转换就是希望遵循当前使用软件的国家语言大小写转换习惯,则使用不带参数的String.toUpperCase()和String.toLowerCase()更好一些,这样的代码反而能够适应不同的语言环境。

  1. 使用包装器对象带来的低效问题

解读

每个基本类型(primitive)都有相应的包装器(wrapper)对象:Integer、Long、Float、Double、Short、Byte、Character和Boolean,我们在使用时不要直接new Integer对象(这样的做法是低效的),而应该调用包装器对象的valueOf方法

为什么以上代码是低效的,而要使用Integer result = Integer.valueOf(-1)或者Integer result = -1来代替?我们来看看JDK的Integer.valueOf方法实现

public static Integer valueOf(int i) {

final int offset = 128;

if (i >= -128 && i <= 127) { // must cache

return IntegerCache.cache[i + offset];

}

return new Integer(i);

}

可以看到内存中已经缓存有-128到127这个区间的256个Integer对象,如果方法传入的i值介于这个范围就不用再new Integer对象了,省去了运行时间,也节省了内存资源。另外的几个包装器对象( Long、Short、Byte、Character和Boolean )类似。

  1. 对于Map元素的遍历使用entrySet还是KeySet?

JDK实现的数据结构中常用的Map有两类:HashMap和TreeMap。keySet和entrySet在Map元素数较少时(小于10000)在查询速度上的区别不大,它们对于程序性能的影响可以忽略不计。但在元素较多时(大于100000)时entrySet的速度要明显快于keySet,尤其是TreeMap更明显。

  1. 对InputStream.skip()返回值的处理(隐藏的异常)

java.io.InputStream.skip(long n):跳过和放弃此输入流中的 n 个数据字节,返回的是跳过的实际字节数。如果skip方法的返回值小于要跳过得字节数,则说明有异常发生,此时需要对异常情况进行处理。

需要比较skip的返回值和输入参数,如果两者不相等时,需做特殊处理。

两者不相等的情况可能的原因有:

1)在跳过 n 个字节之前已到达文件的末尾;

2)输入参数为负;

  1. 正确理解String/StringBuffer/StringBuilder的区别

StringBuffer的内部实现方式和String不同,所以StringBuffer在进行字符串处理时,不生成新的对象,在内存使用上要优于String类。

StringBuilder提供一个与StringBuffer兼容的API,该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。两者的方法基本相同。

11.

  1. Java中流的操作,不要使用匿名流对象,以免出现异常,没有句柄,无法关闭

例子:

try

{

File file = new File("test.exe");

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));

//之后只关闭了一个流bis,匿名流new FileInputStream(file)没有关闭

........

}

改写之后:

try

{

File file = new File("test.exe");

FileInputStream fis = new FileInputStream(file);

BufferedInputStream bis = new BufferedInputStream(fis);

//之后关闭两个流fis和bis

........

}

这个效率相对低点
m.keySet().iterator()
以后最好用下面这个
jmap.entrySet().iterator()

关于JAVA数组的几点注意事项与一些低级错误的更多相关文章

  1. 把Java数组转换为List时的注意事项

    本文由 ImportNew - 飘扬叶 翻译自 mlangc.欢迎加入翻译小组.转载请见文末要求. 不幸的是并不是每件事都尽如人意.举个例子,现在将一个Java数组转换为List.当然,我们可以使用A ...

  2. Java 数组基础,java.util.Arrays

    定义数组 方式1(推荐,更能表明数组类型) 方式2(同C语言) 方式3定义时直接初始化 数组运用基础 数组长度 equals() 数组元素不为基本数据类型时 二维数组 二维数组基础 变长的二维数组 j ...

  3. Java与C++Socket通讯注意事项

    c++与java进行socket通信时注意事项 原文链接: http://my.oschina.net/ypimgt/blog/106439 因为java发送的都是网络字节序(big-endium), ...

  4. Java核心基础第4篇-Java数组的常规操作

    Java数组 一.数组简介 数组是多个相同类型数据的组合,实现对这些数据的统一管理 数组属引用类型,数组型数据是对象(Object) 数组中的元素可以是任何数据类型,包括基本类型和引用类型 数组类型是 ...

  5. Java 数组

    数组对于每一门编程语言来说都是重要的数据结构之一,当然不同语言对数组的实现及处理也不尽相同. Java语言中提供的数组是用来存储固定大小的同类型元素. 你可以声明一个数组变量,如numbers[100 ...

  6. 第5章 Java数组

    1.什么是数组 数组可以想象成一个巨大的盒子,这个盒子里面存放的是同一个数据类型的数据 例如:int[] scores = {78,68,94,93}; 2.如何使用Java中的数组 2.1申明数组 ...

  7. Java 数组基础

    数组 数组(Array):相同类型数据的集合. 定义数组 方式1(推荐,更能表明数组类型) type[] 变量名 = new type[数组中元素的个数]; 比如: int[] a = new int ...

  8. Java数组及其内存分配

    几乎所有的程序设计语言都支持数组.Java也不例外.当我们需要多个类型相同的变量的时候,就考虑定义一个数组.在Java中,数组变量是引用类型的变量,同时因为Java是典型的静态语言,因此它的数组也是静 ...

  9. [转载]Java数组扩容算法及Java对它的应用

    原文链接:http://www.cnblogs.com/gw811/archive/2012/10/07/2714252.html Java数组扩容的原理 1)Java数组对象的大小是固定不变的,数组 ...

随机推荐

  1. Oracle视图编译错误解决办法

    因为新搭的环境,数据库是从另一个现成的环境导过来的,直接后台用exp和imp命令操作.但是新环境的Oracle数据库有问题,一些视图创建不了,导致用到这些视图的视图和存储过程也编译不了.后来手工重新编 ...

  2. Linux 定时任务 crontab 讲解

    linux 系统则是由 cron (crond) 这个系统服务来控制的.Linux 系统上面原本就有非常多的计划性工作,因此这个系统服务是默认启动的.另 外, 由于使用者自己也可以设置计划任务,所以, ...

  3. laravel 中条件查询 function模式

    当需要条件查找时,可以使用下面的注入方法: //我要预约 yudoc_name yudoc_keshi yudoc_jibing yudoc_hospital 这是需要帅选的条件 public fun ...

  4. 关于urlDecode和tomcat一些源码

    1. 看下面源码,找到%号,每次加2,然后将16进制转换为int,也就是%号后两位加2得到16进制,转换为int ) < numChars) && (c=='%')) { ,i+ ...

  5. Java-Maven-Runoob:Maven 构建 Java 项目

    ylbtech-Java-Maven-Runoob:Maven 构建 Java 项目 1.返回顶部 1. Maven 构建 Java 项目 Maven 使用原型 archetype 插件创建项目.要创 ...

  6. 小程序中WXSS样式控制

    WXSS WXSS(WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式. WXSS 用来决定 WXML 的组件应该怎么显示. 为了适应广大的前端开发者,WXSS 具 ...

  7. 微信小程序的基本认识

    小程序与公众号的区别 小程序,不支持关注,消息推送等营销手段. 小程序更倾向于产品,公众号更倾向于营销. 在系统权限方面,小程序能够获得更多. 小程序与APP的区别 小程序,面向微信用户.app面向所 ...

  8. java成神之——注释修饰符

    注释修饰符 自定义注释 元注释 通过反射在runtime访问注释 内置注释 多注释实例 错误写法 使用容器改写 使用@Repeatable元注释 注释继承 使用反射获取注释 获取类的注释 获取方法的注 ...

  9. 可重复使用Tab切换代码和纯js代码

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  10. Android Studio 配置模拟器AVD存放路径(默认在c盘,解决c盘空间不够问题)

    Android Studio 安装之后,默认的会给我们创建一个 Nexus 的模拟器, 这个模拟器的镜像文件放在了 C:\Users\Administrator\.android  中 其中的avd文 ...