进阶Java编程(5)基础类库

Java基础类库

1,StringBuffer类

  String类是在所有项目开发之中一定会使用到的一个功能类,并且这个类拥有如下的特点:

    ①每一个字符串的常量都属于一个String类的匿名对象,并且不可更改;

    ②String有两个常量池:静态常量池、运行时常量池;

    ③String类对象实例化建议使用直接赋值的形式完成,这样可以直接将对象保存在对象池之中以方便下次重用。

  虽然String类很好使用,但是如果认真去思考也会发现其最大的弊端:内容不允许修改,虽然大部分情况下都不会涉及到字符串内容的频繁修改,但是依然可能会存在有这样的情况,所以为了解决此问题,专门提供了一个StringBuffer类可以实现字符串内容的修改处理。

  StringBuffer并不像String类那样拥有两种对象的实例化方式,StringBuffer必须像普通类对象那样首先进行对象实例化,而后才可以进行调用方法执行处理,而这个时候可以考虑StringBuffer类中的如下方法:

    ·构造方法:public StringBuffer()

    ·一参构造方法:public StringBuffer(String str)

    ·数据追加:public StringBuffer append(数据类型 变量),相当于字符串中的【+】操作;

  ·范例:观察String与StringBuffer对比

String类对象引用传递

StringBuffer类对象引用

public class Main {
public static void main(String[] args){
        String str="Hello ";
change(str);
        System.out.println(str);

//内容没有发生修改!!!
}
public static void change(String temp){
        temp+="World !";
    }
}

public class Main {
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 !");
    }
}

Hello

Hello World !

  实际上大部分的情况下,很少会出现有字符串内容的改变,这种改变指的并不是针对于静态常量池的改变。

  ·范例:分析以下已有问题

1 public class Main {
2 public static void main(String[] args){
3         String strA = "www.mldn.cn";
4         String strB = "www."+"mldn."+"cn";
5         System.out.println(strA==strB);
6         System.out.println(strA.equals(strB));
7     }
8 }

这个时候的strB对象的内容并不算改变,或者更加严格意义上来讲,对于现在的strB当程序编译之后会变成如下的形式:

String

String strB = "www."+"mldn."+"cn";

StringBuffer

StringBuffer buf=new StringBuffer();
buf.append("www.").append("mldn.").append("cn");

  所有【+】在编译之后都变为了StringBuffer中的append()方法,并且来讲在程序之中StringBuffer与String类之间本来就可以直接互相转换。

    ①String类对象变为StringBuffer可以依靠StringBuffer类的构造方法或者使用append方法;

    ②所有类对象都可以通过toString()方法将其转变为String类型。

  在StringBuffer类里面除了可以支持有字符串内容的修改之外,实际上也提供有了一些String类所不具备的方法。例如insert()追加数据,删除指定范围的数据delete(),字符串反转reverse()

  实际上与StringBuffer类还有一个类似的功能类:StringBuilder类(JDK1.5),与StringBuffer类的功能基本相同。

  最大的区别在于StringBuffer类中的方法属于线程安全的,全部使用了synchronized关键字进行标注,而StringBuilder类属于非线程安全的。

面试题:请解释String、StringBuffer、StringBuilder的区别?

  ①String类是字符串的首选类型,其最大的特定是内容不允许修改;

  ②StringBuffer类与StringBuilder类的内容允许修改;

  ③StringBuffer是在JDK1.0提供,属于线程安全的操作,而StringBuilder是在JDK1.5提供属于非线程安全操作。

2,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 StringBr extends Object implements Serializable ,CharSequence

wps2

  现在只要有字符串就可以为CharSequence接口实例化。

  ·范例:

public class Main {
public static void main(String[] args) throws CloneNotSupportedException{
        CharSequence str="hello,Mufasa";
    }
}

 

获取指定索引字符

public char charAt(int index)

获取字符串长度

public int length()

截取部分字符串

public CharSequence subSequence(int start,int end)

CharSequence本身是一个接口,在该接口之中也定义有如下操作方法:

·范例:字符串的截取

1 public class Main {
2 public static void main(String[] args) throws CloneNotSupportedException{
3         CharSequence str="hello,Mufasa";
4         CharSequence sub=str.subSequence(2,5);
5         System.out.println(sub);
6     }
7 }

