一些题目的思考

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37256896/article/details/85237534

在群里看到一些对字符串还有静态变量的使用,接下来就看下测试:
 *静态final是不可以改变的不可以二次的赋值;final就是不可变的。
 * 当数据是基本类型时,意味着这是一个永不改变的编译时常量,一个在运行时被初始化的值,你不希望它改变。
 *当数据是引用类型时,用static和final修饰表示这是只占据一块不能改变的内存空间
 * 静态的可以进行赋值所以静态的可以进行对其+“xxx”操作并赋予新的值,但是final的就不可变的。不能对其做任何修改:

/**
 * 静态final是不可以改变的不可以二次的赋值;final就是不可变的。
 * 当数据是基本类型时,意味着这是一个永不改变的编译时常量,一个在运行时被初始化的值,你不希望它改变。
 *当数据是引用类型时,用static和final修饰表示这是只占据一块不能改变的内存空间
 * 静态的可以进行赋值
 * @author Kay三石
 *@date 2018年12月24日
 */
public class StringTest {
	public static String string="ANC";
	public static int str=122;
	public final static String string2="111";
	public static void main(String[] args) {
		str=StringTest.str+1;//在静态中添加  添加final类型的肯定都是错误的。
		System.out.println(str);
		string=StringTest.string+"adb";//在静态中追加
		System.out.println(string);
		String string="123";
		System.out.println(string);//输出的为123
		string=StringTest.string+"adc";
		System.out.println(string);
		//报错:final是不可变的
//		string2=StringTest.string2+"222";
//		System.out.println(string2);
		/**
		 * 字符串的基本操作:
		 * String类代表字符串。 Java程序中的所有字符串文字(例如"abc" )都被实现为此类的实例。
		字符串不变; 它们的值在创建后不能被更改。 字符串缓冲区支持可变字符串。
		 因为String对象是不可变的,它们可以被共享。 例如:
	     String str = "abc";相当于:
	     char data[] = {'a', 'b', 'c'};
	     String str = new String(data);
		 */
		String str1 = "Lance";//在常量池中申请的,就是堆中保存值栈中保存变量然后引用指向堆。
        String str2 = new String("Lance");//这个是无论常量池中有没有都会在堆中进行新建出一个实例,
        String str3 = str2; //引用传递,str3直接指向st2的堆内存地址
        String str4 = "Lance";
        /**
         *  ==:
         * 基本数据类型:比较的是基本数据类型的值是否相同
         * 引用数据类型:比较的是引用数据类型的地址值是否相同
         * 所以在这里的话:String类对象==比较,比较的是地址,而不是内容
         */
         System.out.println(str1==str2);//false
         System.out.println(str1==str3);//false
         System.out.println(str3==str2);//true
         System.out.println(str1==str4);//true
		
		
	}
}

这里对string类官方API是这样解释的:
 String类代表字符串。 Java程序中的所有字符串文字(例如"abc" )都被实现为此类的实例。
        字符串不变; 它们的值在创建后不能被更改。 字符串缓冲区支持可变字符串。
         因为String对象是不可变的,它们可以被共享。 例如:
         String str = "abc";相当于:
         char data[] = {'a', 'b', 'c'};
         String str = new String(data);

String str=”xxx”;就是在常量池中申请的信息。就是堆中保存值栈中保存变量然后引用指向堆。

看下什么是常量池:
常量池在java用于保存在编译期已确定的,已编译的class文件中的一份数据。它包括了关于类,方法,接口等中的常量,也包括字符串常量,如String s = "java"这种申明方式;当然也可扩充,执行器产生的常量也会放入常量池,故认为常量池是JVM的一块特殊的内存空间。

java常量池技术  java中的常量池技术,是为了方便快捷地创建某些对象而出现的,当需要一个对象时,就可以从池中取一个出来(如果池中没有则创建一个),则在需要重复创建相等变量时节省了很多时间。常量池其实也就是一个内存空间,常量池存在于方法区中。

String类也是java中用得多的类,同样为了创建String对象的方便,也实现了常量池的技术。

测试代码如下:

public class Test{

public static void main(String[] args){

//s1,s2分别位于栈中,指向堆中不同的空间

String s1=new String("hello");

String s2=new String("hello");

System.out.println(s1==s2);//输出false

//s3,s4位于池中同一空间

String s3="hello" String s4="hello";

System.out.println(s3==s4);//输出true

}

}

用new String()创建的字符串不是常量,不能在编译期就确定,所以new String()创建的字符串不放入常量池中,他们有自己的地址空间。所以new String()无论他们的字符串相等不相等所在的地址都不会相同。

String 对象(内存)的不变性机制会使修改String字符串时,产生大量的对象,因为每次改变字符串,都会生成一个新的String。 java 为了更有效的使用内存,常量池在编译期遇见String 字符串时,它会检查该池内是否已经存在相同的String 字符串,如果找到,就把新变量的引用指向现有的字符串对象,不创建任何新的String 常量对象,没找到再创建新的。所以对一个字符串对象的任何修改,都会产生一个新的字符串对象,原来的依然存在,等待垃圾回收。

代码:

String a = “test”;

String b = “test”;

String b = b+"java";

a,b同时指向常量池中的常量值"test",b=b+"java"之后,b原先指向一个常量,内容为"test”,通过对b进行+"java" 操作后,b之前所指向的那个值没有改变,但此时b不指向原来那个变量值了,而指向了另一个String变量,内容为”test java“。原来那个变量还存在于内存之中,只是b这个变量不再指向它了。

而这样的是 String str3 = str2; //引用传递,str3直接指向st2的堆内存地址,二者地址必然相同。

下面试运行的截图:

猜你喜欢

转载自blog.csdn.net/qq_37256896/article/details/85237534