重学Java之核心类
重学Java之核心类
一、String
Java字符串的特点:
- 字符串对象可以直接使用"..."表示
- 内容不可变
- 使用equals()判断是否相等
字符串常用操作:
- 是否包含子串
- int contains
- int indexOf/lastIndexOf
- boolean startsWith/endsWith
- 去除首尾空白字符
- trim()
- 移除首尾空白字符
- 空格、\t、\r、\n
- 不改变字符串,返回新字符串
- 提取子串:substring
- 大小写转换:
- toUpperCase/toLowerCase
- 替换子串:
- replace/replaceAll
- 分割:split
- 拼接:join
- 任意类型数据转换为String
- static String valueOf()
- String.valueOf(true) //"true"
- 把String转换为其他类型
- static int Integer.parseInt(String)
- static Integer Integer.valueOf(String)
- String转换为char[]
- char[] toCharArray()
- char[]转换为String
- new String(char[])
- String转换为byte[]
- byte[] getBytes() 不推荐
- byte[] getBytes(String)
- byte[] getBytes(Charset)
- byte[]转换为String
- new String(byte[], String)
- new String(byte[], Charset)
编码
最早的字符编码是ASCII码,一个字符占一个字节,最多表示128个字符。字符'A'的编码是0x41
中文编码:GB2132,GBK,GB 18030。一个中文字符占2个字节,第一个字节最高位是1。其它语言编码:Shift_ JIS, Euc-kr ,
......
全球统一编码: Unicode。全球所有文字都有唯一编码。一个Unicode字符通常占2个字节。Java使用Unicode编码。
有了Unicode为什么还需要UTF-8?
英文Unicode编码和ASCII不一致,同时包含大量英文的文本会浪费空间。
UTF-8编码是变长编码
- 英文UTF-8编码和ASCII一致
- 其它Unicode字符需2~6字节不等
- UTF-8编码容错能力强:
OxXXXXxx
11 OxxxXX 10xXXXXX
111 OxXxx 10xXXxXx 10xXXXXX
编码最佳实践
- Java使用Unicode编码
- Java程序运行时使用Unicode编码
- 输入输出时把String和byte[]转换,需要考虑编码
- 始终优先考虑UTF-8编码
总结
- 字符串是不可变对象
- 字符串操作不改变原字符串内容,而是返回新字符串
- 常用的字符串操作:提取子串、查找、替换、大小写转换等
- 字符串和byte[]互相转换时要注意编码,建议总是使用UTF-8编码
二、StringBuilder
String可以用"+"拼接
- 每次循环都会创建新的字符串对象
- 绝大部分都是临时对象,浪费内存:
- 影响GC效率
StringBuilder可以高效拼接字符串
- StringBuilder是可变对象
- StringBuilder可以预分配缓冲区
StringBuilder可以进行链式操作
1 2 3 4 5 6 7 |
StringBuilder sb =new StringBuilder (1024); String s = sb.append ("Mr ") .append (name) .append("!") .insert(O, "Hello, ") .toString() ; |
原理是append方法返回了this
1 2 3 |
super.append(str); return this; |
不需要特别改写字符串"+"操作
编译器在内部自动把多个连续的+操作优化为StringBuilder操作
1 2 |
String s = "Hel1o," + name + "!"; |
StringBuilder和StringBuffer
- StringBuilder和StringBuffer接口完全相同
- StringBuffer是StringBuilder的线程安全版本
- 没有必要使用StringBuffer(字符串一般很少跨线程拼接)
总结
- StringBuilder是可变对象,用来高效拼接字符串
- StringBuilder可以支持链式操作
- 实现链式操作的关键是返回实例本身
- StringBuffer是StringBuilder的线程安全版本,很少使用
三、包装类型
原理
定义一个Integer类,包含一个实例
字段int。可以把Integer视为int的包装类型
(wrapper)
1 2 3 4 5 6 7 8 9 |
public class Integer ( private int value; public Integer (int value) { this. value = value; } } Integer n = null; Integer n2 = new Integer(99); |
转换
int、Integer和String的相互转换
特别注意Integer.getlInteger(String)
是从系统环境中读取系统变量
1 2 3 4 5 6 7 8 |
int i = 100; Integer n1 = new Integer(i); Integer n2 = Integer.valueOf(i); Integer n3 = Integer.valueOf("100") ; int x1 = n1.intValue() ; int x2 = Integer.parseInt("1OO") ; String s = n1.toString(); |
整数和浮点数包装类型继承自Number
可以利用Number下面的方法相互转换
1 2 3 4 5 6 7 |
Number num = new Integer(999) ; byte b = num.byteValue(); . int n = num.intValue(); long ln = num.longValue(); float f = num.floatValue(); double d = num.doubleValue(); |
装箱拆箱
编译器可以自动在int和Integer之间转型:
自动装箱:int -> Integer
自动拆箱:Interge -> int
1 2 3 4 5 6 7 8 |
Integer n = 99; // Integer.valueOf (99) int i = n; // n.intValue() Object[] arr = new Object[1]; arr[O] = 999; // Integer.valueOf(999) Integer x = null; int y = x; // NullPointerException |
- 自动装箱和自动拆箱只发生在编译阶段
- 装箱和拆箱会影响执行效率
- 编译后的class代码是严格区分基本类型和引用类型的
- Integer -> int 执行时可能会报错
静态变量
1 2 3 4 5 6 7 |
Boolean t = Boolean.TRUE; Boolean f = Boolean.FALSE; int max = Integer.MAX_VALUE; // 2147483647 int min = Integer.MIN_VALUE; // 2147483648 int sizeOfLong = Long.SIZE; // 64 (bits) int bytesOfLong = Long.BYTES; // 8 (bytes) |
总结
JDK的包装类型可以把基本类型包装为class
自动装箱和自动拆箱是编译器完成的(JDK>=1.5)
装箱和拆箱会影响执行效率
注意拆箱时可能发生NullPointerException
四、JavaBean
定义
许多class的定义都符合:
- 若干private实例字段
- 通过public方法读写实例字段
1 2 3 4 5 6 7 8 9 |
public class Person ( private String name; private int age; public String getName() {...} public void setName (String name) {...} public int getAge() {...} public void setAge (int age) {...} ) |
符合命名规范的class被称为JavaBean
- private Type field
- public Type getField()
- public void setField(Type value)
注意方法名称的大小写
Boolean字段的读方法命名为isXXX():
通常把一组对应的getter和setter称为属性(Property)
name属性:
- 对应读方法getName()
- 对应写方法setName()
总结
JavaBean是一种符合命名规范的class
JavaBean通过: getter/setter来定义属性
属性是一种通用的叫法,并非Java语法规定
可以利用IDE快速生成getter/setter
使用Introspector.getBeanlnfo()获取属性列表
五、枚举
普通定义常量方法
编译器不能检测或检查常量的修改
1 2 3 4 5 6 7 8 |
public class Weekday{ public static final int SUN = 0; public static final String RED = "r"; } if(day == Weekday.SUN) if("r".equals(Color.RED)) |
用enum定义常量
- 关键字enum定义常量类型
- 常量本身带有类型信息
- 使用 == 比较
enum定义的类型实际上是class
- 继承自java.lang.Enum
- 不能通过new创建实例
- 所有常量都是唯一实例(引用类型)
- 可以用于switch语句
1 2 3 4 5 6 7 8 9 10 11 12 |
public enum Color{ RED, GREEN, BLUE; } //编译器编译出的class: public final class Color extends Enum{ public static final Color RED = new Color () ; public static final Color GREEN = new Color () ; public static final Color BLUE = new Color () ; private Color() {} } |
例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public enum Weekday { SUN, MON, TUE, WED, THU, FRI, SAT; } public class Main { public static void main(String[] args) { for (Weekday day : Weekday.values()) { System.out.println(day.name()); } Weekday fri = Weekday.FRI; // enum -> String: System.out.println("FRI.name() = " + fri.name()); // 定义时的序号: System.out.println("FRI.ordinal() = " + fri.ordinal()); // String -> enum: System.out.println(Weekday.valueOf("FRI").name()); // 不存在的name: Weekday.valueOf("ABC"); } } |
总结
enum可以定义常量类型,它被编译器编译为:
final class Xxx extends Enum { ... }
name()获取常量定义的字符串,注意不要使用toString()
ordinal()返回常量定义的顺序(无实质意义)
可以为enum类编写构造方法、字段和方法
构造方法申明为private
六、常用工具类
Math:数学计算
Math提供了数学计算的静态方法:
- abs/min/max
- pow / sqrt / exp / log / log10
- sin / cos / tan / asin / acos
常量:
- PI = 3.14159...
- E = 2.71828...
Random:生成伪随机数
Math.random()生成一个随机数
- 0<=随机数<1
- 可用于生成某个区间的随机数
1 2 3 4 5 6 |
// MIN <= R < MAX long MIN = 1000; long MAX = 9000 ; double x2 = Math.random() * (MAX-MIN) + MIN; double r = (long)x2; |
Random()生成一个伪随机数
- nextInt / nextLong / nextFloat...
- nextlnt(N)生成不大于N的随机数
1 2 3 4 |
Random r = new Random(); r.nextInt(); r.nextInt(10); //生成0-10之间的随机数,不包括10 |
什么是伪随机数
- 给定种子后伪随机数算法会生成完全相同的序列
- 不给定种子时Random使用系统当前时间戳作为种子
SecureRandom用来创建安全的随机
BigInteger:表示任意大小的整数
BigDecimal:表示任意精度的浮点数
总结
Math:数学计算
Random:生成伪随机数
SecureRandom:生成安全的随机数
BigInteger:表示任意大小的整数
BigDecimal:表示任意精度的浮点数
BigInteger和BigDecimal都继承自Number