3,AutoCloseable接口  CharSequence描述的就是一个字符串。 

  AutoCloseable主要是用于日后进行资源开发的处理上,以实现资源的自动关闭(释放资源),例如:以后进行文件、网络、数据库开发的过程之中由于服务器的资源有限,所以使用之后一定要关闭资源,这样才可以被更多的使用者所使用。

  下面为了更好的说明资源的问题,将通过一个消息的发送处理来完成。

  ·范例:手工实现资源处理

 1 interface IMessage{
 2 public void send();
 3 }
 4 class NetMessage implements IMessage{
 5 private String msg;
 6 public NetMessage(String msg) {
 7 this.msg = msg;
 8     }
 9 public boolean open(){
10         System.out.println("【OPEN】获取消息发送连接资源");
11 return true;
12     }
13 @Override
14 public void send() {
15         System.out.println("【发送消息】"+this.msg);
16     }
17 public void close(){
18         System.out.println("【CLOSE】关闭消息发送通道");
19     }
20 }
21 public class Main {
22 public static void main(String[] args) throws CloneNotSupportedException{
23         NetMessage netMessage=new NetMessage("Mufasa");
24 
25 //定义发送处理
26 if(netMessage.open()){//是否打开了连接
27 netMessage.send();//消息的发送
28 netMessage.close();//关闭连接
29 }
30     }
31 }

  关闭方法:public void close() thrws Exception;  此时有位设计师说了,既然所有的资源完成处理之后都需要进行关闭操作,那么能否实现一种自动关闭的功能呢?再这样的要求下推出了AutoCloseable访问接口,这个接口是在JDK1.7的时候提供的,并且该接口只提供有一个方法:

wps3

  要想实现自动关闭处理,除了要使用AutoCloseable之外,还要结合异常处理语句才可以正常调用。

  ·范例:实现自动关闭处理

 1 interface IMessage extends AutoCloseable{
 2     public void send();
 3 }
 4 class NetMessage implements IMessage{
 5     private String msg;
 6     public NetMessage(String msg) {
 7         this.msg = msg;
 8     }
 9     public boolean open(){
10         System.out.println("【OPEN】获取消息发送连接资源");
11         return true;
12     }
13     @Override
14     public void send() {
15         System.out.println("【发送消息】"+this.msg);
16     }
17     public void close() throws Exception{
18         System.out.println("【CLOSE】关闭消息发送通道");
19     }
20 }
21 public class Main {
22     public static void main(String[] args) throws Exception{
23         try(IMessage nm=new NetMessage("Mufasa")){
24             nm.send();
25         }catch (Exception e){
26             e.printStackTrace();
27         }
28     }
29 }

4,Runtime类  以后的章节之中会接触到资源的关闭问题,往往都会见到AutoCloseable接口的使用。

  Runtime描述的是运行时的状态,也就是说在整个的JVM重,Runtime类是唯一一个与JVM运行状态有关的类,并且都会默认提供有一个该类的实例化对象。

  由于在每一个JVM进程里面只提供有一个Runtime类的对象,所以这个类的构造方法被默认私有化了,那么就证明该类使用的是单例设计模式,并且单例设计模式一定会提供有一个static方法获取本类实例。

wps4

  由于Runtime类属于单例设计模式,如果要想获取实例化对象,那么就可以使用类中的getRuntime()方法完成。

获取实例化对象

public static Runtime getRuntime()

   

  ·范例:获取Runtime对象

1 public class Main {
2     public static void main(String[] args) {
3         Runtime run=Runtime.getRuntime();
4         System.out.println(run.availableProcessors());//8核心CPU
5     }
6 }

  但是除了以上方法之外,在Runtime类里面还提供有以下四个重要的操作方法:  通过这个类中的【availableProcessors()】方法可以获取本机的CPU的内核数量。

获取最大可用内存空间

public long maxMemory()

默认为本机内存的1/4

获取可用内存空间

public long totalMemory()

默认为本机内存的1/64

获取空闲内存空间

public long freeMemory()

 

手动GC处理

public void gc()

 

  面试题:什么是GC?如何处理?

  答:GC(garbage collector)垃圾收集器,是可以由系统自动调用的垃圾释放功能,或者使用Runtime类中的GC手工调用。

5,System类

  System类是一直陪伴着我们学习的程序类【System.out.println()】

数组拷贝

public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length)

获取当前日期时间

public static long currentTimeMillis()

进行垃圾回收

public static void gc()

  ·范例:操作耗时的统计

 1 public class Main {
 2 public static void main(String[] args) {
 3 long start=System.currentTimeMillis();
 4         String str="";
 5 for(int x=0;x<30000;x++){
 6             str+=x;
 7         }
 8 long end = System.currentTimeMillis();
 9         System.out.println("操作耗时:"+(end-start));
10     }
11 }
操作耗时:602

  在System类中也提供一个【gc()】方法,但是这个gc()方法并不是重新定义的新方法,而是继续执行【Runtime.getRuntime.gc()】。

wps5

