Java包装类

包装类

1.Java中的数据类型int、double等不是对象,无法通过向上转型获取到Object提供的方法,
而像String却可以,只因为String是一个对象而不是一个类型
2.基本数据类型由于这样的特性,导致无法参与转型、泛型、反射等过程
3.为了弥补这个缺陷,Java提供了包装类(将基本的数据类型以及一些辅助方法包装到类中)
主要将基本数据类型封装在包装类中,如int类数值包装类Integer,boolean型的包装类Boolean等

包装类及其对应的基本数据类型(java.lang)

包装类 对应基本数据类型
Byte byte
Short short
Integer int
Long long
Float float
Double double
Character char
Boolean Boolean
Byte类、Short类、Integer类和Long类,将byte、short、int、long封装为一个类,由于这些都是Number的子类,区别是封装不同的数据类型,包含的方法基本相同。

Java数据类型分两种

(1)基本类型:byte,short,int,long,boolean,float,double,char
(2)引用类型:所有class和interface类型
引用类型可以赋值为null,表示空;基本类型不能赋值为null


如何把一个基本类型视为对象(引用类型)?

把int基本类型变成一个引用类型,可以定义一个Integer类,它只包含一个实例字段int,这样,Integer类就可以视为int的包装类(Wrapper Class)

public class Integer {
    private int value;

    public Integer(int value) {
        this.value = value;
    }
    
    public int intValue() {
        return this.value;
    }
}

自动装箱(Auto Boxing)

直接把int变为Integer的赋值写法。基本类型变为引用类型


自动拆箱(Auto Unboxing)

把Integer变为int的赋值写法。引用类型变为基本类型

在Java SE5之前,要进行装箱,可以通过以下代码:

Integer i = new Integer(100);

在Java SE5中,为了减少开发人员的工作,Java提供了自动拆箱与自动装箱功能
Integer i=100;
i为一个Integer类型的引用,100为Java中的基础数据类型(primitive data type)。而这种直接将一个基础数据类型传给其相应的封装类(wrapper class)的做法,便是自动装箱(Autoboxing)

装箱:JDK完成了调用Integer.valueOf(100)
拆箱:JDK自动完成了对Integer.intValue()的调用
区别:基本类型效率更高,包装类型的对象却可以携带更多的信息


注意:自动装箱和自动拆箱只发生在编译阶段,目的是为了少写代码
装箱和拆箱会影响代码的执行效率,因为编译后的class代码是严格区分基本类型和引用类型的。并且自动拆箱执行时可能会报NullPointerException。

所有的包装类型都是不变类。一旦创建了Integer对象,该对象就是不变的。对两个Integer实例进行比较要特别注意:绝对不能用“==”比较,因为Integer是引用类型,必须使用equals()比较。

Integer x = 127;
Integer y = 127;
Integer m = 99999;
Integer n = 99999;
System.out.println("x == y: " + (x == y)); // true
System.out.println("m == n: " + (m == n)); // false
System.out.println("x.equals(y): " + x.equals(y)); // true
System.out.println("m.equals(n): " + m.equals(n)); // true

==比较,较小的两个相同的Integer返回true,较大的两个相同的Integer返回false

因为Integer是不变类,编译器把Integer x = 127;自动变为Integer x = Integer.valueOf(127);,为了节省内存,Integer.valueOf()对于较小的数,始终返回相同的实例,因此,比较“恰好”为true,但绝不能因为Java标准库的Integer内部有缓存优化就用“”比较,必须用equals()方法比较两个Integer

所有的整数和浮点数的包装类型都继承自Number,因此,可以非常方便地直接通过包装类型获取各种基本类型:

// 向上转型为Number:
Number num = new Integer(999);
// 获取byte, int, long, float, double:
byte b = num.byteValue();
int n = num.intValue();
long ln = num.longValue();
float f = num.floatValue();
double d = num.doubleValue();

注意:在计算机内存中,只用二进制表示,不存在十进制或十六进制的表示方法。在内存中总是以4字节的二进制表示

