Java高级编程:Java常用类库
目录标题
一、Java基础类库
StringBuffer类
String类是在所有项目开发之中一定会使用到的一个功能类,并且这个类拥有如下的特点:
-
每一个字符串的常量都属于一个String类的匿名对象,并且不可更改
-
String有两个常量池:静态常量池、运行时常量池
-
String 类对象实例化建议使用直接赋值的形式完成,这样可以直接将对象保存在对象池之中以方便下次重用
虽然String类很好使用,但是如果认真去思考也会发现其最大的弊端:内容不允许修改,虽然大部分的情况下都不会字符串内容的频繁修改,但是依然可能会存在有这样的情况,所以为了解决此问题,专门提供有一个StringBuffer类用于字符串内容的修改处理。
StringBuffer并不像 String 类那样拥有两种对象实例化方式,StringBuffer必须像普通类对象那样首先进行对象实例化,而后才可以调用方法执行处理,而这个时候可以考虑使用 StringBuffer类中的如下方法:
-
构造方法:public StringBuffer()
-
构造方法: public StringBuffer(String str),接收初始化字符串内容
-
数据追加: public StringBuffer append(数据类型变量),相当于字符串中的“+”
范例: 观察 String 与 StringBuffer对比
String类对象引用传递 VS StringBuffer类对象引用传递
public class BaseClass {
public static void main(String[] args) {
String string="Hello";
StringBuffer stringBuffer=new StringBuffer("Hello");
changeString(string);
System.out.println(string);//内容没有发生改变
changeStringBuffer(stringBuffer);//内容发生改变
System.out.println(stringBuffer);
}
public static void changeString(String temp){
temp+="World!";
}
public static void changeStringBuffer(StringBuffer temp){
temp.append("World!");
}
}
实际上大部分的情况下,很少会出现有字符串内容的改变,这种改变指的并不是针对于静态常量池的改变。
范例:分析一下已有问题
public class BaseClass {
public static void main(String[] args) {
String stringA="www.aliyun.com";
String stringB="www."+"aliyun."+"com";
System.out.println(stringA==stringB);//true
}
}
这个时候的 strB对象的内容并不算是改变,或者更加严格的意义上来讲,对于现在的 stB当程序编译之后会变为如下的形式:
new StringBuffer("www.").append("aliyun.").append("com");
**所有的“+”在编译之后都变为了StringBuffer 中的 append()方法,**并且在程序之中 StringBufer与String类对象之间本来就可以直接互相转换
-
String 类对象变为StringBuffer可以依靠StringBuffer类的构造方法或者使用append()方法
-
所有类对象都可以通过toString(方法将其变为String 类型
在 StringBuffer类里面除了可以支持有字符串内容的修改之外,实际上也提供有了一些String 类所具备的方法。
1、插入数据: public StringBuffer insert(int offset,数据类型b)
2、删除指定范围的数据: public StringBuffer delete(int start, int end)
3、字符串内容反转: public StringBuffer reverse()
public class BaseClass {
public static void main(String[] args) {
StringBuffer stringBuffer=new StringBuffer("Hello ");
stringBuffer.insert(6,"World");
stringBuffer.delete(6,9);
stringBuffer.reverse();
System.out.println(stringBuffer);
}
}
实际上与StringBuffer.类还有一个类似的功能类:StringBuilder类,这个类是在JDK 1.5的时候提供的,该类中提供的方法与StringBuffer功能相同,最大的区别在于 StringBuffer 类中的方法属于线程安全的,全部使用了synchronized关键字进行标注,而StringBuilder类属于非线程安全的。
面试题:请解释String、StringBuffer、StringBuilder_的区别?
String类是字符串的首选类型,其最大的特点是内容不允许修改
StringBuffer与 StringBuilder类的内容允许修改
StringBuffer是在JDK 1.0 的时候提供的,属于线程安全的操作,而 StringBuilder是JDK1.5之后提供的,属于非线程安全的操作
CharSequence接口
CharSequence是一个描述字符串结构的接口,在这个接口里面一般发现有三种常用子类:
- String类:
public final class String
extends Object
implements Serializable
Comparable<String>,CharSequence
- StringBuffer类:
public final class StringBuffer
extends Object
implements Serializable,CharSequence
- StringBuilder类:
public final class StringBuilder
extends Object
implements Serializable, Charequence
现在只要有字符串就可以为CharSequence接口实例化。
public class BaseClass {
public static void main(String[] args) {
CharSequence charSequence="Hello"; //子类实例向父接口转型
}
}
CharSequence本身是一个接口,在该接口之中也定义有如下操作方法:
-
获取指定索引字符: public char charAt(int index)
-
获取字符串的长度: public int length()
-
截取部分字符串: public CharSequence subSequence(int start, int end)
范例:字符串截取
public class BaseClass {
public static void main(String[] args) {
CharSequence charSequence="Hello"; //子类实例向父接口转型
CharSequence sub=charSequence.subSequence(4,8);
System.out.println(sub);
}
}
以后只要看见了CharSequence描述的就是一个字符串。
AutoCloseable接口
AutoCloseable主要是用于日后进行资源开发的处理上,以实现资源的自动关闭(释放资源),例如:在以后进行文件、网络、数据库开发的过程之中由于服务器的资源有限,所以使用之后一定要关闭资源,这样才可以被更多的使用者所使用
下面为了更好的说明资源的问题,将通过一个消息的发送处理来完成。
范例:手工实现资源处理.
package com.lut.JavaPlus;
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("【OPEN】获取消息发送连接资源");
return true;
}
public void close(){
System.out.println("【CLOSE】关闭消息发送通道");
}
@Override
public void send() {
if (this.open()){
System.out.println("【***发送消息***】"+this.msg);
}
}
}
public class BaseClass {
public static void main(String[] args) {
NetMessage netMessage=new NetMessage("这是一条消息");
netMessage.open();
netMessage.send();
netMessage.close();
}
}
此时有位设计师说了,既然所有的资源完成处理之后都必须进行关闭操作,那么能否实现一种自动关闭的功能呢?
再这样的要求下,推出了AutoCloseable访问接口,这个接口是在JDK 1.7的时候提供的,并日该接口只有一种方法:
- 关闭方法: public void close() throws Exception:
- 还需要结合异常处理语句才可以正常调用。
package com.lut.JavaPlus;
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("【OPEN】获取消息发送连接资源");
return true;
}
public void close(){
System.out.println("【CLOSE】关闭消息发送通道");
}
@Override
public void send() {
if (this.open()){
System.out.println("【***发送消息***】"+this.msg);
}
}
}
public class BaseClass {
public static void main(String[] args) {
try(NetMessage netMessage=new NetMessage("这是一条消息")) {
netMessage.open();
netMessage.send();
//netMessage.close();
}catch (Exception e){
}
}
}
在以后的章节之中会接触到资源的关闭问题,往往都会见到AutoCloseable接口的使用。
Runtime类
Runtime描述的是运行时的状态,也就是说在整个的JVM之中,Runtime类是唯一一个与JⅣM运行状态有关的类,并且都会默认提供有一个该类的实例化对象。
由于在最每一个JVM进程里面只允许提供有一个Runtime类的对象,所以这个类的构造方法被默认私有化了,那么就证明该类使用的是**单例设计模式,**并且单例设计模式一定会提供有一个static方法获取本类实例。
由于Runtime类属于单例设计模式,如果要想获取实例化对象,那么就可以依靠类中的getRuntime()方法
- 获取实例化对象: public static Runtime getRuntime(); ﹒
通过这个类中的 availableProcessors()方法可以获取本机的CPU 内核数
public class BaseClass {
public static void main(String[] args) {
Runtime runtime=Runtime.getRuntime();//获取实例化对象
System.out.println(runtime.availableProcessors());//8
}
}
但是除了以上的方法之外,在 Runtime类里面还提供有以下四个重要的操作方法:
-
获取最大可用内存空间: public long maxMemory()----默认的配置为本机系统内存的4分之1
-
获取可用内存空间: public long totalMemory()----默认的配置问本机系统内存的16分之1
-
获取空闲内存空间:public long freeMemory()
-
手工进行GC处理:public void gc()
package com.lut.JavaPlus;
public class BaseClass {
public static void main(String[] args) {
Runtime runtime=Runtime.getRuntime();//获取实例化对象
System.out.println("【1】MAX_MEMORY:"+runtime.maxMemory());
System.out.println("【1】TOTAL_MEMORY:"+runtime.totalMemory());
System.out.println("【1】FREE_MEMORY:"+runtime.freeMemory());
String str="";
for (int i = 0; i < 30000; i++) {
str+=i;//产生大量的垃圾空间
}
System.out.println("【2】MAX_MEMORY:"+runtime.maxMemory());
System.out.println("【2】TOTAL_MEMORY:"+runtime.totalMemory());
System.out.println("【2】FREE_MEMORY:"+runtime.freeMemory());
runtime.gc();//手动释放
System.out.println("【3】MAX_MEMORY:"+runtime.maxMemory());
System.out.println("【3】TOTAL_MEMORY:"+runtime.totalMemory());
System.out.println("【3】FREE_MEMORY:"+runtime.freeMemory());
}
}
面试题:请问什么是GC?如何处理?
GC(Garbage Collector)垃圾收集器,是可以由系统自动调用的垃圾释放功能,或者使用Runtime类中的gc()手工调用
System类
System类是一直陪伴着我们学习的程序类,之前使用的系统输出采用的就是 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 BaseClass {
public static void main(String[] args) {
long start= System.currentTimeMillis();
String str="";
for (int i = 0; i < 30000; i++) {
str+=i;//产生大量的垃圾空间
}
long end=System.currentTimeMillis();
System.out.println("程序耗时: "+(end-start));
}
}
在System类里面会发现也提供有一个gc()方法,但是这个gc()方法并不是重新定的gc()操作,就是Runtime的gc方法【Runtime.getRuntime().gc()】
Cleaner类
Cleaner是在 JDK1.9之后提供的一个对象清理操作,其主要的功能是进行 finialize()方法的替代。
在C++语言里面有两种特殊的函数:构造函数、析构函数(对象手工回收),在Java 里面所有的垃圾空间都是通过GC自动回收的,所以很多情况下是不使用这类析构函数的,也正是因为如此,所以Java并没有提供这方面支持。
但是Java 本身依然提供了给用户收尾的操作,每一个实例化对象在回收之前至少给它一个喘息的机会,最初实现对象收尾理的方法是 Object类中所提供的 finalize()方法,这个方法的定义如下:
@Deprecated(since=“9”) protected void finalize() throws Throwable
该替换指的是不建议继续使用这个方法了,而是说子类可以继续使用这个方法名称。但是这个方法上最大的特点是抛出了一个Throwable异常类型,而这个异常类型分为两个子类型:Eror、Exception,平常所处理的都是Exception。
范例:观察传统回收
class Member{
public Member(){
System.out.println("【构造】在一个雷电交加的日子里,XXX诞生了");
}
@Override
protected void finalize() throws Throwable {
System.out.println("【回收】人最终都会死的");
throw new Exception("我还想再活500年");
}
}
public class BaseClass {
public static void main(String[] args) {
Member member=new Member();//诞生
member=null;//成为垃圾
System.gc();
System.out.println("太阳照常升起");
}
}
/*
【构造】在一个雷电交加的日子里,XXX诞生了
太阳照常升起
【回收】人最终都会死的
*/
但是从JDK 1.9开始,这一操作已经不建议使用了,而对于对象回收释放。从JDK1.9开始建议开发者使用AutoCloseable或者使用java.Jlang.ref.Cleaner类进行回收处理(Cleaner也支持有AutoCloseable处理)。
在新一代的清除回收处理的过程之中,更多的情况下考虑的是多线程的使用,即:为了防止有可能造成的延迟处理,所有对象回收前的处理都是单独通过一个线程完成的。
//标注:未成功运行
package com.lut.JavaPlus;
import sun.misc.Cleaner;
class Member implements Runnable{
public Member(){
System.out.println("【构造】在一个雷电交加的日子里,XXX诞生了");
}
@Override
public void run() {
System.out.println("【回收】人最终都会死的");
}
}
class MemberCleaning implements AutoCloseable{ //实现清除的处理
private static final Cleaner cleaner=Cleaner.create();//创建一个清除处理
private Member member;
private Cleaner.Cleanable cleanable;
public MemberCleaning(){
this.member=new Member();//创建新对象
this.cleanable=this.cleaner.register(this,this.member);//注册使用的对象
}
@Override
public void close() throws Exception {
this.cleanable.clean();//启动多线程
}
}
public class BaseClass {
public static void main(String[] args) {
try(MemberCleaning memberCleaning=new MemberCleaning()) {
//中间执行一些先关的代码
}catch (Exception e){}
}
}
对象克隆
所谓的对象克隆指的就是对象的复制,而且属于全新的复制。
即:使用已有对象内容创建一个新的对象,如果要想进行对象克隆需要使用到Object类中提供的clone()方法:
protected Object clone() throws CloneNotSupportedException; .
所有的类都会继承Object父类,所以所有的类都一定会有 clone()方法,但是并不是所有的类都希望被克隆。所以如果要想实现对象克隆,那么对象所在的类需要实现一个Cloneable 接口,此接口并没有任何的方法提供,是因为它描述的是一种能力。
class Member implements Cloneable{
private String name;
private int age;
public Member(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "【"+super.toString()+
"Member{" +
"name='" + name + '\'' +
", age=" + age +
'}'+"】";
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();//调用父类提供的 clone方法
}
}
public class BaseClass {
public static void main(String[] args) throws CloneNotSupportedException {
Member memberA=new Member("AAA",30);
Member memberB=(Member) memberA.clone();
System.out.println(memberA.toString());
System.out.println(memberB.toString());
}
}
/*
【com.lut.JavaPlus.Member@4554617cMember{name='AAA', age=30}】
【com.lut.JavaPlus.Member@74a14482Member{name='AAA', age=30}】
*/
如果在开发之中不是非常特别的需求下,很少会出现有对象克隆的需求。
Cloneable接口没有方法,是一个能力的标识接口
二、数字操作类
Math数学计算类
程序就是一个数学的处理过程,所以在Java语言本身也提供有相应的数字处理的相关类库的支持:Math类
Math类的主要功能是进行数学计算的操作类,提供有基础的计算公式这个类的构造方法被私有化了,而且该类之中提供的所有方法都是static型的方法,即:这些方法都可以通过类名称直接调用。
public class JavaDemo01 {
public static void main(String[] args) {
System.out.println(Math.max(10,20));
System.out.println(Math.abs(-12.01));
System.out.println(Math.log(6));
System.out.println(Math.round(15.1));//15
System.out.println(Math.round(-15.1));//-15
System.out.println(Math.round(-15.6));//-16
}
}
虽然在Math类里面提供有四舍五入的处理方法,但是这个四舍五入字在进行处理的时候是直接将小数点后的所有位进行进位处理了,这样肯定不方便,那么现在最方便的做法是可以实现指定位数的保留。
class MathUtil{
private MathUtil() { }
/**
* 实现数据的四舍五入操作
* @mnum 要进行四舍五入操作的数字
* @scale 四舍五入保留的小数位数
* @return 四舍五入处理后的结果
*/
public static double round(double num,double scale){
return Math.round(num*Math.pow(10,scale))/Math.pow(10,scale);
}
}
public class JavaDemo01 {
public static void main(String[] args) throws Exception{
System.out.println(MathUtil.round(3141.5926,3));
System.out.println(MathUtil.round(3141.5926,2));
}
}
Math类里面提供的基本上都是基础的数学公式,需要的时候需要自己重新整合。
Random随机数生成类
java.util.Random类的主要功能是产生随机数的,这个类主要是依靠内部提供的方法来完成
- 产生一个不大于边界的随机正整: public int nextInt(int bound);
范例:产生随机数
public class JavaDemo01 {
public static void main(String[] args) throws Exception{
Random random=new Random();
for (int i = 0; i <10 ; i++) {
System.out.print(random.nextInt(100)+"、");
}
}
}
在国内有一款神奇的所谓的36选7的彩票,那么就可以利用Random实现随机生成
范例:随机生成彩票号
对于这里面的数字肯定不能有0,不能够重复
public class JavaDemo01 {
/*
*判断传入的数字是否为日以及是否在数组之中存在*@param num要判断的数字
*@param temp已经存在的数据
*@return如果该数字不是0并且可以使用返回true,否则返回false
*/
public static boolean isUse(int num,int temp[]){
if (num==0)
return false;
for (int i = 0; i < temp.length; i++) {
if (num==temp[i])
return false;
}
return true;
}
public static void main(String[] args) throws Exception{
int data[]=new int[7];//开辟七个大小的空间
Random random=new Random();
int foot=0;//脚标
while (foot<7){
int num=random.nextInt(37);
if (isUse(num,data)){
data[foot++]=num;
}
}
System.out.println(Arrays.toString(data));
}
}
以后这种随机的操作都可以利用Random来处理。
大数字处理类
在进行数学计算的过程里面还自一个大数子的操作类,可以实现海量数字的计算(能提供的也只是基础计算)
现在假设一个数字很大,超过了double范围,那么这个时候并没有任何一种数据类型可以保存下此类
可以使用String的方式
String strA= "120"
String strB = “230"
如果现在要想进行加法计算,那么就需要逐位拆分,每一位自己计算,而后自己独立控制进位处理,那么这样的开发难度是非常高的,所以为了解决这类问题,提供有两个大数字的操作类: BigInteger、BigDecimal。
之前分析了,当数字很大的时候只能够利用字符串描述数字操作,所以这一点可以观察两个大数字操作类的构造方法:
BigInteger类构造: public BigInteger(String val):
BigDecimal类构造:public BigDecimal(String val);
范例:使用 BigInteger实现四则运算
public class JavaDemo01 {
public static void main(String[] args) throws Exception{
BigInteger bigIntegerA=new BigInteger("1234567899635241");
BigInteger bigIntegerB=new BigInteger("9635241");
System.out.println("加法操作:"+bigIntegerA.add(bigIntegerB));
System.out.println("减法操作:"+bigIntegerA.subtract(bigIntegerB));
System.out.println("乘法操作:"+bigIntegerA.multiply(bigIntegerB));
System.out.println("除法操作:"+bigIntegerA.divide(bigIntegerB));
}
}
需要注意的是,虽然提供有大数字操作类,但是整体的操作之中还是需要考虑到一个性能问题
范例:观察性能问题
public class JavaDemo01 {
public static void main(String[] args) throws Exception{
BigInteger bigIntegerA=new BigInteger("1234567899635241");
System.out.println(bigIntegerA.pow(Integer.MAX_VALUE));
}
}
此时的计算过程是非常缓慢的,所以任何的电脑都是有极限的。既然在进行数学除法的时候有可能无法进行整除处理,那么,就可以使用其它的除法计算来求出余数:
求余: public BigInteger[ divideAndRemainder(BigInteger val),数组第一个元素为商,第二个为余数;
范例:求余除法
public class JavaDemo01 {
public static void main(String[] args) throws Exception{
BigInteger bigIntegerA=new BigInteger("1234567899635241");
BigInteger bigIntegerB=new BigInteger("9635241");
BigInteger result[]=bigIntegerA.divideAndRemainder(bigIntegerB);
System.out.println("商:"+result[0]+" 余数:"+result[1]);
}
}
如果在开发中真进行计算的时候,该计算没有超过基本数据类型所包含的位数强烈不建议使用大数字类,因为这种计算性性能很差的。
BigDecimal操作形式和 BigInteger是非常类似的,都有基础的数学支持。
范例:使用 BigDecimal计算
public class JavaDemo01 {
public static void main(String[] args) throws Exception{
BigDecimal bigA=new BigDecimal("1234567899635241");
BigDecimal bigB=new BigDecimal("96352412");
System.out.println(bigA.add(bigB));
// System.out.println(bigA.divide(bigB));
//当不整除出现无限循环小数时报错:ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
//可以通过设置小数位数的方式来解决
System.out.println(bigA.divide(bigB,3));
BigDecimal result[]=bigA.divideAndRemainder(bigB);
System.out.println("商:"+result[0]+" 余数:"+result[1]);
}
}
但是在使用BigDecimal的时候有一个数据进位问题,在这个类里面定义有如下的除法计算
除法计算:public BigDecimal divide(BigDecimal divisor,int scale,RoundingMode.HALF_UP)
范例:使用 BigDecimal实现四舍五入处理
class MathUtil{
private MathUtil() { }
/**
* 实现数据的四舍五入操作
* @mnum 要进行四舍五入操作的数字
* @scale 四舍五入保留的小数位数
* @return 四舍五入处理后的结果
*/
public static double round(double num,double scale){
// return Math.round(num*Math.pow(10,scale))/Math.pow(10,scale);
return new BigDecimal(num).divide(new BigDecimal(1.0), (int) scale, RoundingMode.HALF_UP).doubleValue();
}
}
public class JavaDemo01 {
public static void main(String[] args) throws Exception{
System.out.println(MathUtil.round(3141.5926,3));
System.out.println(MathUtil.round(3141.5926,2));
}
}
Math的处理由于使用的都是基本数据类型,所以性能一定要高于大数字处理类的。
三、日期操作类
Date日期处理类
从整体的java来讲一直在强调简单java类的主要设计来自于数据表的结构,那么在数据表的结构里面常用的类型:数字、字符串、日期,所以现在的程序之中只差日期了。
在Java里面提供有一个java.util.Date 的类,这个类如果直接实例化就可以获取当前日期
范例:观察java.util.Date类
public class JavaDemo01 {
public static void main(String[] args) throws Exception{
Date date=new Date();
System.out.println(date);
}
}
这个时候需要进一步去观察 Date类中的构造方法:
public Date() {
this(System. currentTimeMillis());
}
public Date(long date) {
fasttime = date;
}
通过以上的源代码分析可以得出一个结论:Date类中只是对long数据的一种包装。
所以 Date类中一定提供有所谓的日期与long.数据类型之间转换的方法:。
-
将long转为 Date: public Date(long date);
-
将Date转为 long: public long getTime(); .
范例:观察 Date 与 long 之间的转换
public class JavaDemo01 {
public static void main(String[] args) throws Exception{
Date date=new Date();
System.out.println(date);
long current=date.getTime();
current+=24*60*60*1000;//一天后
System.out.println(new Date(current));
}
}
long 之中可唤保存毫秒的数据级,这样方便程序处理
SimpleDateFormat日期处理
虽然Date可以获取当前的日期时间,但是默认情况下Date类输出的日期时间结构并不能够被国人所习惯,那么现在就需要欢显示的格式进行格式化的处理,为了可以格式化日期,在java.text包中提供有SimpleDateFormat程序类。
该类是DateFormati的子类,在该类中提供有如下的方法:
- 构造方法: public SimpleDateFormat(String pattern)
- 【DateFormat】将H期格式化: public final String format(Date date)
- 【DateFormat】将字符串转为日期: public Date parse(String source) throws ParseException
- 构造方法: public SimpleDateFormat(String pattern)
日期格式:年 (yyyy)、月(MM)、日(dd)、时(HH)、分(mm)、秒(ss)、毫秒(SSS);
范例:格式化日期显示
public class JavaDemo01 {
public static void main(String[] args) throws Exception{
Date date=new Date();
System.out.println(date);
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
String str=simpleDateFormat.format(date);
System.out.println(str);
}
}
除了可以将日期格式化为字符串之后,也可以实现字符串与日期之间转换处理。
范例:将日期转为Date
public class JavaDemo01 {
public static void main(String[] args) throws Exception{
String string="1888-12-18 13:24:60.666";
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Date date=simpleDateFormat.parse(string);
System.out.println(date);
}
}
如果在进行字符串定义的时候,所使用的日期时间数字超过了指定的合理范围,则会自动进行进位处理
范例:数字格式化
public class JavaDemo01 {
public static void main(String[] args) throws Exception{
double money=298635478.23;
String string= NumberFormat.getInstance().format(money);
System.out.println(string);
}
}
//298,635,478.23
通过到现在的学习发现,String字符串可以向所有类型转换,基本类型、日期类型。