Java常用类(一)

    • ⭐ 基本数据类型的包装类
      • ⭐ 包装类基本知识
      • ⭐ 包装类的用途
      • ⭐ 自动装箱和拆箱
      • ⭐ 自定义一个简单的包装类
    • ⭐ 字符串相关类

⭐ 基本数据类型的包装类

我们之前写过八种基本数据类型并不是对象,为了将基本类型数据和对象之间实现互相转化,Java 为每一个基本数据类型提供了相应的包装类。
在这里插入图片描述

⭐ 包装类基本知识

Java 是面向对象的语言,但并不是“纯面向对象”的,因为我们经常用到的基本数据类型就不是对象。但是我们在实际应用中经常需要将基本数据转化成对象,以便于操作。比如:将基本数据类型存储到 Object[ ]数组或集合中的操作等等。

为了解决这个不足,Java 在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数据类型对应的类统称为包装类(Wrapper Class)。

包装类位于 java.lang 包,八种包装类和基本数据类型的对应关系:
在这里插入图片描述
在这八个类名中,除了 Integer 和 Character 类以外,其它六个类的类名和基本数据类型一致,只是类名的第一个字母大写而已。
在这里插入图片描述

Number 类是抽象类,因此它的抽象方法,所有子类都需要提供实现。Number 类提供了抽象方法:intValue()、longValue()、floatValue()、doubleValue(),意味着所有的“数字型”包装类都可以互相转型。

下面我们通过一个简单的示例认识一下包装类。

【示例】初识包装类

public class WrapperClassTest {public static void main(String[ ] args) {Integer i = new Integer(10); //从 java9 开始被废弃Integer j = Integer.valueOf(50); //官方推荐}
}

示例内存分析如图所示:
在这里插入图片描述

⭐ 包装类的用途

对于包装类来说,这些类的用途主要包含两种:

  1. 作为和基本数据类型对应的类型存在,方便涉及到对象的操作,如 Object[ ]、集合等的操作。
  2. 包含每种基本数据类型的相关属性如最大值、最小值等,以及相关的操作方法(这些操作方法的作用是在基本数据类型、包装类对象、字符串之间提供相互之间的转化!)。

【示例】包装类的使用

public class Test {
/** 测试 Integer 的用法,其他包装类与 Integer 类似 */
void testInteger() {
// 基本类型转化成 Integer 对象
Integer int1 = new Integer(10); //已经被废弃,不推荐使用
Integer int2 = Integer.valueOf(20); // 官方推荐这种写法
// Integer 对象转化成 int
int a = int1.intValue();
// 字符串转化成 Integer 对象
Integer int3 = Integer.parseInt("334");
Integer int4 = new Integer("999");
// Integer 对象转化成字符串
String str1 = int3.toString();// 一些常见 int 类型相关的常量
System.out.println("int 能表示的最大整数:" + Integer.MAX_VALUE); 
}
public static void main(String[ ] args) {Test test = new Test();test.testInteger();}
}

执行结果如图所示:

⭐ 自动装箱和拆箱

自动装箱(autoboxing)和拆箱(unboxing):将基本数据类型和包装类自动转换。
在这里插入图片描述

自动装箱:

基本类型的数据处于需要对象的环境中时,会自动转为“对象”。

我们以 Integer 为例:

Integer i = 5

编译器会自动转成:

Integer i = Integer.valueOf(5)

这就是 Java 的自动装箱。

自动拆箱:

每当需要一个值时,对象会自动转成基本数据类型,没必要再去显式调用intValue()、doubleValue()等转型方法。

Integer i = Integer.valueOf(5);
int j = i;

编译器会自动转成:

int j = i.intValue();

这样的过程就是自动拆箱。

自动装箱/拆箱的本质是:

自动装箱与拆箱的功能是编译器来帮忙,编译器在编译时依据您所编写的语法,决定是否进行装箱或拆箱动作。

【示例】自动装箱

Integer i = 100;//自动装箱
//相当于编译器自动为您作以下的语法编译:
Integer i = Integer.valueOf(100);//调用的是 valueOf(100),而不是 new Integer(100)

【示例】自动拆箱

Integer i = 100;
int j = i;//自动拆箱
//相当于编译器自动为您作以下的语法编译:
int j = i.intValue();

自动装箱与拆箱的功能是所谓的“编译器蜜糖(Compiler Sugar)”,虽然使用这个功能很方便,但在程序运行阶段得了解 Java 的语义。

如下所示的程序是可以通过编译的:
【示例】包装类空指针异常问题