程序设计的一个重要原则:数据的存储和显示要分离

处理无符号整型
在Java中,并没有无符号整型(Unsigned)的基本数据类型。byte、short、int和long都是带符号整型,最高位是符号位。而C语言则提供了CPU支持的全部数据类型,包括无符号整型。无符号整型和有符号整型的转换在Java中就需要借助包装类型的静态方法完成。

byte是有符号整型,范围是-128 ~ +127,但如果把byte看作无符号整型,它的范围就是0~255。一个负的byte按无符号整型转换为int。

public class Main {
    public static void main(String[] args) {
        byte x = -1;
        byte y = 127;
        System.out.println(Byte.toUnsignedInt(x)); // 255
        System.out.println(Byte.toUnsignedInt(y)); // 127
    }
}

(1)Java核心库提供的包装类型可以把基本类型包装为class
(2)自动装箱和自动拆箱都是在编译期完成的(JDK>=1.5)
(3)装箱和拆箱会影响执行效率,且拆箱时可能发生NullPointerException
(4)包装类型的比较必须使用equals()
(5)整数和浮点数的包装类型都继承自Number
(6)包装类型提供了大量实用方法

Integer类

1.构造方法(2种)

Integer(int number) 以一个int型变量作为参数创建Integer对象
Integer number=new Integer(7);
Integer(String str) 以一个String型变量作为参数创建Integer对象
Integer number=new Integer(“16”);
**注意:**如果要使用字符串变量创建Integer对象,字符串变量一定要是数值型的,否则会抛出NumberFormatException异常。

2.常用方法

方法 描述
Integer valueOf(String str) 返回保存指定的String值的Integer对象
int parseInt(String str) 返回包含在由str指定的字符串的数字的等价整数值
String toString() 返回一个表示该Integer值的String对象(可以指定进制基数)
String toBinaryString(int i) 以二进制无符号整数形式返回一个整数参数的字符串表达形式
String toHexString(int i) 十六进制无符号整数形式返回一个整数参数的字符串表达形式
String toOctalString(int i) 以八进制无符号整数形式返回一个整数参数的字符串表达形式
boolean equals(Object IntegerObj) 比较此对象与指定的对象是否相等
int intValue() 以int类型返回此Integer对象
short shortValue() 以short类型返回此Integer对象
byte byteValue() 以byte类型返回此Integer对象
int compareTo(Integeranother Integer) Integeranother相当于坐标原点 在数字上比较两个Integer对象,如果这两个相等,则返回0;如果调用对象的数值小于Integeranother的数值,则返回负值;如果调用对象的数值大于anotherInteger的数值,则返回正值

3.常量

Integer提供了4个常量

常量 描述
MAX_VALUE 表示int类型的最大值2^31-1
MIN_VALUE 表示int类型的最小值-2^31
SIZE 二进制补码形式表示int值的位数
TYPE 表示基本数据类型int的Class实例

BigInteger类

(1)BigInteger用于表示任意大小的整数
(2)BigInteger是不变类,并且继承自Number
(3)将BigInteger转换成基本类型时可使用longValueExact()等方法保证结果准确

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

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

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

和long型整数运算比,BigInteger不会有范围限制,但缺点是速度比较慢
也可以把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定义了转换为基本类型的几个方法。

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

如果BigInteger的值甚至超过了float的最大范围(3.4x1038),那么返回的float是什么呢?

public class Main {
	public static void main(String[] args) {
		BigInteger n = new BigInteger("999999").pow(99);
		float f = n.floatValue();
		System.out.println(f);
	}
}

Float类

Float类在一个对象中包含一个原始类型float的值。类型为Float的对象包含一个单一字段,其类型为float。此外,该类还提供了几种将float转换为String和String转换为float,以及在处理float时有用的其他常数和方法。

1.构造方法

