纲要
(1)String、StringBuffer and StringBuilder
(2)基本数据类型对应的八个包装类
(3)日期相关类
(4)数字相关类
(5)Random
(6)Enum 枚举类
一、String
String 被声明为 final,因此它不可被继承。(Integer 等包装类也不能被继承)
在 Java 8 中,String 内部使用 char 数组存储数据。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
}
在 Java 9 之后,String 类的实现改用 byte 数组存储字符串,同时使用 coder 来标识使用了哪种编码。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final byte[] value;
/** The identifier of the encoding used to encode the bytes in {@code value}. */
private final byte coder;
}
value 数组被声明为 final,这意味着 value 数组初始化之后就不能再引用其它数组。并且 String 内部没有改变 value 数组的方法,因此可以保证 String 不可变。
public class StringTest01 {
public static void main(String[] args) {
String s1 = "a";
String s2 = "b";
s1=s1 + s2; //ab
//new String(“a”);
System.out.println(s1);
}
}
从以上内存图,大家可以看到,String 对象赋值后不能再修改,这就是不可变对象,如果对字
符串修改,那么将会创建新的对象
注意: 只要采用双引号赋值字符串,那么在编译期将会放到方法区中的字符串的常量池里,如
果是运行时对字符串相加或相减会放到堆中(放之前会先验证方法区中是否含有相同的字符
串常量,如果存在,把地址返回,如果不存在,先将字符串常量放到池中,然后再返回该对
象的地址)
public class StringTest02 {
public static void main(String[] args) {
String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
System.out.println("s1==s2, " + (s1==s2)); // true
System.out.println("s2==s3, " + (s2==s3)); // false
System.out.println("s2 equlas s3," + (s2.equals(s3))); // true
}
}
• 如果是采用双引号引起来的字符串常量,首先会到常量池中去查找,如果存在就不再分配,
如果不存在就分配,常量池中的数据是在编译期赋值的,也就是生成 class 文件时就把它
放到常量池里了,所以 s1 和 s2 都指向常量池中的同一个字符串“abc”
• 关于 s3,s3 采用的是 new 的方式,在 new 的时候存在双引号,所以他会到常量区中查找
“abc”,而常量区中存在“abc”,所以常量区中将不再放置字符串,而 new 关键子会在
堆中分配内存,所以在堆中会创建一个对象 abc,s3 会指向 abc
• 如果比较 s2 和 s3 的值必须采用 equals,String 已经对 eqauls 方法进行了覆盖
String常用方法简介
- endsWith:判断字符串是否以指定的后缀结束
- startsWith,判断字符串是否以指定的前缀开始
- equals,字符串相等比较,不忽略大小写
- equalsIgnoreCase,字符串相等比较,忽略大小写
- indexOf,取得指定字符在字符串的位置
- lastIndexOf,返回最后一次字符串出现的位置
- length,取得字符串的长度
- replaceAll,替换字符串中指定的内容
- split,根据指定的表达式拆分字符串
- substring,截子串
- trim,去前尾空格
- valueOf,将其他类型转换成字符串
使用String时的注意事项
因为 String 是不可变对象,如果多个字符串进行拼接,将会形成多个对象,这样可能会造成内
存溢出,会给垃圾回收带来工作量,如若涉及大量对象创建,建议使用StringBuffer
或StringBuilder
StringBuffer and StringBuilder
StringBuffer 称为字符串缓冲区,它的工作原理是:预先申请一块内存,存放字符序列,如果字符序列满了,会重新改变缓存区的大小,以容纳更多的字符序列。StringBuffer 是可变对象,这个是与 String 最大的不同
StringBuilder用法同 StringBuffer,StringBuilder 和 StringBuffer 的区别是 StringBuffer 中所有的方法都是同步的,是线程安全的,但速度慢,StringBuilder 的速度快,但不是线程安全的
public class StringBufferTest01 {
public static void main(String[] args) {
StringBuffer sbStr = new StringBuffer();
for (int i=0; i<100; i++) {
//sbStr.append(i);
//sbStr.append(",");
//方法链的编程风格
sbStr.append(i).append(",");
//拼串去除逗号
//sbStr.append(i);
//if (i != 99) {
// sbStr.append(",");
//}
}
//可以输出
System.out.println(sbStr);
System.out.println("");
System.out.println(sbStr.toString());
System.out.println("");
//去除逗号
System.out.println(sbStr.toString().substring(0,sbStr.toString().length()-1));
System.out.println("");
System.out.println(sbStr.substring(0, sbStr.length()-1));
}
}
总结:
①可变性
String 不可变
StringBuffer 和 StringBuilder 可变
② 线程安全
String 不可变,因此是线程安全的
StringBuilder 不是线程安全的
StringBuffer 是线程安全的,内部使用 synchronized 进行同步
二、基本类型对应的包装类
基本类型都有对应的包装类型,基本类型与其对应的包装类型之间的赋值使用自动装箱与拆箱完成。基本类型的包装类主要提供了更多的实用操作,这样更容易处理基本类型。所有的包装类都是final 的,所以不能创建其子类,包装类都是不可变对象
基本类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
char | Character |
类层次结构
除了 boolean 和 Character 外,其它的包装类都有 valueOf()和 parseXXX 方法,并且还具有
byteVaue(),shortVaue(),intValue(),longValue(),floatValue()和 doubleValue()方法,这些方法是最
常用的方法
public class IntegerTest01 {
public static void main(String[] args) {
int i1 = 100;
Integer i2 = new Integer(i1);
double i3 = i2.doubleValue();
String s = "123";
int i4 = Integer.parseInt(s);
Integer i5 = new Integer(s);
Integer i6 = Integer.valueOf(s);
}
}
JDK5.0的新特性
在 JDK5.0 以前,包装类和基本类型做运算时,必须将包装类转换成基本类型才可以,而 JDK5.0
提供 Auto-boxing/unboxing(自动装箱和拆箱)即:
•自动将基础类型转换为对象
•自动将对象转换为基础类型
public class IntegerTest01 {
public static void main(String[] args) {
//jdk1.5 以前版本,必须按如下方式赋值
Integer i1 = new Integer(100);
//jdk1.5 及以后版本支持
//自动装箱
Integer i2 = 100;
//jdk1.5 以前版本,必须按如下方式赋值
int i3 = i2.intValue();
//jdk1.5 及以后版本支持
//自动拆箱
int i4 = i2;
}
}
三、日期类
常用日期类:
java.util.Date
java.text.SimpleDateFormat
java.util.Calendar
import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class DateTest01 {
public static void main(String[] args) throws Exception{
//取得今天的日期
Date today = new Date();
System.out.println(today);
//格式化日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(today));
Calendar c = Calendar.getInstance();
System.out.println(c.get(Calendar.DAY_OF_MONTH));
//取得 2020-05-04 为星期几
Date d = new SimpleDateFormat("yyyy-MM-dd").parse("2000-10-01");
c.setTime(d);
System.out.println(c.get(Calendar.DAY_OF_WEEK));
}
}
四、数字类
常用数字类:
java.text.DecimalFormat
java.math.BigDecimal
import java.text.DecimalFormat;
public class DecimalTest01 {
public static void main(String[] args) throws Exception{
//加入千分位,保留两位小数
DecimalFormat df = new DecimalFormat("###,###.##");
System.out.println(df.format(1234.23452));
//加入千分位保留 4 位小数,不够补零
System.out.println(new DecimalFormat("###,###.0000").format(12345.12));
}
}
import java.math.BigDecimal;
public class BigDecimalTest01 {
public static void main(String[] args) throws Exception{
BigDecimal v1 = new BigDecimal(10);
BigDecimal v2 = new BigDecimal(20);
//相加运算
BigDecimal v3 = v1.add(v2);
System.out.println(v3);
}
}
五、Random
java.util.Random 可以产生随机数
生成五个0~100的随机数
import java.util.Random;
public class RandomTest01 {
public static void main(String[] args) throws Exception{
Random r = new Random();
for (int i=0; i<5; i++) {
System.out.println(r.nextInt(100));
}
}
}
六、Enum 枚举类
常用方法:
static Enum valueOf(Class enumClass,String name)
返回指定名字、给定类的枚举常量
String toString()
返回枚举常量名
int ordinal()
返回枚举常量在Enum声明中的位置,位置从0开始计数
int compareTo(E other)
如果枚举常量出现在other之前,返回一个负值;如果this==other,则返回0;否则,返回正值。枚举常量的出现次序在Enum声明中给出
public class EnumTest01 {
public static void main(String[] args) throws Exception{
Result r = method1(10, 2);
if (r == Result.SUCCESS) {
System.out.println("成功!");
}
if (r == Result.FAILURE) {
System.out.println("失败!");
}
}
//正确返回 SUCCESS,失败返回:FAILURE
private static Result method1(int value1, int value2) {
try {
int v = value1/value2;
return Result.SUCCESS;
}catch(Exception e) {
return Result.FAILURE;
}
}
}
enum Result {
SUCCESS,FAILURE
}
写在最后:新手上路,如有问题,欢迎大家指出,给意见。如果这篇文章对你有帮助,麻烦帮忙点一下赞,你们小小的举动能给我无限大的动力。拒绝白嫖,从我做起,从现在做起。Thank you for watching!