Java基础类库

StringBuffer类

String类的特征

  • 每一个字符串的常量都属于一个String类的匿名对象, 并且不可更改
  • String有两个常量池: 静态常量池, 运行时常量池
  • String类对象实例化建议直接赋值的形式完成, 这样可以直接将对象保存在对象池之中以方便下次重用
  • String最大的弊端: 内容不允许修改, StringBuffer允许修改
String与StringBuffer的对比

StringBuffer并不像String类那样拥有两种对象实例化方式, StringBuffer必须像普通类对象那样首先进行对象实例化而后可以调用方法执行处理
构造方法

public StringBuffer();

数据追加

public StringBuffer append(数据类型 变量)   //   相当于字符串中的 "+" 操作

所有的 "+" 在编译以后都变成了StrngBuffer中的append()方法, 并且在程序之中StringBuffer和String可以相互转换:

  • String类对象变为StringBuffer可以依靠StringBuffer类的构造方法或者用append()方法
  • 所有的类对象都可以通过toString()转成String类对象
StringBuffer常用方法

1.插入数据

public StringBuffer insert(int offset, 数据类型 b)
public static void main(String[] args) {
        StringBuffer buf = new StringBuffer();
        buf.append("哈哈哈哈").insert(0, "yyyy").insert(4, "xxx");
        System.out.println(buf);
    }

2.删除数据

public StringBuffer delete(int start, int end)
public static void main(String[] args) {
        StringBuffer buf = new StringBuffer();
        buf.append("哈哈哈哈").insert(0, "yyyy").insert(4, "xxx").delete(2, 6);
        System.out.println(buf);
    }

3.字符串翻转

public StringBuffer reverse()
public static void main(String[] args) {
        StringBuffer buf = new StringBuffer();
        buf.append("哈哈哈哈").append("yyyy").reverse();
        System.out.println(buf);
    }

实际上与StringBuffer类还有一个类似的功能类StringBuilder类.StringBuffer是线程安全类, 方法全部使用了synchronized关键字修饰, 而StringBuilder类不是.

String, StringBufferStringBuilder三者的区别
  • String类是字符串的首选类型, 其最大的特点是内容不允许改变
  • StringBufferStringBuilder允许修改
  • StringBuffer是在JDK 1.0的时候提供的, 属于线程安全的操作, 而StringBuilder是在JDK1.5提供的不属于线程安全的操作

CharSequence

CharSequence是一个描述字符串结构的接口, 在这个接口里一般有三种常用的子类

String类 StringBuffer类 StringBuilder类
public final class String extends Object implemens Serializable, Comparable<String>, CharSequence public final class StringBuffer extends Object implemens Serializable, CharSequence public final class StringBuilder extends Object implemens Serializable, CharSequence

CharSequence

现在只要有字符串就可以为CharSequence接口实例化.
CharSequence本身就是一个接口, 在该接口之中也定义了如下的操作方法

  • 获取指定索引字符: public char charAt(int index);
  • 获取字符串的长度: public int length();
  • 截取部分字符串: public CharSequence subSequence(int start, int end)

AutoCloseable

主要用于实现资源的自动关闭(释放资源)

  • 关闭方法: public void close() throws Exception;
    AutoCloseable

    注意事项
  • 要想实现自动关闭处理, 除了要使用AutoCloseable之外, 还需要结合有异常处理语句才可以正常调用

Runtime类

Runtime描述的事运行时的状态, 也就是在整个JVM中, Runtime类是唯一一个与JVM运行状态有关的类, 并且会默认提供一个该类的实例化对象.
由于在一个JVM进程只允许有一个Runtime类的对象, 所以类的构造方法被私有化, Runtime类使用的是单例设计模式
由于是单例设计模式, 如果想获取实例化对象, 那么就要依靠类中的getRuntime()方法完成.

  • 获取实例化对象: public static Runtime getRuntime();
  • 获取最大可用内存空间: public long maxMemory() // 默认配置为本机系统内存的1/4
  • 获取可用内存空间: public long totalMemory() // 默认配置是本机系统的1/64
  • 获取空闲内存空间: public long freeMemory()
  • 手工进行GC处理: public void gc()
