动手动脑1:请运行以下示例代码StringPool.java,查看其输出结果。如何解释这样的输出结果?从中你能总结出什么?
输出结果:
结论:在Java中,内容相同的字串常量(“Hello”)只保存一份以节约内存,所以s0,s1,s2实际上引用的是同一个对象。
编译器在编译s2一句时,会去掉“+”号,直接把两个字串连接起来得一个字串(“Hello”)。这种优化工作由Java编译器自动完成。
当直接使用new关键字创建字符串对象时,虽然值一致(都是“Hello”),但仍然是两个独立的对象。
再看。。。
为什么会有上述的输出结果?从中你又能总结出什么?
给字串变量赋值意味着:两个变量(s1,s2)现在引用同一个字符串对象“a”!
String对象的内容是只读的,使用“+”修改s1变量的值,实际上是得到了一个新的字符串对象,其内容为“ab”,它与原先s1所引用的对象”a”无关,所以,s1==s2返回false;
代码中的“ab”字符串是一个常量,它所引用的字符串与s1所引用的“ab”对象无关。
String.equals()方法可以比较两个字符串的内容。
动手动脑2:请查看String.equals()方法的实现代码,注意学习其实现方法。
源代码:
public class StringEquals {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
String s1=new String("Hello");
String s2=new String("Hello");
System.out.println(s1==s2);
System.out.println(s1.equals(s2));
String s3="Hello";
String s4="Hello";
System.out.println(s3==s4);
System.out.println(s3.equals(s4));
}
}
输出结果:
实现方法:首先为s1寻找String缓冲池内是否有与"Hello"相同值的String对象存在,此时String缓冲池内是空的,没有相同值的String对象存在,所以虚拟机会在String缓冲池内创建此String对象,其动作就是new String("Hello");。然后把此String对象的引用赋值给s1。接着为s2寻找String缓冲池内是否有与"Hello"相同值的String对象存在,此时虚拟机找到了一个与其相同值的String对象,这个String对象其实就是为s1所创建的String对象。既然找到了一个相同值的对象,那么虚拟机就不在为此创建一个新的String对象,而是直接把存在的String对象的引用赋值给s2。
动手动脑3:
String类的方法可以连续调用:
String str="abc";
String result=str.trim().toUpperCase().concat("defg");
请阅读JDK中String类上述方法的源码,模仿其编程方式,编写一个MyCounter类,它的方法也支持上述的“级联”调用特性,其调用示例为:
MyCounter counter1=new MyCounter(1);
MyCounter counter2=counter1.increase(100).decrease(2).increase(3);
….
public class test{
public static void main(String[] args) {
// TODO Auto-generated method stub
String str="abc";
String result=str.trim().toUpperCase().concat("defg");
System.out.println(result);
}
}
结果:
ABCdefg
package test;
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyCounter counter1=new MyCounter();
MyCounter counter2=new MyCounter();
counter1.set(1);
counter2=counter1.increase(100).decrease(2).increase(3);
System.out.println(counter2.data);//注意此处不能写成counter2,否选择输出结果为哈希值
}
}
class MyCounter
{
int data;
public void set(int d)
{
data=d;
}
public MyCounter increase(int i)
{
MyCounter a=new MyCounter();
a.data=data+i;
return a;
}
public MyCounter decrease(int d)
{
MyCounter a=new MyCounter();
a.data=data-d;
return a;
}
}
结果:
102
整理String类的Length()、charAt()、 getChars()、replace()、 toUpperCase()、 toLowerCase()、trim()、toCharArray()使用说明。
Length():获取字串长度,字符串是一个对象,在这个对象中包含length属性,它是该字符串的长度,使用String类中的length()方法可以获取该属性值。
charAt():获取指定位置的字符
getChars():获取从指定位置起的子串复制到字符数组中(它有四个参数,1.被拷贝字符在字串中的起始位置 2.被拷贝的最后一个字符在字串中的下标再加1 3.目标字符数组 4.拷贝的字符放在字符数组中的起始下标)
replace():子串替换,通过String类的replace()方法,可以将原字符串中的某个字符替换为指定的字符,并得到一个新的字符串,该方法的具体定义如下:public String replace(char oldChar,char newChar)
toUpperCase()、 toLowerCase():大小写转换,在String类中提供了两个用来实现字母大小写转换的方法,它们的返回值均为转换后的字符串,其中toLowerCase()用来将字符串中的所有大写字母改为小写字母,,方法toUpperCase()用来将字符串中的所有小写字母改为大写字母。
trim():去除头尾空格,通过String类的trim()方法,可以通过去掉字符串的首尾空格得到一个新的字符串,该方法的具体定义如下:public String trim()
toCharArray():将字符串对象转换为字符数组
动手动脑4:古罗马皇帝凯撒在打仗时曾经使用过以下方法加密军事情报:
请编写一个程序,使用上述算法加密或解密用户输入的英文字串要求设计思想、程序流程图、源代码、结果截图。
源代码:
package Test;
import java.util.Scanner;
public class test {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
System.out.println("输入密报:");
String x=input.next();
int number =x.length();
char a[]=new char[number];
a=x.toCharArray();
System.out.println("加密之后:");
int i;
for( i=0;i<number;i++)
{
if(a[i]=='X')
a[i]='A';
else
if(a[i]=='Y')
a[i]='B';
else
if(a[i]=='Z')
a[i]='C';
else
a[i]=(char)(a[i]+3);
System.out.print(a[i]);}
input.close();
}
}
程序流程图:
输出结果:
设计思想:人输入一组字符串,在经过代码转换成整型,在原有基础上加上3再转换成字符输出。