Float(double value) 构造一个新分配 Float对象,它表示转换为类型参数float
Float(float value) 构造一个新分配的 Float对象,该对象表示基元 float参数
Float(String s) 构造一个新分配 Float对象,它表示类型的浮点值 float用字符串表示

精度失准?

浮点数都是以二进制数的形式存储的,这样就会产生一个问题,有许多的小数无法被准确的表示。如同十进制无法准确表示 1/3 那样,二进制也有许多无法精确表示的数,计算机只能进行舍入,取近似值来表示


Double类

1.构造方法(2种)

// 以double参数创建Double类对象
Double number=new Double(3.14);
// 以String型变量作为参数获取Double对象
Double number=new Double(“3.14”);

2.常用方法

方法 描述
double valueOf(String str) 返回保存用参数字符串str表示的double值的Double对象
double parseDoble(String s) 返回一个新的double值,该值被初始化为指定String表示的值,这与Double的valueOf方法一样
double doubleValue() 以double形式返回此Double对象
boolean isNaN() 如果此double值是非数字(NaN)值,则返回true;否则返回false
int intValue() 以int形式返回double值
byte byteValue() 以byte形式返回Double对象值(通过强制转换)
long longValue() 以long形式返回此double的值(通过强制转换为long类型)
int compareTo(Double d) 对两个Double对象进行数值比较。如果两个值相等,则返回0;如果调用对象的数值小于d的数值,则返回负值;如果调用的对象大于d的值,则返回正值
boolean equals(Object ojb) 将此对象与指定的对象比较
String toString() 返回此Double对象的字符串表示形式
String toHexString(double d) 返回double参数的十六进制字符串表示形式

3.常量

常量 描述
MAX_EXPONENT 返回int值,表示有限double变量可能具有最大的指数
MIN_EXPONENT 返回int值,表示标准化double变量可能具有最小的指数
NEGATIVE_INFINITY 返回double值,表示保存double类型的负无穷大值的常量
POSITIVE_INFINITY 返回double值,表示保存double类型的正无穷大值的常量

BigDecimal(精度正确的浮点数)

和BigInteger类似,BigDecimal可以表示一个任意大小且精度完全准确的浮点数

BigDecimal bd = new BigDecimal("123.4567");
System.out.println(bd.multiply(bd)); // 15241.55677489

//BigDecimal用scale()表示小数位数
BigDecimal d1 = new BigDecimal("123.45");
BigDecimal d2 = new BigDecimal("123.4500");
BigDecimal d3 = new BigDecimal("1234500");
System.out.println(d1.scale()); // 2,两位小数
System.out.println(d2.scale()); // 4
System.out.println(d3.scale()); // 0

通过BigDecimal的stripTrailingZeros()方法,可以将一个BigDecimal格式化为一个相等的,但去掉了末尾0的BigDecimal:

BigDecimal d1 = new BigDecimal("123.4500");
BigDecimal d2 = d1.stripTrailingZeros();
System.out.println(d1.scale()); // 4
System.out.println(d2.scale()); // 2,因为去掉了00

BigDecimal d3 = new BigDecimal("1234500");
BigDecimal d4 = d3.stripTrailingZeros();
System.out.println(d3.scale()); // 0
System.out.println(d4.scale()); // -2		

如果一个BigDecimal的scale()返回负数,例如,-2,表示这个数是个整数,并且末尾有2个0

可以对一个BigDecimal设置它的scale,如果精度比原始值低,那么按照指定的方法进行四舍五入或者直接截断

import java.math.BigDecimal;
import java.math.RoundingMode;

public class Main {
    public static void main(String[] args) {
        BigDecimal d1 = new BigDecimal("123.456789");
		// 四舍五入,123.4568
        BigDecimal d2 = d1.setScale(4, RoundingMode.HALF_UP); 
		// 直接截断,123.4567
        BigDecimal d3 = d1.setScale(4, RoundingMode.DOWN); 
        System.out.println(d2);
        System.out.println(d3);
    }
}

Boolean类

