String/final/StringBuffer

final关键字(最终)

final修饰的类无法被继承.

final修饰的方法无法被覆盖.

final修饰的局部变量,一旦赋值,不可再改变.

class A{

public void m1(){

//声明

final int i;

//第一次赋值

i = 100;

//不能重新赋值

i = 1200;

}}

final修饰的成员变量必须“显示的”初始化.

class A{

//final修饰的成员变量必须手动初始化.

final int i = 100;

//成员

final int k;

//Constructor

A(){

k = 200;

}}

//常量.java规范中要求所有的常量“大写”

//常量:值不可再改变的变量.

public static final double PI = 3.14;

深入final

final修饰的引用类型,该引用不可再重新指向其他的java对象。

但是fianl修饰的引用,该引用指向的对象的属性是可以修改的

public static void main(String[] args){

final Customer c = new Customer("JACK",15);

//c是final的,无法重新赋值。

//c = new Customer("LUCY",20);//Error

c.name = "李四";

c.age = 25;

System.out.println(c.name);

System.out.println(c.age);

}

(String)java.lang.String;是字符串类型。

1.字符串一旦创建不可再改变。"abc"字符串对象一旦创建,不可再改变成"abcd"

2.提升字符串的访问效率:在程序中使用了“缓存”技术。所以在java中所有使用“双引号”括起来

的字符串都会在“字符串常量池”中创建一份。字符串常量池在方法区中被存储。

3.在程序执行过程中,如果程序用到某个字符串,例如"abc",那么程序会在字符串常量池

中去搜索该字符串,如果没有找到则在字符串常量池中新建一个"abc"字符串,如果找到

就直接拿过来用。(字符串常量池是一个缓存区,为了提高访问字符串的效率)

//创建一个"abc"字符串对象,该对象的内存地址,让s1变量保存。

//s1是一个引用,s1指向 "abc" 对象.

String s1 = "abc";

//可以让s1重新指向吗?s1是局部变量,s1前边没有final,所以s1可以重新指向。

//但是"def"字符串本身不可变.

s1 = "def";

String s2 = "Hello"; //在字符串常量池中新建一个"Hello"字符串对象,该对象不可变

String s3 = "Hello"; //从字符串常量池中直接拿来用。

System.out.println(s2==s3); //true

//比较两个字符串是否相等,不能用"=="

String s4 = new String("abc");

String s5 = new String("abc");

System.out.println(s4==s5); //false

//比较两个字符串是否一致,必须使用String类提供的equals方法.

System.out.println(s4.equals(s5)); //true

//以下程序执行结束之后,会在字符串常量池中创建3个字符串对象

//"aaa" "bbb"  "aaabbb"

String s6 = "aaa";

String s7 = "bbb";

String s8 = s6 + s7;


字符串对象的区别

1.String s1 = "abc"; 只会在字符串常量池中创建一个"abc"字符串对象.

2.String s2 = new String("hello"); 会在字符串常量池中创建一个"hello"字符串对象,并且会在堆中再创建一个字符串对象。

第二种方式比较浪费内存,常用的是第一种方式。

面试题

//判断以下程序创建了几个对象? 3个

//堆中2个

//方法区字符串常量池中1个.

String s1 = new String("Hello");

String s2 = new String("Hello");


使用String的时候我们应该注意的问题:尽量不要做字符串频繁的拼接操作。

因为字符串一旦创建不可改变,只要频繁拼接,就会在字符串常量池中创建

大量的字符串对象,给垃圾回收带来问题。

String[] ins = {"sport","music","food","sleep"};

//要求将上面的兴趣爱好拼接成一个字符串“sport,music,food,sleep”

String temp = "";

for(int i=0;ins.length; I++){

if(i==ins.length-1){

temp += ins[i];

}else{

temp += ins[i] + ",";

}

}

System.out.println(temp);

字符串常用构造方法

//1.String s1 = "abc";

//2.String s2 = new String("abc");

//3.byte[] bytes = {97,98,99,100};

String s3 = new String(bytes);

System.out.println(s3); //abcd  String已经重写了Object中的toString

//4.String s4 = new String(bytes,1,2);

System.out.println(s4); //bc

//5.char[] c1 = {'我','是','中','国','人'};

String s5 = new String(c1);

System.out.println(s5); //我是中国人

//6.String s6 = new String(c1,2,2);

System.out.println(s6); //中国


字符串常用的方法

//1.char charAt(int index);返回指定索引处的char值

String s1 = "我是王勇,是坏人!";

char c1 = s1.charAt(2);System.out.println(c1); //王

//2.boolean endsWith(String endStr);此字符串是否以指定的后缀结束

