第7 章 : Java基础类库

26 StringBuffer类

String有两个常量池:
静态常量池,运行时常量池

String对象实例化直接赋值形式,可以保存到常量池中以便重用

// 构造方法
public StringBuffer(String str)

// 追加
public synchronized StringBuffer append(String str)

// 插入
public synchronized StringBuffer insert(int offset, String str)

// 删除指定范围数据
public synchronized StringBuffer delete(int start, int end)

// 字符串内容反转
public synchronized StringBuffer reverse()

代码示例

class Demo{
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("hello");
        sb.append(" world");
        System.out.println(sb.toString());
        // hello world
    }
}

String 转换为 StringBuffer 使用构造方法
StringBuffer 转换为 String 使用toString

操作示例

class Demo{
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("hello");

        // 可以连续操作
        sb.append(" ").append("world");
        System.out.println(sb.toString());
        // hello world

        // 插入
        sb.insert(5, " Java");
        System.out.println(sb);
        // hello Java world

        // 删除
        sb.delete(5, 10);
        System.out.println(sb);
        // hello world

        // 反转
        sb.reverse();
        System.out.println(sb);
        // dlrow olleh

    }
}

类似功能类 StringBuilder
JDK >= 1.5

区别
String 字符串,内容不可修改
StringBuffer JDK>=1.0 线程安全, 使用了synchronized
StringBuilder JDK>=1.5 非线程安全

27 CharSequence接口

CharSequence描述字符串结构的接口

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence

public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence

public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence

CharSequence接口方法

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

28 AutoCloseable接口

AutoCloseable接口 用于资源的自动关闭
JDK >= 1.7

public interface AutoCloseable {
    void close() throws Exception;
}

不使用自动关闭代码示例

interface IMessage{
    public void send();
}

class MessageImpl implements IMessage{
    private String message;

    public MessageImpl(String message) {
        this.message = message;
    }

    @Override
    public void send() {
        System.out.println("发送消息: " + this.message);
    }

    public boolean open(){
        System.out.println("打开资源");
        return true;
    }

    public void close(){
        System.out.println("关闭资源");
    }
}

class Demo{
    public static void main(String[] args) {
        MessageImpl message = new MessageImpl("消息内容");
        if(message.open()){
            message.send();
            message.close();
        }
        /**
         * 打开资源
         * 发送消息: 消息内容
         * 关闭资源
         */

    }
}

结合异常处理语句实现资源自动关闭

interface IMessage extends AutoCloseable{
    public void send();
}

class MessageImpl implements IMessage{
    private String message;

    public MessageImpl(String message) {
        this.message = message;
    }

    @Override
    public void send() {
        System.out.println("发送消息: " + this.message);
    }

    public boolean open(){
        System.out.println("打开资源");
        return true;
    }

    public void close(){
        System.out.println("关闭资源");
    }
}

class Demo{
    public static void main(String[] args) {
        try(MessageImpl message = new MessageImpl("消息内容")){
            if(message.open()){
                message.send();
            }
        }catch(Exception e){

        }

        /**
         * 打开资源
         * 发送消息: 消息内容
         * 关闭资源
         */

    }
}

29 Runtime类

Runtime描述运行时状态
一个JVM进程只允许提供一个Runtime,使用了单例设计模式
可以使用静态方法获取实例化对象

public static Runtime getRuntime()
class Demo {
    public static void main(String[] args) {
        Runtime run = Runtime.getRuntime();

        // 读取CPU内核数量
        System.out.println(run.availableProcessors());
        //  8

        // 获取最大可用内存空间 1/4
        System.out.println(run.maxMemory());

        // 获取可用内存空间 1/64
        System.out.println(run.totalMemory());

        // 获取空闲内存空间
        System.out.println(run.freeMemory());

        // 手工进行GC处理
        run.gc();

    }
}

GC (Garbage Collector) 垃圾收集器
由系统自动调用
或者使用Runtime类中的gc()方法,手工清除

30 System类

常用方法

// 数组拷贝
public static native void arraycopy(Object src,  int  srcPos,
                                    Object dest, int destPos,
                                    int length);

// 获取时间数值
System.out.println(System.currentTimeMillis());
// 1573918888172

// 垃圾回收
public static void gc() {
    Runtime.getRuntime().gc();
}

31 Cleaner类

JDK>=1.9
Cleaner类提供对象清理操作
替代finialize()方法
C++提供了构造函数,析构函数
Java垃圾使用GC回收

class Demo {
    public Demo() {
        System.out.println("构造函数");
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("垃圾回收");
        super.finalize();
    }

    public static void main(String[] args) {
        Demo demo = new Demo();
        demo = null;
        System.gc();
        /**
         * 构造函数
         * 垃圾回收
         */
    }
}

