包装类(String、Integer、BigInteger、BigDecimal)

包装类(将基本数据类型封装成对象,好处在于可以在对象中定义更多的功能方法操作该数据)

String

public String(char[] value,int index,int count):把字符数组的一部分转成字符串

  • String,StringBuffer和StringBuilder对比:包装类(String、Integer、BigInteger、BigDecimal)_第1张图片

  • String为什么要设计成final
    1、常量池中的数据可以被共享,导致可能很多地方都在操作这个对象,尤其在多线程中是很危险的。定义成final不可变可以保证线程安全
    2、字符串进入常量池后,数据共享,再次调用可节省资源,调高效率

  • String 中的 equals 方法是被重写过的,因为 object 的 equals 方法是比较的对象的内存地址,而 String 的 equals 方法比较的是对象的值。

下面这句话在内存中创建了几个对象?

String s1 = new String(“abc”); //创建两个对象,一个在常量池,一个在堆内存中

判断定义为String类型的s1和s2是否相等

String s1 = new String(“abc”); //在堆内存中的地址值
String s2 = “abc”; //在常量池中的地址值
System.out.println(s1 == s2); //false
System.out.println(s1.equals(s2)); //true

判断定义为String类型的s1和s2是否相等

String s1 = “a” + “b” + “c”;
String s2 = “abc”;
System.out.println(s1 == s2); //true,Java中有常量优化机制
System.out.println(s1.equals(s2)); //true

判断定义为String类型的s1和s2是否相等

String s1 = “ab”; //常量池中
String s2 = “abc”; //常量池中
String s3 = s1 + “c”; //在堆中,由toString方法化为字符串
System.out.println(s3 == s2); //false
System.out.println(s3.equals(s2)); //true

String中的特殊方法

boolean equalsIgnoreCase(String str):比较字符串的内容是否相同,忽略大小写
boolean contains(String str):判断大字符串中是否包含小字符串
boolean startsWith(String str):判断字符串是否以某个指定的字符串开头
boolean endsWith(String str):判断字符串是否以某个指定的字符串结尾
boolean isEmpty():判断字符串是否为空。
""表示字符串为空,而不是null
""和null的区别:
""是字符串常量,同时也是一个String类的对象,既然是对象当然可以调用String类中的方法
null是空常量,不能调用任何的方法,否则会出现空指针异常,null常量可以给任意的引用数据类型赋值
byte[] getBytes():把字符串转换为字节数组。
char[] toCharArray():把字符串转换为字符数组。

Java intern() 方法

  • 返回值
    一个字符串,内容与此字符串相同,但一定取自具有唯一字符串的常量池
    包装类(String、Integer、BigInteger、BigDecimal)_第2张图片
    b.intern() == a和b.intern() == c(比较的是地址值)可知,采用new 创建的字符串对象不进入字符串池,并且通过b.intern() == d和b.intern() == f可知,字符串相加的时候,都是静态字符串的结果会添加到字符串池,如果其中含有变量(如f中的e)则不会进入字符串池中。但是字符串一旦进入字符串池中,就会先查找池中有无此对象。如果有此对象,则让对象引用指向此对象。如果无此对象,则先创建此对象,再让对象引用指向此对象。

Integer

public static void main(String[] args) {
	System.out.println(Integer.toBinaryString(60));//111100,整数转成二进制字符串
	System.out.println(Integer.toOctalString(60));//74,整数转成八进制字符串
	System.out.println(Integer.toHexString(60));//3c,整数转成十六进制字符串
}

Integer.MAX_VALUE:2147483647整型的最大值(2*10^9)
Integer.MIN_VALUE:‐2147483648整型的最小值

int转化为String

  • 和""进行拼接

  • public static String valueOf(int i)
    String.valueOf(i);

  • int ‐‐ Integer ‐‐ String(Integer类的toString()方法)

    Integer i2 = new Integer(i);
    String s3 = i2.toString();
    
  • public static String toString(int i)(Integer类的静态方法)

    String s4 = Integer.toString(i);
    

