Java基础:String不可变性和final修饰
转载请注明出处: jiq•钦's technical Blog - 季义钦
String的不可变性
Java规定String是不可变的(immutable)。事实上这个不可变具备两层含义:
1 内容不可变
不论什么看起来改动它们的操作。实际上都是又一次new出一个对象。
String s = new String("111");
String newS = s;
newS = "dsfsd";
System.out.println(s); //111
假设不能做到内容不可变。在两个引用同一时候指向一个内存的时候,改动当中一个也会影响到另外一个。
2 实现方式不可变
使用String类型变量时,其不能表现出其他行为。这就是为什么String类须要用finalkeyword来进行修饰的原因,设想一下String不用final修饰。则其能够被继承并重写方法:
/**
* 模拟非final的String
* @author jiyiqin
*
*/
class MyString{
public char value[] = new char[10];
MyStringtoLowerCase(MyString s)
{
System.out.println("将s转换为小写,但不改变原有s");
char newValue[] = new char[s.value.length];
for(int i = 0; i < s.value.length; i++)
newValue[i]= LowerUtils.Lower(s.value[i]);
MyStringnewString = newMyString();
newString.value = newValue;
return newString;
}
} /**
* 继承MyString,将其toLowerCase重写
* @author jiyiqin
*
*/
class OverrideString extends MyString{
MyStringtoLowerCase(MyString s)
{
System.out.println("直接改动传递进来的s的内存。将s转换为小写");
for(int i = 0; i < s.value.length; i++)
s.value[i] = LowerUtils.Lower(s.value[i]);
return s;
}
} public classFinalStringTest {
/**
* 測试函数,java设计String是不可变的
* 所以必须将String修饰为final。否则其
* 一旦被继承。相似以下这样的调用时。若传递
* 进来的參数是其被继承的子类。调用的就是
* 被重写的方法,这个重写的方法可能会破坏
* String的不可变特性。
* @param s
* @return
*/
static MyStringLowerCusString(MyString s)//多态
{
return s.toLowerCase(s);
} public static void main(String[] args) {
OverrideStringss = newOverrideString();
LowerCusString(ss);//传入重写后的字符串类
LowerUtils.testFinalClass();
}
}
能够看到LowerCusString方法想要的是MyString对象,可是其子类能够传递进来使用,调用之后发现传递进来的对象s的内容被改动了,表现出和父类不同的行为!!
!
同样地。应用程序能够编写新的String类,改动hasCode方法,让内容同样的String对象返回的hashCode不同,这样HashMap在使用String类型变量作为Key的时候,发现同样内容的Key居然哈希到不同的位置。
除了实现方法不可改动这个原因。将String修饰为final另一个优点就是效率。
String其他特性
除了上面讲的不可变性。String还其具备以下特性:
特性1:编译时和执行时差别
u 编译时能确定的String对象都放入常量池
u 执行时才干确定或者new出的String对象都放入堆
特性2:hasCode唯一性
两个内容同样的String对象hashCode返回值一定同样
以下通过一个样例总结一下这两个特性:
final String tmp = "ji"; //常量池、编译时确定
String tmp2 = "ji"; //常量池、编译时确定
String s1 = "jiyiqin"; //常量池、编译时确定 String s2 = "jiyiqin"; //常量池、编译时确定
String s3 = "ji" + "yiqin"; //常量池、编译时确定
String s4 = tmp + "yiqin"; //常量池、编译时确定(final一旦初始化就不可变)
String s5 = tmp2 + "yiqin";//堆、执行时确定
String s6 = new String("jiyiqin");//堆、执行时确定 System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
System.out.println(s3.hashCode());
System.out.println(s4.hashCode());
System.out.println(s5.hashCode());
System.out.println(s6.hashCode()); //所有同样 System.out.println(s1 == s2); //true。指向常量池中同样内存
System.out.println(s1 == s3); //true,指向常量池中同样内存
System.out.println(s1 == s4); //true,指向常量池中同样内存
System.out.println(s1 == s5); //false,一个指向堆一个指向常量池
System.out.println(s1 == s6); //false,一个指向堆一个指向常量池
System.out.println(s5 == s6); //false,指向堆中不同内存区域
Double、Long、Integer
对于String的不可变性(包含内容不可变和实现方式不可变),以及hashCode唯一性,Double、Long、Integer也是一样的。
不同的是它们没有执行时和编译时的差别,都是在堆上分配内存。
Java基础:String不可变性和final修饰的更多相关文章
- Java基础 -- String,StringBuilder,StringBuffer三者的区别
结论 1-String,StringBuilder,StringBuffer 之间的区别主要是在两个方面,即运行速度和线程安全这两方面: 首先说运行速度,或者说是执行速度,在这方面运行速度快慢为:St ...
- Java基础String的方法
Java基础String的方法 字符串类型写法格式如下: 格式一: String 变量名称; 变量名称=赋值(自定义或传入的变量值); 格式二: String 变量名称=赋值(自定义或传入的变量值); ...
- Java基础 String 裸暴力算法- 五个小练习
之间的博客,承上启下: Java基础 String/StringBuff 常用操作方法复习/内存分析 Java数组直接选择排序.sort()排序 Java基础 String 算法 - 五个练 ...
- Java基础—String构造方法
Java基础--String构造方法 public String(): 创建一个空表字符串对象,不包含任何内容 public String(char[]chs): 根据字符数组的内容,来创建字符串对象 ...
- Java基础学习笔记(四) - 认识final关键字、权限修饰符和内部类
一.final关键字 为什么要使用 final 关键字? 通过继承我们知道,子类可以重写父类的成员变量和方法.final 关键字可以用于修饰父类,父类成员变量和方法,使其内容不可以被更改. 1.被修饰 ...
- Java基础-String、StringBuffer、StringBuilder
看下面这段代码: public class Main { public static void main(String[] args) { String string = ""; ...
- Java基础String类
String是一个对象 String不属于8种基本数据类型(byte, char, short, int, float, long, double, boolean),String是对象,所以其默认值 ...
- java的String类型为什么是final
(转自:http://www.cnblogs.com/ikuman/archive/2013/08/27/3284410.html) 最佳答案: 主要是为了“效率” 和 “安全性” 的缘故.若 Str ...
- java基础-String不可变的好处
一.java内部String类的实现: java 8: public final class String implements java.io.Serializable, Comparable< ...
随机推荐
- Struts之 拦截器配置 ( Interceptor )
struts2体系结构的核心就是拦截器. 以链式执行,对真正要执行的方法(execute())进行拦截.首先执行Action配置的拦截器,在Action和Result执行之后,拦截器再一次执行(与先前 ...
- 【转】Java 集合系列04之 fail-fast总结(通过ArrayList来说明fail-fast的原理、解决办法)
概要 前面,我们已经学习了ArrayList.接下来,我们以ArrayList为例,对Iterator的fail-fast机制进行了解.内容包括::1 fail-fast简介2 fail-fast示例 ...
- (转) Quartz学习——SSMM(Spring+SpringMVC+Mybatis+Mysql)和Quartz集成详解(四)
http://blog.csdn.net/u010648555/article/details/60767633 当任何时候觉你得难受了,其实你的大脑是在进化,当任何时候你觉得轻松,其实都在使用以前的 ...
- C# 获取表中最大值
; if (db.LPicture.Any()) { // LPicture Newmode = db.LPicture.Where(n => ).FirstOrDefault(); start ...
- Memcached 在Linux上的安装
1.安装libevent wget https://github.com/libevent/libevent/releases/download/release-2.1.8-stable/libeve ...
- ES6 Array返回只出现一次的元素
234
- Java中面向对象三大特性之——多态
多态的概述: 多态是继封装.继承之后,面向对象的第三大特性. 生活中,比如跑的动作,小猫.小狗和大象,跑起来是不一样的.再比如飞的动作,昆虫.鸟类和飞机,飞起来也是不一样的.可见,同一行为,通过不同 ...
- CAD全屏显示控件
主要用到函数说明: MxDrawXCustomFunction::Mx_FullScreen 全屏显示控件,详细说明如下: 参数 说明 int iFull = 2 0: 不完屏,1:全屏,2:自动切换 ...
- 字符串问题:去掉字符串中连续出现 k 个 0 的子串
[题目] 给定一个字符串 str 和 一个整数 k, 如果 str 中正好有连续 k 个 ‘0’ 字符出现时,把 k 个连续的 ‘0’ 字符去除,返回处理后的字符串. [举例] str="A ...
- web前端学习总结--CSS
CSS 什么是CSS? CSS 指层叠样式表(Cascading Style Sheets) 样式定义如何显示HTML元素 样式通常存储在样式表中 如何使用CSS 内联方式 样式定义在单个的HTML元 ...