不建议使用 finalize()方法, 使用AutoCloseable接口
使用Cleaner类,使用单独的线程去回收资源,能提高整体性能

32 对象克隆

protected native Object clone() throws CloneNotSupportedException;

// 只有接口名,没有任何方法,只是能力标识接口
public interface Cloneable {
}

接口作用:
标准
能力

class Demo implements Cloneable{
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public static void main(String[] args) {
        Demo demo = new Demo();
        Demo demo2 = null;

        try {
            demo2 = (Demo)demo.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }

        System.out.println(demo);
        System.out.println(demo2);
        /**
         * Demo@2503dbd3
         * Demo@4b67cf4d
         */
    }
}

第8 章 : 数字操作类

33 Math数学计算类

Math提供的方法都是static方法,都是基本数学公式

Math.abs(-10) // 10
Math.max(10, 1) // 10
Math.pow(10, 2) //100.0
Math.sqrt(9) //3.0
Math.round(10.4) // 10
Math.round(10.5) // 11
class MathUtil {
    private MathUtil() {
    }

    // 自定义保留位数
    public static double round(double num, int scale) {
        return Math.round(num * Math.pow(10, scale)) / Math.pow(10, scale);
    }
}


class Demo {
    public static void main(String[] args) {
        System.out.println(MathUtil.round(10.98766, 2)); // 10.99

    }
}

34 Random随机数生成类

import java.util.Random;

class Demo {
    public static void main(String[] args) {

        Random random = new Random();
        // 产生随机数范围[0, 10)
        System.out.println(random.nextInt(10));

    }
}

彩票号码生成示例

import java.util.Random;

/**
 * 随机示例
 * 36 选 7
 */
class Demo {
    public static int[] getCodeList(){
        int[] data = new int[7];
        int foot = 0;
        Random random = new Random();

        while (foot<7){
            int code = random.nextInt(37);
            if(isUse(code, data)){
                data[foot++] = code;
            }
        }
        return data;
    }