String转化为int

  • String ‐‐ Integer ‐‐ int
    public static int parseInt(String s)//要求传入的字符串是数字字符串,跟public Integer(String s)完全一样

    String s = "200";
    Integer i3 = new Integer(s);
    int i4 = i3.intValue();//200,Integer对象的整型值方法转换成了int数
    
    int i5 = Integer.parseInt(s);//200,Integer的静态解析整型方法,将String转换为int,推荐用这种
    
  • JDK5的新特性自动装箱和拆箱:
    Integer ii = 100;//基本类型转换为包装类类型,自动装箱
    ii += 200;//把包装类类型转换为基本类型,自动拆箱,底层调用了包装类对象的intValue方法,所以ii不能为null

    自动拆箱,底层调用了包装类对象的intValue方法,如int z = i2 + 200;底
    层调用的是int z = i2.intValue() + 200;所以,对象i2不能赋值为null再调用
    方法,否则会报运行时异常的空指针异常,但是编译符合语法是通过的,这个要
    区别开哦!
    Integer i5 = 127;//自动装箱底层调用的是valueOf方法,Integer i5 = Integer.valueOf(127);

常见题目

Integer i1 = new Integer(97);
Integer i2 = new Integer(97);
System.out.println(i1 == i2);//false
System.out.println(i1.equals(i2));//true
System.out.println("‐‐‐‐‐‐‐‐‐‐‐");

Integer i3 = new Integer(197);
Integer i4 = new Integer(197);
System.out.println(i3 == i4);//false
System.out.println(i3.equals(i4));
System.out.println("‐‐‐‐‐‐‐‐‐‐‐");

Integer i5 = 97;
Integer i6 = 97;
System.out.println(i5 == i6);//true,自动装箱,真相只有一个,在字节范围内就使用,否则创建对象!
System.out.println(i5.equals(i6));
System.out.println("‐‐‐‐‐‐‐‐‐‐‐");

Integer i7 = 197;
Integer i8 = 197;
System.out.println(i7 == i8);//false
System.out.println(i7.equals(i8));

/*‐128到127是byte的取值范围,如果在这个取值范围内,自动装箱就不会新创建对象,而是从常量池中获取,
 如果超过了byte取值范围就会再新创建对象,看自动装箱底层调用的valueOf方法的源码就知道了,如下所示:
public static Integer valueOf(int i) {
	assert IntegerCache.high >= 127;
	if (i >= IntegerCache.low && i <= IntegerCache.high)//i>= ‐128 && i <= 127,字节范围内,
	return IntegerCache.cache[i + (‐IntegerCache.low)];//满足条件,从常量池获取
	return new Integer(i);//否则,创建新对象!!!
}*/

这里凡是new出来的地址值都不同,另外如果是自动装箱,基本类型值范围在byte字节范围内**-128到+127**,就不用创建对象,直接使用byte常量池的值,地址值相同,否则要创建新对象,地址值不同,而equals方法重写了,比较的是内容,所以都相等

BigInteger

在Java中,由CPU原生提供整型最大范围是64位long型整数。使用long型整数可以直接通过CPU指令进行计算速度非常快

如果我们使用的整数范围超过了long型怎么办?这个时候,就只能用软件来模拟一个大整数java.math.BigInteger就是用来表示任意大小的整数BigInteger内部用一个int[]数组模拟一个非常大的整数

BigInteger bi = new BigInteger("1234567890");
System.out.println(bi.pow(5)); // 2867971860299718107233761438093672048294900000

对BigInteger做运算的时候,只能使用实例方法,例如,加法运算:

BigInteger i1 = new BigInteger("1234567890");
BigInteger i2 = new BigInteger("12345678901234567890");
BigInteger sum = i1.add(i2); // 12345678902469135780

和long型整数运算比,BigInteger不会有范围限制,但缺点是速度比较慢

BigInteger类的常用方法:

public BigInteger add(BigInteger val)   返回当前大整数对象与参数指定的大整数对象的和

public BigInteger subtract(BigInteger val)  返回当前大整数对象与参数指定的大整数对象的差

public BigInteger multiply(BigInteger val)   返回当前大整数对象与参数指定的大整数对象的积

public BigInteger devide(BigInteger val)    返回当前大整数对象与参数指定的大整数对象的商

public BigInteger remainder(BigInteger val)    返回当前大整数对象与参数指定的大整数对象的余

public int compareTo(BigInteger val)    返回当前大整数对象与参数指定的大整数对象的比较结果,返回值是1、-1、0,分别表示当前大整数对象大于、小于或等于参数指定的大整数。

public BigInteger abs()    返回当前大整数对象的绝对值

public BigInteger pow(int exponent)   返回当前大整数对象的exponent次幂。

public String toString()    返回当前当前大整数对象十进制的字符串表示。

