十六、包装类

文章目录

  • 包装类
    • 2.1 基本用法
    • 2.2 共同点
    • 2.3 剖析Character

包装类

本文为书籍《Java编程的逻辑》1和《剑指Java:核心原理与应用实践》2阅读笔记

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

基本类型包装类
booleanBoolean
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charChar

包装类有什么用呢?Java中很多代码只能操作对象,为了能操作基本类型,需要使用其对应的包装类。另外,包装类提供了很多有用的方法,可以方便对数据的操作。

2.1 基本用法

各个包装类都可以与其对应的基本类型相互转换,方法也是类似的,部分类型如下表所示。

包装类与基本类型的转换示例代码
Boleanboolean b1=false;
Boolean bObj = Boolean.valueOf(b1);
boolean b2=bObj.booleanValue();
Integerint i1=12345;
Integer iObj = Integer.valueOf(i1);
int i2=iObj.intValue();
Doubledouble d1=123.45;
Double dObj = Double.valueOf(d1);
double d2=dObj.doubleValue();
Characterchar c1=‘A’;
Character cObj = Character.valueOf(c1);
char c2=cObj.charValue();

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

将基本类型转换为包装类的过程,一般称为“装箱”,而将包装类型转换为基本类型的过程,则称为“拆箱”。装箱/拆箱写起来比较烦琐,Java 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实现代码:

// Byte@IntrinsicCandidatepublic static Byte valueOf(byte b) {final int offset = 128;return ByteCache.cache[(int)b + offset];}
// Shortpublic static Short valueOf(short s) {final int offset = 128;int sAsInt = s;if (sAsInt >= -128 && sAsInt <= 127) { // must cachereturn ShortCache.cache[sAsInt + offset];}return new Short(s);}
// Integerpublic static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}
// Long@IntrinsicCandidatepublic static Long valueOf(long l) {final int offset = 128;if (l >= -128 && l <= 127) { // will cachereturn LongCache.cache[(int)l + offset];}return new Long(l);}
// Character@IntrinsicCandidatepublic static Character valueOf(char c) {if (c <= 127) { // must cachereturn CharacterCache.cache[(int)c];}return new Character(c);}
// Boolean@IntrinsicCandidatepublic static Boolean valueOf(boolean b) {return (b ? TRUE : FALSE);}
// Double@IntrinsicCandidatepublic static Double valueOf(double d) {return new Double(d);}
// Floatpublic static Float valueOf(float f) {return new Float(f);}

从上面的代码可以知道,除了FloatDouble外的其他包装类,都会缓存包装类对象,减少需要创建对象的次数,节省空间,提升性能,这种机制称为包装类缓存机制。所以,一般都建议使用valueOf而不是new新建包装类。

包装类缓存对象范围如下表所示:

序号包装类缓存范围
1Byte[-128,127]
2Short[-128,127]
3Integer[-128,127]
4Long[-128,127]
5Character[0,127]
6Booleantrue 和 false

2.2 共同点

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

1、重写Object方法

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

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

(1)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。现在看下面代码:

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 1 1Doubleequals方法与Float类似,它有一个静态方法doubleToLongBits,将double的二进制表示看作long,然后再按long比较。

(2)hashCode

hashCode返回一个对象的哈希值。哈希值是一个int类型的数,由对象中一般不变的属性映射得来,用于快速对对象进行区分、分组等。一个对象的哈希值不能改变,相同对象的哈希值必须一样。不同对象的哈希值一般应不同,但这不是必需的,可以有对象不同但哈希值相同的情况。

包装类都重写了hashCode,根据包装的基本类型值计算hashCode,对于ByteShortIntegerCharacter, hashCode就是其内部值,代码为:

public int hashCode() {return (int)value;
}

对于BooleanhashCode代码为:

public int hashCode() {return value ? 1231 : 1237;
}

根据基类类型值返回了两个不同的数,为什么选这两个值呢?它们是质数(即只能被 1 1 1和自己整除的数),质数用于哈希时比较好,不容易冲突。

