1、位于java.lang.*
这个包中,具体是java.lang.String;
2、内容不可变,具体说是,这个类所指的对象,一旦初始化之后,就不能改变了
指向可以改变,但是内容不能改变。
String中的内容不能改,不是因为成员是final类型的,因为,比如final []vlaue,它所指向对象的内容是可以改变的,但是对象是不能改变的。也就是final对象不能变,但是数值可以变。
String中内容不能改,是因为,成员是private类型的,外部访问不到。
3、String内部采用了字符数组
4、例题1
public class NI
{
public static void main(String[] args)
{
String s="Hello";
s=s+" World";
System.out.println(s);
}
}
问:上面的代码是否正确呢?
答案:正确
解析:原对象叫Hello,之后,有+号,作用是字符串连接,但是注意,因为String类型所指对象的内容是不能改变的,所以,jvm会自动复制一份,生成了一个新对象Hello,之后,在新对象的基础上再进行的连接,最终为Hello World,把这个新对象赋值给s,所以说,原对象并没有改变,所以是正确的。
5、String生成对象的方式和内存分配方式
(1)可以直接赋值成一个常量字符串,不需要new一个新对象。
(2)new出的对象才放在堆中,但是常量字符串则放在数据区。
(3)在数据区进行赋值的时候,会先找数据区中有没有一样的东西,如果有的话,就直接指向它即可,否则,就在数据区中新开辟内存生成对象。
(4)例题1
- 首先因为将一个常量字符串赋值给s1,所以说,Mondy存放在数据区,之后因为是将一个字符串赋值给s2,所以,同样也是存放在数据区中,因为数据区中已经有了Mondy,所以s2也指向Mondy
- ==是判断逻辑地址的,两者的逻辑地址一样,所以说,输出 s1 ==s2
(5)例题2 String类已经将equals进行了重写,同时也重写了toString方法,自动继承了Comparable接口,实现了compareTo接口
- 一个放在数据区,一个放在堆区,所以说两者逻辑地址不相同,所以会打印s1!=s2
- String类已经将equals进行了重写,所以,只要两者的内容相同即可,所以说会打印s1 equals s2
- 注意==和equals之间的区别
(6)实例3
- toUpperCase()意思是将所有的英文字符转换为大写字母
- 答案是==(意味着逻辑地址是相等的)
- 因为原本全为大写,所以相当于返回s的引用,因此两者指向同一个对象
public class NI
{
public static void main(String[] args)
{
String s="Hello";
String t=s.toUpperCase();
System.out.println(s);
System.out.println(t);
}
}
输出结果为:
Hello
HELLO
这个例题的打印结果要注意了,打印s的时候,s还是原值,而不是大写的值,是因为,虽然是有toUpperCase()这个函数,但是,没有改变s所指对象的内容,s所指的对象仍然是Hello,仅仅是在数据区中又生成了一个对象而已,如下图所示:
- 答案!=
- 因为之后t全为大写,两者的内容不同,因此指向的对象也是不同的
经过上面的两个例子,我们可以发现,如果原字符串本身就是一个大写形式或者是一个小写的形式,那么返回原始对象,jvm不会在原来的基础上复制出一份来,但是如果本身不是大写或者是小写的话,toUpperCase()和toLowerCase()方法返回一个新String对象。
当需要改变字符串的内容的时候,String类的方法会返回一个新的String对象,但是如果内容没有改变的话,String的相关方法只能返回指向原有对象的引用,不会生成新对象。
6、String类函数总结
(1)如果是String s="Hello";然后s.XXX();
这样的话,s所指对象没有变,而且s所指对象的内容没有变,因为,这样相当于在s外赋值一份和s一模一样的东西,然后在复制的东西上进行改变,返回的是这个复制且改变的东西。
如此图所示,其实原来在外面复制了一份Hello,然后在外面Hello的基础上进行的改变,改成了大写的HELLO,返回的也是外部的HELLO;
(2)如果是String s="Hello";然后s=s.XXX();
这样的话,s所指对象变了,但是s原对象所指的内容没有变,相当于是s指向了在外面复制且改变之后的数据
- string.length()是用来求字符串的长度,返回值为字符串的长度。
- string.charAt()为取该字符串某个位置的字符,从0开始,例如string.charAt(0)就会返回该字符串的第一个字符。
- string.getChars()为将这个字符串中的字符复制到目标字符数组。
- string.replace()将在外面复制出来string 中的元素或子串替换。返回替换后的string。
s.replace('我', '你');
把字符串中所有的“我”都换成“你”;
- string.toUpperCase()为将在外面复制出来字符串string中字符变为大写。
- string.toLowerCase()为将在外面复制出来字符串string中字符变为小写。
- string.trim()为去除在外面复制出来字符串的前后的空格,中间的空格没有去除,返回外部复制出的对象。
- string.toCharArray()为将字符串转换为字符数组。
- string.indexOf()所判断的对象中,有没有括号中写的字符串,有的话,就返回首字母所在的位置,注意例如
String s1="sun java";
System.out.println(s1.indexOf("java"));
结果是4,因为s是0,中间有空格
- string.equalsIgnoreCase(),忽略大小写,比较与括号中的内容是否相同
- string.equals()比较与括号中的内容是否相同
- string.startsWith()是不是以括号中的为开头
- string.endsWith()是不是以括号中的为结尾
- string.substring()求子串方法是重载的,有很多用法
(1)str.substring(int beginIndex,int endIndex);中最终得到的值:
beginIndex =< str的值 < endIndex
(2)str=str.substring(int beginIndex);从str中截取掉长度为beginIndex的字符串,将剩余字符串赋值给str
比如String sub=s.substring(1);
意思是,截取掉第一个元素即可;
String sub=s.substring(0);
截取掉第0个元素即可,相当于没有截取;
(1)例题1
public static void main(String[] args)
{
String s1="sun java",s2="Sun Java";
System.out.println(s1.charAt(1));
System.out.println(s2.length());
System.out.println(s1.indexOf("java"));
System.out.println(s1.equals(s2));
System.out.println(s1.equalsIgnoreCase(s2));
String s="我是程序员,我在学java";
String sr=s.replace('我', '你');
System.out.println(sr);
}
答案:
u
8
4
false
true
你是程序员,你在学java
(2)例题2
public static void main(String[] args)
{
String s="Welcome to Java World!";
String s1=" sum java";
System.out.println(s.startsWith("Welcome"));
System.out.println(s.endsWith("World"));
String sL=s.toLowerCase();
String sU=s.toUpperCase();
System.out.println(sL);
System.out.println(sU);
String subS=s.substring(11);
System.out.println(subS);
String sub=s.substring(1);
System.out.println(sub);
String sp=s1.trim();
System.out.println(sp);
}
答案:
true
false
welcome to java world!
WELCOME TO JAVA WORLD!
Java World!
elcome to Java World!
sum java
7、String类中提供的静态方法
(1)String.valueOf(j);
把形参中的内容,转换成前面类的类型,这里也就是String类型
这也是将整形换成字符串的一种方法;还有一个方法就是int类型的数据+“”
将引用转化为字符串的方法,实际上是调用引用中toString方法。