public String toString(int p)   返回当前大整数对象p进制的字符串表示。

也可以把BigInteger转换成long型:

BigInteger i = new BigInteger("123456789000");
System.out.println(i.longValue()); // 123456789000
System.out.println(i.multiply(i).longValueExact()); // java.lang.ArithmeticException: BigInteger out of long range

使用longValueExact()方法时,如果超出了long型的范围,会抛出ArithmeticException。

BigInteger和Integer、Long一样,也是不可变类,并且也继承自Number类。因为Number定义了转换为基本类型的几个方法:

转换为byte:byteValue()
转换为short:shortValue()
转换为int:intValue()
转换为long:longValue()
转换为float:floatValue()
转换为double:doubleValue()

因此,通过上述方法,可以把BigInteger转换成基本类型。如果BigInteger表示的范围超过了基本类型的范围,转换时将丢失高位信息,即结果不一定是准确的。如果需要准确地转换成基本类型,可以使用intValueExact()、longValueExact()等方法,在转换时如果超出范围,将直接抛出ArithmeticException异常

  • 计算1+2+…前30项和:

    import java.math.BigInteger;
    
    public class jc{
    	public static void main(String[] args) {
    		BigInteger sum=new BigInteger("0"),
    				xiang=new BigInteger("1"),
    				oNE=new BigInteger("1"),
    				i=oNE,m=new BigInteger("30");
    		while (i.compareTo(m)<=0) {
    			sum=sum.add(xiang);
    			i=i.add(oNE);
    			xiang=xiang.multiply(i);
    		}
    		System.out.println(sum);
    	}
    }
    

BigDecimal

和BigInteger类似,BigDecimal可以表示一个任意大小且精度完全准确的浮点数。商业计算往往要求结果精确,这时候就应该使用BigDecimal。

  • 构造实例

    public static void main(String[] args)
        {
            BigDecimal bigDecimal = new BigDecimal(2);
            BigDecimal bDouble = new BigDecimal(2.3);
            BigDecimal bString = new BigDecimal("2.3");
            System.out.println("bigDecimal=" + bigDecimal);//输出:bigDecimal=2
            System.out.println("bDouble=" + bDouble);//输出:bDouble=2.9999999
            System.out.println("bString=" + bString);//输出:bString=2.3
        }
    
  • 构造方法注意事项
    参数类型为double的构造方法的结果有一定的不可预知性;String 构造方法是完全可预知的;所以我们在编写代码时尽量都用String 构造方法。当double必须用作BigDecimal的源时可以用BigDecimal的静态方法 valueOf() 如:BigDecimal bDouble1 = BigDecimal.valueOf(2.3);

  • 运算方法

    public BigDecimal add(BigDecimal value);                        //加法
    
    public BigDecimal subtract(BigDecimal value);                   //减法 
    
    public BigDecimal multiply(BigDecimal value);                   //乘法
    
    public BigDecimal divide(BigDecimal value);                     //除法
    
  • 运算注意事项
    除法运算 divide() 方法,可能出现不能整除的情况,比如 4.5/1.3,这时会报错java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result。其实divide方法有可以传三个参数

    public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)
    第一参数表示除数(num/divisor)
    第二个参数表示小数点后保留位数,
    第三个参数表示舍入模式,只有在作除法运算或四舍五入时才用到舍入模式。
    
  • 舍入模式

    ROUND_CEILING    //向正无穷方向舍入
    
    ROUND_DOWN    //向零方向舍入
    
    ROUND_FLOOR    //向负无穷方向舍入
    
    ROUND_HALF_DOWN    //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向下舍入, 例如1.55 保留一位小数结果为1.5
    
    ROUND_HALF_EVEN    //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,如果保留位数是奇数,使用ROUND_HALF_UP,如果是偶数,使用ROUND_HALF_DOWN
    
    ROUND_HALF_UP    //(四舍五入)向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向上舍入, 1.55保留一位小数结果为1.6
    
    ROUND_UNNECESSARY    //计算结果是精确的,不需要舍入模式
    
    ROUND_UP    //向远离0的方向舍入
    
    
  • 舍入实例方法

    public static void main(String[] args)
        {
            BigDecimal a = new BigDecimal("4.5635");
    
            a = a.setScale(3, RoundingMode.HALF_UP);    //保留3位小数,且四舍五入
            System.out.println(a);
        }
    

你可能感兴趣的:(Java)