《Java 编程的逻辑》笔记——第7章 常用基础类(一)

本文详细介绍了Java中的包装类,包括它们的基本用法、共同点,如重写Object方法、实现Comparable接口,以及与String的相关方法。特别讨论了Integer类与二进制算法,如位翻转、循环移位,以及valueOf方法的实现,揭示了Integer对象的缓存机制。此外,还剖析了Character类,强调了Unicode基础知识和字符属性的处理。
摘要由CSDN通过智能技术生成

声明:

本博客是本人在学习《Java 编程的逻辑》后整理的笔记,旨在方便复习和回顾,并非用作商业用途。

本博客已标明出处,如有侵权请告知,马上删除。

开头语

本章介绍 Java 编程中一些常用的基础类,探讨它们的用法、应用和实现原理,这些类有:

  • 各种包装类
  • 文本处理的类 String 和 StringBuilder
  • 数组操作的类 Arrays
  • 日期和时间处理
  • 随机

7.1 包装类

Java 有八种基本类型,每种基本类型都有一个对应的包装类。

包装类是什么呢?它是一个类,内部有一个实例变量,保存对应的基本类型的值,这个类一般还有一些静态方法、静态变量和实例方法,以方便对数据进行操作。

Java 中,基本类型和对应的包装类如表 7-1 所示:

在这里插入图片描述

包装类也都很好记,除了 Integer 和 Character 外,其他类名称与基本类型基本一样,只是首字母大写。

包装类有什么用呢?Java 中很多代码(比如后续文章介绍的集合类)只能操作对象,为了能操作基本类型,需要使用其对应的包装类,另外,包装类提供了很多有用的方法,可以方便对数据的操作。

下面先介绍各个包装类的基本用法及其共同点,然后重点介绍 Integer 和 Character。

7.1.1 基本用法

我们先来看各个基本类型和其包装类是如何转换的,我们直接看代码:

Boolean

boolean b1 = false;
Boolean bObj = Boolean.valueOf(b1);
boolean b2 = bObj.booleanValue();

Byte

byte b1 = 123;
Byte byteObj = Byte.valueOf(b1);
byte b2 = byteObj.byteValue();

Short

short s1 = 12345;
Short sObj = Short.valueOf(s1);
short s2 = sObj.shortValue();

Integer

int i1 = 12345;
Integer iObj = Integer.valueOf(i1);
int i2 = iObj.intValue();

Long

long l1 = 12345;
Long lObj = Long.valueOf(l1);
long l2 = lObj.longValue();

Float

float f1 = 123.45f;
Float fObj = Float.valueOf(f1);
float f2 = fObj.floatValue();

Double

double d1 = 123.45;
Double dObj = Double.valueOf(d1);
double d2 = dObj.doubleValue(); 

Character

char c1 = 'A';
Character cObj = Character.valueOf(c1);
char c2 = cObj.charValue(); 

这些代码结构是类似的,每种包装类都有一个静态方法 valueOf(),接受基本类型,返回引用类型,也都有一个实例方法 xxxValue() 返回对应的基本类型。

将基本类型转换为包装类的过程,一般称为"装箱",而将包装类型转换为基本类型的过程,则称为"拆箱"。装箱/拆箱写起来比较啰嗦,Java 1.5 以后引入了自动装箱和拆箱技术,可以直接将基本类型赋值给引用类型,反之亦可,如下代码所示:

Integer a = 100;
int b = a;

自动装箱/拆箱是 Java 编译器提供的能力,背后,它会替换为调用对应的 valueOf()/xxxValue(),比如说,上面的代码会被 Java 编译器替换为:

Integer a = Integer.valueOf(100);
int b = a.intValue();

每种包装类也都有构造方法,可以通过 new 创建,比如说:

Integer a = new Integer(100);
Boolean b = new Boolean(true);
Double d = new Double(12.345);
Character c = new Character('马');

那到底应该用静态的 valueOf 方法,还是使用 new 呢?一般建议使用 valueOf。new 每次都会创建一个新对象,而除了 Float 和 Double 外的其他包装类,都会缓存包装类对象,减少需要创建对象的次数,节省空间,提升性能,后续我们会分析其具体代码。

7.1.2 共同点

各个包装类有很多共同点,比如,都重写了 Object 中的一些方法,都实现了 Comparable 接口,都有一些与 String 有关的方法,大部分都定义了一些静态常量,都是不可变的。下面具体介绍。

7.1.2.1 重写 Object 方法

所有包装类都重写了 Object 类的如下方法:

boolean equals(Object obj)
int hashCode()
String toString()

我们逐个来看下。

equals

equals 用于判断当前对象和参数传入的对象是否相同,Object 类的默认实现是比较地址,对于两个变量,只有这两个变量指向同一个对象时,equals 才返回 true,它和比较运算符(==)的结果是一样的

但,equals 应该反映的是对象间的逻辑相等关系,所以这个默认实现一般是不合适的,子类需要重写该实现。所有包装类都重写了该实现,实际比较用的是其包装的基本类型值,比如说,对于 Long 类,其 equals 方法代码是:

public boolean equals(Object obj) {
   
    if (obj instanceof Long) {
   
        return value == ((Long)obj).longValue();
    }
    return false;
}

对于 Float,其实现代码为:

public boolean equals(Object obj) {
   
    return (obj instanceof Float)
           && (floatToIntBits(((Float)obj).value) == floatToIntBits(value));
}

Float 有一个静态方法 floatToIntBits(),将 float 的二进制表示看做 int。需要注意的是,只有两个 float 的二进制表示完全一样的时候,equals 才会返回 true。在 2.2 节的时候,我们提到小数计算是不精确的,数学概念上运算结果一样,但计算机运算结果可能不同,比如说,看下面代码:

Float f1 = 0.01f;
Float f2 = 0.1f*0.1f;
System.out.println(f1.equals(f2));
System.out.println(Float.floatToIntBits(f1));
System.out.println(Float.floatToIntBits(f2)); 

输出为:

false
1008981770
1008981771

也就是,两个浮点数不一样,将二进制看做整数也不一样,相差为 1。

Double 的 equals 方法与 Float 类似,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bm1998

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值