对于LonghashCode代码为:

public int hashCode() {return(int)(value ^ (value >>> 32));
}

是高 32 32 32位与低 32 32 32位进行位异或操作。

对于FloathashCode代码为:

public int hashCode() {return floatToIntBits(value);
}

equals方法类似,将float的二进制表示看作int。对于DoublehashCode代码为:

public int hashCode() {long bits = doubleToLongBits(value);return(int)(bits ^ (bits >>> 32));
}

equals方法类似,将double的二进制表示看作long,然后再按long计算hashCode

(3)toString

每个包装类也都重写了toString方法,返回对象的字符串表示,这个一般比较自然,不详细叙述。

2、Comparable

每个包装类都实现了Java API中的Comparable接口。Comparable接口代码如下:

public interface Comparable<T> {public int compareTo(T o);
}

<T>是泛型语法,T表示比较的类型,由实现接口的类传入。接口只有一个方法compareTo,当前对象与参数对象进行比较,在小于、等于、大于参数时,应分别返回 − 1 -1 1 0 0 0 1 1 1。各个包装类的实现基本都是根据基本类型值进行比较,不再赘述。对于Booleanfalse小于true

3、包装类和String

除了toString方法外,包装类还有一些其他与String相关的方法。除了Character外,每个包装类都有一个静态的valueOf(String)方法,根据字符串表示返回包装类对象,如:

Boolean b = Boolean.valueOf("true");
Float f = Float.valueOf("123.45f");

也都有一个静态的parseⅩⅩⅩ(String)方法,根据字符串表示返回基本类型值,如:

boolean b = Boolean.parseBoolean("true");
double d = Double.parseDouble("123.45");

都有一个静态的toString方法,根据基本类型值返回字符串表示,如:

System.out.println(Boolean.toString(true));
System.out.println(Double.toString(123.45));

对于整数类型,字符串表示除了默认的十进制外,还可以表示为其他进制,如二进制、八进制和十六进制,包装类有静态方法进行相互转换,比如:

System.out.println(Integer.toBinaryString(12345));       //输出二进制
System.out.println(Integer.toHexString(12345));          //输出十六进制
System.out.println(Integer.parseInt("3039", 16));        //按十六进制解析

4、常用常量

包装类中除了定义静态方法和实例方法外,还定义了一些静态变量。对于Boolean类型,有:

public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);

所有数值类型都定义了MAⅩ_VALUEMIN_VALUE,表示能表示的最大/最小值,比如,对Integer

public static final int MIN_VALUE = 0x80000000;
public static final int MAX_VALUE = 0x7fffffff;

FloatDouble还定义了一些特殊数值,比如正无穷、负无穷、非数值,如Double类:

public static final double POSITIVE_INFINITY = 1.0 / 0.0; //正无穷
public static final double NEGATIVE_INFINITY = -1.0 / 0.0; //负无穷
public static final double NaN = 0.0d / 0.0; //非数值

5、Number

6 6 6种数值类型包装类有一个共同的父类NumberNumber是一个抽象类,它定义了如下方法:

byte byteValue()
short shortValue()
int intValue()
long longValue()
float floatValue()
double doubleValue()

通过这些方法,包装类实例可以返回任意的基本数值类型。

6、不可变性

包装类都是不可变类。所谓不可变是指实例对象一旦创建,就没有办法修改了。这是通过如下方式强制实现的:

  • 所有包装类都声明为了final,不能被继承。
  • 内部基本类型值是私有的,且声明为了final
  • 没有定义setter方法。

为什么要定义为不可变类呢?不可变使得程序更为简单安全,因为不用操心数据被意外改写的可能,可以安全地共享数据,尤其是在多线程的环境下。

2.3 剖析Character

Character类除了封装了一个char外,还有很多静态方法,封装了Unicode字符级别的各种操作,是Java文本处理的基础,注意不是char级别,Unicode字符并不等同于char

1、Unicode基础

