一、工具类
1.1、工具类的设计
把很多完成通用功能的方法抽取分类存放到类中,这些类就叫工具类
工具类如何设计(分两种)
- 工具方法全部使用public static修饰**(常用)**
此时只需要使用工具类类名调用工具方法,且须把工具类的构造器私有化,防止创建工具类的对象来调用静态方法
- 如果工具方法没有使用static修饰
此时必须使用工具类的对象去调用工具类的方法,且必须把工具类设计成单例模式
1.1.1、公共静态方法
需求一:使用公共静态方法的方式,设计一个数组的工具类
ArraysUtils类
public void ArraysUtils{ //1. 先私有化构造器,防止被实例化对象 private ArraysUtils(){ } //2.写工具方法 public static void sort(){ System.out.println("我是排序方法") } public static void print(){ System.out.println("我是打印方法方法") } } 复制代码
TsstDemo类
public class TsstDemo{ public static void main(String[] args){ ArraysUtils.sort() } } 复制代码
调用者必须通过工具类名.工具方法名称完成调用
1.2、单例模式
设计模式(Design pattern)
是一套被反复使用的代码设计经验总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性,Java常用的设计模式有23种
单例设计模式(singleton)
最常用、最简单的设计模式,单例模式分为两种:懒汉式和饿汉式
目的
保证在整个应用中某一个类有且只有一个实例
步骤(以饿汉式为例)
- 私有化自身构造器,防止外界通过构造器实例化出对象
- 在该类中,自己先创建出一个对象
- 向外暴露一个公共的静态方法用于返回自身的对象
public class SingletonUtil{ // 1. 先私有化构造器,防止被实例化对象 private SingletonUtil(){ } //2. 自己创建出一个对象 private static SingletonUtil instance = new SingletonUtil(); //3. 暴露给外界调用方法,返回创建好的对象 public static SingletonUtil getInstance(){ return instance; } public void sort() { System.out.println("排序操作"); } public void binarySearch() { System.out.println("二分查找操作"); } } 复制代码
调用方法:
SingletonUtil.getInstance().sort(); 复制代码
二、包装类
Java中的基本数据类型没有方法和属性,而包装类就是为了让这些拥有方法和属性,实现对象化交互,数值型包装类都继承至Number,而字符型和布尔型继承至Object
2.1、基本类型的包装类
基本数据类型和包装类对应关系:
基本类型 | 对于包装类 |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
2.1.1、Integer
Integer内部封装了int类型的基本数据类型value,并提供了方法对int值进行操作和String之间进行互换(开发中常用)
2.1.1.1、Integer >> int
Integer i = new Integer(); int intValue = i.intValue(); 复制代码
2.1.1.2、int >> Integer
int i = 20; Integer integer = Integer.valueOf(i); 复制代码
2.1.1.3、Integer >>String
int i = 30; Stirng value = Integer.valueOf(i); 复制代码
2.1.1.4、String >> Integer
Integer i = Integer.valueOf("3"); 复制代码
2.1.1.5、String >> int
int i = Integer.parseInt("134"); 复制代码
2.1.1.6、int >> String
String str = Integer.toString(134); 复制代码
2.2、拆箱和装箱
2.2.1、装箱
把基本数据类型转为对于的包装类对象
Integer num2 = Integer.valueOf(17); 复制代码
2.2.2、拆箱
把包装类对象转化为对应的基本数据类型
int val = num3.intValue(); 复制代码
2.2.3、自动拆箱和装箱
从JDK5之后提供了自动装箱和自动拆箱,我们再也不用频繁的去手动拆箱和装箱了
Integer num4 = 17; //装箱操作 int val2 = num4; //拆箱操作 复制代码
2.3、缓存设计
从性能上考虑,把常用数据存储到缓存区域,使用时不需要每次都创建新的对象,可以提高性能
常用包装类型的缓存范围
- Byte、Short、Integer、Long:缓存范围[-128,127]
- Character:缓存范围[0,127]
//第一种 Integer i1 = new Integer(123); Integer i2 = new Integer(123); System.out.println(i1 == i2);// false,因为都在堆中new了一个新的对象 //第二种 Integer i3 = Integer.valueOf(123); Integer i4 = Integer.valueOf(123); System.out.println(i3 == i4);// true,由于在[-128,127]之间,所以直接在缓存中取,都是同一个对象 //第三种 Integer i5 = 123; // 底层等价于第二种 Integer i6 = 123; System.out.println(i5 == i6);// true 复制代码
注意
- 如果数字都不在缓存范围内,那么返回的结果都是false
- 如果要比较两个对象的数据是否相等,必须使用equals方法来判断,
==比较的是两个数据的内存空间是否是同一块,equals比较的是存储数据是否相等
- int类型的默认值为0,Integer的默认值为null,在开发中建议使用Integer,因为Integer既可以表示0,也可以表示null
2.4、BigDecimal
float和double都不能表示精确的小数,使用BigDecimal类可以解决该问题,BigDecimal用于处理金钱或任意精度要求高的数据
2.4.1、基本运算
BigDecimal不能直接把赋值和运算操作,只能通过构造器传递数据,而且必须使用字符串类型的构造器
System.out.println(0.09 + 0.01); 复制代码
我们运行这段代码,结果是
他会生成一个无限接近0.1的值,说明这个并不适合我们运算
BigDecimal num1 = new BigDecimal(0.09); BigDecimal num2 = new BigDecimal(0.01); System.out.println(num1.add(num2)); 复制代码
如果我们不用字符串类型的构造器的话,BigDecimal无法开启高精度模式
BigDecimal num3 = new BigDecimal("0.09"); BigDecimal num4 = new BigDecimal("0.01"); System.out.println(num3.add(num4)); 复制代码
终于运行处了正确结果,需要注意一定要使用字符串的构造方法,才可以开启高精度计算模式
2.4.2、精度控制
我们在运算的时候需要进行精度控制操作
/* 1. 保留位数和精度控制 RoundingMode 舍入模式 RoundingMode.HALF_UP 四舍五入 */ BigDecimal num5 = new BigDecimal("0.987"); BigDecimal bigDecimal = num5.setScale(2, RoundingMode.HALF_UP); System.out.println(bigDecimal); 复制代码
2.4.3、无理数问题
/* java.lang.ArithmeticException Non-terminating decimal expansion; no exact representable decimal result. 报错原因:除不尽(3.333333333...333...) */ BigDecimal num1 = new BigDecimal("10.0"); BigDecimal num2 = new BigDecimal("3.0"); BigDecimal r2 = num1.divide(num2,3,RoundingMode.HALF_UP); System.out.println(r2);