首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > J2SE开发 >

好诡谲的内存分配!

2013-12-17 
好诡异的内存分配!!!!!!!!!!!!!import java.io.Fileimport java.io.FileInputStreamimport java.io.File

好诡异的内存分配!!!!!!!!!!!!!
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;


public class StringBufferTest
{
public static void main(String[] args)
{
StringBuffer strPre = new StringBuffer();
//strPre = null;
System.out.println(strPre + "wenchxong");
System.out.println(strPre + "----------");
System.out.println(strPre);
Person person = new Person();
System.out.println(person);
String str = new String();
System.out.println("++++++++++++");

File file = new File("H:\\test3.txt");
try
{
InputStream is = new FileInputStream(file);
System.out.println(is + "=============");
} catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
List<String> list = new ArrayList<String>();
System.out.println(list);
Set<String> set = new HashSet();
System.out.println(set);
}
}
class Person
{
}
代码如上:
下面是打印结果:
wenchxong
----------

Person@1fc4bec
++++++++++++
java.io.FileInputStream@dc8569=============
[]
[]
问题如下:

StringBuffer,String类实例化为啥没分配内存地址?就是没有打印出来内存地址?
还有list,set实例化为啥也没打印出来内存地址?是不是很诡异????



[解决办法]
list,set 这种容器对象,为什么不打印出类似:类名+@+ hashCode() 这种格式,是因为java所有的对对象的输出(print)操作,都是输出的 String.toValue(obj)操作。可看PrintStream源码。

    public void println(Object x) {
        String s = String.valueOf(x);
        synchronized (this) {
            print(s);
            newLine();
        }
    }

而String类的这个静态方法valueOf(Object obj), 是返回的 obj.toString().
   public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
    }

任何对象都继承自Object, Object 对这个 toString()方法的定义是:返回类名 + @ + 对象的hashCode值。

   public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
 

所以一般的对象(不重写这个toString()方法的话),都会输出“返回类名 + @ + 对象的hashCode值”这样的结果。

但List 和Set 这些接口的实现类,都重写了这个方法。实现List接口的类,比如ArrayList,继承了 AbstractList类,而Arstarctlist类,继承了 AbstractCollection类,而后者重写了toString()方法。



   public String toString() {
        Iterator<E> i = iterator();
if (! i.hasNext())
    return "[]";

StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
    E e = i.next();
    sb.append(e == this ? "(this Collection)" : e);
    if (! i.hasNext())
return sb.append(']').toString();
    sb.append(", ");
}
    }


public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

。。。。。

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

。。。。。




类似, 实现接口Set的类都继承自AbstractSet类,而这个类继承了类AbstractCollection,所以输出也改变了。以HashSet为例,看看继承关系:



public class HashSet<E>
    extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable


。。。。


public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> {

。。。。



对于String 本身,就不再转换,直接输出了。

   public void println(String x) {
synchronized (this) {
    print(x);
    newLine();
}
    
    public void print(String s) {
if (s == null) {
    s = "null";
}
write(s);
    }



对于StringBuffer ,重写了toString() 方法。

  public synchronized String toString() {
return new String(value, 0, count);
    }

所以都不输出 带类名 @ + hashCode的格式了。

以上为个人浅见,共楼主参考。
[解决办法]
引用:
list,set 这种容器对象,为什么不打印出类似:类名+@+ hashCode() 这种格式,是因为java所有的对对象的输出(print)操作,都是输出的 String.toValue(obj)操作。可看PrintStream源码。
    public void println(Object x) {
        String s = String.valueOf(x);
        synchronized (this) {
            print(s);
            newLine();
        }
    }

而String类的这个静态方法valueOf(Object obj), 是返回的 obj.toString().
   public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
    }

任何对象都继承自Object, Object 对这个 toString()方法的定义是:返回类名 + @ + 对象的hashCode值。

   public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
 

所以一般的对象(不重写这个toString()方法的话),都会输出“返回类名 + @ + 对象的hashCode值”这样的结果。

但List 和Set 这些接口的实现类,都重写了这个方法。实现List接口的类,比如ArrayList,继承了 AbstractList类,而Arstarctlist类,继承了 AbstractCollection类,而后者重写了toString()方法。



   public String toString() {
        Iterator<E> i = iterator();
if (! i.hasNext())
    return "[]";

StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
    E e = i.next();
    sb.append(e == this ? "(this Collection)" : e);
    if (! i.hasNext())
return sb.append(']').toString();
    sb.append(", ");
}
    }


public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

。。。。。

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

。。。。。




类似, 实现接口Set的类都继承自AbstractSet类,而这个类继承了类AbstractCollection,所以输出也改变了。以HashSet为例,看看继承关系:



public class HashSet<E>
    extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable
。。。。


public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> {

。。。。



对于String 本身,就不再转换,直接输出了。

   public void println(String x) {
synchronized (this) {
    print(x);
    newLine();
}
    
    public void print(String s) {
if (s == null) {
    s = "null";
}
write(s);
    }



对于StringBuffer ,重写了toString() 方法。

  public synchronized String toString() {
return new String(value, 0, count);
    }

所以都不输出 带类名 @ + hashCode的格式了。

以上为个人浅见,共楼主参考。
 高见 学习了 

热点排行