Unicode给世界上每个字符分配了一个编号,编号范围为0x000000~0x10FFFF。编号范围在0x0000~0xFFFF的字符为常用字符集,称BMPBasic Multilingual Plane)字符。编号范围在0x10000~0x10FFFF的字符叫做增补字符(supplementary character)。Unicode主要规定了编号,但没有规定如何把编号映射为二进制。

UTF-16是一种编码方式,或者叫映射方式,它将编号映射为 2 2 2个或 4 4 4个字节,对BMP字符,它直接用两个字节表示,对于增补字符,使用 4 4 4个字节表示,前两个字节叫高代理项(high surrogate),范围为0xD800~0xDBFF,后两个字节叫低代理项(lowsurrogate),范围为0xDC00~0xDFFFUTF-16定义了一个公式,可以将编号与 4 4 4​字节表示进行相互转换。Java内部采用UTF-16编码,char表示一个字符,但只能表示BMP中的字符,对于增补字符,需要使用两个char表示,一个表示高代理项,一个表示低代理项。

java为什么选择UTF-16呢?曾经,大家天真地认为两个字节( 16 16 16位二进制)足以表示一切字符,所以就为Unicode规定了UTF-8UCS-2(即UTF-16的旧标准) 这两种编码,UTF-8是兼容ASCIIUCS-2是定长编码。后来发现错了:两个字节根本存不下一切字符,需要四个字节( 32 32 32​​位二进制)来储存一切字符。于是Unicode新标准规定UTF-8UTF-16UTF-32三种编码,UTF-8是兼容 ASCIIUTF-32是定长编码,而UTF-16则是为了向下兼容旧标准(UCS-2),重新规定成了一个 既不兼容ASCII 又是变长编码 的方案。而Java由于过早地尝试去支持Unicode,使用了UCS-2来储存String ,当时的目的也是为了定长编码。结果Unicode新标准出来,UCS-2升级成UTF-16,成了变长编码。这下Java也改不了了。

2、检查 code point 和 char

// 判断一个 int 是不是一个有效的代码点,小于等于 0x10FFFF 的为有效,大于的为无效
public static boolean isValidCodePoint(int codePoint)
// 判断一个 int 是不是 BMP 字符,小于等于 0xFFFF 的为 BMP 字符,大于的不是
public static boolean isBmpCodePoint(int codePoint)
// 判断一个 int 是不是增补字符,0x010000~0X10FFFF 为增补字符
public static boolean isSupplementaryCodePoint(int codePoint)
// 判断 char 是否是高代理项,0xD800~0xDBFF 为高代理项
public static boolean isHighSurrogate(char ch)
// 判断 char 是否为低代理项,0xDC00~0xDFFF 为低代理项
public static boolean isLowSurrogate(char ch)
// 判断 char 是否为代理项,char 为低代理项或高代理项,则返回 true
public static boolean isSurrogate(char ch)
// 判断两个字符 high 和 low 是否分别为高代理项和低代理项
public static boolean isSurrogatePair(char high, char low)
// 判断一个代码点由几个 char 组成,增补字符返回 2, BMP 字符返回 1
public static int charCount(int codePoint)

3、code point和char转换

// 根据高代理项 high 和低代理项 low 生成代码点,这个转换有个公式,这个方法封装了这个公式
public static int toCodePoint(char high, char low)
// 根据代码点生成 char 数组,即 UTF-16 表示,如果 code point 为 BMP 字符,则返回的char
// 数组长度为1,如果为增补字符,长度为 2, char[0] 为高代理项,char[1] 为低代理项
public static char[] toChars(int codePoint)
// 将代码点转换为 char 数组,与上面方法类似,只是结果存入指定数组 dst 的指定位置 index
public static int toChars(int codePoint, char[] dst, int dstIndex)
// 对增补字符 code point,生成低代理项
public static char lowSurrogate(int codePoint)
// 对增补字符 code point,生成高代理项
public static char highSurrogate(int codePoint)

