实用类
1.包装类
1.1 定义
- 包装类是把基本类型转换为对象,是引用类型
1.2作用
- 包装类可以有很多操作的方法
- 之前我们学习的集合比如add(1)在底层中会转换成包装类型integer类型插入到集合容器中,集合里面插入的都是引用类型。
1.3 包装类型继承关系图
1.4 构造方法创建包装类型
-
在构造方法中可以将与之对应的基本数据类型作为构造方法参数,来创建包装类的对象
-
charcater除外,在构造方法中可将对应的基本类型以字符串类型作为构造方法参数,来创建包装类的对象
/** * 以构造方法创建包装类型对象 * @author Administrator * */ public class Test { public static void main(String[] args) { Integer i = new Integer(1000); System.out.println(i.MIN_VALUE); System.out.println(i.MAX_VALUE); Integer i2 = new Integer("2000"); System.out.println(i2); //方式1:以基本类型为构造方法的参数创建包装类型对象 Double d = new Double(98.7); Boolean b = new Boolean(true); Float f = new Float(87.4); Character c = new Character('男'); //方式2:以字符串形式创建包装类型对象 Double d2 = new Double("98.7"); Boolean b2 = new Boolean("true"); Float f2 = new Float("87.4"); // Character c2 = new Character("男");//character只能是字符类型 //方式3:自动装箱 可以把基本类型直接赋给包装类型对象,底层自动实现 int a = 3; Integer a2 = a; Integer a3 = 100; System.out.println(a2+" " +a3); } }/** * 以构造方法创建包装类型对象 * @author Administrator * */ public class Test { public static void main(String[] args) { Integer i = new Integer(1000); System.out.println(i.MIN_VALUE); System.out.println(i.MAX_VALUE); Integer i2 = new Integer("2000"); System.out.println(i2); //方式1:以基本类型为构造方法的参数创建包装类型对象 Double d = new Double(98.7); Boolean b = new Boolean(true); Float f = new Float(87.4); Character c = new Character('男'); //方式2:以字符串形式创建包装类型对象 Double d2 = new Double("98.7"); Boolean b2 = new Boolean("true"); Float f2 = new Float("87.4"); // Character c2 = new Character("男");//character只能是字符类型 //方式3:自动装箱 可以把基本类型直接赋给包装类型对象,底层自动实现 int a = 3; Integer a2 = a; Integer a3 = 100; System.out.println(a2+" " +a3); } }
1.5 valueof()方法创建包装类型
/**
* 通过valueof()方法创建包装类型对象
* @author Administrator
*
*/
public class Test2 {
public static void main(String[] args) {
Integer invalue = Integer.valueOf(21);
Integer invalue2 = Integer.valueOf("21");
System.out.println(invalue);
System.out.println(invalue2);
//方式1:以基本类型为参数类型创建包装类型对象
Double d1 = Double.valueOf(98.7);
Boolean b1 = Boolean.valueOf(true);
Float f1 = Float.valueOf(77.8f);
//方式2:以字符串为参数类型创建包装类型对象
Double d2 = Double.valueOf("98.7");
Boolean b2 = Boolean.valueOf("true");
Float f2 = Float.valueOf("77.8");
Character c2 = Character.valueOf('男');
}
}
1.6 xxxValue()方法将包装类型转换成基本类型
public class Test3 {
public static void main(String[] args) {
Integer i = new Integer(1000);
int intValue = i.intValue();
System.out.println(intValue);
Double d = new Double(99.9);
double doublevalue = d.doubleValue();
Integer i1 = 2000;
int i2 = i1;//拆箱:把包装类型自动转换成了基本类型
}
}
1.7 拆箱和装箱
-
装箱:把基本类型转换成包装类型
Integer i1 = 2000;
-
拆箱:把包装类型转换成基本类型
Integer i1 = new Integer(1100); int i2 = i1;//拆箱:把包装类型自动转换成了基本类型
1.8 总结包装类的特点
- 所有的包装类型都是final类型,不能被继承
- java5之后,允许基本类型和包装类型进行混合运算
- 包装类是引用类型存储在堆内存里面,基本类型是存储在栈内存里面,由于存储简单的值存储在栈内存效率更快,但是在基本类型需要用到对象的时候或者调用方法的时候需要使用到包装类
2.String类详解
2.1 内容一:
-
注意:String不是一个基本数据类型
-
String是一个特殊的包装类型,之前我们其他的包装类都是需要Integer i= new Integer()来创建,是保存在堆内存里面的。
可以String str = new string();来创建 也可以string str2 = "abc";来创建
-
关于==String str2 = “abc”;==java内部将此语句转换分为几个步骤:
- 先定义一个名为str2的对string类的对象的引用变量存入栈中
- 在常量池中查找是否存在内容为"abc"的字符串对象
- 如果不存在则在常量池中创建"abc",并让str2引用对象
- 如果存在则直接让str2引用该对象
-
代码验证
public class Test { public static void main(String[] args) { String str1 = "abc"; String str2 = "abc"; //==用于比较两个字符串的地址,equals是判断两个字符串的值是否相等 System.out.println(str1==str2);//true } }
2.2 内容二:
-
常量池
-
常量池用于存放字符串常量和基本类型常量
-
常量池的好处是为了避免频繁的创建和销毁对象而影响性能,其实现类对象的共享。
-
比如字符串常量池,在编译阶段就把使用的字符串文字放到一个常量池中,
-
优势:1.节约内存空间
如:
String str1 = "abcd"; String Str2 = "ab" +"cd"; //str2是在编译阶段优势为"abcd",在去判断常量池是否"abcd",有就把常量池地址也指引给str2,所以str1和str2共享地址,节约资源 System.out.println(str1==str2);//true
-
2.节省运行时间,字符串比较有两种方式:
-
== 比较是两个字符串的地址,用于判断引用是否是同一个地址,如果是同一个地址那么值肯定相等
-
equals()方法比较,如果不是同一个地址那么就去比较字符串之间的值
public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }
-
-
2.3 面试题1:
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2);//true
- 第一次创建String str1=“abc”;的时候,先在常量池判断有没有“abc”,如果没有就在常量池中创建"abc"然后将常量池的引用地址赋给在栈内存开辟的str1(str1是在常量池中“abc“的引用)
- 第二次创建String str2=“abc”;的时候也先判断常量池有没有“abc”,如果有就不需要在常量池再次创建“abc”,可以将已经创建好了的"abc"指引赋给str2;
- 因此str1==str2去比较两个指引的地址的时候,是指向了同一个地址,所以返回true
2.4 面试题2
String str1 = "abc";
String str2 = "abc";
str = "bcd";
System.out.println(str1+" "+str2);//bcd abc
System.out.println(str1==str2);//false
2.5 面试题3
String str1 = "abc";
String str2 = "abc";
str1 = "bcd";
String str3 = str1;
String str4 = "bcd";
System.out.println(str1==str4);//true
System.out.println(str1==str3);//true
2.6 面试题4
-
然后我们在来看看String str = new String(“abc”);创建的过程
- 先定义一个名为str的对String类的对象引用变量放入栈中
- 然后在堆中(不是常量池)创建一个指定的对象,并让str引用指向该堆内存中存储的对象
- 在常量池中查找是否存在内容是"abc"的字符串对象
- 如果不存在,则在常量池中创建内容为"abc"的字符串对象,并将堆中的对象与之关联起来
- 如果存在,则将堆内存中new出来的字符串对象与常量池中的对象关联起来
-
代码示例
String str1 = new String("abc"); String str2 = new String("abc"); String str3 = "abc"; System.out.println(str1==str2);//false //在堆内存创建了两个地址,返回false System.out.println(str1==str3);//false //创建了两个引用,两个引用分别指向堆内存的地址和常量池中的地址,地址不同返回false
-
如图
2.7 面试题5
public class Test4 {
public static void main(String[] args) {
String str1 = "abc";
String str2 = new String("abc");
String str3 = str2.intern();//intern方法用于获取堆内存中指引到常量池中的"abc"
System.out.println(str1==str2);//false
System.out.println(str1==str3);//true
}
}
2.8 总结
- 对于字符串,其对象的引用都是存储在栈内存中的
- 如果是编译期间已经创建好的(直接用""定义的String str2 = “abc”;)就存储在常量池中
- 如果是运行期(new String(“abc”);)才能确定到存储在堆中
- 在常量池中数据会共享,常量池只有一份;在堆中有多份,数据不共享
最常见的面试题
问题:String s = new String(“abc”);产生了几个对象?
答:一个或者两个,如果常量池有"abc"就是创建一个,常量池没有"abc"就需要创建两个。
注意:
- 基本数据况的包装类都是final修饰的,值都不可以被改变,不仅仅是String类的值不可修改,所有的基本类型的包装类都不能更改其内部的值。
3.String 常用的方法
-
得到字符串长度
str.length();
-
查找字符的位置
str.indexOf("语")
-
字符串截取
System.out.println(str.substring(16, 21));//第一个参数包含,第二个参数不包含
-
字符串替换
String str = "我是一个技术很好的程序员"; System.out.println(str.replace('员', '师'));//我是一个技术很好的程序师
-
字符串变大写,变小写,忽略大小写
// String str3 = "aBCd".toLowerCase();//变小写 // System.out.println(str3); // System.out.println("abcd".toUpperCase());//变大写 // System.out.println("abCD".equalsIgnoreCase("ABcd"));//忽略大小写
-
字符串分割
// String str = "我 是 最 帅 的 程 序 员"; // String words[] = str.split(" ");
-
字符串拼接
String names[] = {"20","09","15"}; //将数组的值以"-"字符拼接 String str1 = String.join("-", names); System.out.println(str1);//20-09-15
-
字符串转换成字节数组
String str3 = "我们是社会主义接班人"; byte[] words = str3.getBytes();
-
字符串转换成字符数组
//将字符串转换成字符类型数组 char words2[] = str3.toCharArray(); System.out.println(words2[0]);
-
返回字符串索引的字符
char v1 = "最好的".charAt(2);
public class Test {
public static void main(String[] args) {
String str = "java是最好的编程语言,能找到最好的工作!";
//按照执行的下标位置获取该字符
char v1 = "最好的".charAt(2);
System.out.println(v1);//的
System.out.println(str.indexOf("语"));//10
System.out.println(str.indexOf("最好"));//5
System.out.println(str.indexOf("员"));//-1
System.out.println(str.indexOf("最", 10));//16
System.out.println(str.indexOf("最"));//5
System.out.println(str.lastIndexOf("最"));//16
//最好的工作
System.out.println(str.substring(16, 21));//第一个参数包含,第二个参数不包含
System.out.println(str.substring(16,str.indexOf("!")));
// String str3 = "aBCd".toLowerCase();//变小写
// System.out.println(str3);
// System.out.println("abcd".toUpperCase());//变大写
// System.out.println("abCD".equalsIgnoreCase("ABcd"));//忽略大小写
// System.out.println("字符串长度:" + str.length());
// String str4 = " ab cd ".trim();//去掉两边空格
// System.out.println(str4);//ab cd
//控制台输入用户密码,判断密码长度必须是6位长度,忽略大小写登录验证
Scanner input = new Scanner(System.in);
System.out.println("请输入密码:");
String pwd = input.next();
if(pwd.length()!=6) {
System.out.println("密码必须是6位");
}else if("WuMing".equalsIgnoreCase(pwd)) {
System.out.println("登录成功");
}
// System.out.println("========================");
// String str = "我 是 最 帅 的 程 序 员";
// String words[] = str.split(" ");
// String str2 = "我是技术最好的程序员";
// String words2[] = str2.split("");
//输入zhang san,输出ZhangSan
System.out.println("请输入姓名");
String name = input.nextLine();
String names[] = name .split(" ");
String newnames="";
for (int i = 0; i < names.length; i++) {
names[i] = names[i].substring(0,1).toUpperCase()+names[i].substring(1).toLowerCase();
newnames +=names[i];
}
System.out.println("姓名是:"+newnames);
String str = "我是一个技术很好的程序员";
System.out.println(str.replace('员', '师'));//我是一个技术很好的程序师
System.out.println(str.replace("程序员", "工程师"));//我是一个技术很好的工程师
System.out.println(str.replaceAll("程序员", "工程师"));//我是一个技术很好的工程师
String names[] = {"20","09","15"};
//将数组的值以"-"字符拼接
String str1 = String.join("-", names);
System.out.println(str1);//20-09-15
String str3 = "我们是社会主义接班人";
byte[] words = str3.getBytes();
//将字符串转换成字符类型数组
char words2[] = str3.toCharArray();
System.out.println(words2[0]);
}
}
4.StringBuffer和StringBuilder
-
由于String是一个常量,每次字符串拼接都会在常量池中创建新的值的存储,所以字符串拼接需要开辟新的内存空间,消耗内存,所以就提出了Stringbuffer和Stringbuilder,Stringbuffer和Stringbuilder都是用于可变长度的字符串,不需要开辟新的空间。
public class Test { public static void main(String[] args) { //定义一个可变长度的字符串对象StringBuffer //用于字符串经常拼接或者改变值的时候用StringBuffer效率高 StringBuffer sb = new StringBuffer(); sb.append("张三"); sb.append("是程序员,"); sb.append("喜欢编程!"); System.out.println(sb); String str = sb.toString();//把StringBuffer对象转换成String StringBuffer sb1 = new StringBuffer("hello!"); sb1.append("我是张三!"); System.out.println(sb1); //StringBuffer和StringBuilder作用一样,StringBuffer线程安全,StringBuilder非线程安全,效率高 StringBuilder sb2 = new StringBuilder(); sb2.append("张三"); sb2.append("是程序员,"); sb2.append("喜欢编程!"); System.out.println(sb2); } }
[面试题]
Stringbuffer和Stringbuilder的区别?
- StringBuffer和StringBuilder作用一样,StringBuffer线程安全,StringBuilder非线程安全,效率高
5.数学操作
5.1 math类
public static void main(String[] args) {
double v1 = Math.floor(99.2);//向下取整
double v2 = Math.ceil(99.8);//向上取整
double v3 = Math.round(99.8);//四舍五入
double v4 = Math.random();//取0.0到1.0之间的随机数
}
5.2 Random类
注意:生成的是一个伪随机数
import java.util.Random;
public class Test2 {
public static void main(String[] args) {
Random rand1 = new Random(1000);
Random rand2 = new Random(1000);
//根据种子通过算法算出来的随机数,因此两个实例的种子一样,生成的随机数一样
System.out.println(rand1.nextInt());
System.out.println(rand2.nextInt());
Random ran = new Random();
//0-10但是不包含10的整数
int num = ran.nextInt(10);
System.out.println(num);
}
}
6. 日期操作
6.1 Date类
public class Test {
public static void main(String[] args) {
Date date = new Date();
System.out.println(date);
System.out.println(date.getYear()+1900);
System.out.println(date.getMonth()+1);
System.out.println(date.getDate());
System.out.println(date.getDay());
}
}
Tue Sep 15 15:35:50 CST 2020
2020
9
15
2
6.2 SimpleDateFormat类
public class Test2 {
public static void main(String[] args) {
Date date = new Date();
//SimpleDateFormat用于设置日期的格式
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//将date日期转换成自定义时间格式
String now = format.format(date);
System.out.println(now);
}
}
2020-09-15 15:44:18
6.3 Calendar类
import java.util.Calendar;
public class Test3 {
public static void main(String[] args) {
Calendar time = Calendar.getInstance();
System.out.println("今天是"+time.get(Calendar.YEAR)+"年"
+(time.get(Calendar.MONTH)+1)+"月"+time.get(Calendar.DAY_OF_MONTH)+"日");
//Calendar.DAY_OF_WEEK中的Sunday是1
System.out.println("今天是星期"+(time.get(Calendar.DAY_OF_WEEK)-1));
}
}
今天是2020年9月15日
今天是星期2
用于设置日期的格式
SimpleDateFormat format = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
//将date日期转换成自定义时间格式
String now = format.format(date);
System.out.println(now);
}
}
```java
2020-09-15 15:44:18
6.3 Calendar类
import java.util.Calendar;
public class Test3 {
public static void main(String[] args) {
Calendar time = Calendar.getInstance();
System.out.println("今天是"+time.get(Calendar.YEAR)+"年"
+(time.get(Calendar.MONTH)+1)+"月"+time.get(Calendar.DAY_OF_MONTH)+"日");
//Calendar.DAY_OF_WEEK中的Sunday是1
System.out.println("今天是星期"+(time.get(Calendar.DAY_OF_WEEK)-1));
}
}
今天是2020年9月15日
今天是星期2