Boolean类将基本类型为boolean的值包装在一个对象中,一个Boolean类型的对象只包含一个类型为boolean的字段,此类还为boolean和String的相互转换提供了许多方法,并提供了处理boolean时非常有用的其他常量和方法

1.构造方法(2种)

// 该方法创建一个表示value参数的Boolean对象
new Boolean(boolean value);
// 该方法以String变量作为参数创建Boolean对象,如果String参数不为null且在忽略大小时等于true,则分配一个表示true值得Boolean对象,否则获得一个false值得Boolean对象
new Boolean(String str);

2.常用方法

方法 描述
booleanValue() 将Boolean对象的值以对应的boolean值返回
equals(Object obj) 判断调用该方法的对象与obj是否相等,仅当参数不是null,而且与调用该方法的对象一样都表示同一个boolean值的Boolean对象时,才返回true
parseBoolean(String s) 将字符串参数解析为boolean值
valueOf(String s) 返回一个用指定的字符串表示值的boolean值
toString() 返回表示该boolean值的String对象

3.常量

常量 描述
TRUE 对应基值true的Boolean对象
FALSE 对应基值false的Boolean对象
TYPE 基本类型boolean的Class对象

Character类

1.构造方法(1种)

// 该类的构造方法的参数必须是一个char类型的数据,将一个char类型数据包装成一个Character类对象;一旦Character类被创建,它包含的数值就不能改变了
new Character(char value);
new Character mychar=new Character(‘s’);

2.常用方法

方法 描述
int compareTo(Character anotherCharacter) 根据数字比较两个Character对象,若两个对象相等则返回0
boolean equals(Object obj) 将调用该方法的对象与指定的对象项比较
char toUpperCase(char ch) 将字符参数转换为大写
char toLowerCase(Char ch) 将字符参数转换为小写
String toString() 返回一个表示指定char值的对象
char charValue() 返回此Character对象的值
boolean isUpperCase(char ch) 判断指定字符是否是大写字符
boolean isLowerCase(char ch) 判断指定字符是否为小写字符
boolean isLetter(char ch) 判断指定字符是否为字母
boolean isDigit(char ch) 判断指定字符是否为数字

3.常量

常量 描述
CONNECTOR_PUNCTUATION 返回byte型值,表示Unicode规范中的常规类别“Pc.”
UNASSIGNED 返回byte型值,表示Unicode规范中的常规类别“Cn.”
TITLECASE_LETTER 返回byte型值,表示Unicode规范中的常规类别“Lt.”

Number类

对于数值型的包装类,他们有一个共同的父类(Number类);该类是个抽象类,它是Byte、Interger、Short、Long、Float、Double类的父类,其子类必须提供将表示的数值转换为byte、short、int、long、float、double的方法

数值型包装类的共有方法

方法 描述
xxxValue() 以xxx形式返回指定的数值

xxx为八种基本数据类型(上所列,有不包含)


Math类(Math.数学方法,java.lang)

系统默认调用(就是默认导入这个包),提供了许多的数学函数;主要包括三角函数方法、指数函数方法、取整数函数方法、取最大值、最小值、绝对值等;这些方法都被定义为static形式

常量 描述
Math.PI 圆周率的值
Math.E 自然对数底数e的值

三角函数

方法 返回值 功能
sin(double a) Double 返回角的三角正弦
cos(double a) 返回角的三角余弦
tan(double a) 返回角的三角正切
asin(double a) 返回一个值的反正弦
acos(double a) 返回一个值的反余弦
atan(double a) 返回一个值的反正切
toRadians(double angdeg) 将角度转换为弧度
toDegrees(double angrad) 将弧度转换为角度

指数函数

方法 返回值 功能
exp(double a) Double 用于获取e的a次方,即取e^a
log(double a) 用于取自然对数,即取ln a的值
log10(double a) 用于取底数为10的对数
sqrt(double a) 用于取a的平方根,其中a的值不能为负值
cbrt(double a) 用于取a的立方根
pow(double a,double b) 用于取a的b次方