4、按code point 处理 char 数组或序列

Character包含若干方法,以方便按照code point处理char数组或序列。

返回char数组a中从offset开始count个char包含的code point个数:

public static int codePointCount(char[] a, int offset, int count)

比如,如下代码输出为 2 2 2, char个数为 3 3 3,但code point为2。

char[] chs = new char[3];
chs[0] = '马';
Character.toChars(0x1FFFF, chs, 1);
System.out.println(Character.codePointCount(chs, 0, 3));

除了接受char数组,还有一个重载的方法接受字符序列CharSequence

public static int codePointCount(CharSequence seq, int beginIndex, int endIndex)

CharSequence是一个接口,它的定义如下所示:

public interface CharSequence {int length();char charAt(int index);CharSequence subSequence(int start, int end);public String toString();
}

它与一个char数组是类似的,有length方法,有charAt方法根据索引获取字符,String类就实现了该接口。

返回char数组或序列中指定索引位置的code point

public static int codePointAt(char[] a, int index)
public static int codePointAt(char[] a, int index, int limit)
public static int codePointAt(CharSequence seq, int index)

如果指定索引位置为高代理项,下一个位置为低代理项,则返回两项组成的codepoint,检查下一个位置时,下一个位置要小于limit,没传limit时,默认为a.length

返回char数组或序列中指定索引位置之前的code point:

public static int codePointBefore(char[] a, int index)
public static int codePointBefore(char[] a, int index, int start)
public static int codePointBefore(CharSequence seq, int index)

codePointAt是往后找,codePointBefore是往前找,如果指定位置为低代理项,且前一个位置为高代理项,则返回两项组成的code point,检查前一个位置时,前一个位置要大于等于start,没传start时,默认为 0 0 0

根据code point偏移数计算char索引:

public static int offsetByCodePoints(char[] a, int start, int count, int index, int codePointOffset)
public static int offsetByCodePoints(CharSequence seq, int index, int codePointOffset)

如果字符数组或序列中没有增补字符,返回值为index+codePointOffset,如果有增补字符,则会将codePointOffset看作code point偏移,转换为字符偏移,startcount取字符数组的子数组。比如,如下代码:

char[] chs = new char[3];
Character.toChars(0x1FFFF, chs, 1);
System.out.println(Character.offsetByCodePoints(chs, 0, 3, 1, 1));

输出结果为 3 3 3indexcodePointOffset都为1,但第二个字符为增补字符,一个code point偏移是两个char偏移,所以结果为 3 3 3

5、字符属性

Unicode在给每个字符分配一个编号之外,还分配了一些属性,Character类封装了对Unicode字符属性的检查和操作,下面介绍一些主要的属性。

获取字符类型(general category):

public static int getType(int codePoint)
public static int getType(char ch)

