【java 基础 9】原来我从没有了解过String类

原创 2017年01月03日 11:45:52

导读:这两天没有做项目,然后就想着把之前在项目中用到过的东西总结总结。记得之前做今日开讲项目时,在比较学生学号的时候,我最开始用的是“==”,但是,实践证明,这个玩意儿吧,总是很奇怪,有时候对有时候不对。后来就换成了equals,结果就好多了。那时候我就在想,这两个有什么区别,string类型到底是怎么回事?现在总结总结,也祭奠一下当年面试笔试题的那些亡魂!


一、实例分析

首先,看看代码段:

public class stringTest {

	private static String getA()
	{
		return "a";
	}
	
	public static void testString()
	{
		String a="a";
		final String c="a";
		
		String b=a+"b";
		String d=c+"b";
		String e=getA()+"b";
		
		String compare="ab";
		
		System.out.print(b==compare);
		System.out.print(d==compare);
		System.out.print(e==compare);
	}
}

我先说一下,我最开始得出的答案:true,true,true。原因如下:

1,因为a变量代表了一个常量定值“a”,然后b在编译的时候就会得到b="ab",所以结果是true;

2,因为C变量用了final关键字修饰,代表这个变量不会被更改,那么d 就会是一个固定的值“ab”,而==比较的是地址值,所以true;

3,因为getA()方法是静态方法嘛,这个我觉得跟 2 的原因差不多,所以就是true。


对于我的答案,我只能借用我宇哥的一句台词,拿出你的红笔。。。。。。(画个大大的 × )


运行结果输出:


对此,我竟无言以对!


解析:

1,false:compare是个常量,而b不是。b=a+"b",a不是一个常量,尽管a作为一个局部变量,指向一个常量。但是,它的引用上并未进行“强制约束”是不可被改变的。它只会在这段代码中不会改变,但是在运行的时候,则不一定。在“字节码增强”技术(话说,这个好像是java 8的东西)面前,代码被切入,就可能会发生改变。所以,编译器时不会将b在编译的时候,优化为“ab”的。在运行时,会被编译为:

StringBuilder temp=new StringBuilder();
temp.append(a).append("b");
String b=temp.toString();

2,true,我解释正确!请看上面。因为final进行修饰为不可改变,所以代码在编译时被优化为"ab",结果true

3,false:这个e值的内容来源于一个方法和一个常量的叠加。虽然方法内部返回了一个常量的引用,但是,编译器不会去看方法内部做了什么,如果编译器非要知道方法内部返回什么,那么则需要采用递归。一旦采用递归,深度就不可控,同时也并不是递归后就一定能够确保返回一个指定的常量。(即使是常量,这也是通过对引用拷贝返回,这个引用还可能发生变化)所以,编译器不会做出优化,结果false!


备注:编译器优化一定是在编译阶段能确定优化后,不会影响整体功能,类似于final引用,这个引用只能被赋值一次,但是它无法确定赋值的内容是什么,只有在编译阶段能确定这个final引用赋值的内容,编译器才有可能进行编译时优化。而在编译阶段能确定的内容,只能来自于常量池,例如int、long、string等常量。(顿时想到了当年学习C++时的编译时多态和运行时多态)


看了上面的分析,再来一个代码段:

	public static void main(String[] agrs)
	{
		String a="a";
		String b=a+"b";
		String c="ab";
		String d=new String(b);
		
		System.out.println(b==c);
		System.out.println(c==d);
		System.out.println(c==d.intern());
		System.out.println(b.intern()==d.intern());
	}

经过上一个代码段,这个我全对了,但是,只有前面两个是自己经过分析,后面两个一半分析,一半感觉(之前总结JVM溢出时,有查过这个intern()的方法)

intern():JVM会在这个常量池中通过equals方法查找是否存在等值的String,如果存在,则直接返回常量池中这个String对象的地址,如果没有找到,则会创建等值的字符串,然后再返回这个新创建空间的地址。只要是同样的字符串,当电泳intern()方法时,都会得到常量池中对应的String引用,所以,两个字符串通过intern()操作后用等号是可以匹配的。


二、代码总结

对于每一个代码段,我都自己分析了一下。其实我会得出错误的结果,一方面是由于对string类本身的不理解,另外也有对于java内存分配运行机制不了解,还有一个也是对于“==”和equals的不理解。因为有些答案,如果换成equals就对了。从这也反映出,自己对于基础功底的忽略和总结,接下来要继续努力学习啦。之前做的项目没有好好总结,感觉自己都废了!

练武不练功,到老一场空!

版权声明:每天进步一点点——我也只是写着玩儿——随便转随便评

相关文章推荐

Java 9 新特性快速预览

Java 8 已经出来三年多的时间了,原本计划2016年七月份release Java 9,但是基于种种原因,Java 9 被推迟到了2017年的3月份,本人也在Open JDK的官网上看到了Java...

9、Java基本数据类型包装类String类

一、 String类 一、概述         String是字符串的类类型,用于描述字符串事物。字符串是一个特殊的对象。特殊之处就在于:         Stings= new String();...

我太过爱你.从没有想过被爱的感动

1.她下班回家。他坐在沙发上。面无表情地抽着烟,突然他开口了:喂,我说,我们像这样同居两年了,你不觉得厌倦吗?她停下了正换着拖鞋的手,转过身愣愣的看着他:你说....什么?他还是一样面无表情:我说,我...

String类的迷惑之解 By 凌云志 发表于 2006-9-4 17:27:00

昨天晚上我看一些java的资料,碰到这样一个论断:问:String s = new String("xyz");创建了几个String Object? 答:两个Demo:package test;pu...

Java基础9--继承--抽象类--接口

9-1,子父类的构造函数-子类的实例化过程 1,在子类构造对象的时候,发现访问子类构造函数时,父类的构造函数也运行了,这时为什么呢? 原因是:在自类的构造函数中第一行有一个默认的隐式语句,就是supe...

黑马程序员--java基础9--File类

------- android培训、java培训、期待与您交流! --------- day20File类**********************************************...

【Dongle】【Java】基础(六)之常用类——String

String类型的常用方法总结。

Java里String类基础及面试常见题

String 常用方法 面试题
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【java 基础 9】原来我从没有了解过String类
举报原因:
原因补充:

(最多只允许输入30个字)