1.String类型
1.1 String类型的特点
- 字符串不可改变,他的值在创建之后就不能被更改
- 虽然String的值是不可变的,但是他们是可以被共享的
- 字符串效果上相当于字符数组(char[]),但底层原理却是字节数组
1.2 String类的构造方法
- String()创建一个空字符序列
- String(char[] value) 通过字符数组创建字符串
- String(byte[ ] bytes) 通过字节数组创建字符串
- String s = “abc” 直接赋值的方式创建字符串abc
public static void main(String[] args) {
String s1 = "aaaa";//直接赋值
String s2 = new String();//创建一个空字符串
char[] c = {'a','b','c'};
String s3 = new String(c);//字符数组
byte[] b = {97,98,99};
String s4 = new String(b);//字节数组
System.out.println("s1=" + s1);
System.out.println("s2=" + s2);
System.out.println("s3=" + s3);
System.out.println("s4=" + s4);
}
1.3 创建字符串的两种方式及对应的内存位置
- 使用new创建字符串对象,每一次new都会申请一个内存空间,虽然内容相同,但引用所指向的内存地址是不同的
char[] c = {'a','b','c'};
String s3 = new String(c);//字符数组
String ss3 = new String(c);
- 使用直接赋值的方式创建字符串,只要字符序列相同,不论代码出现了几次,jvm都只会创建一个String对象,并把它放在 字符串常量池中维护。所有以这种方式创建的字符串的引用必定都指向这个String对象,地址都是相同的
- 字符串常量存储在字符串常量池中,并且是共享,字符串非常量存储在堆中
1.3 两种字符串的比较方式
- 使用==比较字符串的地址
- 使用equals比较字符串的内容
public static void main(String[] args) {
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2);//true
// 使用字符数组构造一个字符串
char[] c = {'a','b','c'};
String s3 = new String(c);
String s4 = new String(c);
System.out.println(s3 == s4);//false
String s5 = new String("abc");
String s6 = new String ("abc");
System.out.println(s5==s6);// false
System.out.println(s1 == s3);//false
System.out.println(s4 == s5);//false
System.out.println(s1.equals(s3));//true
System.out.println(s4.equals(s6));//true
}
- 常量和常量的拼接,结果在常量池中且常量池中不会存在相同内容的常量
- 只要其中有一个是变量,结果就在堆中
- intern()会在常量池中寻找和实例字面量相同的常量字符串,并返回地址;若找不到,则会在常量池中记录首次出现实例引用。
public static void main(String[] args) {
String str1 = new String("str") + new String("01");
str1.intern();
String str2 = "str01";
System.out.println(str1 == str2);//true
}
public static void main(String[] args) {
String s1 = new String("he") +new String("llo");
String s2 = new String("h") +new String("ello");
String s3 = s1.intern();
String s4 = s2.intern();
System.out.println(s1==s3);//true
System.out.println(s2 == s4);//false
System.out.println(s3 == s4);//true
}
1.4 疑问
public static void main(String[] args) {
String str1 = new StringBuilder("计算机").append("软件开发").toString();
System.out.println(str1.intern()== str1);//true
String str2 = new StringBuilder("ja").append("va").toString();//
System.out.println(str2.intern()==str2);//false
}
1.为什么相同的程序,结果却不一样?字符串常量池中有默认字符串吗?
答:jvm从启动到执行main里的第一条代码,要经历很多指令,会经常用到"java"这个字符串,所以java是之前有程序创建了这个字符串常量,放进了常量池中
2.既然存在字符串常量池,为什么有的方法还会在堆中重复创建对象而不直接引用常量池
答:如果每创建一个对象都需要到常量池中查找一下,这样会有时间和性能的开销,虽然节省了内存,需要保持开销间的平衡
1.5 String类常用方法
charAt(int index)` //返回 `char`指定索引处的值。
concat(String str)` //拼接字符串
endsWith(String suffix)` //测试此字符串是否以指定的后缀结尾。
startsWith(String prefix)` //测试此字符串是否以指定的前缀开头。
equals(Object anObject)` //字符串比较
equalsIgnoreCase(String anotherString) //字符串比较,忽略大小写
indexOf(...) //返回指定字符/子串 第一次出现在主串的位置
lastIndexOf(...)//返回指定字符/子串 最后一次出现在主串的位置
intern()` //返回字面量相同且位于字符串常量池中字符串的地址
length()` //返回此字符串的长度。
isEmpty() //判空
getByte() //获得该字符串的字节序列
toLowerCase() toUpperCase() //改变字符串大小写
substring(int beginIndex, int endIndex) //返回子串
valueof() //静态方法,将其他基本类型转换成字符串
replace(char oldChar, char newChar) //替换字符
split(正则表达式)//按照指定的正则表达式,分割为字符串数组
2.StringBuilder类型
2.1 介绍
- 是一个可变的字符序列,但不保证同步,线程不安全,多线程环境下建议使用StringBuffer
- 主要是为了解决String类型字符串动态拼接所造成的大量内存损耗问题
2.2 构造方法
- StringBuilder(int capacity) //capticty指定初始容量,默认为16个字符
- StringBuilder(String str) //将字符串转换成StringBuilder类型
2.3 常用方法
append(...); //拼接各种类型数据为字符序列
insert(int offset, String str) //在指定位置插入字符串
length();//返回长度
reverse();//翻转字符串
toString();//StringBuilder型转换成字符串类型
indexOF(); lastIndexOf();//返回第一次和最后一次出现子串位置的索引
subString(int start,int end);//返回一个子串,类型String
注意:采用toString()方法返回的字符串不位于字符串常量池中,且每次调用都会在内存中创建一个该字符串对象
3.Arrays类型
2.1 介绍
Arrays类提供了大量的公共静态方法,用于数组操作,不用创建对象就能使用这些函数。
2.2 注意
Arrays没有对从Object继承下来的equals(object b)进行重写,该方法仍然是比较地址,而是创建了一个新的方法equals(a,b)用于字符串内容的比较。
int e[] = {1,2,3};
int f[] = {1,2,3};
System.out.println(e.equals(f)); //false
System.out.println(Arrays.equals(e,f)); //true
2.3 常用方法
fill();//填充数组
sort();//排序(升序)
equals(a,b);//比较数组内容
binarysearch();//二分查找,被查找数组必须有序
toString();//转换成字符串
4.Math类型
4.1 介绍
math中包含了对基本数字进行运算的方法,均为静态方法,可以不用创建对象直接使用。
4.2 两个常用常量
static double E
static double PI
4.3 常用方法
abs(...) //返回绝对值
random() //返回0.0到1.0(不包括1.0)间的随机数
max();
min();
5.Random类型
5.1 常用方法
Random()//构造方法
/*生成随机数*/
nextBoolean() // true or false
nextDouble() //0.0 -1.0
nextfloat()// 0.0 -1.0
nextInt()// Int所能存储的范围
nextInt(int bound)// 0 - bound
nextLong()// long所能存储的范围
6.System类型
6.1 常用方法
//static类型
currentTimeMillis();//返回当前时间,常用于测试代码运行时间
exit();//终止当前虚拟机
arraycopy(Object src,int srcPos,Object dest,int desPos,int length)//拷贝字符串
7.时间日期类
7.1 Date
Date();//初始化为系统时间
Date(long date);//初始化为从基准时间经过指定毫秒数的时间
getTime();//返回自1970年1月1日以来,由date对象记录的所经过时间
toString();//以某种格式返回但钱时间 ,如Sat Jul 10 0:0:0 CST 2021
7.2 SimpleDateFormat
作用:格式化日期文本,本质是将一个Date类型的日期按照一定的格式转换为了String类型
日期的解析,将一个字符串表示的日期,解析为Date类型
format(Date) //将所给的Date按给定的格式转换成字符串
parse(String) //将所给的字符串按给定的格式转换成date格式
SimpleDateFormat("yyyy-MM-dd hh:mm:ss");//传入格式的构造函数
注意:当传入的格式与parse所给的字符串格式不同时,会发生ParseException异常
7.3 Calendar
getInstance();//获取一个Calendar对象
get(int field);//返回给定日历字段的值
//字段有 YEAR MONTH DAY_OF_MONTH HOUR_OF_DAY MINUTE SECOND 注意month取值为0-11
set(...)//设置Calender的时间
8.BigDecimal
8.1 作用
BigDecimal用来对超过16位有效位的数进行精确地运算。float和double类型不能精确地表示一个浮点数,所以它们只能用来做科学计算或者是工程计算,在商业计算中,一定要使用BigDecimal
8.2 构造方法
//三种构造方法
BigDecimal(int val);
BigDecimal(String val);
BigDecimal(double val);//不建议使用,因为double本身的精度不能准确表示一个小数
public static void main(String[] args) {
BigDecimal bd1 = new BigDecimal(0.1);
System.out.println(bd1);//0.1000000000000000055511151231257827021181583404541015625
BigDecimal bd2= new BigDecimal("0.1");//推荐使用字符串来创建浮点数的Bigdecimal对象
System.out.println(bd2);
}
8.3 常用方法
add(BigDecimal augend) // 加
subtract(BigDecimal subtrahend) // 减
multiply(BigDecimal multiplicand) // 乘
divide(BigDecimal divisor, int scale, int roundingMode) // 除
示例:
public static void main(String[] args) {
BigDecimal bd1 = new BigDecimal(0.1);
System.out.println(bd1);//0.1000000000000000055511151231257827021181583404541015625
BigDecimal bd2= new BigDecimal("0.1");//推荐使用字符串来创建浮点数的Bigdecimal对象
System.out.println(bd2);
BigDecimal bd3 = new BigDecimal(17);
BigDecimal bd4 = new BigDecimal(4);
BigDecimal add = bd3.add(bd4);
BigDecimal sub = bd3.subtract(bd4);
BigDecimal mul = bd3.multiply(bd4);
BigDecimal div = bd3.divide(bd4,1, RoundingMode.HALF_EVEN );
System.out.println(add);
System.out.println(sub);
System.out.println(mul);
System.out.println(div);
}
9.包装类型
9.1 介绍
为了弥补java设计中的8基本类型不满足面向对象思想缺陷,同时便于在开发中对基本数据类型的数据进行相关的操作,因此引入了八种基本类型所对应的类。这个类就称为基本类型的包装类。
八种基本类型对应的包装类
基本类型 | byte | short | int | long | float | double | char | boolean |
---|---|---|---|---|---|---|---|---|
包装类 | Byte | Short | Integer | Long | Float | Double | Character | Boolean |
Byte Short Integer Long Float double 他们都是Number的子类 都是数字型
在Number类中 提供了可以将包装类转换为基本类型的方法。intValue();longValue() ;floatValue()
9.2 以Integer为例
9.2.1 推荐的创建对象的方法
Integer integer1 = 100;
Integer integer2 = Integer.parseInt("100");
Integer integer3 = Integer.valueOf(100);
Integer integer4 = Integer.valueOf("100");
9.2.2 常用方法
intValue();//把Integer转换成int类型
toString();//把Integer转换成String
//static类型
parseInt(String s);//字符串转换成int类型
toString(int i);//int类型转换成String类型
valueOf(int i);//int类型转换成Integer
valueOf(String s);//String类型转换成Integer
max(int a,int b);//返回两个int的较大值
min(int a, int b);//返回两个int的较小值
int 转换成 String
static String valueOf()
String s = i1 +""; //直接在数字后边加上一个空字符串
String 转换成 int
static Integer valueOf(String s)
static int parseInt(String s)
9.3 自动装箱和自动拆箱
自动装箱: 可以将基本类型直接赋值给对应的包装类 jvm会自动将基本类型的数据转换为对应的包装类的对象 ,而且这种转换是自动完成的,所以称为自动装箱
自动拆箱:就是和自动装箱相反的过程
Integer i1 = 100;//自动装箱
int ii1 = i1;//自动拆箱
9.3 包装类的缓存机制
9.3.1 缓存机制是什么
- 当通过自动装箱机制创建包装类对象时,首先会判断数值是否在-128~127的范围内,如果满足条件,则会从缓存(常量池)中寻找指定数值,若找到缓存,则不会新建对象,而是指向该常量池中的包装类对象。
- 当包装类加载时,该包装类中的内部类xxCache会初始化一个包装类类型数组,最小值(固定值)为-128,而最大值(默认值)为127【可修改】,这个长度的缓存值放在方法区的常量池中,是所有线程共享的
public static void main(String[] args) {
Integer i1 = 100;//自动装箱
Integer i2 = 100;
System.out.println(i1 == i2);//true
Integer i3 = 128;
Integer i4 = 128;
System.out.println(i3 == i4);//false
}
Integer 、Byte 、Short 、Long 、Character 五大包装类都有缓冲机制,且缓冲的默认值范围都是-128~127,而Float,Double,Boolean 三大包装类并没有缓冲机制。