	public class Test1 {public static void main(String[ ] args) {Integer i = null;int j = i;}
}

执行结果如图所示:
在这里插入图片描述

运行结果之所以会出现空指针异常,是因为如上代码相当于:

	public class Test1 {public static void main(String[ ] args) {Integer i = null; int j = i.intValue();}
}

包装类的缓存问题

整型、char类型所对应的包装类,在自动装箱时,对于-128~127之间的值会进行缓存处理,其目的是提高效率。

缓存原理为:如果数据在-128~127这个区间,那么在类加载时就已经为该区间的每
个数值创建了对象,并将这256个对象存放到一个名为cache的数组中。每当自动装箱过程发生时(或者手动调用valueOf()时),就会先判断数据是否在该区间,如果在则直接获取数组中对应的包装类对象的引用,如果不在该区间,则会通过new调用包装类的构造方法来创建对象。

下面我们以Integer类为例,看一看Java为我们提供的源码,加深对缓存技术的理解,如下所示。

【示例】Integer 类相关源码

	public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);
}

这段代码中我们需要解释下面几个问题:

  1. IntegerCache类为Integer类的一个静态内部类,仅供Integer类使用。
  2. 一般情况下 IntegerCache.low为-128,

IntegerCache.high为127,IntegerCache.cache为内部类的一个静态属性,如示例所示。

【示例】IntegerCache 类相关源码

private static class IntegerCache {static final int low = -128;static final int high;static final Integer cache[ ];static {// high value may be configured by propertyint h = 127;String integerCacheHighPropValue =sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");if (integerCacheHighPropValue != null) {try {int i = parseInt(integerCacheHighPropValue);i = Math.max(i, 127);// Maximum array size is Integer.MAX_VALUEh = Math.min(i, Integer.MAX_VALUE - (-low) -1);} catch( NumberFormatException nfe) {// If the property cannot be parsed into an int, ignore it.}}high = h;cache = new Integer[(high - low) + 1];int j = low;for(int k = 0; k < cache.length; k++)cache[k] = new Integer(j++);// range [-128, 127] must be interned (JLS7 5.1.7)assert IntegerCache.high >= 127;}private IntegerCache() {}
}

由上面的源码我们可以看到,静态代码块的目的就是初始化数组cache的,这个过程
会在类加载时完成。

下面我们做一下代码测试,如示例所示。

【示例 8-9】包装类的缓存测试

	public class Test3 {public static void main(String[ ] args) {Integer in1 = -128;Integer in2 = -128;System.out.println(in1 == in2);//true 因为 123 在缓存范围内System.out.println(in1.equals(in2));//trueInteger in3 = 1234;Integer in4 = 1234;System.out.println(in3 == in4);//false 因为 1234 不在缓存范围内System.out.println(in3.equals(in4));//true}
}

注意:

🐟	自动装箱调用的是 valueOf()方法,而不是 new Integer()方法。
🐟	自动拆箱调用的 xxxValue()方法。
🐟	包装类在自动装箱时为了提高效率,对于-128~127 之间的值会进行缓存处理。超过范围后,对象之间不能再使用==进行数值的比较,而是使用 equals 方法。

⭐ 自定义一个简单的包装类

public class MyInteger {private int value;private static MyInteger[] cache = new MyInteger[256];public static final int LOW = -128;public static final int HIGH = 127;static {//[-128,127]for(int i=MyInteger.LOW;i<=HIGH;i++){//-128,0;-127,1;-126,2;cache[i+128] = new MyInteger(i);}}public static MyInteger valueOf(int i) {if(i>=LOW&&i<=HIGH) {return cache[i+128];}return new MyInteger(i);}@Overridepublic String toString() {return this.value+"";}public int intValue(){return value;}private MyInteger(int i) {this.value = i;}public static void main(String[] args) {MyInteger m = MyInteger.valueOf(30);System.out.println(m);}
}

⭐ 字符串相关类

String 类代表不可变的字符序列
StringBuilder 类和 StringBuffer 类代表可变字符序列。
在这里插入图片描述

这三个类的用法,在实际开发中经常用到,必须掌握好。

String 类源码分析

String 类对象代表不可变的 Unicode 字符序列,因此我们可以将 String 对象称为“不
可变对象”。 那什么叫做“不可变对象”呢?指的是对象内部的成员变量的值无法再改变。

我们打开 String 类的源码,如图所示:
在这里插入图片描述

我们发现字符串内容全部存储到 value[ ]数组中,而变量 value 是 final 类型的,也就是常量(即只能被赋值一次)。 这就是“不可变对象”的典型定义方式。

我们发现 String 的某些方法,比如:substring()是对字符串的截取操作,但本质是读取原字符串内容生成了新的字符串。测试代码如下:

【示例】String 类的简单使用

