我是靠谱客的博主 神勇小霸王,最近开发中收集的这篇文章主要介绍数组一些底层原理,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

参考:
https://www.cnblogs.com/qlky/p/7351235.html

  1. Array父类是Object
public class Test {
public static void main(String[] args) {
int[] array = new int[10];
System.out.println("array的父类是:" + array.getClass().getSuperclass());
System.out.println("array的类名是:" + array.getClass().getName());
}
}
-------Output:
array的父类是:class java.lang.Object
array的类名是:[I
  1. 数组不同于类,没有生命任何成员变量、成员方法、构造函数、Annotation甚至连length成员变量这个都没有
public class Test {
public static void main(String[] args) {
int[] array = new int[10];
Class clazz = array.getClass();
System.out.println(clazz.getDeclaredFields().length);
System.out.println(clazz.getDeclaredMethods().length);
System.out.println(clazz.getDeclaredConstructors().length);
System.out.println(clazz.getDeclaredAnnotations().length);
System.out.println(clazz.getDeclaredClasses().length);
}
}
----------------Output:
0
0
  1. 用javap -verbose XX.class查看数组
int[] array1 = new int[10];
int length = array1.length;

javap -verbose XX.class显示:

0: bipush
10
//数组大小为10
2: newarray
int
//int数组
4: astore_1
//将数组的引用从操作数栈中弹出,保存在索引为1的局部变量(即array1)中
5: aload_1
//将索引为1的局部变量(即array1)压入操作数栈 
6: arraylength
//从操作数栈弹出数组引用(即array1),并获取其长度(JVM负责实现如何获取),并将长度压入操作数栈
7: istore_2
//将索引为2的局部变量(即length)压入操作数栈
8: return
  1. 性能

数组与其他种类的容器之间的区别有三个方面:效率、类型和保存基本类型的能力。在java中,数组是一种效率最高的存储和随机访问对象引用序列的方式

  1. 数组复制问题

若数组元素为对象,则数组里面数据是对象引用

通过Arrays.copyOf()方法产生的数组是一个浅拷贝。同时数组的clone()方法也是,集合的clone()方法也是,所以我们在使用拷贝方法的同时一定要注意浅拷贝这问题。

  1. 数组转换为List注意地方

我们经常需要使用到Arrays这个工具的asList()方法将其转换成列表。方便是方便,但是有时候会出现莫名其妙的问题。如下:

public static void main(String[] args) {
int[] datas = new int[]{1,2,3,4,5};
List list = Arrays.asList(datas);
System.out.println(list.size());
}
------------Output:
1

结果是1,是的你没有看错, 结果就是1。但是为什么会是1而不是5呢?先看asList()的源码

public static <T> List<T> asList(T... a) {
return new ArrayList<T>(a);
}

注意这个参数:T…a,这个参数是一个泛型的变长参数,我们知道基本数据类型是不可能泛型化的,也是就说8个基本数据类型是不可作为泛型参数的,但是为什么编译器没有报错呢?这是因为在java中,数组会当做一个对象来处理,它是可以泛型的,所以我们的程序是把一个int型的数组作为了T的类型,所以在转换之后List中就只会存在一个类型为int数组的元素了。所以我们这样的程序System.out.println(datas.equals(list.get(0)));输出结果肯定是true。当然如果将int改为Integer,则长度就会变成5了。

我们再看下面程序:

enum Week{Sum,Mon,Tue,Web,Thu,Fri,Sat}
public static void main(String[] args) {
Week[] weeks = {Week.Sum,Week.Mon,Week.Tue,Week.Web,Week.Thu,Week.Fri};
List<Week> list = Arrays.asList(weeks);
list.add(Week.Sat);
}

这个程序非常简单,就是讲一个数组转换成list,然后改变集合中值,但是运行呢?

Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:131)
at java.util.AbstractList.add(AbstractList.java:91)
at com.array.Test.main(Test.java:18)

编译没错,但是运行竟然出现了异常错误!UnsupportedOperationException ,当不支持请求的操作时,就会抛出该异常。从某种程度上来说就是不支持add方法,我们知道这是不可能的!什么原因引起这个异常呢?先看asList()的源代码:

public static <T> List<T> asList(T... a) {
return new ArrayList<T>(a);
}

这里是直接返回一个ArrayList对象返回,但是注意这个ArrayList并不是java.util.ArrayList,而是Arrays工具类的一个内之类:

private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable{
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;
ArrayList(E[] array) {
if (array==null)
throw new NullPointerException();
a = array;
}
/** 省略方法 **/
}

但是这个内部类并没有提供add()方法,那么查看父类:

public boolean add(E e) {
add(size(), e);
return true;
}
public void add(int index, E element) {
throw new UnsupportedOperationException();
}

这里父类仅仅只是提供了方法,方法的具体实现却没有,所以具体的实现需要子类自己来提供,但是非常遗憾

这个内部类ArrayList并没有提高add的实现方法。在ArrayList中,它主要提供了如下几个方法:


1、size:元素数量
2、toArray:转换为数组,实现了数组的浅拷贝。
3、get:获得指定元素。
4、contains:是否包含某元素。

所以综上所述,asList返回的是一个长度不可变的列表。数组是多长,转换成的列表是多长,我们是无法通过add、remove来增加或者减少其长度的。

最后

以上就是神勇小霸王为你收集整理的数组一些底层原理的全部内容,希望文章能够帮你解决数组一些底层原理所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(48)

评论列表共有 0 条评论

立即
投稿
返回
顶部