StringBuffer类
- String类特点:
- 每一个字符串常量都属于一个String类的匿名对象,并且不可更改;
- String有两个常量池:静态常量池、运行时常量池;
- String类对象实例化建议使用直接赋值的形式完成,这样可以直接将对象保存在对象池之中以方便下次重用;
- StringBuffer并不像String类那样拥有两种对象实例化方式,StringBuffer必须像普通类对象那样首先进行对象实例化,而后才可以调用方法执行处理,这个时候可以考虑使用StringBuffer类中的如下方法:
- 构造方法:public StringBuffer()
- 构造方法:public StringBuffer(String str)
- 数据追加:public StringBuffer append(数据类型 变量)
//String类对象引用传递
public class StringBufferFun {
public static void main(String[] args) {
String str = "Hello";
change(str);
System.out.println(str);
}
public static void change(String temp) {
temp += " World";
}
}
//StringBuffer类对象引用传递
public class StringBufferFun {
public static void main(String[] args) {
StringBuffer str = new StringBuffer("Hello");
change(str);
System.out.println(str);
}
public static void change(StringBuffer temp) {
temp.append(" World!");
}
}
- 在StringBuffer类里面除了提供有字符串修改之外,实际上也提供有一些String所不具备的方法:
- 插入数据:public StringBuffer insert(int offset, 数据类型 b)
- 删除制定范围的数据:public StringBuffer delete(int start, int end)
- 字符串内容反转:public StringBuffer reverse()
//插入数据
public class StringBufferFun {
public static void main(String[] args) {
StringBuffer str = new StringBuffer();
str.append(" World").insert(0, "Hello");
System.out.println(str);
}
}
//删除数据
public class StringBufferFun {
public static void main(String[] args) {
StringBuffer str = new StringBuffer("Hello World!");
str.delete(5, 12);
System.out.println(str);
}
}
//字符串反转
public class StringBufferFun {
public static void main(String[] args) {
StringBuffer str = new StringBuffer("Hello World!");
str.reverse();
System.out.println(str);
}
}
- 实际上与StringBuffer类还有一个类似的功能类:StringBuilder类,这个类是JDK1.5的时候提供的,该类中提供的方法与StringBuffer功能相同,最大的区别在于StringBuffer类中的方法属于线程安全的,全部使用了synchronized关键字进行标注,而StringBuilder类属于非线程安全的;
CharSequence接口
- CharSequence是一个描述字符串结构的接口,在这个接口里面一般发现有三种常用的子类:
String类 | StringBuffer类 | StringBuilder类 |
---|---|---|
public final class String extends Object implements Serializable, Comparable<String>, CharSequence | public final class StringBuffer extends Object implements Serializable, CharSequence | public final class StringBuilder extends Object implements Serializable, CharSequence |
此图来源于李兴华老师
- 现在只要有字符串就可以为CharSequence接口实例化
public class JavaFun {
public static void main(String[] args) {
CharSequence str = "Hello World"; //子类实例向父接口转型
}
}
- CharSequence本身是一个接口,在该接口中也定义有如下操作方法:
- 获取指定索引字符:public char charAt(int index)
- 获取字符串的长度:public int length()
- 截取部分字符串:CharSequence subSequence(int start, int end)
AutoCloseable接口
- AutoCloseable主要是用于资源开发的处理上,以实现资源的自动关闭(释放资源),例如:在进行文件、网络、数据库开发的过程之中,由于服务器的资源有限,所以使用之后一定要关闭资源,这样才可以被更多的使用者所使用;
//模拟消息发送
package com.company;
interface IMessage {
public void send();
}
class NetMessage implements IMessage {
private String msg;
public NetMessage(String msg) {
this.msg = msg;
}
public boolean open() {
System.out.println("消息链接成功");
return true;
}
@Override
public void send() {
if (this.open()) {
System.out.println("消息发送:" + this.msg);
}
}
public void close() {
System.out.println("消息断开链接");
}
}
public class AutoCloseableApi {
public static void main(String[] args) {
NetMessage nm = new NetMessage("Hello World");
nm.send();
nm.close();
}
}
- 此时会有一个疑问:既然所有的资源完成处理之后都需要进行关闭操作,那么是否可以实现一种自动关闭的功能呢,所以推出了AutoCloseable访问接口,这个接口是在JDK1.7的时候提供的,并且该接口只提供有一个方法:public void close() throws Exception;
此图来源于李兴华老师
- 要想实现自动关闭处理,除了要使用AutoCloseable之外,还需要结合异常处理语句才可以正常调用;
package com.company;
interface IMessage extends AutoCloseable {
public void send();
}
class NetMessage implements IMessage {
private String msg;
public NetMessage(String msg) {
this.msg = msg;
}
public boolean open() {
System.out.println("消息链接成功");
return true;
}
@Override
public void send() {
if (this.open()) {
System.out.println("消息发送:" + this.msg);
}
}
public void close() {
System.out.println("消息断开链接");
}
}
public class AutoCloseableApi {
public static void main(String[] args) {
try (NetMessage nm = new NetMessage("Hello World")) {
nm.send();
} catch (Exception e) {}
}
}
Runtime类
- Runtime描述的是运行时的状态,在整个的JVM之中,Runtime类是唯一一个与JVM运行状态有关的类,并且都会默认提供有一个该类的实例化对象;
- 由于在每一个JVM进程里面只允许提供有一个Runtime类的对象,所以这个类的构造方法被默认私有化了,那么就证明该类使用的是单例设计模式,并且单例设计模式一定会提供有一个static方法获取本类实例;
此图来源于李兴华老师
- 由于Runtime类属于单例设计模式,如果想要获取实例化对象,那么就可以依靠类中的getRuntime()方法完成:
- 获取实例化对象:public static Runtime getRuntime()
- 通过Runtime类中的availableProcessors()方法可以获取本机的CPU内核数:public int availableProcessors()
//获取Runtime类对象
public class RuntimeApi {
public static void main(String[] args) {
Runtime run = Runtime.getRuntime();
System.out.println(run.availableProcessors());
}
}
- 除了以上的方法之外,在Runtime类里面还提供有一下四个重要的操作方法:
- 获取最大可用内存空间:public long maxMemory(),默认的配置为本机系统内存的四分之一;
- 获取可用内存空间:public long totalMemory(),默认的配置为本机系统内存的六十四分之一;
- 获取空闲内存空间:public long freeMemory()
- 手工进行GC处理:public void gc()
//观察内存状态
public class RuntimeApi {
public static void main(String[] args) throws Exception {
Runtime run = Runtime.getRuntime();
System.out.println("【1】MAX_MEMORY " + run.maxMemory());
System.out.println("【1】TOTAL_MEMORY " + run.totalMemory());
System.out.println("【1】FREE_MEMORY " + run.freeMemory());
String str = "";
for (int x = 0; x < 30000; x ++) {
str += x;
}
System.out.println("【2】MAX_MEMORY " + run.maxMemory());
System.out.println("【2】TOTAL_MEMORY " + run.totalMemory());
System.out.println("【2】FREE_MEMORY " + run.freeMemory());
run.gc();
System.out.println("【3】MAX_MEMORY " + run.maxMemory());
System.out.println("【3】TOTAL_MEMORY " + run.totalMemory());
System.out.println("【3】FREE_MEMORY " + run.freeMemory());
}
}
System类
- System定义的处理方法:
- 数组拷贝:public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
- 获取当前的日期时间数值:public static long currentTimeMillis()
- 进行垃圾回收:public static void gc()
//操作耗时的统计
public class SystemApi {
public static void main(String[] args) {
long start = System.currentTimeMillis();
String str = "";
for (int x = 0; x < 30000; x ++) {
str += x;
}
long end = System.currentTimeMillis();
System.out.println(end - start);
}
}
- 在System类里面会发现也提供有一个gc()方法,但是这个gc()方法并不是重新定义的新方法,而是调用了Runtime.getRuntime().gc();
Cleaner类
- Cleaner类是在JDK1.9之后提供的对象清理操作,其主要功能是进行finalize()方法的替代,在C++语言里面有两种特殊的函数:构造函数、析构函数(对象的手工回收),在Java里面所有的垃圾空间都是通过GC自动回收的,所有很多情况下是不需要使用析构函数的,也正是因为如此,Java也没有提供这方面的支持;
- 但是Java本身依然提供了给用户收尾的操作,每一个实例化对象在回收之前至少给它一个喘息的机会,最初实现对象收尾处理的方法是Object类中所提供的finalize()方法,这个方法定义如下:
- @Deprecated(since="9") protected void finalize() throws Throwable
- 该替换指的是不建议继续使用这个方法了,而是说子类可以继续使用这个方法名称,这个方法最大的特征是抛出了一个Throwable异常类型,而这个异常类型分为两个子类型:Error、Exception,平常所处理的都是Exception;
//传统回收
import java.lang.ref.Cleaner;
class Member {
public Member() {
System.out.println("对象产生");
}
@Override
protected void finalize() throws Throwable {
System.out.println("对象回收");
throw new Exception("程序继续执行");
}
}
public class CleanerApi {
public static void main(String[] args) {
Member mb = new Member();
mb = null;
System.gc();
System.out.println("程序结束");
}
}
//Cleaner回收
class Member implements Runnable {
public Member() {
System.out.println("对象产生");
}
@Override
public void run() {
System.out.println("对象回收");
}
}
class MemberCleaning implements AutoCloseable {
public static final Cleaner cleaner = Cleaner.create();
private Member member;
private Cleaner.Cleanalbe cleanalbe;
public MemberCleaning() {
this.member = member;
this.cleanalbe = this.cleaner.register(this, this.member);
}
@Override
public void close() throws Exception {
this.cleanalbe.clear();
}
}
public class CleanerApi {
public static void main(String[] args) throws Exception {
try(MemberCleaning mc = new MemberCleaning()) {
} catch (Exception e) {}
}
}
对象克隆
- 对象克隆指的就是对象的复制,而且属于全新的复制,即:使用已有对象内容创建一个新的对象,如果要想进行对象克隆需要使用到Object类中的clone()方法:protected Object clone() throws CloneNotSupportedException,所有的类都会继承Object父类,所以所有的类都一定会有clone()方法,但是并不是所有的类都希望被克隆,如果当前对象需要被克隆,那么对象所在类需要实现一个Cloneable接口,此接口并没有任何的方法提供,是因为它描述的是一种能力;
class MemberClone implements Cloneable {
private String name;
private int age;
public MemberClone(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "【" + super.toString() + "】name='" + this.name + '\'' + ", age=" + this.age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class ObjectClone {
public static void main(String[] args) throws Exception {
MemberClone mcA = new MemberClone("张三", 18);
MemberClone mcB = (MemberClone) mcA.clone();
System.out.println(mcA);
System.out.println(mcB);
}
}