将基本数据类型值作为对象处理
基本数据类型值不是一个对象 , 但是可以使用
Java API
中的包装类来包装成一个对象 。出于对性能的考虑 , 在 Java 中基本数据类型不作为对象使用, 因为处理对象需要额外
的系统开销
在Java.lang
包里为基本数据类型提供了Boolean
、Character
、Double
、Float
、Byte
、Short
、Integer
、Long
等包装类。 大多数基本类型的包装类的名称与对应的基本數据类型名称一样 , 第一个字母要大写 。Integer
和 Character
例外
- 每一个数值包装类都有常量
MAX _ VALUE
和MIN _ VALUE
- 对于
Byte 、 Short 、 Integer 、 Long
而言 ,MIN _ VALUE
表示对应的基本类型byte 、 short 、 int 、 long
的最小值 - 对
Float
和Double
类而言 ,MIN _ VALUE
表示float
型和double
型的最小正值 。
- 数值包装类有一个有用的静态方法
valueOf(String s )
。 该方法创建一个新对象 , 并将
它初始化为指定字符串表示的值。 - 每个数值包装类都有两个重载的方法 , 将数值字符串转换为正确的以 10 ( 十进制 ) 或指定值为基数 ( 例如 , 2 为二进制 , 8 为八进制 , 16 为十六进制 ) 的数值
Integer.parseInt("11", 2) returns 3;
Integer.parseInt("12", 8) returns 10;
Integer.parseInt("13", 10) returns 13;
Integer.parseInt("1A", 16) returns 26;
Integer.parseInt("12", 2) ; // error! 12不是二进制数
// 使用format方法将一个十进制数转换为十六进制数
String.format("%x", 26) returns 1A;
基本类型和包装类类型之间的自动转换
根据上下文环境 , 基本数据类型值可以使用包装类自动转换成一个对象 , 反过来的自动转换也可以
将基本类型值转换为包装类对象的过程称为装箱(boxing)
, 相反的转换过程称为开箱(unboxing)
过程:
-
Java
允许基本类型和包装类类型之间进行自动转换
。 如果一个基本类型值
出现在需要对象的环境
中 , 编译器会将基本类型值进行自动装箱
; 如果一个对象
出现在需要基本类型值的环境
, 编译器会将对象进行自动开箱
Integer[] intArray = {1, 2, 3};
System.out.println(intArray[0] + intArray[1] + intArray[2]);
- 第一行中,基本类型值1、2、3被自动装箱成对象
new Integer[1]
、new Integer[2]
、new Integer[3]
- 第二行中,对象
intArray[0]
、intArray[1]
、intArray[2]
被自动转换为int
值,然后进行相加
BigInteger
和BigDecimal
类
这两种类可以用于表示任意大小和精度的整数或者十进制数
在
java.math
包中
long
类型的最大整数值仅仅为long.MAX_VALUE(即9223372036854775807)
使用new BigInteger(String)
和new BigDecimal(String)
来创建BigInteger
和BigDecimal
的实例,有以下方法进行运算:
- 算术运算
- add
- subtract
- multiply
- divide
- remainder
- 比较
- compareTo
BigInteger a = new BigInteger("9223372036854775807");
BigInteger b = new BigInteger("2");
BigInteger c = a.multiply(b);
对 BigDecimal
对象的精度没有限制 。 如果结果不能终止 , 那么 divide
方法会抛出ArithmeticException
异常。 可以使用重载的 divide ( BigDecimal d, int scale, int roundingMode)
方法来指定尺度和舍入方式来避免这个异常, scale
是小数点后最小的整数位数
BigDecimal a = new BigDecimal(1.0);
BigDecimal b = new BigDecimal(3.0);
BigDecimal c = a.divide(b, 20, BigDecimal.ROUND_UP);
System.out.println(c);
Result:0.33333333333333333334
实例
一个整数的阶乘可能会很大。该代码可以返回任意整数阶乘的方法
import java.math.*;
public class LargeF{
public static void main(String[] args){
System.out.println("50! is \n" + F(50));
}
public static BigInteger F(long n){
BigInteger result = BigInteger.ONE; // 相当于初始化为 1
for(int i = 1; i <= n; i++){
result = result.multiply(new BigInteger(i + ""));
}
}
}
String类
String对象是不可改变的,字符串一旦创建,内容不能改变
构造字符串
可以使用字符串直接量
或者字符数组
创建一个字符串对象
创建一个字符串:String newString = new String(stringLiteral);
- 直接量方法
String message = new String("Gqq's page");
- 字符数组方法
char[] charArray = {'G', 'q', 'q', '\'', 's', ' ', 'p', 'a', 'g', 'e'};
String message = new String(charArray);
不可变字符串和限定字符串
String s = "Java";
s = "HTML"; // 这里并不能改变原始字符串内容,只是引用对象变了
限定字符串
:因为字符串在程序设计中不可变,但同时频繁使用,所以Java虚拟机
为了提高效率并节约内存,对具有相同字符序列的字符串直接量使用同一个实例,这种实例称为限定的字符串
尽管s1和s2内容相同,但它们是不同的字符串对象
字符串的替换和分隔
+ replace(oldChar: char, newChar: char): String // 将字符串中所有匹配的字符替换成新的宇符,然后返冋新的字符串
+ replaceFirst(oldChar: char, newChar: char): String // 将字符串中第一个匹配的子字符串替换成新的子字符串,然后返回新的字符串
+ replaceAll(oldChar: char, newChar: char): String // 将字符串中所有匹配的子字符串替换成新的子字符串,然后返回新的字符串
+ split(delimiter: String): String[] // 返回一个字符串数组 , 其中包含被分隔符分隔的子宇符串集
字符串一旦创建其内容就不能改变,上述方法返回一个源自原始字符串的新字符串(并没有改变原始字符串)
split 方法
可以从一个指定分隔符的字符串中提取标识
String[] tokens = "Java#HTML#PERL".split("#");
for(int i = 0; i < tokens.length; i++){
System.out.print(tokens[i] + " ");
}
Result : Java HTML PERL
依照模式匹配、替换、分隔
正则表达式(regular expression)(regex)
:是一个字符串, 用于描述匹配一个字符串集的模式。 可以通过指定某个模式来匹配 、 替换或分隔一个字符串
虽然equals
方法亦可以来判断两个字符串是否相同,但是利用matches
方法功能更加强大
"Java is fun".matches("Java.*"); // return true
"Java is powerful".matches("Java.*"); // return true
举几个例子:
"440-02-4534".matches("\\d{3}-\\d{2}-\\d{4}")
\\d表示单个数字位,\\\d{3}表示三个数字位,所以返回true
String s = "a+b#c".replaceAll("[$+#]", "NNN");
[\(+#]表示能够匹配\)、+、#的模式,所以返回aNNNbNNNNNNc
String[] tokens = "Java,C?C#,C++".split("[.,:;?]");
for(int i = 0; i < tokens.length; i++){
System.out.println(tokens[i]);
}
返回Java、C、C#、C++
字符串和数字之间的转换
字符串不是数组,但是它们可以相互转换。
toCharArray()
如:将字符串"java"转换为数组:
char[] chars = "Java".toCharArray();
此时,chars [ 0 ] 是 3
, chars [1 ] 是a
, chars [ 2 ] 是 v
, chars [ 3 ] 是a
getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
将下标从srcBegin
到 srcEnd - 1
的子串复制到字符数组 dst
中下标从 dstBegin
开始的位置 。 例如 ,下面的代码将字符串 "CS3720" 中下标从 2 到 6 - 1 的子串 " 3720 " 复制到字符数组 dst 中下标从 4 开始的位置 :
char[] dst = {'J', 'A', 'V', 'A', '1', '3', '0', '1'};
"CS3720".getChars(2, 6, dst, 4);
这样 , dst 就变成了{'J', 'A', 'V', 'A', '3', '7', '2', '0'};
- 构造方法
String(char[])
或者valueOf(char[])
String str = new String(new char[]{'J', 'A', 'V', 'A'});
String str = String.valueOf(new char[]{'J', 'A', 'V', 'A'});
将字符和数值转换成字符串
回顾下 , 可以使用 Double.parseDouble(str)
或者 Integer.parselnt(str)
将一个字符串转换为一个 double值
或者一个 int值
, 也可以使用字符串的连接操作符来将字符或者数
字转换为字符串 。 另外一种将数字转换为字符串的方法是使用重载的静态 valueOf 方法 。 该
方法可以用于将字符和数值转换成字符串
格式化字符串
String 类
包含静态format
方法 , 它可以创建一个格式化的字符串 。 调用该方法的语法是
String.format(foramt, item1, item2, ....., itemk);
如:
String s = String.format("%7.2f%6d%-4s", 45.556, 14, "AB");
显示:
注意,System.out.printf(format, item1, item2, ..., itemk);
等价于System.out.print(String.format(format, item1, item2, ..., itemk));
StringBuilder和StringBuffer类
StringBuilder和StringBuffer类似于String类,区别在于String类是不可改变,而StringBuilder或StringBuffer中可以添加、插入、追加新的内容
区别:除了 StringBuffer 中修改缓冲区的方法是同步的 , 这意味着只有一个任务被允许执
行方法之外 ,**StringBuilder 类与 StringBuffer 类是很相似的 **
- 如果是多任务并发访问 ,就使用 StringBuffer , 因为这种情况下需要同步以防止 StringBuffer 崩溃
- 如果是单任务访问 , 使用 StringBuilder 会更有效
- 在一般情况下,这两种的方法是差不多的
StringBuilder类
有 3个构造方法和30多个用于管理构建器或修改构建器内字符串的方法 。 可以使用构造方法创建一个空的构建器或从一个字符串创建一个构建器 , 如图所示 。
修改StringBuilder中的字符串
可以使用下图中列出的方法:
- 在字符串构建器的末尾追加新内容
- 在字符串构建器的特定位置插入新的内容 ,
- 还可以删除或替换字符串构建器中的字符
StringBuilder 类提供了几个重载方法 , 可以将 boolean 、 char 、 char 数组 、 double 、 float 、 int 、 long 和 String 类型值
追加到字符串构建器,如:
public class StringBuilderTest {
public static void main(String[] args) {
StringBuilder s = new StringBuilder();
s.append("Welcome");
s.append(' ');
s.append("to");
s.append(' ');
s.append("Java");
System.out.println(s);
}
}
StringBuilder 类提供了几个重载方法 , 可以将 boolean 、 char 、 char 数组 、 double 、 float 、 int 、 long 和 String 类型值
插入到字符串构建器,如:
s.insert(11, " C++ and ");
删除、倒置、代替字符串中的字符、设置新的字符
除了 setCharAt方法
之外 , 所有这些进行修改的方法都做两件事 :
- 🅰改变字符串构建器的内容
- 🅱返回字符串构建器的引用
如,StringBuilder stringBuilder1 = stringBuilder.reverse();
,将构建器中的字符倒置并把构建器的引用赋值给 stringBuilder1
。 这样,stringBuilder
和stringBuilder1
都指向同一个 StringBuffer
对象 。
注意: 如果一个字符串不需要任何改变 , 则使用 String 类
而不使用 StringBuffer 类
。Java
可以完成对 String 类
的优化 ,例如, 共享限定字符串等
toString,capacity,length,setLength,charAt方法
StringBuilder类
提供了许多其他处理字符串构建器和获取它的属性的方法
capacity()
方法返回字符串构建器当前的容量 。 容量是指在不增加构建器大小的情况下能够存储的字符数量length()
方法返回字符串构建器中实际存储的字符数量setLength(newLength)
方法设置字符串构建器的长度
- 如果参数
newLength
小于字符串构建器的当前长度 ,则字符串构建器会被截短到恰好能包含由参数newLength
给定的字符个数 - 如果参数
newLength
大于或等于当前长度, 则给字符串构建器追加足够多的空字符\u0000
, 使其长度length
变成新参数newLength
- 参数
newLength
必须大于等于0
charAt(index)
方法返回字符串构建器中某个特定下标index
的字符
注意
- 字符串的长度总是小于或等于构建器的容量
- 长度是存储在构建器中的字符串的实际大小
- 容量是构建器的当前大小
- 如果有更多的字符添加到字符串构建器,超出它的容量,则构建器的容量就会自动增加
- 在计算机内部,字符串构建器是一个字符数组,因此,构建器的容量就是数组的大小
- 如果超出构建器的容量, 就用新的数组替换现有数组。新数组的大小为
2x
(之前数组的长度+ 1
)
提示
- 可以使用
new StringBuilder(initialCapacity)
创建指定初始容量的StringBuilder
- 通过仔细选择初始容量能够使程序更有效 。
- 如果容量总是超过构建器的实际使用长度 ,JVM 将永远不需要为构建器重新分配内存 。
- 如果容量过大将会浪费内存空间, 可以使用
trimToSize()
方法将容量降到实际的大小
示例学习:判断回文串时忽略既非字母又非数字的字符
解题
- 通过删除既非字母又非数字的字符过滤这个字符串
- 倒置过滤后的字符串得到一个新字符串
- 使用 equals 方法对倒置后的字符串和过滤后的字符串进行比较
import java.util.Scanner;
public class PalindromelgnoreNonAlphanumeric {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String myString = input.nextLine();
boolean flag = isPalindrome(myString);
if(flag)
System.out.println("是满足条件的回文串\n");
else
System.out.println("不是满足条件的回文串\n");
}
public static boolean isPalindrome(String s){
String s1 = filter(s);
String s2 = reverse(s1);
return s1.equals(s2);
}
public static String filter(String s){
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < s.length(); i++){
if(Character.isLetterOrDigit(s.charAt(i))){
stringBuilder.append(s.charAt(i));
}
}
return stringBuilder.toString();
}
public static String reverse(String s){
StringBuilder stringBuilder = new StringBuilder(s);
stringBuilder.reverse(); // 反转
return stringBuilder.toString();
}
}
ab < c > cb ? a
是满足条件的回文串
abccx ? cab
不是满足条件的回文串
Write by Gqq