	public class TestString1 {public static void main(String[ ] args) {String s1 = new String("abcdef");String s2 = s1.substring(2, 4);// 打印:ab199863System.out.println(Integer.toHexString(s1.hashCode()));// 打印:c61, 显然 s1 和 s2 不是同一个对象System.out.println(Integer.toHexString(s2.hashCode()));}
}

在遇到字符串常量之间的拼接时,编译器会做出优化,即在编译期间就会完成字符串的拼接。因此,在使用(==)进行 String 对象之间的比较时,我们要特别注意,如示例所示。

【示例】字符串常量拼接时的优化

	public class TestString2 {public static void main(String[ ] args) {//编译器做了优化,直接在编译的时候将字符串进行拼接String str1 = "hello" + " java";//相当于 str1 = "hello java";String str2 = "hellojava";System.out.println(str1 == str2);//trueString str3 = "hello";String str4 = " java";//编译的时候不知道变量中存储的是什么,所以没办法在编译的时候优化String str5 = str3 + str4;System.out.println(str2 == str5);//false}
}

StringBuffer 和 StringBuilder 可变字符序列
在这里插入图片描述

StringBuffer 和 StringBuilder 都是可变的字符序列。

🐟	StringBuffer 线程安全,做线程同步检查, 效率较低。
🐟	StringBuilder 线程不安全,不做线程同步检查,因此效率较高。建议采用该类。

常用方法列表:

🐟	重载的 public StringBuilder append(…)方法
🐟	可以为该 StringBuilder 对象添加字符序列,仍然返回自身对象。
🐟	方法 public StringBuilder delete(int start,int end)
🐟	可以删除从 start 开始到 end-1 为止的一段字符序列,仍然返回自身对象。
🐟	方法 public StringBuilder deleteCharAt(int index)
🐟	移除此序列指定位置上的 char,仍然返回自身对象。
🐟	重载的 public StringBuilder insert(…)方法可以为该 StringBuilder 对象在指定位置插入字符序列,仍然返回自身对象。
🐟	方法 public StringBuilder reverse()
🐟	用于将字符序列逆序,仍然返回自身对象。
🐟	方法 public String toString() 返回此序列中数据的字符串表示形式。
🐟	和 String 类含义类似的方法:⭐	public int indexOf(String str)⭐	public int indexOf(String str,int fromIndex)⭐	public String substring(int start)⭐	public String substring(int start,int end)⭐	public int length() ⭐	char charAt(int index)

【示例】StringBuffer/StringBuilder 基本用法