取整数函数

方法 返回值 功能
ceil(double a) Double 返回大于等于参数的最小整数
floor(double a) 返回小于等于参数的最大整数
rint(double a) 返回与参数最接近的整数,如果两个同为整数且同样接近,则结果取偶数
round(float a) 将参数加上0.5后返回与参数最近的整数
Round(double a) 将参数加上0.5后返回与参数最近的整数,然后强制转换为长整型

取最大值、最小值、绝对值

方法 功能
Double max(double a,double b) 取a与b之间的最大值
int min(int a,int b) 取a与b之间的最小值,参数为整型
long min(long a,long b) 取a与b之间的最小值,参数为长整型
float min(float a,float b) 取a与b之间的最小值,参数为浮点型
Double min(double a,double b) 取a与b之间的最小值,参数为双精度型
int abs(int a) 返回整型参数的绝对值
long abs(long a) 返回长整型参数的绝对值
float abs(float a) 返回浮点型参数的绝对值
Double abs(double a) 返回双精度参数的绝对值

随机数

方法 功能
Math.random() 取值范围:0<=Math.random()<1.0 类型:double类型随机数

Random类(伪随机数)

除了Math类中的random()方法可以产生随机数之外,Java还提供了一种可以获取随机数的方式
Random用来创建伪随机数。所谓伪随机数,是指只要给定一个初始的种子,产生的随机数序列是完全一样的。
要生成一个随机数,可以使用nextInt()、nextLong()、nextFloat()、nextDouble()

Random类随机数

Random r = new Random();
Random r = new Random(seedValue);

r:Random类对象
seedValue:随机数生成器种子

以这种方式实例化对象时,Java编译器以系统当前时间作为随机数生成器的种子,因为每时每刻的事件不可能相同,所以生成的随机数将不同,但是运行速度太快,也会生成两次运行结果相同的随机数。

Random类中常用生成随机数的方法

方法 功能
int nextInt() 返回一个随机整数
int nextInt(int n) 返回一个大于等于0小于n的随机数
long nextLong() 返回一个随机长整型值
boolean nextBoolean() 返回一个数据布尔值
float nextFloat() 返回一个随机浮点型值
Double nextDouble() 返回一个随机双精度型值
Double nextGaussian() 返回一个概率密度为高斯分布的双精度值

SecureRandom(真随机数)

有伪随机数,就有真随机数。实际上真正的真随机数只能通过量子力学原理来获取,而想要的是一个不可预测的安全的随机数,SecureRandom就是用来创建安全的随机数的(java.security.SecureRandom;)

SecureRandom sr = new SecureRandom();
System.out.println(sr.nextInt(100));

SecureRandom无法指定种子,它使用RNG(random number generator)算法。JDK的SecureRandom实际上有多种不同的底层实现,有的使用安全随机种子加上伪随机数算法来产生安全的随机数,有的使用真正的随机数生成器。实际使用的时候,可以优先获取高强度的安全随机数生成器,如果没有提供,再使用普通等级的安全随机数生成器:

// 获取高强度安全随机数生成器
SecureRandom sr = SecureRandom.getInstanceStrong();
SecureRandom sr = new SecureRandom(); // 获取普通的安全随机数生成器
byte[] buffer = new byte[16];
sr.nextBytes(buffer); // 用安全随机数填充buffer
System.out.println(Arrays.toString(buffer));

SecureRandom的安全性是通过操作系统提供的安全的随机种子来生成随机数。这个种子是通过CPU的热噪声、读写磁盘的字节、网络流量等各种随机事件产生的“熵”

在密码学中,安全的随机数非常重要。如果使用不安全的伪随机数,所有加密体系都将被攻破。因此,时刻牢记必须使用SecureRandom来产生安全的随机数

需要使用安全随机数的时候,必须使用SecureRandom,绝不能使用Random





上一篇:正则表达式                        下一篇:日期与时间




你可能感兴趣的:(Java,java,jvm,数据结构)