String StringBuffer StringBuilder 深度剖析

String

  /** The value is used for character storage. */
    private final char value[];
 /** The offset is the first index of the storage that is used. */
    private final int offset;  //第一个元素

    /** The count is the number of characters in the String. */
    private final int count;

    /** Cache the hash code for the string */
private int hash; // Default to 0   哈希码

/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;

这里有一个问题:为什么final的东西没有直接初始化但编译不报错?

只要在 对象 初始化OK之前给它赋值就行 。
你可以在 显示初始化—隐式初始化-初始化块初始化-构造器
任何一个地方给它初始化,编译就不会报错

说到String就不得不说一个事,叫做内存图解

内存管理

Java内存分配与管理是Java的核心技术之一,之前我们曾介绍过Java的内存管理与内存泄露以及Java垃圾回收方面的知识,今天我们再次深入Java核心,详细介绍一下Java在内存分配方面的知识。一般Java在内存分配时会涉及到以下区域:
  ◆寄存器:我们在程序中无法控制
  ◆栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中(new 出来的对象)
  ◆堆:存放用new产生的数据
  ◆静态域:存放在对象中用static定义的静态成员
  ◆常量池:存放常量
◆非RAM存储:硬盘等永久存储空间

首先是 学基础的程序员们最常提到的三块地儿: 栈内存 堆内存 方法区

Stack栈内存

计算机中用来存放 非静态变量 的区域, Stack负责 你在创建非静态变量时,让 这个东西进栈 ,当 这个变量出了作用域 , Stack 再让它出栈。

静态变量 是保存在 方法区静态区域的。

Heap 堆内存

堆内存 里边可以开辟空间 分配对象,对象的首地址 赋值给 引用变量,这个就是Java里边的指针,这几乎是唯一一块受GC管理的地儿!

方法区

方法区里边 不仅放着方法而且放着静态变量。里边有这么几块区域比较重要:

方法区静态区域 方法区非静态区域 常量池

方法区静态/非静态区域 存的是什么大家可以看我的另一篇博文:
//网址

常量池的话自然存的是常量

比如说 int a= 10; //编译器就会去常量池找 有没有10,如果之前用过就直接拿来,如果没用过就 在常量池创建 10这个东西

但是 要注意的是 String的对象 也可以是常量:
String st=”123”; //这个就是String最特殊的地方

大家注意一下 String就这么两种表达方式:
字符串两种打开方式

这个地方最容易出的问题就是 == equals 的问题
== 与 equals方法 的区别
== 比较的是地址值
equals比较的也是地址值(更确切的说是hashCode),但是String里边重写了这个方法,比较的是具体内容public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n– != 0) { //直接比较的是每个字符
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}

字符串拼接

学这块内容 大家务必搞清楚每一步 这些变量 常量 对象 在内存上的变化

String s1 = “hello”;
String s2 = “world”;
String s3 = “helloworld”;
System.out.println(s3 == s1 + s2); //false,s1+s2是一个新的String的地址的引用
s3.equals((s1 + s2));
System.out.println(s3 == “hello” + “world”);//true,拼接起来的是常量池中找到的
s3.equals(“hello” + “world”);

现在大家只要知道:
凡是有变量参加的字符串拼接 拼出来的东西 一定是 new 出来的对象
若都是字符串常量的拼接 则还是直接去常量池找的常量

    String a = "ab";
  final String bb = "b";   //编译时已经放入常量池
  String b = "a" + bb;
  System.out.println((a == b)); //result = true返回

    String a = "ab";
  final String bb = getBB();
  String b = "a" + bb;
  System.out.println((a == b)); //result = false
  private static String getBB() {  return "b";   }

这两个东西我放到 一个对象两种状态 这篇文章给大家分析一下
2016-20-21 更新

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值