6,Cleaner类

  Cleaner是在JDK1.9之后提供的对象清理操作,其主要功能是进行【finialize()】方法的替代。在C++语言里面有两种特殊的函数:①构造函数(对象初始化);②析构函数(对象手工回收),在Java里面所有的垃圾空间都是通过GC进行自动回收的,所以很多情况下是不需要使用这类析构函数的,也正是因为如此,所以Java并没有提供这一方面的支持。

  但是Java本身依然提供了给用户收尾的操作,每一个实例化对象在回收之前至少给它一个喘息的机会,最初提供对象收尾处理的方法是Object类中所提供的【finalize】方法,这个方法的定义如下:

1 @Deprecated(since="9")
2 protected void finalize() throws Throwable

  ·范例:观察传统回收  该替换指的是不建议继续使用这个方法了,而是子类可以继续使用这个方法名称。这个方法最大的特征是Throwable异常类型,而这个异常类型分为:Error、Exception,平常所处理的都是Exception。

 1 class Member{
 2 public Member(){
 3         System.out.println("【构造】实例化对象诞生");
 4     }
 5 @Override
 6 protected void finalize() throws Throwable {
 7         System.out.println("【回收】实例化对象收尾");
 8 throw  new Exception("还想继续存在");
 9     }
10 }
11 public class Main {
12 public static void main(String[] args) throws Exception{
13         Member member=new Member();
14         member=null;
15         System.out.println("对象失去索引称为垃圾");
16 Runtime.getRuntime().gc();
17         System.out.println("手动进行GC处理");
18     }
19 }
 1 import java.lang.ref.Cleaner;
 2 class Member implements Runnable{
 3     public Member(){
 4         System.out.println("【构造】实例化对象诞生");
 5     }
 6     @Override
 7     public void run() {//执行清除最终执行的是此操作
 8         System.out.println("【回收】实例化对象收尾");
 9     }
10 }
11 class MemberCleaning implements AutoCloseable{//实现清除的处理
12     private static final Cleaner CLEANER=Cleaner.create();
13     //创建一个清除处理
14     private Member member;
15     private Cleaner.Cleanable cleanable;
16     public MemberCleaning(){
17         this.member=new Member();//创建新对象
18         this.cleanable=this.CLEANER.register(this,this.member);
19         //注册使用的对象
20     }
21     @Override
22     public void close() throws Exception {
23         this.cleanable.clean();//启动多线程
24     }
25 }
26 public class Main {
27     public static void main(String[] args) throws Exception{
28         try(MemberCleaning mc=new MemberCleaning()) {
29             ;
30         }catch (Exception e){
31             e.printStackTrace();
32         }
33     }
34 }

  在新一代的清除回收处理过程之中,更多情况下考虑的是多线程的使用,即:为了防止有可能造成的延迟处理,所以许多对象回收前的处理都是单独通过一个线程完成的。  但是从JDK1.9开始,这个操作已经不建议使用了,而对于对象的回收释放。从JDK1.9开始建议开发者使用AutoCloseable或者使用java.lang.ref.Cleaner类进行回收处理(Cleaner也支持有AutoCloseable处理)。

7,对象与克隆

  所谓的对象克隆指的就是对象的复制,而且属于全新的复制。即:使用已有对象创建新对象,使用Object类中提供的clone()方法。

  所有的类都会继承Object父类,所以所有的类都一定会有clone()方法,但是并不是所有的类都希望被克隆。所以如果想要实现对象克隆,那么对象所在的类需要实现一个Cloneable接口,此接口没有任何方法提供,是因为它描述的是一种能力。

  备注:接口的作用①标准;②能力(接口没有方法是一种能力标识的接口)

  ·范例:实现对象克隆

 1 class Member implements Cloneable{//clone是一个protected权限方法
 2     private String name;
 3     private int age;
 4     public Member(String name, int age) {
 5         this.name = name;
 6         this.age = age;
 7     }
 8     @Override
 9     public String toString() {
10         return "【"+super.toString()+"】name="+this.name+",age="+this.age;
11     }
12     @Override
13     public Object clone() throws CloneNotSupportedException {
14         return super.clone();//覆写clone方法,调用父类方法,更改权限
15     }
16 }
17 public class Main {
18     public static void main(String[] args) throws CloneNotSupportedException{
19         Member memberA=new Member("万雨",25);
20         Member memberB=(Member) memberA.clone();
21         System.out.println(memberA.toString());
22         System.out.println(memberB.toString());
23     }
24 }

  如果在开发之中不是非常特别的需求下,很少会出现对象克隆的需求。

posted on 2019-07-05 20:59  周健康  阅读(291)  评论(0编辑  收藏  举报

导航