String常见题分析

1. 例1

1.1 代码

package com.ilaoda.day0903;

/**
 * 字符串的常见题1
 * @author iLaoda
 *
 */
public class Test1 {

	public static void main(String[] args) {
		String s1 = "hello";
		String s2 = "world";

		System.out.println(s1 + s2 == "helloworld");  // false
		System.out.println("hello" + "world" == "helloworld");  // true
	}
}

1.2 答案

false true

1.3 解释

  • 静态区  常量池中的内容不能重复
  • String s1 = "hello";

    会在栈中声明s1,并将"hello"存进常量池中,同时s1存"hello"在常量池中的地址 java

  • String s2 = "world";
     会在栈中声明s2,并将"world"存进常量池中,同时s2存"world"在常量池中的地址
  • System.out.println(s1 + s2 == "helloworld");
     s1 + s2:会产生一个新的地址空间,里面存的是不知道的地址
     helloworld:此时发现常量池中没有"helloworld"字符串,就立马建立,并将建立
     后的字符串地址与s1 + s2后不知名的地址作一比较,发现不想等。因此false
  • System.out.println("hello" + "world" == "helloworld");
     hello:常量池中有,不用建立
     world:常量池中有,不用建立
     "hello" + "world":相加后为helloworld,发现常量池中已经有helloworld,直接拿来用。
     与后面的helloworld比较以后地址相等(实际就是本身跟本身比较地址,由于内容不能重复)

2. 例2

2.1 代码

package com.ilaoda.day0903;

/**
 * 字符串的常见题2
 * @author iLaoda
 */
public class Test2 {

	public static void main(String[] args) {
		final String s1 = "hello";
		final String s2 = "world";

		System.out.println(s1 + s2 == "helloworld");
		System.out.println("hello" + "world" == "helloworld");
	}
}

2.2 答案

true  true

2.3 解释

  • final String s1 = "hello";
     final修饰,表示是常量,此时与栈无关。直接是在常量池中存入"hello"。能够把s1自己就理解为常量,不要理解为引用
  • String s2 = "world";
     final修饰,表示是常量,此时与栈无关。直接是在常量池中存入"world"。能够把s2自己理解为常量,不要理解为引用
  • s1 + s2 == "helloworld"就相等于"hello" + "world" == "helloworld"是一个样子


3. 例3

3.1 

String s1 = "abc";
String s2 = new String("abc");  //这句话建立了几个对象
  • 答案: 1个
  • 解释:第一句已经在常量池中建立一个“abc”,执行第二句时,在堆中new String,发现常量池中已经有“abc”,直接让堆中的new stirng再指向常量池中的“abc”,因此就建立了一个对象。

3.2

String s1 = new String("abc");   //这句话建立了几个对象
  • 答案:两个
  • 解释:在堆中new String,堆内开辟了空间,建立了一个对象。发现常量池中没有“abc”,这时再在常量池中建立一个字符串对象。因此两个。
  • 我以为这两句话挺重要的:1. 常量池中的内容不能重复     2.字符串常量池中的内容也做为字符串对象存在

3.3

String s1 = new String("abc"); // 建立两个对象
String s2 = new String("abc"); // 建立1个对象

4. 关于final修饰的成员变量和局部变量初始化赋值的几种形式

    如下代码没有执行,可是都没有报错。说明语法上没有问题。 this


package com.ilaoda.day0904;

/**
 * 关于final修饰的成员变量和局部变量初始化赋值的几种形式
 * @author iLaoda
 *
 */
public class Test3 {
	
	/**
	 * final修饰的成员变量,能够用如下三种方式初始化赋值:
	 * 		1. 声明的时候直接赋值
	 * 		2. 构造方法中赋值
	 * 		3. 构造代码快赋值(其实也是构造方法赋值)
	 */
	
	//1. 声明的时候直接赋值
	final int a1 = 1;
	final int a2;
	final int a3;
	
	//3. 构造代码快赋值(其实也是构造方法赋值)
	{
		a2 = 2;
	}
	
	public Test3(int a3) {	
		this.a3 = a3;
	}
	
	// 2. 构造方法中赋值
	Test3 test3 = new Test3(5);
	
	
	/**
	 * final修饰的局部变量,能够用如下三种方式初始化赋值:
	 */
	public static void haha(int a) {
		//1. 能够在声明的时候初始化赋值
		final int a1 = 1;	
		final int a2;
		
		//2. 或者表达式给它赋值。
		a2 = a1 + 5;
		
		final int a3 = a;
	}
	
	public static void main(String[] args) {
		//3. 在第一次使用的经过方法
		haha(3);
	}
}


5. 输出的结果为多少呢?

5.1 代码

package com.ilaoda.day0905;

/**
 * @author iLaoda
 */
class C {	
	C() {
		System.out.print("C");
	}
}

class A {
	/**
	 * 
	 * 对父类中的c成员进行初始化,调用了C类的无参构造
	 *  由于A类中有C类的成员,在Test建立
	 */
	C c = new C();

	A() {
		this("A");
		System.out.print("A");
	}

	A(String s) {
		System.out.print(s);
	}
}

class Test extends A {
	
	/**
	 * 执行父类的带参构造前要先对父类中的对象进行初始化,
	 */
	Test() {
		super("B");
		System.out.print("B");
	}

	public static void main(String[] args) {
		new Test();
	}
}

5.2 答案

CBB


6. 输出结果为多少?

6.1 代码

package com.ilaoda.day0905;

/**
 * 输出结果为多少
 * @author iLaoda
 *
 */
public class Test2 {
	static {
		int x = 5;
	}
	static int x, y;   // 0   0

	public static void main(String args[]) {
		x--;	// x=-1;
		myMethod();
		System.out.println(x + y + ++x); 
		// 从下面可知第一个x为1,y为1
		// ++x为2
		// 因此:结果为3
	}

	public static void myMethod() {
		y = x++ + ++x; //真正计算时: y = -1 + 1 = 0
		// 第一个 x 进行加运算时为:-1, x++后为:0
		// 第二个 x 进行加运算时,这时x已经为0。因此 ++x后,x为1
		// 所以 y = 0+1 = 1
	}
}

6.2 答案

3
相关文章
相关标签/搜索