Unicode给每个字符分配了一个类型,这个类型是非常重要的,很多其他检查和操作都是基于这个类型的。getType方法的参数可以是int类型的code point,也可以是char类型。char类型只能处理BMP字符,而int类型可以处理所有字符。返回值是int,表示类型,Character类中定义了很多静态常量表示这些类型,下面代码列出了type值。

    /*** General category "Cn" in the Unicode specification.* @since   1.1*/public static final byte UNASSIGNED = 0;/*** General category "Lu" in the Unicode specification.* @since   1.1*/public static final byte UPPERCASE_LETTER = 1;/*** General category "Ll" in the Unicode specification.* @since   1.1*/public static final byte LOWERCASE_LETTER = 2;/*** General category "Lt" in the Unicode specification.* @since   1.1*/public static final byte TITLECASE_LETTER = 3;/*** General category "Lm" in the Unicode specification.* @since   1.1*/public static final byte MODIFIER_LETTER = 4;/*** General category "Lo" in the Unicode specification.* @since   1.1*/public static final byte OTHER_LETTER = 5;/*** General category "Mn" in the Unicode specification.* @since   1.1*/public static final byte NON_SPACING_MARK = 6;/*** General category "Me" in the Unicode specification.* @since   1.1*/public static final byte ENCLOSING_MARK = 7;/*** General category "Mc" in the Unicode specification.* @since   1.1*/public static final byte COMBINING_SPACING_MARK = 8;/*** General category "Nd" in the Unicode specification.* @since   1.1*/public static final byte DECIMAL_DIGIT_NUMBER = 9;/*** General category "Nl" in the Unicode specification.* @since   1.1*/public static final byte LETTER_NUMBER = 10;/*** General category "No" in the Unicode specification.* @since   1.1*/public static final byte OTHER_NUMBER = 11;/*** General category "Zs" in the Unicode specification.* @since   1.1*/public static final byte SPACE_SEPARATOR = 12;/*** General category "Zl" in the Unicode specification.* @since   1.1*/public static final byte LINE_SEPARATOR = 13;/*** General category "Zp" in the Unicode specification.* @since   1.1*/public static final byte PARAGRAPH_SEPARATOR = 14;/*** General category "Cc" in the Unicode specification.* @since   1.1*/public static final byte CONTROL = 15;/*** General category "Cf" in the Unicode specification.* @since   1.1*/public static final byte FORMAT = 16;/*** General category "Co" in the Unicode specification.* @since   1.1*/public static final byte PRIVATE_USE = 18;/*** General category "Cs" in the Unicode specification.* @since   1.1*/public static final byte SURROGATE = 19;/*** General category "Pd" in the Unicode specification.* @since   1.1*/public static final byte DASH_PUNCTUATION = 20;/*** General category "Ps" in the Unicode specification.* @since   1.1*/public static final byte START_PUNCTUATION = 21;/*** General category "Pe" in the Unicode specification.* @since   1.1*/public static final byte END_PUNCTUATION = 22;/*** General category "Pc" in the Unicode specification.* @since   1.1*/public static final byte CONNECTOR_PUNCTUATION = 23;/*** General category "Po" in the Unicode specification.* @since   1.1*/public static final byte OTHER_PUNCTUATION = 24;/*** General category "Sm" in the Unicode specification.* @since   1.1*/public static final byte MATH_SYMBOL = 25;/*** General category "Sc" in the Unicode specification.* @since   1.1*/public static final byte CURRENCY_SYMBOL = 26;/*** General category "Sk" in the Unicode specification.* @since   1.1*/public static final byte MODIFIER_SYMBOL = 27;/*** General category "So" in the Unicode specification.* @since   1.1*/public static final byte OTHER_SYMBOL = 28;/*** General category "Pi" in the Unicode specification.* @since   1.4*/public static final byte INITIAL_QUOTE_PUNCTUATION = 29;/*** General category "Pf" in the Unicode specification.* @since   1.4*/public static final byte FINAL_QUOTE_PUNCTUATION = 30;

检查字符是否在Unicode中被定义:

public static boolean isDefined(int codePoint)

