1.工具类的设计
2.单例模式
3.包装类
4.BigDecimal类
5.String
6.StringBuilder和StringBuffer类
把很多的通用的方法集合在一起装到一个类中,这个类就叫做工具类
两种设计
使用类名调用工具方法
构造器需要私有化,静态方法,防止工具类创建对象来调用静态方法
使用工具类的对象来调用工具方法,把工具类设计为单例模式(后讲)
/**
* 这是一个数组的工具类,包含了打印数组,排序等方法
* e.g:
* int[] arr=...
* ArrayUtils.printArray(arr)
* @author kent
* @since 2021-01-22
* @see " "
* */
public class ArrayUtils {
private ArrayUtils(){
} //私有构造方法,这样就可以防止实例被创建
//定义static方法,用类名调用方法
public static void printArray(){
System.out.println("假装是数组的算法");
}
public static void sort(){
System.out.println("排序");
}
}
设计模式:一套可以被反复使用的代码设计经验总结
单例设计模式(singleton):最常用、最简单的设计模式,单例的编写有N种写法
单例模式保证整个应用中某一类有且只有一个实例(对象)
私有化构造方法,事先创建好类的(static)一个对象
提供一个公共静态方法(用于外界访问),在该方法中进行判断是否有对象,有返回预先创建好的对象,没有就new一个 ,
其他方法可以不用static修饰
调用
调用 类名.静态方法名(相当于一个对象)
调用方法 类名.静态方法名.方法
/*
*
* 懒汉模式 ( 存在线程安全 )
* */
public class AppSingleton {
//要求:保持该类在系统中只有一个实例
private static AppSingleton instance = null;
//1.私有化构造方法
private AppSingleton(){
}
//2.对外界提供统一的访问方式
public static AppSingleton getInstance(){
if (null == instance){
instance =new AppSingleton();
}
return instance;
}
//3.把工具方法附载到该单例上
public void printArray(){
System.out.println("数组");
}
}
/*
*
* 饿汉模式
* */
public class AppSingleton01 {
//要求:保持该类在系统中只有一个实例,提前创建(JVM加载AppSingleton01单例时已经被创建好了 )
private static AppSingleton01 instance = new AppSingleton01();
//1.私有化构造方法
private AppSingleton01(){
}
//2.对外界提供统一的访问方式
public static AppSingleton01 getInstance(){
return instance;
}
//3.把工具方法附载到该单例上
public void printArray(){
System.out.println("数组");
}
}
包装类就是把基本数据类型封装到一个类中,让开发者更方便的操作基本类型
byte | short | int | long | float | double | char | boolean |
---|---|---|---|---|---|---|---|
Byte | Short | Integer | Long | Float | Double | Character | Boolean |
常用转换方法
public class Test01 {
public static void main(String[] args) {
//常用方法
//Integer -> int
Integer i1 = new Integer("100");
int a = i1.intValue();
//int ->Integer
//这种通过静态方法返回一个本类的对象 =>工厂方法
//new Integer(int/String) =>valueOf(int /String)
Integer i2 = Integer.valueOf(100);
//Integer -> String
Integer i3 = Integer.valueOf(300);
System.out.println(i3.toString());
//String ->Integer
Integer i4 = Integer.valueOf("500");
//String -> int
int i = Integer.parseInt("100");
//int ---> String
String s = Integer.toString(200);
/*
*总结:
* int <->String
* Integer 桥梁 =>
* int <-> Integer <-> String
*
* */
}
}
//装箱 把基本数据类型 ->对应的包装类的过程
Integer i1 = Integer.valueOf(10);
Integer i2 = new Integer(10); //一般不用这个了,被淘汰
//拆箱 把包装类对象 ->对于基本数据类型
int t1 = i1.intValue();
int t2 = i2.intValue();
所谓自动就是jvm自动帮我们转换了,调用了装箱与拆箱的方法
1.自动装箱
Integer i1 = 13;
jvm实际调用 Integer i1 = Integer.valueOf(13)
2.自动拆箱
int i2 = i1; // jvm实际调用 i1.intValue()
思考?
Object obj =10;
/*
* Integer i1 =10; //自动装箱操作
* Object obj =i1; // 把子类对象赋值给父类变量 (父引子)
*/
从性能上考虑,把常用数据存储到缓存区域,使用时不需要每次都创建新的对象,可以提高性能。
cache原理
个人理解:
Integer 中的 cache缓存机制是将范围为(-128,127)的值,提前与加载缓存,
当我们去初始化这个范围的值时(不用new),其实就已经存在了
.当超出这个范围的值时,就是相当于真正开辟(new)了一块空间.
Integer i1 = new Integer(10);
Integer i2 = new Integer(10);
System.out.println(i1 == i2);// false new相当于new出了两块空间,肯定是不一样的
Integer i3 = Integer.valueOf(10);
Integer i4 = Integer.valueOf(10);
System.out.println(i3 == i4);// true
Integer i5 = 10; // 底层等价于
Integer i6 = 10;
System.out.println(i5 == i6);// true
float和double都不能表示精确的小数,使用BigDecimal类可以解决该问题
BigDecimal不能直接把赋值和运算操作,只能通过构造器传递数据,而且必须使用字符串类型的构造器
RoundingMode 舍入模式
RoundingMode.HALF_UP
四舍五入RoundingMode.HALF_Down
四舍六入例子:
import java.math.BigDecimal;
import java.math.RoundingMode;
public class Test01 {
public static void main(String[] args) {
System.out.println(0.01+0.09); //精度缺失
//一定要使用字符串的构建方式
BigDecimal b1 = new BigDecimal("0.01");
BigDecimal b2 = new BigDecimal("0.09");
//相加
BigDecimal add = b1.add(b2);
System.out.println(add);
//相减
BigDecimal b9 = new BigDecimal("0.01");
BigDecimal b10 = new BigDecimal("0.09");
BigDecimal subtract = b9.subtract(b10);
System.out.println(subtract);
//精度控制
BigDecimal b3 = new BigDecimal("3.1418");
BigDecimal b4 = new BigDecimal("2");
//6.2836
//multiply 乘法操作,保留两位小数(setScale 2),四舍五入(RoundingMode.HALF_UP)
b3.multiply(b4).setScale(2, RoundingMode.HALF_UP);
//除法
BigDecimal b5 = new BigDecimal("10");
BigDecimal b6 = new BigDecimal("3");
b5.divide(b6).setScale(2, RoundingMode.HALF_UP);//3.33
}
}
String类型表示字符串,在内存中是以字符数组的形式存在的
String是字符数组的包装类,并提供以只读的形式操作其包装的字符数组的方法。
String str = "ABCD"; 等价于 char[] cs = new char[]{
'A','B','C','D'};
String对象是不可变的,所以可以共享
1.通过字面量创建的字符串分配在常量池中 字面量字符串是常量,值在创建之后是不能更改的
通过new操作创建的字符串分配在堆中,当String对象创建完毕之后,该对象的内容是不能改变的,一旦内容改变就会变成了一个新的对象
1.直接赋予字面量
String str1 ="ABC"; //常量池
2.通过构造器创建
String str2 = new String("ABC"); //堆中
1.表示引用为空(null)
String str1 = null; //没有初始化,没有分配内存空间
2.内容为空字符串
String str2 = "" //已经初始化,分配内存空间,不过没有内容
== 与equals的区别
String str1 = "abc";
String str2 = "abc";
System.out.println(str1 ==str2); //true 同样放在常量池,表示唯一引用同一地址
String s1 = new String("abc");
String s2 = new String("abc");
System.out.println(s1.equals(s2)); // equals 重写后比较当前两个对象的内容是否相等
System.out.println(str1 ==s1); // str1在常量池中,new出来的s1在堆中
//面试题
String str3 = "" + "abc";
String str4 = str1 + "";
System.out.println(str1==str3); //true ,常量词中,允许字符串拼接,"+拼接了"abc" 还是等于"abc"
System.out.println(str1 ==str4);//false , str1 + ""表示已经在堆中,地址不同
public static boolean ifNull(String str){
return str !=null && !"".equals(str.trim());
}
public class Test04 {
public static void main(String[] args) {
String str = "小小罗nb";
String str1 = "小月";
String str2 = "小小罗NB";
//length():返回字符串的个数
System.out.println(str.length()); //4
//char(int index):返回指定索引字符
System.out.println(str.charAt(0)); //小
//int indexOf(String str) 返回指定子字符串在此字符串中第一次出现处的索引位置
System.out.println(str.indexOf("小")); //0
//boolean equals(Object anObject) 比较内容是否相同
System.out.println(str.equals(str1)); //false
//boolean equalsIgnoreCase(String anotherString) 忽略虑大小写,比较内容是否相同
System.out.println(str.equalsIgnoreCase(str2)); //true
//String toUpperCase() 把当前字符串转换为大写
System.out.println(str.toUpperCase()); //小小罗NB
//String toLowerCase() 把当前字符串转换为小写
System.out.println(str2.toLowerCase()); //小小罗nb
//String substring(int beginIndex):从指定位置开始截取字符串
System.out.println(str.substring(2)); //罗nb
//String substring(int beginIndex, int endIndex):截取指定区域的字符串
System.out.println(str.substring(0, 2)); //小小
}
}
StringBuffer和StringBuilder都表示可变的字符串,可以对字符串进行拼接
开发中建议使用StringBuilder(线程不安全,但是性能较高)
如果事先知道需要拼接多少个字符,可以在创建StringBuilder对象时指定字符数组容量
StringBuilder re = new StringBuilder(17);
使用append方法在原字符串后面进行拼接
re.append("小轩").append(520).append("小月");