Runtime

System类

  • 数组拷贝: public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
  • 获取当前的日期时间数值: public static long currentTimeMillis();
  • 进行垃圾回收: public static void gc();
利用currentTimeMillis获取操作耗时
public static void main(String[] args) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < 30000; i++) {
            System.out.println("i");
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start);

    }
System也提供了一个gc方法, 这个方法并不是重新定义的新方法, 而是继续执行了Runtime类中的gc方法.

对象克隆

所谓的对象克隆, 其实就是深复制, 用已有对象的内容创建一个新的对象. 需要使用到Object类中提供的clone方法:

protected Object clone() throws CloneNotSupportedException;

所有的类都会继承Object父类, 所以所有的类都一定有clone()方法, 如果想实现对象克隆, 那么对象所在的类需要实现一个Cloneable接口

class Eg implements Cloneable {
    private int age;
    private String name;
    public Eg(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "[" + super.toString() + "]" + ", age:" + this.age + ", name:" + this.name;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class Main {
    public static void main(String[] args) throws Exception {
        Eg eg = new Eg("A", 20);
        Eg egs = (Eg)eg.clone();
        System.out.println(eg);
        System.out.println(egs);
    }
}

Math数学计算类

Math构造方法被私有化, 但是并不是单例, 所有的方法均是static.都可以通过类名直接调用.

Random随机数生成类

  • 产生一个不大于边界的随机数(正整数和0): public int nextInt(int bound)

大数字处理类

大数字处理类可以实现海量数字的计算(能提供的也只是基础计算),
大数字处理类分为两种:

  • BigInteger
    BigInteger类构造: public BigInteger(String val);
  • BigDecimal
    BigDecimal类构造: public BigDecimal(String val);

两个类均继承Number

Number类

四则运算

public static void main(String[] args) throws Exception {
        BigInteger bigA = new BigInteger("273827382738927837");
        BigInteger bigB = new BigInteger("273827382738927837");
        System.out.println(bigA.add(bigB)); // 加法
        System.out.println(bigA.subtract(bigB)); // 减法
        System.out.println(bigA.multiply(bigB)); // 乘法
        System.out.println(bigA.divide(bigB)); // 除法
        BigInteger result [] = bigA.divideAndRemainder(bigB);
        System.out.println("商:" + result[0] + ", 余数:" + result[1]);
    }

Date日期处理类

Date类的构造方法

 public Date() {
        this(System.currentTimeMillis());
}
public Date(long date) {
        fastTime = date;
}

获取当前日期

public static void main(String[] args) throws Exception {
        Date date = new Date();
        System.out.println(date);
    }

获取当前时间戳

public static void main(String[] args) throws Exception {
        long currentTime = new Date().getTime();
        System.out.println(currentTime);
}

将时间戳转为日期

public static void main(String[] args) throws Exception {
        long time = 1563375702346L;
        Date date = new Date(time);
        System.out.println(date);
}

SimpleDateFormat

`SimpleDateFormat`的继承关系

构造方法: public SimpleDateFormat(String pattern);

格式化日期

  • 日期格式化: public final String format(Date date);
  • 将字符串转为日期: public Date parse(String source) throws ParseException;

日期格式

年(yyyy)-月(MM)-日(dd)  时(HH):分(mm):秒(ss).毫秒(SSS)

将当前时间格式化

public static void main(String[] args) throws Exception {
        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        System.out.println(format.format(date));
        
    }

将某个时间转为日期

String str = "2019-07-17 22:57:36.029";
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        Date date = fmt.parse(str);
        System.out.println(date);

将某个时间戳格式化

public static void main(String[] args) throws Exception {
        long time = 1563375702346L;
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        System.out.println(format.format(time));
}

将某个日期转成时间戳

 public static void main(String[] args) throws Exception {
        String str = "2019-07-17 22:57:36.029";
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        Date date = fmt.parse(str);
        System.out.println(date.getTime());
}

NumberFormat(货币格式化)

public static void main(String[] args) throws Exception {
        double money = 2829839389d;
        String moneyStr = NumberFormat.getInstance().format(money);
        System.out.println(moneyStr);
    }

输出

2,829,839,389

UUID类

UUID 根据时间戳生成一个无重复的字符串定义.

  • 获取UUID对象: public static UUID randomUUID();
  • 根据字符串获取UUID对象: public static UUID fromString(String name);
public static void main(String[] args) throws Exception {
        UUID uuid = UUID.randomUUID();
        String uuidStr = uuid.toString();
        uuid = UUID.fromString(uuidStr);
        System.out.println(uuidStr);
        System.out.println(uuid);
}

Optional

可以实现null的处理操作, 提供了以下的操作方法:

  • 返回空数据: public static <T> Optional <T> empty();
  • 获取数据: public T get();
  • 保存数据, 但是不允许出现null: public static <T> Optional <T> of(T value);
    • 如果在保存数据的时候存在null, 则会抛出NullPointerException异常;
  • 保存数据, 允许为空: public static <T> Optional <T> ofNullable(T value);
  • 空的时候返回其他数据: public T orElse(T other)

ThreadLocal

ThreadLocal主要用于解决多线程资源引用传递的问题, 很多地方叫做线程本地变量,也有些地方叫做线程本地存储, 即按照线程来存储数据.

  • 构造方法
public ThreadLocal();
  • 设置数据
public void set(T value);
  • 取出数据
public T get();
  • 删除数据
public void remove();

问题代码
三个线程发送三个消息.

class Message { // 要发送的消息体
    private String info;
    public void setInfo(String info) {
        this.info = info;
    }
    public String getInfo() {
        return info;
    }
}
class Channel { // 消息的发送通道
    private static Message message;
    private Channel() {}
    public static void setMessage(Message m) {
        message = m;
    }
    public static void send() {
        System.out.println("[" + Thread.currentThread().getName() + ", 消息发送" + message.getInfo());
    }
}
public class JavaAPIDemo {
    public static void main(String[] args) {
        new Thread(()->{
            Message msg = new Message();
            msg.setInfo("发送消息A");
            Channel.setMessage(msg);
            Channel.send();
        }, "线程A").start();
        new Thread(()->{
            Message msg = new Message();
            msg.setInfo("发送消息B");
            Channel.setMessage(msg);
            Channel.send();
        }, "线程B").start();
        new Thread(()->{
            Message msg = new Message();
            msg.setInfo("发送消息C");
            Channel.setMessage(msg);
            Channel.send();
        }, "线程C").start();
    }
}

输出结果(跑几次)

[线程A, 消息发送发送消息A
[线程B, 消息发送发送消息A
[线程C, 消息发送发送消息C

问题产生: 多个线程之间的消息产生了相互影响, 主要的原因是Channel中的message使用的是static定义的, 在B线程先给message赋值, 尚未发送的时候, A线程重新赋值, 然后A线程发出, B线程发出, 导致出现问题

在不改变代码结构的情况下需要使用ThreadLocal解决这个问题, 代码如下:

class Message { // 要发送的消息体
    private String info;
    public void setInfo(String info) {
        this.info = info;
    }
    public String getInfo() {
        return info;
    }
}
class Channel { // 消息的发送通道
    private static final ThreadLocal<Message> THREAD_LOCAL = new ThreadLocal<Message>();
    private Channel() {}
    public static void setMessage(Message m) {
        THREAD_LOCAL.set(m); // 想ThreadLocal中保存数据
    }
    public static void send() {
        System.out.println("[" + Thread.currentThread().getName() + ", 消息发送:" + THREAD_LOCAL.get().getInfo());
    }
}
public class JavaAPIDemo {
    public static void main(String[] args) {
        new Thread(()->{
            Message msg = new Message();
            msg.setInfo("发送消息A");
            Channel.setMessage(msg);
            Channel.send();
        }, "线程A").start();
        new Thread(()->{
            Message msg = new Message();
            msg.setInfo("发送消息B");
            Channel.setMessage(msg);
            Channel.send();
        }, "线程B").start();
        new Thread(()->{
            Message msg = new Message();
            msg.setInfo("发送消息C");
            Channel.setMessage(msg);
            Channel.send();
        }, "线程C").start();
    }
}

输出结果, 不论运行多少次, 线程和消息都可以一一对应

[线程B, 消息发送:发送消息B
[线程A, 消息发送:发送消息A
[线程C, 消息发送:发送消息C
ThreadLocal

定时调度

定时器的主要操作就是定时任务的处理, 只是实现了一种间隔出发的操作.
如果想要实现定时的处理操作, 主要需要有一个定时操作的主体类, 以及定时任务的控制, 可以使用两个类来控制

  • java.util.TimerTask类: 实现定时任务处理
  • java.util.Timer类: 进行任务的启动
    • 任务启动: public void schedule(TimerTask task, long delay); //delay为延时, 延时的单位是毫秒
    • 间隔触发: public void scheduleAtFixedRate(TimerTask task, long delay, long period);
class myTask extends TimerTask {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + ": " + System.currentTimeMillis());
    }
}

public class JavaAPIDemo {
    public static void main(String[] args) {
        Timer timer = new Timer();
        // 定义间隔任务, 1000毫秒后开始执行, 每次执行1次, 周期为1000毫秒
        timer.scheduleAtFixedRate(new myTask(), 1000, 1000);
    }
}

Base64

since: JDK1.8

  • Base64.Encoder: 进行加密处理
    • 加密处理: public byte[] encode(byte[] src);
  • Base64.Decoder: 进行解密处理
    • 解密处理: public byte[] decode(String src);
 public static void main(String[] args) {
        String msg = "这是需要加密的字符串";
        String encMsg = new String(Base64.getEncoder().encode(msg.getBytes()));
        System.out.println("encMsg:" + encMsg);
        String decMsg = new String(Base64.getDecoder().decode(encMsg.getBytes()));
        System.out.println("decMsg:" + decMsg);
  }

最好的加密应该增加盐值, 并且盐值先加密, 最后使用2-3种加密方式.

比较器

系统类型(Integer, String)数组比较, 一般使用sort(). 自定义对象比较, 一般使用比较器.

Comparable比较器

实现一个Person类, 比较年纪

class Person implements Comparable<Person> {
    private String name;
    private int age;
    public Person(String name, int age) {
        this.age = age;
        this.name = name;
    }

    @Override
    public int compareTo(Person o) {
        return this.age - o.age;
    }

    @Override
    public String toString() {
        return "姓名:" + this.name + ", 年龄:" + this.age;
    }
}
public class JavaAPIDemo {
    public static void main(String[] args) {
        Person perA = new Person("小强A", 26);
        Person perB = new Person("小强B", 126);
        Person perC = new Person("小强C", 86);
        Person list [] = new Person[] {
                perA,
                perB,
                perC
        };
        Arrays.sort(list);
        System.out.println(Arrays.toString(list));
    }
}
Comparator比较器

Comparator是一种挽救的比较器支持, 目的是解决一些没有使用Comparable排序的类的数组排序操作.
比如上面的Person类并没有继承Comparable, 在Person类本体不被修改的情况下, 需要进行排序

class PersonComparator implements Comparator<Person> {
    @Override
    public int compare(Person o1, Person o2) {
        return o1.getAge() - o2.getAge();
    }
}
class Person {
    private String name;
    private int age;
    public Person(String name, int age) {
        this.age = age;
        this.name = name;
    }
    public int getAge() {
        return this.age;
    }
    public String getName() {
        return this.name;
    }
    @Override
    public String toString() {
        return "姓名:" + this.name + ", 年龄:" + this.age;
    }
}
public class JavaAPIDemo {
    public static void main(String[] args) {
        Person perA = new Person("小强A", 26);
        Person perB = new Person("小强B", 126);
        Person perC = new Person("小强C", 86);
        Person list [] = new Person[] {
                perA,
                perB,
                perC
        };
        Arrays.sort(list, new PersonComparator());
        System.out.println(Arrays.toString(list));
    }
}

排序尽量使用Comparable.

ComparableComparator的区别

  • java.lang.Comparable是在类定义的时候实现的父接口, 主要用于定义排序规则, 里面只有一个compareTo的方法
  • java.util.Comparator是挽救的比较器操作, 需要单独设置比较器规则类实现排序, 里面有compare方法.
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343