_____基本数据类型和字符串_____
基本数据类型包装类
为了方便对基本数据类型进行限定(最大最小值等等)和各种操作,建立了基本数据类型包装类,对应如下:
byte Byte
short Short
char Character
int Integer
float Float
long Long
double Double
下面我们以Integer为具体事例来讲解:
自动装箱与拆箱:
在JDK1.5版本以前,int和Integer的转换是这样的//Integer转换成int
Integer in = new Integer(1);
int i = in.intValue();
//int转换成Integer
int i = 1;
Integer in = Integer.valueOf();
JDK1.5版本以后就简化了这些操作,基本数据类型实现了自动装拆箱
//Integer转换成int
Integer in = new Integer(1);
int i = in;//内部还是intValue()实现
//int转换成Integer
int i = 1;
Integer in = i;//内部还是valueOf()实现
有人会问为什么是用valueOf()而不是new Integer(),如下:
class Demo {
public static void main(String[] args) {
Integer i1 = 4;
Integer i2 = 4;
out("i1==i2:"+(i1==i2));
Integer i3 = Integer.valueOf(4);
Integer i4 = Integer.valueOf(4);
out("i3==i4:"+(i3==i4));
Integer i5 = new Integer(4);
Integer i6 = new Integer(4);
out("i5==i6:"+(i5==i6));
out("i1==i3:"+(i1==i3));
out("i3==i5:"+(i3==i5));
}
public static void out(Object o) {
System.out.println(o);
}
}
/*
结果:
i1==i2:true
i3==i4:true
i5==i6:false
i1==i3:true
i3==i5:false
*/
所以我们可以推断:
Integer in = Integer.valueOf(1);
Integer in = 1;
是等价的。
但是Double却不是这样
class Demo {
public static void main(String[] args) {
Double d1 = Double.valueOf(4);
Double d2 = Double.valueOf(4);
out("d1==d2:"+(d1==d2));
Long l1 = Long.valueOf(4);
Long l2 = Long.valueOf(4);
out("l1==l2:"+(l1==l2));
Short s1 = Short.valueOf("4");
Short s2 = Short.valueOf("4");
out("s1==s2:"+(s1==s2));
}
public static void out(Object o) {
System.out.println(o);
}
}
/*
结果:
d1==d2:false
l1==l2:true
s1==s2:true
*/
这里就要讲解下基本数据类型中整型的缓存机制了,以Integer为例:
Integer的缓存机制:
在说缓存机制前,我们先看一个现象:class Demo {
public static void main(String[] args) {
Integer i1 = -128
Integer i2 = -128
out("i1==i2:"+(i1==i2));
Integer i3 = -129
Integer i4 = -129
out("i3==i4:"+(i3==i4));
}
public static void out(Object o) {
System.out.println(o);
}
}
/*
i1==i2:true
i3==i4:false
*/
为什么会存在这样的现象呢?
首先我翻阅了下Integer的源码,找到如下两段:
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
......
}
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
很显然Integer定义了一个缓存内部类,而且low就是缓存的最小值,于是超过这个值就不再是缓存数组里面的对象了,就会建立一个新的对象,这就是导致以上现象的原因,那缓存的最大值呢?我们接着看
IntegerCache内部类中的静态初始化代码块:
static {
// high value may be configured by property
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);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
很显然,最大值是从javaVM虚拟机配置中取出来的,但是最小为127,你可通过运行时设置参数来控制它
class Demo {
public static void main(String[] args) {
Integer i1 = 127;
Integer i2 = 127;
out("i1==i2:"+(i1==i2));
Integer i3 = 128;
Integer i4 = 128;
out("i3==i4:"+(i3==i4));
}
public static void out(Object o) {
System.out.println(o);
}
}
/*
E:\Mark\JavaBase\02>java Demo
i1==i2:true
i3==i4:false
E:\Mark\JavaBase\02>java -Djava.lang.Integer.IntegerCache.high=250 Demo
i1==i2:true
i3==i4:true
*/
常用方法:
1.与字符串之间的转换:
//数字转换成字符串
String s = 1 + "";
String s = Integer.toString(1);
//字符串转换成数字
int i = Integer.valueOf("1");//返回int
int i = parseInt("1");//返回Integer
2.进制转换:
Integer.toBinaryString(int i)//返回二进制表示的字符串
Integer.toHexString(int i)//返回十六进制表示的字符串
Integer.toOctalString(int i)//返回八进制表示的字符串
字符串String类
字符串不属于基本数据类型,是对象。打开String源代码:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
public String() {
this.value = new char[0];
}
}
由此可见String内部其实是封装了一个final修饰的char数组,而且没有提供获取value的方法,所以String对象一旦创建就是
不可变的。
先来看看如何创建String对象:
class Demo {
public static void main(String[] args) {
//第一种
String s1 = "a";
String s2 = "a";
out("s1==s2:"+(s1==s2));
//第二种
String s3 = String.valueOf('a');
String s4 = String.valueOf('a');
out("s3==s4:"+(s3==s4));
//第三种
String s5 = new String("a");
String s6 = new String("a");
out("s5==s6:"+(s5==s6));
}
public static void out(Object o) {
System.out.println(o);
}
}
/*
s1==s2:true
s3==s4:false
s5==s6:false
*/
上面就是常见的三种创建方式,但是与Integer的不同在于,显然
String s1 = "a";
String s3 = String.valueOf('a');
并不等价,但是仍然存在缓存一说,这是因为
字符串常量池的原因。
在使用第二种方式创建字符串数组源代码如下:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
而所以的基本数据类型toString()方法都是通过
return new String(char[] ch)来返回,等同于第三中方式,而new是在堆内存中新建一个对象,所以不地址不相同
第一种方式是先在栈中创建一个对String类的对象引用变量str,然后通过符号引用去字符串常量池里找有没有"abc",如果没有,则将"abc"存放进字符串常量池,并令str指向”abc”,如果已经有”abc” 则直接令str指向“abc”。所以第一种利用了常量池来进行缓存,相同字符串地址相同。
String的常见方法:
先申明:String str = "abcd";1.取得字符串中指定位置的值:
</pre><pre name="code" class="java">str.charAt(1);
//返回'b'
2.按字典顺序比较:
str.compareTo("aBcd");
str.compareToIgnoreCase("aBcd");//无视大小写比较
str.compareTo("abcdef");
/*
32 //若顺序比较到不一样的字符返回差值
0
-2 //若最短的比较完后都相等,那么就返回长度差
*/
3.前缀后缀:
str.startWith("ab")//判断是否以"ab"打头
str.endsWith("de")//判断是否以"de"结尾
/*
true
false
*/
4.比较内容是否相等:
str.equals("abc")//判断是否字符串内容是否相同
str.equalsIgnoreCase("AbcD");//忽视大小写
/*
false
true
*/
5.查找内容:
str.indexOf("bc");//(向右)顺序查找"bc"在str中第一次出现时的索引位置,没有返回-1
str.indexOf("bc",2);//从索引位置2开始顺序查找
str.lastIndexOf("bc");//(向左)反向查找"bc"在str中第一次出现时的索引位置,没有返回-1
str.lastIndexOf("bc",1);//从索引位置1开始反向查找
str.lastIndexOf("bc",0);//从索引位置0开始反向查找
/*
1
-1
1
1
-1
*/
6.替换:
str.replace('a','F');//替换str中所有的a为F
/*
Fbcd
*/
7.拆分:
String s = "deas dea as de";
s.split(" ");//返回String数组,以" "拆分,长度为4
8.裁剪字符串:
"unhappy".substring(2) returns "happy"
"Harbison".substring(3) returns "bison"
"emptiness".substring(9) returns ""
9.大小写转换:
str.toLowerCase();//全转换成小写,返回"abcd";
str.toUpperCase();//全转换成大写,返回"ABCD";
10.去除前后空白:
" abc ".trim() returns "abc"
StringBuffer和StringBuilder类
因为String对象一旦初始化就不可改变,所以才进行大量的字符串操作时,难免产生大量的临时数据,所以出现了StringBuilder和StringBuffer,其内部的char数组是可变长度的,两个类的唯一区别在于StringBuffer是线程安全的,我们下面以StringBuilder为例:1.创建:
StringBuilder sb = new StringBuilder();//可以不指定初始值
StringBuilder sb = new StringBuilder(String str);//也可以指定初始值
2.拼接:
sb.append("aa");//也可以添加基本数据类型
sb.toString();//"aa"
sb.append("bcd");
sb.toString();//"aabcd"
3.删除:
sb.delete(int start, int end);//删除指定索引范围内的数据,包含start不包含end
StringBuilder sb = new StringBuilder("aabcd");
sb.delete(1,2);
sb.toString();//"abcd"
其他方法都与String类似...