文章目录
StringBufferStringBuffer类的概述StringBuffer类的构造方法StringBuffer的添加功能:StringBuffer的删除功能:StringBuffer的替换和反转功能StringBuffer的截取功能及注意事项StringBuffer和String的相互转换案例1:(反转字符串!)案例2:(按照格式输出字符串!)
StringBuffer和StringBuilder的区别:String和StringBuffer分别作为参数传递:ArraysArrays类的概述和方法使用Arrays类的源码解析
基本数据类型的包装类基本类型包装类的概述Integer类的概述和构造方法String和int类型的相互转换
JAVA的自动拆装箱:案例:(判断手机号码的格式是否正确)
StringBuffer
StringBuffer类的概述
概述: a. 我们如果对字符串进行拼接操作,(由于字符串是不可变对象)每次拼接,都会构建一个新的String对象,既耗时,又浪费空间。 b. 而StringBuffer就可以解决这个问题。 c. 定义:它是线程安全的可变字符序列。线程安全的概念:???(这个还不太清楚)StringBuffer和String的区别 : a. String一旦定义,这个内容和长度就固定了。String 是一个长度不可变的字符串。 b. StringBuffer是可变的字符序列容器。小结:Java 给我们提供了一个类 StringBuffer 这个类是一个长度可变的字符串序列容器,那么使用它进行拼串,比你用+=去拼接的更好,它的内容也是可变的,如果要改变一个字符串的内容的话,最好是使用StringBuffer,然后把它最后处理的结果转换为String即可。(节省字符串拼接过程中的内存开销!)StringBuffer的特点: x. 它是一个容器。 a. 可变字符序列通过某些方法调用可以改变该序列的长度和内容。 b. 当你超过容器初始定义的容量后,它会自动扩容! c. 容器中可以存放任何类型的数据!容器的容量和长度有什么区别?
容量:器皿本身就具有容量,不管你放不放水,它的大小都是那么大长度:相当于放类多少水,就有多少长度(放了多少个字符长度的字符串,它就有多长)
StringBuffer类的构造方法
构造方法:
public StringBuffer(): 无参构造方法
(构造一个其中不带字符的字符串缓冲区,初始容量为
16 个字符。
)
public StringBuffer(int capacity
): 指定容量的字符串缓冲区对象
(构造一个不带字符,但具有指定初始容量的字符串缓冲区。
)
public StringBuffer(String str
): 指定字符串内容的字符串缓冲区对象
StringBuffer的方法:
public int capacity(): 返回当前容量。 理论值
public int length(): 返回长度(字符数)。 实际值
示例:
public class MyTest {
public static void main(String
[] args
) {
String str
="abc";
StringBuffer sb
= new StringBuffer();
StringBuffer sb2
= new StringBuffer(100);
StringBuffer sb3
= new StringBuffer("asdf");
int capacity
= sb
.capacity();
System
.out
.println(capacity
);
int length
= sb
.length();
System
.out
.println(length
);
int capacity1
= sb2
.capacity();
System
.out
.println(capacity1
);
int length1
= sb2
.length();
System
.out
.println(length1
);
int capacity2
= sb3
.capacity();
System
.out
.println(capacity2
);
int length2
= sb3
.length();
System
.out
.println(length2
);
}
}
------------------
输出:
16
0
100
0
20
4
StringBuffer的添加功能:
可以把任意类型数据添加到字符串缓冲区里面(末尾位置),并返回字符串缓冲区本身:
public StringBuffer
append(String str
):
在指定位置把任意类型的数据插入到字符串缓冲区里面,并返回字符串缓冲区本身:
public StringBuffer
insert(int offset
,String str
):
sb
.insert(0,"eee")
示例:
public class MyTest2 {
public static void main(String
[] args
) {
StringBuffer sb
= new StringBuffer();
StringBuffer append
= sb
.append(100);
append
.append(600);
StringBuffer append1
= sb
.append(true);
StringBuffer append2
= sb
.append(3.125844);
String string
= sb
.toString();
System
.out
.println(string
);
System
.out
.println(sb
== append
);
System
.out
.println(append1
==append
);
System
.out
.println(append2
==append1
);
}
}
-----------------
输出:
100600true3
.125844
true(证明:返回的都是同一个对象,操作的也是这个对象!
)
true
true
示例2:
public class MyTest3 {
public static void main(String
[] args
) {
StringBuffer sb
= new StringBuffer();
StringBuffer abc
= sb
.append(100).append(true).append(3.14).append("abc");
System
.out
.println(sb
==abc
);
System
.out
.println(sb
);
System
.out
.println(abc
);
}
}
-----------------
输出:
true
100true3
.14abc
100true3
.14abc
StringBuffer的删除功能:
删除指定位置的字符,并返回本身:
public StringBuffer
deleteCharAt(int index
)
----------------------------
StringBuffer sb
= new StringBuffer("abc");
sb
.append("bbb").append("ddd");
在指定索引处插入内容
,返回值还是原来得容器
StringBuffer ss
= sb
.insert(2, "eee");
ss
.append(200);
String string
= sb
.toString();
System
.out
.println(string
); abeeecbbbddd200
根据索引删除容器中某个字符 返回还是原来得容器
StringBuffer stringBuffer
= sb
.deleteCharAt(0); beeecbbbddd200
除从指定位置开始指定位置结束的内容,并返回本身:
public StringBuffer
delete(int start
,int end
)
--------------------------------------------
StringBuffer delete
= sb
.delete(5, 7+1); 含头不含尾
(所以要➕
1)
System
.out
.println(delete
); beeecddd200
StringBuffer的替换和反转功能
从start开始到end用str替换
public StringBuffer
replace(int start
,int end
,String str
) 含头不含尾
-----------------------------------
sb
===> beeecddd200
StringBuffer buffer
= sb
.replace(0, 5, "我爱你");
System
.out
.println(buffer
); 我爱你ddd200
StringBuffer的反转功能
public StringBuffer
reverse():
---------------------------------
StringBuffer reverse
= sb
.reverse();
System
.out
.println(reverse
); 002ddd你爱我
StringBuffer的截取功能及注意事项
StringBuffer的截取功能:
public String
substring(int start
): 从指定位置截取到末尾
public String
substring(int start
,int end
): 截取从指定位置开始到结束位置,包括开始位置,不包括结束位置
(含头不含尾
)
--------------------------------------------
sb
=====> 002ddd你爱我
String s
= sb
.substring(sb
.indexOf("你"),sb
.lastIndexOf("爱")+1);
System
.out
.println(s
);
注意:返回值类型不再是StringBuffer本身,而是String!
StringBuffer和String的相互转换
String -->>> StringBuffera
:通过构造方法
b
:通过
append()方法
StringBuffer -->>>> Stringa
:使用substring方法
b
:通过构造方法
c
:通过
toString()方法
案例1:(反转字符串!)
public class MyTest4 {
public static void main(String
[] args
) {
Scanner scanner
= new Scanner(System
.in
);
System
.out
.println("请录入字符串");
String s
= scanner
.nextLine();
String string
= new StringBuffer(s
).reverse().toString();
System
.out
.println(string
);
}
}
---------------
输出:
请录入字符串
asdf
fdsa
案例2:(按照格式输出字符串!)
public class MyTest3 {
public static void main(String
[] args
) {
int[] arr
= {1, 2, 3};
StringBuffer sb
= new StringBuffer("[");
for (int i
= 0; i
< arr
.length
; i
++) {
if(i
==arr
.length
-1){
sb
.append(arr
[i
]).append("]");
}else{
sb
.append(arr
[i
]).append(",");
}
}
String string
= sb
.toString();
System
.out
.println(string
);
}
}
----------------
输出:
[1,2,3]
StringBuffer和StringBuilder的区别:
StringBuffer() 线程安全效率低(一般常用于:多线程环境下!)
StrringBuilder() 线程不安全效率高(单线程环境下建议使用这个类)
这两者的API完全一致!
String和StringBuffer分别作为参数传递:
注意:(String 类型作为参数传递的一个大坑)
基本类型作为参数传递:值传递,形参的改变不影响实参 但String(不属于基本类型) 但他符合值传递的特点(它是一个常量!)引用类型传递:引用传递,形参的改变会影响实参 StringBuffer作为参数传递 :符合引用传递的特点!
StringBuilder sb
= new StringBuilder("哈哈");
test(sb
);
private static void test(StringBuilder sb
) {
sb
.append("呵呵").reverse();
System
.out
.println(sb
.toString());
}
示例:
public class MyTest5 {
public static void main(String
[] args
) {
String str
="hello";
test(str
);
System
.out
.println(str
);
StringBuilder sb
= new StringBuilder("哈哈");
test(sb
);
System
.out
.println(sb
);
}
private static void test(StringBuilder sb
) {
sb
.append("呵呵").reverse();
System
.out
.println(sb
.toString());
}
private static void test(String s
) {
s
+="world";
System
.out
.println(s
);
}
}
-----------
输出:
helloworld
hello
呵呵哈哈
呵呵哈哈
Arrays
Arrays类的概述和方法使用
概述: 针对数组进行操作的工具类。 提供了排序,查找等功能。主要成员方法:(这些主要方法都是函数重载,可以针对任意类型的数组进行操作,相当于数组中的万能工具类!)
public static String
toString(int[] a
) 不仅针对
int[]类型,任意类型都可以!
public static void sort(int[] a
) 不仅针对
int[]类型,任意类型都可以!
public static int binarySearch(int[] a
,int key
) 不仅针对
int[]类型,任意类型都可以!
static boolean equals(int[] a
, int[] a2
) 比较两个数组中的元素,是否一样
(不仅针对
int[]类型,任意类型都可以!
)
static int[] copyOf(int[] original
, int newLength
) 复制旧数组中的元素到一个新的数组中,新的数组长度是newLength 从
0开始复制旧数组
(不仅针对
int[]类型,任意类型都可以!
)
static int[] copyOfRange(int[] original
, int from
, int to
) 从指定索引处,拷贝旧数组元素到你指定的终止索引处,复制到新的数组中,含头不含尾
(不仅针对
int[]类型,任意类型都可以!
)
案例演示:(通过Arrays类的功能来进排序和查找)
public class MyTest {
public static void main(String
[] args
) {
int[] arr
= {10, 20, 5, 3, 8, 7, 6};
Arrays
.sort(arr
);
String string
= Arrays
.toString(arr
);
System
.out
.println(string
);
int index
= Arrays
.binarySearch(arr
, 7);
System
.out
.println(index
);
}
}
--------------
输出:
[3, 5, 6, 7, 8, 10, 20]
3
Arrays类的源码解析
源码解析:
public static String
toString(int[] a
)
-----------------------------
int[] arr
= {10, 20, 5, 3, 8, 7, 6};
Arrays
.toString(arr
);
查看源码可知:
(他是利用StringBuilder创建了一个字符容器,遍历数组后,将内容添加到容器后,
这里应该有一步将容器变成字符串返回的操作,但是没看,估计是什么高级特性导致的!
)
public static String
toString(int[] a
) {
if (a
== null
)
return "null";
int iMax
= a
.length
- 1;
if (iMax
== -1)
return "[]";
StringBuilder b
= new StringBuilder();
b
.append('[');
for (int i
= 0; ; i
++) {
b
.append(a
[i
]);
if (i
== iMax
)
return b
.append(']').toString();
b
.append(", ");
}
}
源码解析:
public static int binarySearch(int[] a
,int key
)
-------------------------------------------
int[] arr
= {10, 20, 5, 3, 8, 7, 6};
Arrays
.binarySearch(arr
,5);
跳转至:
public static int binarySearch(int[] a
, int key
) {
return binarySearch0(a
, 0, a
.length
, key
);
}
查看源码可知:()
private static int binarySearch0(int[] a
, int fromIndex
, int toIndex
,
int key
) {
int low
= fromIndex
;
int high
= toIndex
- 1;
while (low
<= high
) {
int mid
= (low
+ high
) >>> 1;
int midVal
= a
[mid
];
if (midVal
< key
)
low
= mid
+ 1;
else if (midVal
> key
)
high
= mid
- 1;
else
return mid
;
}
return -(low
+ 1);
}
基本数据类型的包装类
基本类型包装类的概述
需求: a. 将100转换成二进制 , 八进制 , 十六进制 b. 判断一个数是否在int的范围内为什么会有基本类型包装类? JAVA为了我们方便的去操作这些基本类型的数据,那么针对每个基本类型数据,都提供了他所对应的包装类(引用数据类型)常用操作: 常用的操作之一:用于基本数据类型与字符串之间的转换。基本类型和包装类的对应
基本类型对应的包装类
byteByteshortShortintIntegerlongLongfloatFloatdoubleDoublecharCharacterbooleanBoolean
Integer类的概述和构造方法
Integer类概述: 通过JDK提供的API,查看Integer类的说明: a. Integer 类在对象中包装了一个基本类型 int 的值, b. 该类提供了多个方法,能在 int 类型和 String 类型之间互相转换, c. 还提供了处理 int 类型时非常有用的其他一些常量和方法注意: Integer类型还能进行运算!构造方法:(把基本类型,包装成它所对应的包装类)
public Integer(int value
)
public Integer(String s
)
示例1:(基本进制的转换)
public class MyTest {
public static void main(String
[] args
) {
int num
=100;
String string
= Integer
.toBinaryString(num
);
String string1
= Integer
.toHexString(num
);
String string2
= Integer
.toOctalString(num
);
System
.out
.println("二进制:"+string
);
System
.out
.println("八进制:"+string2
);
System
.out
.println("十六进制:"+string1
);
if(2000>=Integer
.MIN_VALUE
&& 2000<=Integer
.MAX_VALUE
){
System
.out
.println("int 类型的值");
}
}
}
-------------
二进制:
1100100
八进制:
144
十六进制:
64
int 类型的值
示例2:(构造函数)
public class MyTest2 {
public static void main(String
[] args
) {
int num
=100;
Integer integer
= new Integer(num
);
Integer integer1
= new Integer("123");
}
}
String和int类型的相互转换
int------String 方法一:
int num
= 100;
String str
= num
+ "";
方法二:(记忆!)String s
= String
.valueOf(num
);
方法三:Integer integer
= new Integer(num
);
String string
= integer
.toString();
String------int 方法一:Integer integer1
= new Integer(strNum
);
int i
= integer1
.intValue();
方法二:(记忆!)
int nun
= Integer
.parseInt(strNum
);
JAVA的自动拆装箱:
JDK1.5之后,JAVA实现了自动拆装箱。 自动装箱:将基本类型自动转换成他所对应的包装类型 自动拆箱:将包装类型自动转换成它所对应的基本类型
示例:(自动拆装箱还是很有用的!)
public class MyTest2 {
public static void main(String
[] args
) {
Integer integer
= new Integer(20);
Integer integer2
= new Integer(200);
int num2
=integer
+integer2
;
int i
= integer
.intValue();
int i1
= integer2
.intValue();
int num
=i
+i1
;
System
.out
.println(num
);
int aa
=200;
Integer integer1
=aa
;
Integer integer3
= Integer
.valueOf(200);
Integer ii
= 100;
ii
+= 200;
}
}
自动装箱的一个问题:127的分界线!(牵扯到了Integer的缓存问题,查看Integer.valueof()的源码!)
public class MyTest3 {
public static void main(String
[] args
) {
Integer i1
= new Integer(127);
Integer i2
= new Integer(127);
System
.out
.println(i1
== i2
);
System
.out
.println(i1
.equals(i2
));
System
.out
.println("-----------");
Integer i3
= new Integer(128);
Integer i4
= new Integer(128);
System
.out
.println(i3
== i4
);
System
.out
.println(i3
.equals(i4
));
System
.out
.println("-----------");
Integer i5
= 128;
Integer i6
= 128;
System
.out
.println(i5
== i6
);
System
.out
.println(i5
.equals(i6
));
System
.out
.println("-----------");
Integer i7
= 127;
Integer i8
= 127;
这里才是重点问题所在:为什么这里是ture
?128都是
false?
System
.out
.println(i7
== i8
);
System
.out
.println(i7
.equals(i8
));
}
}
------------
输出:
false
true
-----------
false
true
-----------
false
true
-----------
true
true
仔细探究:(这两者是一样的,只不过一个手动,另一个是自动的)
Integer i5
= 128;
Integer i5
= Integer
.valueOf(128);
示例:(探究缓存!)
public class MyTest4 {
public static void main(String
[] args
) {
Integer i5
= Integer
.valueOf(128);
Integer i6
= Integer
.valueOf(128);
System
.out
.println(i5
== i6
);
Integer i7
= 127;
Integer i8
= 127;
System
.out
.println(i7
== i8
);
Integer
.valueOf(127);
}
}
----------------
输出:
false
true
结论:发现一个问题,就是只要没有超出127,自动装箱(或手动)产生的对象都是同一个,但是超过127之后,自动装箱(或手动)产生的对象都不是同一个对象! 查看手动装箱(自动装箱也是调用的这个接口!)的源码:
public static Integer
valueOf(int i
) {
if (i
>= IntegerCache
.low
&& i
<= IntegerCache
.high
)
return IntegerCache
.cache
[i
+ (-IntegerCache
.low
)];
return new Integer(i
);
}
发现这里,有三个东西: 第一个东西:
IntegerCache
.low
== -128
第二个东西:
IntegerCache
.high
== 127
第三个东西:(进一步查看源码)
private static class IntegerCache {
static final int low
= -128; 这里就是上面代码中的IntegerCache
.low的来源!
static final int high
; 这里就是上面代码中的IntegerCache
.high的来源!
static final Integer cache
[];
静态代码块:当这个类被加载的时候就调用了!
static {
int h
= 127;
String integerCacheHighPropValue
=
sun
.misc
.VM
.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue
!= null
) {
try {
int i
= parseInt(integerCacheHighPropValue
);
i
= Math
.max(i
, 127);
h
= Math
.min(i
, Integer
.MAX_VALUE
- (-low
) -1);
} catch( NumberFormatException nfe
) {
}
}
high
= h
;
上面主要做了一个工作:初始化定义了high和low的数值范围!
(所以我们也可以自定义这些!
)
创建了一个Integer数组作为缓存!(缓存范围:
127+128+1=256个
,-128~127)
cache
= new Integer[(high
- low
) + 1];
int j
= low
;
for(int k
= 0; k
< cache
.length
; k
++)
把这个
256个Integer缓存数组进行了初始化!
(范围:
-128~127)
cache
[k
] = new Integer(j
++);
assert IntegerCache
.high
>= 127;
}
.......省略其他部分!
}
结论:我们通过上面的源码分析发现,如果我门自动装箱(或者手动装箱)一个在(-128~127)范围内的数字时,其是从类:IntegerCache静态代码块执行的Integer cache[]初始化后得到的缓存中取出来的。因为:Integer cache[]数组中存储的Integer对象(256个)从类加载的时候就存在了,所以装箱得到的对象自然都是相同的(地址都是一样的!)
示例3:(new 和 自动拆装箱有关系吗?)
Integer i7
= new Integer(127);
Integer i8
= new Integer(127);
System
.out
.println(i7
== i8
);
----------------------------
Integer i7
= 127;
Integer i8
= 127;
System
.out
.println(i7
== i8
);
结论: a. new 对象就是创建了一个新的Integer对象。 b. 自动装箱(手动装箱)其实也是返回了一个Integer对象。(只不过在-128~127的对象一早就缓存好了,取出来的都是相同的对象) c. 但是在自动装箱(手动装箱)中,如果数值范围在(-128~127)范围外,看源码可知:它们都是调用了new方法,所以,就没什么差别了。
案例:(判断手机号码的格式是否正确)
示例:
public class Demo {
public static void main(String
[] args
) {
Scanner scanner
= new Scanner(System
.in
);
System
.out
.println("请输入你的手机号码:");
String input
= scanner
.nextLine();
boolean result
= checkPhoneNumber(input
);
if(result
){
System
.out
.println("您输入的手机号格式正确!");
}else{
System
.out
.println("您输入的手机号格式不正确!");
}
}
private static boolean checkPhoneNumber(String input
) {
if(input
.length()!=11){
return false;
}
for (int i
= 0; i
< input
.length(); i
++) {
char digit
= input
.charAt(i
);
if(Character
.isDigit(digit
)){
if(i
!=0||i
!=1){
continue;
}else{
if(digit
== '1' && i
==0){
continue;
}else if( i
==1 && "35789".contains(Character
.valueOf(digit
).toString()) ){
continue;
}else{
return false;
}
}
}else{
return false;
}
}
return true;
}
}
---------------
请输入你的手机号码:
13289226786
您输入的手机号格式正确!