由一个问题看JAVA面向对象思想(一)

今天在用java写一个程序的时候,遇到了一个小问题。写出来,一起分享。 

由于写的是一个简单的一段代码,并不打算长期使用,所以我用set的过滤能力,对一个较大的数组进行过滤,去掉重复的项,可是遇到了问题。

出问题部分的主要代码:

int n=cin.nextInt();
int a[]=new int[n];
for(int i=0;i<n;i++){ 
a[i]=cin.nextInt();
} Set set = new HashSet(Arrays.asList(a)); Iterator it=set.iterator(); while(it.hasNext()){ System.out.println(it.next()); }

假设输入的为一段长度的数字:10 2 49 89 123 2 19 10 89

当这样写的时候,总是出现输出:[I@1270b73 这显然是对象地址。。。

下断点得到set集合的各种属性:

查看器table映射情况:

大家可以看到,作为初值15个位置,只映射了一个位置,本应映射更多位置的。

其将数组当成一个对象,直接映射了:

 由此,我记得以前使用String[]数组的时候就没有出现这种情况,因此使用String[]将原程序改了,立刻就得到了相关的7个映射位置,实现了所需要的功能,当然中间多了些转换,然后回过头来看看这里到底发生了什么。

为什么会出现这种情况?

首先,想到的是String本身就被当做对象对待,而int被当做基本类型对待,这两个是有区别的。因此问题可能出现在这里。

那么对于int来讲,他的包装类为Integer,更改一下,试一下。

当将int a[]=new int[n];改为Integer a[]=new Integer[n];就好了:

int n=cin.nextInt();
Integer a[]=new Integer[n];
for(int i=0;i<n;i++){ 
a[i]=cin.nextInt();
} 
Set set = new HashSet(Arrays.asList(a));
Iterator it=set.iterator();
while(it.hasNext()){
 System.out.println(it.next());
}

再次下断点,查看相关属性:

 查阅文档:

Arrays.asList()的文档:  

asList

public static <T> List<T> asList(T... a)
Returns a fixed-size list backed by the specified array. (Changes to the returned list "write through" to the array.) This method acts as bridge between array-based and collection-based APIs, in combination with Collection.toArray. The returned list is serializable and implements RandomAccess.

This method also provides a convenient way to create a fixed-size list initialized to contain several elements:

     List stooges = Arrays.asList("Larry", "Moe", "Curly"); 
Parameters:
a - the array by which the list will be backed.
Returns:
a list view of the specified array.
See Also:
Collection.toArray()

并没有得到什么实质性有用的信息,只是了解了这个方法的一些特性。

通过在工作空间中追源码得到:

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

我们看到这里定义了泛型,也就是说传进来的东西的对象类型被隐性接受。

 继续找ArrayList<T>(a)

    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;
	}

在此之前,我没认真看过这类的代码,泛型在这里起了作用,当你传入int[] a=new int[n];没注意都,int就进去了  

 

     由上,我们得知,数组的基础类型(int/Integer)通过我们调用asList方法的时候,已经进入到ArrayList之中,并返回给我们调用的左部。

     又基于Set set = new HashSet(Arrays.asList(a));我使用的是HashSet,那么HashSet在映射的时候,需要一个对象的hashcode,那么如果这个传入的类型不能够提供hashcode会怎么样呢?

实验:

    在int a[]=new int[n];为数组下,我们都知道a[i]不能够调用.hashCode()方法,因为没有包装,没有这个方法。

    在Integer a[]=new Integer[n];为数组下,我们可以轻松调用.hashCode()方法,因为其为包装类,有该方法。

那么我们就可以思考,为什么会出现那种情况了,因为java根据泛型接收的外部参数的类型,然后查看这个外部参数是否有.hashCode()方法,如果有则调用,用于映射(在内部机制中,我认为这里使用的接口,查看其是否实现了这类接口),如果没有这个方法(就像这个int基础类型),则追溯其传入参数的更大范围的对象(在这里是数组对象),这里将数组当成一个对象映射到桶中(如下图)。

     学校运动会放假,明天去华山旅游,所以这篇日志不能够接着写下去,赶紧睡觉,但是具体的意思已经表达出来了,下一篇文章会接着这个问题从实现方面思考,来对java面向对象带来的方便和麻烦作一个自己的思考总结。

论证期间的一些思考和证明:

int c=3;

对于c这个基础类型是没有任何方法可以调用的,因为其不是对象。

可是对于int a[]=new int[n];  Integer b[]=new Integer[n];

a.clone();是可以执行的,而且查看列表,与b数组的方法是一样的。

这是数组作为一种“容器”,所具有的方法和相关性质。

所以可以认为int数组形式下,数组时被看做对象来处理的,而对象都有了方法。但是这两个不同类型数组的基类是不一致的。

进一步探究》》

对于不同的类型的数组:

	  int n=cin.nextInt();
	  int  a[]=new int [n];
	  Integer b[]=new Integer[n];
	    for(int i=0;i<n;i++){         
             a[i]=cin.nextInt();
	    }
	    Set set = new HashSet(Arrays.asList(a));
	    
        System.out.println("int型数组的类的名字:"+a.getClass().getName());
        System.out.println("Integer型数组的类的名字:"+b.getClass().getName());

    得到结果为:

int型数组的类的名字:[I
Integer型数组的类的名字:[Ljava.lang.Integer;

 这样可以看出这两个数组的基类是不同的,这样做似乎多余。但严格证明了这点。

对于同样是基类的char进行一步测试:

 char c[]=new char[n];

System.out.println("char型数组的类的名字:"+c.getClass().getName());

方法同上,结果为:

char型数组的类的名字:[C

又出来一个[C

可是即使一个类也好,传进去按照泛型,不至于说所有的方法都失效了啊。而且只要是基础类型进去后,length都变成了1。也就是说当成了单个对象进去了。

动用调试:

发现,在使用int[] a=new int[n];时候,查看set的hashmap的值只有单个不为null(hashmap初始为15,只映射了1个位置),

同样测试Integer数组的时候,发现,set的hashmap的值全部被映射。

得出结论:

对于这两个被传进来的数组,由于类型不同,被用作不同的处理方式,int数组的整个数组被当做一个对象,进行映射,而Integer数组的每一个值均被当做一个对象用来映射。

对于int值他们被当做了整体。

原文地址:https://www.cnblogs.com/zdcaolei/p/2433572.html