System.out.println("HelloWorld.java".endsWith("java")); //true

System.out.println("HelloWorld.java".endsWith("txt")); //false

//3. boolean equalsIgnoreCase(String anotherString);将一个Str和另一个str比较,不考虑大小写

System.out.println("abc".equalsIgnoreCase("ABc")); //true

//4.byte[] getBytes();将字符串转换为byte数组

byte[] bytes = "abc".getBytes()

//5.int indexOf(String str);判断此字符串在另一个字符串第一次出现的索引

System.out.println("http://192.168.1.100:8080/oa/login.action?username=jack&pwd=123".indexOf("/oa"));//25

//6.int indexOf(String str, int fromIndex); 判断此字符串在另一个字符串第一次出现的索引,从指定索引开始,

System.out.println("javaoraclec++javavb".indexOf("java",1)); //13

isEmpty()当且仅当length()为0时返回true

//7.int lastIndexOf(String str)返回此字符串在此字符串中最右边出现的索引

System.out.println("javaoraclec++javavb".lastIndexOf("java")); //13

//8.int lastIndexOf(String str, int fromIndex)从指定的索引反向搜索

System.out.println("javaoraclec++javavb".lastIndexOf("java",14)); //13

//9.int length();

System.out.println("abc".length()); //数组是length属性,String是length()方法

//10. String replaceAll(String s1,String s2);替换,把java替换成mysql

System.out.println("javaoraclec++javavb".replaceAll("java","mysql")); //这个程序是4个字符串//mysqloraclec++mysqlvb

//11.String[] split(String s);

String myTime = "2008,08,08";

String[] ymd = myTime.split(",");以逗号分隔

for(int i=0;ymd.length;i ++){

System.out.println(imd[I]);

}

//12.boolean startsWith(String s);测试此字符串是否以指定的前缀开始

System.out.println("/system/login.action".startsWith("/")); //true

//13.String substring(int begin);截取字符串

System.out.println("/oa/login.action".substring(3)); //  /login.action

//14. String substring(int beginIndex, int endIndex)截取字符串

System.out.println("/oa/login.action".substring(4,9)); //login

//15.char[] toCharArray();将此字符串转换为一个新的字符串数组

char[] c2 = "我是李海波".toCharArray();

//16.转换成大写

System.out.println("Abcdef".toUpperCase());

//17.转换成小写

System.out.println("ABCDEf".toLowerCase());

//18.String trim(); 去掉前面空格和后面空格,但去不掉a后和e前的空格

System.out.print("      a  bcd e          ".trim());

//19.String valueOf(Object obj);返回新的字符串(类型转换)

Object o = null;

System.out.println(o); //不会,因为并不是直接调用toString方法,String.valueOf(Object)这个方法对空值进行处理了。

System.out.println(String.valueOf(o));

//System.out.println(o.toString()); //会出现空指针


java.lang.StringBuffer;

java.lang.StringBuilder;

1.StringBuffer和StringBuilder是什么?

是一个字符串缓冲区.

2.工作原理

预先在内存中申请一块空间,以容纳字符序列,

如果预留的空间不够用,则进行自动扩容,以

容纳更多字符序列。

3.StringBuffer,StringBuilder  和  String最大的区别?

String是不可变得字符序列,存储字符串常量池中。

StringBuffer底层是一个char数组,但是该char数组是可变的。

并且可以自动扩容。

char中是否可以存储一个中文汉字?

解:char底层存储的是unnicode编码格式的中文,

只要unnicode编码中有的中文汉字,就可以在char中声明

4.StringBuffer和StringBuilder的默认初始化容量是16

5.如何优化StringBuffer和StringBuilder呢?

最好在创建StringBuffer之前,预测StringBuffer的存储字符数量,

然后再创建StringBuffer的时候采用指定初始化容量的方式创建StringBuffer.

为了减少底层数组的拷贝。提高效率。

6.StringBuffer和StringBuilder的区别?

StringBuffer是线程安全的。(可以在多线程的环境下使用不会出现问题.)

StringBuilder是非线程安全的。(在多线程环境下使用可能出现问题.)

//创建字符串缓冲区对象

StringBuffer sb = new StringBuffer(); //16

//可以向StringBuffer中追加字符串.

String[] ins = {"体育","音乐","睡觉","美食"};

//推荐字符串频繁拼接使用StringBuffer或者StringBuilder

for(int i = 0; I<ins.length;i ++){

if(i==ins.length-1){

sb.append(ins[i]);

}else{

sb.append(ins[i]);

sb.append(",");

}

System.out.println(sb);

}

推荐阅读更多精彩内容