    // 检查号码是否可以使用,不能为0,不能重复
    public static boolean isUse(int code, int[] temp){
        if(code == 0){
            return false;
        }

        for(int x : temp){
            if(code == x){
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        int[] data = getCodeList();

        for(int x : data){
            System.out.print(x + ", ");
        }
        // 15, 19, 9, 11, 33, 2, 21, 

    }
}

35 大数字处理类

可以使用String保存,不过操作麻烦

继承体系

Object
    -Number
        -Integer
        -Byte
        -Long
        -Short
        -Float
        -Double
        -BigInteger
        -BigDecimal
    -Boolean
    -Character

BigInteger 和 BigDecimal使用方法基本相似

过大的数据也会影响程序性能,优先使用基础数据类型

减法运算

import java.math.BigInteger;

class Demo{
    public static void main(String[] args) {
        BigInteger big1 = new BigInteger("98960973126687599871");
        BigInteger big2 = new BigInteger("98960973126687599872");

        System.out.println(big2.subtract(big1));
        // 1
    }
}

求余运算

import java.math.BigInteger;

class Demo{
    public static void main(String[] args) {
        BigInteger big1 = new BigInteger("1001");
        BigInteger big2 = new BigInteger("10");
        BigInteger[] ret = big1.divideAndRemainder(big2);
        System.out.println(ret[0] + ", " +  ret[1]);
        // 100, 1
    }
}

使用BigDecimal实现四舍五入进位

import java.math.BigDecimal;
import java.math.RoundingMode;

class MathUtil {
    private MathUtil() {
    }

    // 自定义保留位数
    public static double round(double num, int scale) {
        return new BigDecimal(num).divide(
            new BigDecimal(1.0), scale, RoundingMode.HALF_UP).doubleValue();
    }
}


class Demo {
    public static void main(String[] args) {
        System.out.println(MathUtil.round(10.98766, 2)); // 10.99

    }
}

Math使用的是基本数据类型,性能高于大数据处理类

第9 章 : 日期操作类

36 Date日期处理类

Date类只是对long数据的一种包装

Date无参构造函数

 public Date() {
        this(System.currentTimeMillis());
    }
 ``` 

示例
```java
import java.util.Date;

class Demo {
    public static void main(String[] args) {
        Date date = new Date();
        System.out.println(date);
        // Sun Nov 17 20:39:41 CST 2019

        // 日期转long
        long time = date.getTime();
        System.out.println(time);
        // 1573994381189

        // long转日期 增加1分钟
        Date date1 = new Date(time + 60 * 1000);
        System.out.println(date1);
        // Sun Nov 17 20:40:41 CST 2019

    }
}

37 SimpleDateFormat日期处理类

继承关系

abstract Format
    -abstract DataFormat
        -SimpleDateFormat
// 日期格式化
public final String format (Object obj)

// 字符串转日期
public Date parse(String source) throws ParseException

日期格式化

 yyyy
 MM
 dd
 HH
 mm
 ss
毫秒 SSS

指定字符串定义的时候,日期数字超过指定的范围会自动进位

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

class Demo {
    public static void main(String[] args) {
        Date date = new Date();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:MM:ss");

        // 日期转字符串
        String dateStr = sdf.format(date);
        System.out.println(dateStr);
        // 2019-11-17 20:11:35

        // 字符串转日期
        try {
            System.out.println(sdf.parse(dateStr));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        // Sun Nov 17 20:00:35 CST 2019

    }
}

数字格式化

import java.text.NumberFormat;

class Demo {
    public static void main(String[] args) {
        double money = 323223210.09;

        System.out.println(NumberFormat.getInstance().format(money));
        // 323,223,210.09
    }
}

String 字符串可以向任何类型转换

第10 章 : 正则表达式

38 认识正则表达式

JDK >= 1.4
使用正则方便进行数据验证处理,复杂字符串修改

实现字符串转数字

class Demo {
    public static boolean isNumber(String temp){
        char[] chars = temp.toCharArray();
        for(char c : chars){
            if(c > '9' || c < '0'){
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        String number = "123";
        if(isNumber(number)){
            int i  = Integer.parseInt(number);
            System.out.println(i);
            // 123
        }
    }
}

使用正则表达式

String number = "123";
if(number.matches("\\d+")){
    int i  = Integer.parseInt(number);
    System.out.println(i);
    // 123
}

39 常用正则标记

1、字符匹配

x   任意字符
\\  \
\n  换行
\t  制表符

2、字符集

[abc] 任意一个
[^abc]  不在其中任意一个
[a-zA-Z] 任意字母
[0-9] 一个数字

3、简化字符集

. 任意一个字符
\d 数字[0-9]
\D 等价于[^0-9]
\s 匹配任意空格,换行,制表符
\S 匹配非空格数据
\w 字母、数字、下划线等价于[a-zA-Z_0-9]
\W 非字母、数字、下划线等价于[^a-zA-Z_0-9]

4、边界匹配

^ 匹配开始
$ 匹配结束

5、数量

? 0次或1
* 0次、1次或多次
+ 1次或多次
{n} 长度=n次
{n,} 长度>=n次
{n,m} 长度>=n and 长度<=m次

6、逻辑表达式,多个正则

XY X之后是Y
X|Y 
() 整体描述
String str = "123";
String regex = "\\d+";
System.out.println(str.matches(regex));
// true

40 String类对正则的支持

public boolean matches(String regex)
public String replaceFirst(String regex, String replacement) 
public String replaceAll(String regex, String replacement)
public String[] split(String regex)
public String[] split(String regex, int limit) 

示例1:删除非字母和非数字

String str = "asfasdfw3414^&*^&%^&wefwerfdc^&*&*fafdasd";
String regex = "[^a-zA-Z0-9]+";
System.out.println(str.replaceAll(regex, ""));
// asfasdfw3414wefwerfdcfafdasd

示例2:数字分隔拆分字符串

String str = "sdasdf123123ffsadfsda232edasf";
String regex = "\\d+";
String[] list = str.split(regex);
for(String s : list){
    System.out.println(s);
}
/**
 * sdasdf
 * ffsadfsda
 * edasf
 */

示例3:判断字符串是否为数字

String str = "10.1";
String regex = "\\d+(\\.\\d+)?";

if(str.matches(regex)){
    System.out.println(Double.parseDouble(str));
    // 10.1
}

示例4:判断字符串是否为日期

import java.text.ParseException;
import java.text.SimpleDateFormat;

class Demo {

    public static void main(String[] args) throws ParseException {
        String str = "2019-11-17";
        String regex = "\\d{4}-\\d{2}-\\d{2}";

        if (str.matches(regex)) {
            System.out.println(new SimpleDateFormat("yyyy-MM-dd").parse(str));
            // Sun Nov 17 00:00:00 CST 2019
        }
    }
}

示例5:判断电话号码
电话号码

51283346      \\d{7,8}
010-51283346  (\\d{3}-)?
(010)51283346 (\(\\d{3}\))?
class Demo {

    public static void main(String[] args) {
        String[] numbers = new String[]{
                "51283346",
                "010-51283346",
                "(010)51283346"
        };

        String regex = "((\\d{3}-)|(\\(\\d{3}\\)))?\\d{7,8}";

        for(String number : numbers){
            System.out.println(number.matches(regex));
        }
        /**
         * true
         * true
         * true
         */
    }
}

示例6:邮箱验证
用户名:数字、字母、下划线(不能开头)
域名:数字、字母、下划线
域名后缀:com、cn、net、com.cn、org

String email = "google@qq.com";
String regex = "[0-9a-zA-Z]\\w+@\\w+\\.(com|cn|net|com.cn|org)";
System.out.println(email.matches(regex));
// true

41 java.util.regex包支持

Pattern 正则表达式编译

private Pattern(String p, int f)
public static Pattern compile(String regex)

Mather 正则匹配

public Matcher matcher(CharSequence input)
public boolean matches()

Pattern示例

import java.text.ParseException;
import java.util.regex.Pattern;

class Demo {

    public static void main(String[] args) throws ParseException {
        String email = "ooxx12ooxx000ooxx";
        Pattern pattern = Pattern.compile("\\d+");
        String[] list = pattern.split(email);
        for (String s : list) {
            System.out.println(s);
        }

        /**
         * ooxx
         * ooxx
         * ooxx
         */
    }
}

Matcher示例

import java.text.ParseException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class Demo {

    public static void main(String[] args) throws ParseException {
        String number = "6687";
        Pattern pattern = Pattern.compile("\\d+");
        Matcher matcher = pattern.matcher(number);
        System.out.println(matcher.matches());
        // true

    }
}

拆分,替换,匹配使用String类就可以实现

String不具备的功能:

示例:提取sql中的变量名

import java.text.ParseException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class Demo {

    public static void main(String[] args) throws ParseException {
        String sql = "insert into student(name, age) values(#{name}, #{value})";

        Pattern pattern = Pattern.compile("#\\{\\w+\\}");
        Matcher matcher = pattern.matcher(sql);

        while (matcher.find()){
            System.out.println(matcher.group(0).replaceAll("#|\\{|\\}", ""));
        }
        /**
         * name
         * value
         */


    }
}

第11 章 : 国际化程序实现

42 国际化程序实现原理

统一程序代码,根据不同国家实现不同语言描述
需要解决问题:
1、定义保存文字信息
2、根据不同区域语言编码读取文件信息

43 Locale类

Locale类:专门描述区域和语言编码的类

构造方法

public Locale(String language)
public Locale(String language, String country)

国家语言代码
中文:zh_CN
美国:en_US

使用示例

import java.util.Locale;

class Demo {

    public static void main(String[] args){

        Locale loc = new Locale("zh", "CN");
        System.out.println(loc);
        // zh_CN

    }
}

读取本地默认环境

Locale loc = Locale.getDefault();
System.out.println(loc);
// zh_CN

使用常量

Locale loc = Locale.CHINA;
System.out.println(loc);
// zh_CN

44 ResourceBundle读取资源文件

public static final ResourceBundle getBundle(String baseName)
// baseName 没有后缀的文件名

资源文件 message.properties

info="这是消息"

读取实例

import java.io.UnsupportedEncodingException;
import java.util.ResourceBundle;

class Demo {

    public static void main(String[] args) throws UnsupportedEncodingException {

        ResourceBundle bundle = ResourceBundle.getBundle("message");

        // 解决中文乱码问题
        String message = new String(bundle.getString("info").getBytes("ISO-8859-1"), "utf-8");

        System.out.println(message);
        // "这是消息"

    }
}

45 实现国际化程序开发

CLASSPATH 下建立文件

cat Message.properties
info=默认资源 

cat Message_zh_CN.properties
info=中文资源 

cat Message_en_US.properties
info=英文资源

执行程序会读取中文资源

import java.io.UnsupportedEncodingException;
import java.util.ResourceBundle;

class Demo {

    public static void main(String[] args) throws UnsupportedEncodingException {

        ResourceBundle bundle = ResourceBundle.getBundle("message");

        // 解决中文乱码问题
        String message = new String(bundle.getString("info").getBytes("ISO-8859-1"), "utf-8");

        System.out.println(message);
        // 中文资源
    }
}

getBundle方法默认加载Locale.getDefault()

public static final ResourceBundle getBundle(String baseName)
    {
        return getBundleImpl(baseName, Locale.getDefault(),
                             getLoader(Reflection.getCallerClass()),
                             getDefaultControl(baseName));
    }

使用重载函数,读取英文资源

Locale locale = Locale.US;
ResourceBundle bundle = ResourceBundle.getBundle("message", locale);

// 解决中文乱码问题
String message = new String(bundle.getString("info").getBytes("ISO-8859-1"), "utf-8");

System.out.println(message);
// 英文资源

如果没有对应区域编码的资源文件,读取默认资源
读取流程:

指定区域的资源文件 > 默认的本地资源文件 > 公共的资源文件

46 格式化文本显示

格式化方法

public class MessageFormat extends Format {
    public static String format(String pattern, Object ... arguments)
}

代码示例

import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

class Demo {

    public static void main(String[] args) {
        // 占位符{}
        String message = "hello {0} date: {1}";
        System.out.println(MessageFormat.format(message, "admin", new SimpleDateFormat("yyyy-MM-dd").format(new Date())));
        // hello admin date: 2019-11-18
    }
}