每个被定义的字符,其getType()返回值都不为 0 0 0,如果返回值为 0 0 0,表示无定义。注意与isValidCodePoint的区别,后者只要数字不大于``0x10FFFF`都返回true。

检查字符是否为数字:

public static boolean isDigit(int codePoint)

getType()返回值为DECIMAL_DIGIT_NUMBER的字符为数字。需要注意的是,不光字符 0 0 0 1 1 1、……、 9 9 9是数字,中文全角字符的0~9也是数字。

检查是否为字母(Letter):

public static boolean isLetter(int codePoint)

如果getType()的返回值为下列之一,则为Letter

UPPERCASE_LETTER
LOWERCASE_LETTER
TITLECASE_LETTER
MODIFIER_LETTER
OTHER_LETTER

检查是否为字母或数字:

public static boolean isLetterOrDigit(int codePoint)

只要其中之一返回true就返回true

检查是否为字母(Alphabetic):

public static boolean isAlphabetic(int codePoint)

这也是检查是否为字母,与isLetter的区别是:isLetter返回true时,isAlphabetic也必然返回true;此外,getType()值为LETTER_NUMBER时,isAlphabetic也返回true,而isLetter返回falseLETTER_NUMBER中常见的字符有罗马数字字符,如I

检查是否为空格字符:

public static boolean isSpaceChar(int codePoint)

getType()值为SPACE_SEPARATORLINE_SEPARATORPARAGRAPH_SEPARATOR时,返回true。这个方法其实并不常用,因为它只能严格匹配空格字符本身,不能匹配实际产生空格效果的字符,如Tab控制键\t

更常用的检查空格的方法:

public static boolean isWhitespace(int codePoint)

\t\n、全角空格’ ‘和半角空格’ '的返回值都为true

检查是否为小写字符:

public static boolean isLowerCase(int codePoint)

常见的小写字符主要是小写英文字母a~z

检查是否为大写字符:

public static boolean isUpperCase(int codePoint)

常见的大写字符主要是大写英文字母A~Z

检查是否为表意象形文字:

public static boolean isIdeographic(int codePoint)

大部分中文都返回为true

检查是否为ISO 8859-1编码中的控制字符:

public static boolean isISOControl(int codePoint)

检查是否可作为Java标识符的第一个字符:

public static boolean isJavaIdentifierStart(int codePoint)

Java标识符是Java中的变量名、函数名、类名等,字母(Alphabetic)、美元符号($)、下画线(_)可作为Java标识符的第一个字符,但数字字符不可以。

检查是否可作为Java标识符的中间字符:

public static boolean isJavaIdentifierPart(int codePoint)

相比isJavaIdentifierStart,主要多了数字字符,Java标识符的中间字符可以包含数字。

检查是否为镜像(mirrowed)字符:

public static boolean isMirrored(int codePoint)

常见镜像字符有( ){ }< >[ ],都有对应的镜像。

6、字符转换

Unicode除了规定字符属性外,对有大小写对应的字符,还规定了其对应的大小写;对有数值含义的字符,也规定了其数值。

我们先来看大小写,Character有两个静态方法,对字符进行大小写转换:

public static int toLowerCase(int codePoint)
public static int toUpperCase(int codePoint)

这两个方法主要针对英文字符a~zA~Z,由大写转为小写,由小写转为大写。

返回一个字符表示的数值:

public static int getNumericValue(int codePoint)

字符’0’~’9’返回数值0~9,对于字符a~z,无论是小写字符还是大写字符,无论是普通英文还是中文全角,数值结果都是10~35

返回按给定进制表示的数值:

public static int digit(int codePoint, int radix)

radix表示进制,常见的有二进制、八进制、十进制、十六进制,计算方式与getNumericValue类似,只是会检查有效性,数值需要小于radix,如果无效,返回 − 1 -1 1。例如:digit('F',16)返回 15 15 15,是有效的;但digit('G',16)就无效,返回 − 1 -1 1

返回给定数值的字符形式:

public static char forDigit(int digit, int radix)

digit(int codePoint, int radix)相比,进行相反转换,如果数字无效,返回'\0'。例如, Character.forDigit(15, 16)返回'F'

Integer类似,Character也有按字节翻转:

public static char reverseBytes(char ch)

例如,翻转字符0x1234

System.out.println(Integer.toHexString(Character.reverseBytes((char)0x1234)));

输出为 3412 3412 3412


  1. 马俊昌.Java编程的逻辑[M].北京:机械工业出版社,2018. ↩︎

  2. 尚硅谷教育.剑指Java:核心原理与应用实践[M].北京:电子工业出版社,2023. ↩︎

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

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

相关文章

SpirngBoot整合Redis解决缓存穿透、缓存击穿、缓存雪崩问题

一、Redis缓存 Redis是一个高性能的键值对存储数据库&#xff0c;也是一个基于内存的数据结构存储系统&#xff0c;同时也支持持久化数据存储。Redis提供了丰富的数据结构&#xff0c;包括字符串、哈希、列表、集合、有序集合等。在缓存方面&#xff0c;Redis最大的优点就是支持…

回避型人格适合什么职业?如何改善回避型人格?

回避型人格最突出的特点,就是对外界的排斥极度敏感&#xff0c;他们非常害怕别人的不认可&#xff0c;也特别害惧失败&#xff0c;因此不敢与人交往&#xff0c;同时也害怕新事物。因为受到这一性格的影响&#xff0c;他们极度缺乏社交能力&#xff0c;也一直在否定自身能力。 …

Flutter框架性泛学习系列之二、Flutter应用层(Application Layer)上-常用Widgets与简单动画

文章目录 概述一、应用程序&#xff08;Application&#xff09;&#xff1a;1、创建应用对象2、定义应用主页 二、Widgets&#xff1a;1. 基础的内置Widgets应用1.1 Text Widget1.2 RaisedButton Widget1.3 Image Widget1.4 Icon Widget 2. 自定义Widgets的创建与应用2.1 创建…

网络协议汇总

1.HTTP协议 1.认识URL 平时我们俗称的 "网址" 其实就是说的 URL URL中的字符只能是ASCII字符&#xff0c;但是ASCII字符比较少&#xff0c;而URL则常常包含ASCII字符集以外的字符&#xff0c;如非英语字符、汉字、特殊符号等等&#xff0c;所以要对URL进行转换。这个…

已解决Application run failed org.springframework.beans.factory.BeanNot

问题原因&#xff1a;SpringBoot的版本与mybiats-puls版本不对应且&#xff0c;spring自带的mybiats与mybiats-puls版本不对应 这里我用的是3.2.2版本的SpringBoot&#xff0c;之前mybiats-puls版本是3.5.3.1有所不同。 问题&#xff1a;版本对不上 解决办法&#xff1a;完整…

将JWT令牌存储到浏览器中localStorage中,并且往页面请求头中添加token

将JWT令牌存储到浏览器中localStorage中 localStorage.setItem(token, response.data.data) 其中response.data.data是后端返回的数据为jwt字符串 往页面请求头中添加token 在vue中的main.js添加如下再带&#xff0c;axios便会拦截所有请求并且如果localStorage有token则会…

宝塔nginx配置SpringBoot服务集群代理

宝塔nginx配置SpringBoot服务集群代理 1、需求&#xff1a; 现有一个springboot服务需要部署成集群&#xff0c;通过nginx负载均衡进行访问&#xff0c;其中这个springboot服务内置了MQTT服务、HTTP服务、TCP服务。 MQTT服务开放了1889端口 HTTP服务开放了8891端口 HTTP服务开…

LeetCode94.二叉树的中序遍历

题目 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 示例 &#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,3,2] 思路 中序遍历的顺序是左子树 -> 根节点 -> 右子树。因此&#xff0c;我们可以通过递归的方式遍历二叉树&…

《白话C++》第8章 8.4.1 INI文件简介,8.4.2面向过程的设计 Page 761

以下是一个INI例子文件的内容&#xff1a; [DISPLAY_SETTING] #是否显示启动窗口&#xff1a; will_show_splash_window yes default_title welcom... [NETWORK_SETTING] svc_host www.d2school.com svc_port 80 带中括号的行代表一个“配置段&#xff08;section&#x…

[word] word 怎样批量把英文单词的首字母全部改成大写 #笔记#其他#学习方法

word 怎样批量把英文单词的首字母全部改成大写 word在处理长文档的过程中&#xff0c;有时候一个单词在多页重复出现。如果要把该单词的首字母改成大写&#xff0c;如果一个一个的改&#xff0c;费时费力。 方法&#xff1a;替换功能 如&#xff1a;我要把camtasia批量改成C…

【riscv】使用qemu运行riscv裸机freestanding程序

文章目录 1. 运行显示2. 工具准备3. 裸机代码和编译3.1 源码3.2 编译 4. 使用qemu仿真运行riscv裸机程序 1. 运行显示 详见左下角&#xff0c; 运行时串口输出的字符 A ; 2. 工具准备 # for riscv64-linux-gnu-gcc sudo apt-get install gcc-riscv64-linux-gnu# for qemu-s…

P6279 题解

P6279 题解 Overview 结论&#xff08;待论证&#xff09; Description 给定一个有向图&#xff0c;这个有向图的每一个点所连接的点都属于同一个集合。 求集合数量最大且字典序最小的集合标号方案。 Solution 先讲结论。 结论&#xff1a;用 vector 存储每个点所连接的…

Spring Cloud Sleuth:分布式链路跟踪

1. 理解分布式链路跟踪 1.1 什么是分布式链路跟踪 在分布式系统中&#xff0c;由于服务间的调用涉及多个节点和网络通信&#xff0c;出现问题时追踪问题的根源变得异常困难。分布式链路跟踪是一种技术&#xff0c;旨在解决这个问题。它允许开发人员追踪分布式系统中请求的流转…

C#是什么?可以用来做什么?

C#是什么&#xff1f;可以用来做什么&#xff1f; C#简介 C#&#xff08;读作“C Sharp”&#xff09;是一种容易使用不复杂新型的编程语言&#xff0c;不仅是面向对象&#xff0c;它的类型还安全。C# 源于 C 语言系列&#xff0c;C、C、Java 和 JavaScript 程序员很快就可以上…

适用于高云FPGA的JTAG

目标板卡&#xff1a;小梅哥芯海无涯GOWIN高云ACG525(GW5A-LV25UG324) 1.软件要求&#xff1a;必须用商业版&#xff0c;因为教育版(V1.9.9Beta-4 Education)不支持此封装的GW5A。商业版需要上网申请License&#xff0c;此处提供D4D853392AD8.lic文件&#xff08;此方法为临时…

Linux ----防火墙值SNAT与DNAT

一、SNAT ①SNAT 应用环境: 局域网主机共享单个公网IP地址接入Internet (私有IP不能在Internet中正常路由) ②SNAT原理: 源地址转换&#xff0c;根据指定条件修改数据包的源IP地址&#xff0c;通常被叫做源映射 数据包从内网发送到公网时&#xff0c;SNAT会把数据包的源IP由…

基于stm32F103的蜂鸣器周期发声实验

蜂鸣器作为一种声音报警器件,应用广泛。本实验基于stm32F103单片机,通过控制蜂鸣器的IO口电平电压,使其周期性地进行电平翻转,从而驱动蜂鸣器发出周期性的鸣叫声。该实验主要运用了stm32的GPIO和定时器TIM的相关功能,不仅可以巩固这些外设的使用,也可以通过改变时间参数,控制蜂…

档案数字化加工涉密资质申请

等级介绍 涉密印制资质分为甲级和乙级两个等级。甲级资质单位可以从事绝密级、机密级和秘密级涉密印制业务。乙级资质单位可以从事机密级、秘密级涉密印制业务。 类别介绍 涉密印制资质包括涉密文件资料、国家统一考试试卷、涉密防伪票据证书、涉密光电磁介质、 涉…

题目 1138: C语言训练-求矩阵的两对角线上的元素之和

问题描述&#xff1a; 求矩阵的两对角线上的元素之和 样例输入&#xff1a; 3 1 2 3 4 5 6 7 8 9 样例输出&#xff1a; 25 问题分析&#xff1a; 因为奇数阶矩阵的主对角线和副对角线上的元素有重复&#xff0c;偶数阶矩阵的主对角线和副对角线上的元素无重复&#x…

软件测试面试题汇总

一、面试基础题 简述测试流程: 1、阅读相关技术文档&#xff08;如产品PRD、UI设计、产品流程图等&#xff09;。 2、参加需求评审会议。 3、根据最终确定的需求文档编写测试计划。 4、编写测试用例&#xff08;等价类划分法、边界值分析法等&#xff09;。 5、用例评审(…