	public class TestStringBufferAndBuilder{public static void main(String[ ] args) {/**StringBuilder*/StringBuilder sb = new StringBuilder();for (int i = 0; i < 7; i++) {sb.append((char) ('a' + i));//追加单个字符}System.out.println(sb.toString());//转换成 String 输出sb.append(", I can sing my abc!");//追加字符串System.out.println(sb.toString());/**StringBuffer,下面的方法同样适用 StringBuilder*/StringBuffer sb2 = new StringBuffer("北京最美丽");sb2.insert(0, "爱").insert(0, "我");//插入字符串System.out.println(sb2);sb2.delete(0, 2);//删除子字符串System.out.println(sb2);sb2.deleteCharAt(0).deleteCharAt(0);//删除某个字符System.out.println(sb2.charAt(0));//获取某个字符System.out.println(sb2.reverse());//字符串逆序}
}

下节我们继续带大家了解Java常用类!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/26550.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【EXCEL】数据录入的快捷键和正确格式

目录 0.环境 1.内容概述 2.具体内容 2.1数据录入换行换列的快捷键&#xff08;标准的数据输入方式&#xff09; 2.2日期的正确格式和使用&#xff08;标准日期格式与长日期&#xff09; 2.2.1 标准日期 2.2.2 长日期 2.2.3 显示当前日期和时间的快捷键 2.3百分比的正确…

stm32(串口知识点)

HAL串口发送/接收函数&#xff1a; HAL_UART_Transmit(); 串口发送数据&#xff0c;使用超时管理机制HAL_UART_Receive(); 串口接收数据&#xff0c;使用超时管理机制HAL_UART_Transmit_IT(); 串口中断模式发送 HAL_UART_Receive_IT(); 串口中断模式接收 HAL_UART_Transmit(…

人工智能LLM模型:奖励模型的训练、PPO 强化学习的训练、RLHF

人工智能LLM模型&#xff1a;奖励模型的训练、PPO 强化学习的训练 1.奖励模型的训练 1.1大语言模型中奖励模型的概念 在大语言模型完成 SFT 监督微调后&#xff0c;下一阶段是构建一个奖励模型来对问答对作出得分评价。奖励模型源于强化学习中的奖励函数&#xff0c;能对当前…

数据库三范式

MySQL系列文章 MySQL&#xff08;一&#xff09;基本架构、SQL语句操作、试图 MySQL&#xff08;二&#xff09;索引原理以及优化 MySQL&#xff08;三&#xff09;SQL优化、Buffer pool、Change buffer MySQL&#xff08;四&#xff09;事务原理及分析 MySQL&#xff08;五&a…

LoggerFactory is not a Logback LoggerContext but Logback is on the classpath

springboot项目报错如下&#xff1a; 这个错误是由于在你的Java代码中使用了Logback日志库&#xff0c;但是同时又存在与Logback竞争的其他日志库&#xff08;例如slf4j-simple&#xff09;导致的冲突。 要解决这个问题&#xff0c;你可以尝试以下几个步骤&#xff1a; 1. 检…

设计模式——享元模式

享元模式 定义 享元模式&#xff08;Flyweight Pattern&#xff09;是池技术的重要实现方式。 使用共享对象可以有效地支持大量的细粒度对象。 优缺点、应用场景 优点 可以大大减少应用程序创建对象的数量&#xff0c;降低程序内存占用。 缺点 提高了系统的复杂度&…

【杨氏矩阵】

这篇文章的对应思维导图为&#xff1a;思维导图 思维导图对应代码&#xff1a; //杨氏矩阵 #include<stdio.h>//void ysjz1(int a[3][3],int k) { // int x 0; // int y 2; // while (x < 2 && y > 0) { // if (a[x][y] > k) { // y--; // } // …

微服务系列文章 之SpringBoot之定时任务详解

序言 使用SpringBoot创建定时任务非常简单&#xff0c;目前主要有以下三种创建方式&#xff1a; 一、基于注解(Scheduled)二、基于接口&#xff08;SchedulingConfigurer&#xff09; 前者相信大家都很熟悉&#xff0c;但是实际使用中我们往往想从数据库中读取指定时间来动态…

机器学习-线性代数-5-空间中的向量投影与最小二乘法

空间中的向量投影与最小二乘法 文章目录 空间中的向量投影与最小二乘法一、引入二、投影和投影的描述1、投影描述最近2、利用矩阵描述投影(1)向一维直线投影(2)向二维平面投影(3)向n维子空间投影的一般情况 三、最小二乘法1、重要的子空间(1)互补的子空间(2)正交的子空间(3)相互…

微服务day1

一、认识微服务 1、单体架构 将业务的所有功能集中在一个项目中开发&#xff0c;打成一个包部署。 优点 架构简单部署成本低 缺点 耦合度高 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fPfsQXAn-1689593800699)(https://picture.wangkay.tec…

gitee 使用

1.打开git bash 2.cd 进入到合适位置 3.git clone 项目 4.配置用户名和email&#xff08;不然没法记录谁操作的&#xff09; pycharm &#xff08;ctrlk&#xff09;

如何设计一个注册中心?(2)实现注册接口

1. 创建SpringBoot工程 创建父工程及三个子模块&#xff0c;其中一个模块作为注册中心&#xff0c;另外两个作为服务提供者。 pom <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns…