--------------------- android培训、java培训、java学习型技术博客、期待与您交流! -------------------
【Sing】【StringBuffer】【StringBuilder】【基本类型包装类】
1 String类
String类的定义:
public final class String 没有子类,因为用final修饰了
String 类是描述字符串的类。Java 程序中的所有字符串字面值(如"abc")都作为此类的实例实现。也就是说只要用“”双引号引起来的,都是一个String的一个具体对象。
查看API发现String有很多构造函数,其中就有空参数构造函数
String s =new String();
String s = “ ”;
上面两条指令一个意思,因为第一个比较麻烦,一般都是用第二种。
String s1 = “abc”;s1是一个类类型变量,所以”abc”是一个类类型变量。
字符串的特点是一旦被初始化,就不能改变。字符串常量就是这个意思,固定不变的一个值。
如果再输入s1 = “kk”这个时候如果输出s1就是kk。这个时候上面的abc没有改变,只不过s1的地址指向了kk,上面的abc还是常量。
String s2=new String(“abc”);
1. s1==s2
2. s1.equals(s2)
上面的第一个为false,第二个true,因为s2是new出来的对象,new String(“abc”)实质是创建了两个对象,s2指向了该对象;而第二个equals判断是内存中的地址值,s1和s2指向的是同一个地址。String类复写了Object类中equals方法,该方法用于判断字符串是否相同。
String s1 = “abc”
String s2=new String(“abc”);
String s3 = “abc”
S1==s2 输出结果是false
S1==s3 输出结果是true
S1和s2的区别
S1在内存中有一个对象,s2在内存中有两个对象。就这一个区别。S2有两个对象是因为一个常量abc,另一个是new String,分别存在于常量池和堆内存中,两个对象。
其实内存块里面有个常量池,字符串会存放在常量池里面。
s1==s3是因为s3建立的时候,发现内存中已经有abc了,所以就不单独再开空间了。所以相等。
字符串四个特点
|--字符串类型的数据是一个对象
|--是一个常量,不能被改变
|--s1和s2的区别
4|--s1.equals(s2),字符串类中覆写了object类中的equals方法,用来判断字符串内容是否相同
扩展知识:
“==”判断的是两个变量或实例是否是指向同一个内存地址;
equals是判断两个变量或实例所指向的内存空间的值是不是相同;
instanceof是判断两个变量(引用)是否是同一个类类型的。
(1)对于字符串变量来说,使用“==”和“equals()”方法比较字符串时,其比较方法不同。
“==”比较两个变量本身的值,即两个对象在内存中的首地址。
“equals()”比较字符串中所包含的内容是否相同。
比如:
String s1,s2,s3 = "abc", s4 ="abc" ;
s1 = new String("abc");
s2 = new String("abc");
那么:
s1==s2 是 false //两个变量的内存地址不一样,也就是说它们指向的对象不 一样,
故不相等。
s1.equals(s2) 是 true //两个变量的所包含的内容是abc,故相等。
注意:
如果: StringBuffer s1 =new StringBuffer("a");
StringBuffer s2 = new StringBuffer("a");
结果: s1.equals(s2) //是false
解释:StringBuffer类中没有重新定义equals这个方法,因此这个方法就来自Object类, 而Object类中的equals方法是用来比较“地址”的,所以等于false.
注意:
对于s3和s4来说,有一点不一样要引起注意,由于s3和s4是两个字符
串常量所生成的变量,其中所存放的内存地址是相等的,
所以s3==s4是true(即使没有s3=s4这样一个赋值语句)
(2)对于非字符串变量来说,"=="和"equals"方法的作用是相同的都是用来比较其
对象在堆内存的首地址,即用来比较两个引用变量是否指向同一个对象。
例子:
class A
{
A obj1 = new A();
A obj2 = new A();
}
那么:obj1==obj2是false
obj1.equals(obj2)是false
但是如加上这样一句:obj1=obj2;
那么 obj1==obj2 是true
obj1.equals(obj2) 是true
总之:equals方法对于字符串来说是比较内容的,而对于非字符串来说是比较
其指向的对象是否相同的。
“==” 比较符也是比较指向的对象是否相同的也就是对象在对内存中的的首地址。
String类中重新定义了equals这个方法,而且比较的是值,而不是地址。所以是true。
equals方法和instanceof 的区别:
instanceof操作符用于判断一个引用类型所引用的对象是否是一个类的实例 .对于引用类型变量,Java 编译器只根据变量被先生声明的类去编译。
instanceof 左边操作元被显式声明的类型与右边操作元必须是同种类或者有继承关系,即位于继承树的同一个继承分支上,否则编译出错.
Object 类的 equals() 方法的比较规则为:当参数 obj 引用的对象与当前对象为同一个对象时,就返回true,否则返回false
在JDK中有一些类覆盖了 Object 类的equals()方法,它们的比较规则为:
如果两个对象的类型一致,并且内容一致,则返回true。
这些类包括:java.io.File、java.util.Date、java.lang.String、包装类(如java.lang.Integer和java.lang.Double类)。
如果是自己定义的类的话,可以复写equals()方法,自己定义比较规则
Java语言对equals()的要求如下,这些要求是必须遵循的,以下几点也算是和instanceof 的区别:
|----对称性:如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true”。
|----反射性:x.equals(x)必须返回是“true”。
|---- 类推性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也应该返回是“true”。
|---- 还有一致性:如果x.equals(y)返回是“true”,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是“true”。
|---- 任何情况下,x.equals(null),永远返回是“false”;x.equals(和x不同类型的对象)永远返回是“false”。
String中的方法:
常见字符串操作:
1. 获取
|----字符串中包含的字符数,也就是字符串的长度int length()(数组有长度但是是属性,通过arr.length返回这个属性来完成。而这里是一个方法,带(),功能是获取长度。)
|----根据位置获取位置上某个字符。
CharcharAt(int index):
|----根据换字符获取该字符串中的位置。
IntindexOf (int ch):返回的是ch在字符串中第一次出现的位置。当访问到字符串中不存在的角标时会发生StringIndexOutOfBoundsException。字符角标越界。
int indexOf(intch, int fromIndex) :从fromIndex指定位置开始,获取ch在字符串中出现的位置。如果ch值没有出现在字符串中,输出的值为-1
int indexOf(String str):返回的是str在字符串中第一次出现的位置。
intindexOf(String str, int fromIndex) :从fromIndex指定位置开始,获取str在字符串中出现的位置。String型,字符串应该用单引号’a’
int lastIndexOf(int ch):反向索引,输出的结果还是正常的角标,只不过系统会从后面往前数数。注意这里是int型,字符串a应该加双引号”a”
简单例子:
1
7 import java.util.Scanner;
8
9
10 public class Lianxi {
11 public static void main(String[] args) {
12 //定义键盘输入功能
13 Scanner sc=new Scanner(System.in);
14 //输入字符串
15 System.out.println("请输入字符串:");
16 //接收字符串
17 String str=sc.nextLine();
18 //定义计数器
19 int big=0;
20 int num=0;
21 int small=0;
22 //遍历字符判断类型
23 for(int x=0;x<str.length();x++){
24 char ch=str.charAt(x);
25 if(ch>='a'&&ch<='z'){
26 small++;
27 }
28 else if(ch>='A'&&ch<='Z'){
29 big++;
30 }
31 else{
32 num++;
33 }
34 }
35 System.out.println("大写字母个数:"+big);
36 System.out.println("小写字母个数:"+small);
37 System.out.println("数字个数:"+num);
38 }
39 }
2,判断。
|----字符串中是否包含某一个子串。(两个方法)
boolean contains(str):
特殊之处重要掌握:indexOf(str):可以索引str第一次出现位置,如果返回-1.表示该str不在字符串中存在。所以,也可以用于对指定判断是否包含。
if(str.indexOf("aa")!=-1)
而且该方法即可以判断,有可以获取出现的位置。
|----字符中是否有内容。
boolean isEmpty(): 原理就是判断长度length()是否为0.
|---- 字符串是否是以指定内容开头。
boolean startsWith(str);
|---- 字符串是否是以指定内容结尾。
boolean endsWith(str);
|---- 判断字符串内容是否相同。复写了Object类中的equals方法。不忽略大小写 boolean equals(str);
|---- 判断内容是否相同,并忽略大小写。
boolean equalsIgnoreCase();
3,转换。
|----将字符数组转成字符串。
构造函数:String(char[])
String(char[],offset,count):将字符数组中的一部分转成字符串。
Offset是角标,count是个数,从offset开始后面的count数目的数组内容转换成字符串。如果有对象建立,放到新的对象里面
char[] arr = {'a','b','c','d','e','f'};
String s= new String(arr,1,3);
sop("s="+s);
输出结果是s=bcd
静态方法:
static String copyValueOf(char[]);
static String copyValueOf(char[]data, int offset, int count)
static String valueOf(char[]):
要回去找这些方法并使用。静态的方法是因为方法内部没有特殊变量
|----将字符串转成字符数组。**
char[] toCharArray():
|---- 将字节数组转成字符串。
String(byte[])一定要记住这个函数
String(byte[],offset,count):将字节数组中的一部分转成字符串。
|---- 将字符串转成字节数组。
byte[] getBytes():
|---- 将基本数据类型转成字符串。
static String valueOf(int)
static String valueOf(double)
//3+"";//String.valueOf(3);这两个的意思是一样的。3和空字符,后者比较准确,但比较麻烦,一般写前者。
特殊:字符串和字节数组在转换过程中,是可以指定编码表的。
简单例子:
40
48 import java.util.Scanner;
49
50 public class Test {
51 public static void main(String[] args) {
52 // 封装键盘录入字符串
53 Scanner sc = new Scanner(System.in);
54 System.out.println("请输入字符串:");
55 String str = sc.nextLine();
56 // 截取字符串
57 String str1 = str.substring(0, 1);
58 String str2 = str.substring(1, str.length());
59 // 转换大小写
60 String str3 = str1.toUpperCase();
61 // 连接字符串
62 String str4 = str3.concat(str2);
63 System.out.println("str4=" + str4);
64 }
}
4,替换
String replace(oldchar,newchar);
示例:
String s = "Hello Java";
String s1 = s.replace(‘a’,’n’);
Sop(s);
Sop(s1);
输出结果是Hello Java和Hello Jnvn。因为s字符串用final修饰,不会变的。调用replace函数以后赋值给了s1
如果用q替换n呢?没有q,所以返回的是原字符串
5,切割
String[] split(regex);
示例: public static void method_split()
{
String s ="zhagnsa,lisi,wangwu";
String[] arr = s.split(",");//建立一个字符串数组,arr,用来放s切割后的字符串。
for(int x = 0; x<arr.length; x++)
{
sop(arr[x]);//打印数组
}
}
注意这是个分割函数,用’,’分割,这个逗号是拿不到的。
简单例子:
65
73 public class Demo {
74 public static void main(String[] args) {
75 // 输入字符串
76 String str1 = "basckd";
77 // 转换成字符数组
78 char[] chs = str1.toCharArray();
79 // 定义排序功能,选择排序
80 selectSort(chs);
81 // 将字符数组转换成字符串
82 String str2 = String.valueOf(chs);
83 System.out.println(str2);
84 }
85
86 private static void selectSort(char[] chs) {
87 for (int x = 0; x < chs.length - 1; x++) {
88 for (int y = x + 1; y < chs.length; y++) {
89 if (chs[x] > chs[y]) {
90 char temp = chs[x];
91 chs[x] = chs[y];
92 chs[y] = temp;
93 }
94 }
95 }
96
97 }
98 }
6,子串。获取字符串中的一部分。
String substring(begin);
String substring(begin,end);
示例 String s ="abcdef";
sop(s.substring(2));//从指定位置开始到结尾。如果角标不存在,会出现字符串角标越界异常。
sop(s.substring(2,4));//包含头,不包含尾。
上面输出的结果是cdef和cd。获取所有的数组的就是s.substring(0,s.length());
7,转换,去除空格,比较。
|---- 将字符串转成大写或则小写。
String toUpperCase();
String toLowerCase();
|----将字符串两端的多个空格去除。
String trim();
|---- 对两个字符串进行自然顺序的比较。
int compareTo(string);
2 StringBuffer、StringBuilder类
StringBuffer是字符串缓冲区。是一个容器。可以对字符串内容进行增删。字符串的组成原理就是通过该类实现的。publicfinal class StringBuffer,同样被final修饰,不能修改
特点:
1,长度是可变化的。
2,可以字节操作多个数据类型。
3,最终会通过toString方法变成字符串。
数组的个数和类型是固定的,所以当数值类型和个数不固定时一般都用StringBuffer
特点:
1,长度是可变化的。
2,可以字节操作多个数据类型。
3,最终会通过toString方法变成字符串。
1,存储。
StringBuffer append():将指定数据作为参数添加到已有数据结尾处。
Byte short没有,因为接收int无法提升
StringBuffer insert(index,数据):可以将数据插入到指定index位置。
示例:StringBuilder sb = new StringBuffer ();
StringBuffer sb1 =sb.append(34);
Sop(sb.toString());
Sop(sb1.toString());
此时输出结果一样,并且sb==sb1,原因是StringBuffer是一个容器,放了sb,改变了sb为sb1,还是那个容器并没有变。所以改变后两者相等。并且可以这样使用
Sb.appen(“abc”).apend(34);方法调用链,方法使用后返回的仍然为原来的对象可以继续调用方法
Sb.insert(1,”qq”)从第一位后插入qq这个字符串
2,删除。
StringBuffer delete(start,end):删除缓冲区中的数据,包含start,不包含end。
StringBuffer deleteCharAt(index):删除指定位置的字符。
清空缓冲区的命令:sb.delete(0,sb.length());最大角标是length-1,因为这个delete命令包含头不包含尾,所以是sb.length()。
3,获取。
char charAt(int index)
int indexOf(String str)
int lastIndexOf(String str)
int length()
String substring(int start, int end)
4,修改。
StringBuffer replace(start,end,string);
void setCharAt(int index, char ch) ;
5,反转。
StringBuffer reverse();
6,将缓冲区中指定数据存储到指定字符数组中。
void getChars(int srcBegin, int srcEnd,char[] dst, int dstBegin)
JDK1.5 版本之后出现了StringBuilder.
StringBuffer与StringBuilder的区别:StringBuffer是线程安全的,效率低;StringBuilder是线程不安全的,效率高
StringBuffer是线程同步。
StringBuilder是线程不同步。
以后开发,建议使用StringBuilder
升级三个因素:
1,提高效率。
2,简化书写。
3,提高安全性。
简单例子:
99
105 public class Lianxi {
106 public static void main(String[] args) {
107 int[] arr = { 3, 7, 9, 0, 5 };
108 String str = arrayToString(arr);
109 System.out.println(str);
110 }
111
112 private static String arrayToString(int[] arr) {
113 // 建立StringBuilder对象
114 StringBuilder sb = new StringBuilder();
115 // 遍历数组,添加字符串
116 sb.append("[");
117 for (int x = 0; x < arr.length; x++) {
118 if (x != arr.length - 1) {
119 sb.append(arr[x] + ",");
120 } else {
121 sb.append(arr[x] + "]");
122 }
123 }
124 return sb.toString();
125 }
126 }
3 基本数据类型包装类
在许多情况下包装与解包装是由编译器自行完成的(在这种情况下包装成为装箱,解包装称为拆箱);
可理解理解自动装箱就可以简单的理解为将基本数据类型封装为对象类型,来符合java的面向对象;
例如用int:
Integer num = 10; //声明一个Integer对象 此声明就是用到了自动的装箱:解析为
Integer num = new Integer(10);以上就是一个很好的体现,因为10是属于基本数据类型的,原则上它是
不能直接赋值给一个对象Integer的,但jdk1.5后你就可以进行这样的声明,这就是自动装箱的魅力
自动将基本数据类型转化为对应的封装类型。成为一个对象以后就可以调用对象所声明的所有的方法
自动拆箱:故名思议就是将对象重新转化为基本数据类型:
Integer num = 10;//装箱
int num1 = num;//拆箱
自动拆箱有个很典型的用法就是在进行运算的时候:因为对象时不能直接进行运算的,而是要转化为基本数据类型后才能进行加减乘除 。
Integer num = 10;
//进行计算时隐含的有自动拆箱
System.out.print(num--);
在-128~127 之外的数
Integer num1 = 297; Integer num2 = 297; //在-128~127 之外的数
System.out.println("num1==num2: "+(num1==num2)); //num1==num2: false
Integer num3 = 97; Integer num4 = 97;// 在-128~127 之内的数
System.out.println("num3==num4: "+(num3==num4)); //num3==num4: true
说明:
加大对简单数字的重利用,java定义:在自动装箱时对于值从–128到127之间的值,它们被装箱。
这就归结于java对于Integer与int的自动装箱与拆箱的设计,是一种模式:叫享元模式(flyweight)
为Integer对象后,会存在内存中被重用,始终只存在一个对象 而如果超过了从–128到127之间
的值,被装箱后的Integer对象并不会被重用,即相当于每次装箱时都新建一个 Integer对象。
自动装箱拆箱不仅在基本数据类型中有应用,在String类中也有应用:
String str = "sl";
//代替下面的声明方式
String str = new String("sl");
例题 1、 Integer a = new Integer(100); Integer b = 100; Integer c =100; int d = 100;a、b、c、d这四个数通过“==”和equals方法,进行比较,都哪些结果是true,哪些是false?
public class T1 {
public static void main(String[] args) {
Integer a = new Integer(100);
Integer b = 100;
Integer c =100;
int d = 100;
// 下面是测试证明“==”
System.out.println(d==a); //true
System.out.println(d==b); //true
System.out.println(d==c); //true
System.out.println(a==b) ;//false
System.out.println(a==c);//false
System.out.println(b==c);//true
// 下面是测试证明“equals”
// System.out.println(d.equals(a));//不能调用基本类型 int 的 equals(Integer)
// System.out.println(d.equals(b));//不能调用基本类型 int 的 equals(Integer)
// System.out.println(d.equals(c));//不能调用基本类型 int 的 equals(Integer)
System.out.println(b.equals(c));//true
System.out.println(a.equals(b));//true
System.out.println(a.equals(c));//true
System.out.println(a.equals(d));//true
System.out.println(b.equals(d));//true
System.out.println(c.equals(d));//true
}
}
讲解:
1. d==a;d==b;d==c;为true
因为JDK1.5版本以后的新特性可以可以Integer对象自动拆箱成为int型变量,所以结果为true。
2. a==b与a==c;为false,
因为b和c为自动装箱后才生的两个新对象,该对象与a不是同一对象。
3. b==c为true
因为他们都是由int型变量自动装箱而来,他们的比较是先拆箱还原成int型变量之后才进行比较,由于d为int型变量,不是对象,没有equals方法,所以不能和a,b,c对象做比较。
4. b.equals(c);a.equals(b);a.equals(c);都为true
因为equals只针对对象的内容进行比较。
5. a.equals(d);b.equals(d);c.equals(d) 都为true
因为此时的int型变量被自动装箱为Integer对象,而equals只针对对象的内容进行比较。
总结:
操作字符串的方法有很多,刚开始学的时候感觉知识点太多了,但学完一回顾大致也就分为四类,增删改查.StringBuffer和StringBuilder的区别就在于是否是线程安全,线程安全的有同步代码,每次运行都需要判断同步锁,效率相比之下也就比较低
基本数据类型:
1.在进行编译时,编译器再自动根据您写下的语句,判断是否进行自动装箱动作。
在上例中integer参考的会是Integer类的实例。同样的动作可以适用于 boolean、
byte、short、char、long、float、double等基本数据类型,分别会使用对应的打
包类型(Wrapper Types)Boolean、Byte、Short、Character、Long、Float或Double。
2.在JAVA中利用"=="比较变量时,系统使用变量在"栈"中所存的值作为比较的依据。
基本数据类型在"栈"中存的是其内容值,而对象类型在"栈"中存的是地址,这些地址指向"堆"中的对象。==只针对变量的值;equals只针对对象的内容。
本篇博文结束!
@感谢老师的辛苦批阅