String类是在所有项目开发之中一定会使用到的一个功能类,并且这个类拥有如下的特点:
String类最大的弊端:内容不允许修改。虽然大部分情况下都不会设计到字符串的内容的频繁修改,但是依然可能存在有着样的情况,所以为了解决此问题,专门提供了一个StringBuffer类可以实现内容的修改处理
StringBuffer类并不像String那样有两种对象实例化方法,StringBuffer必须像普通类对象那样首先进行对象的实例化,而后才可以调用方法执行处理而这个时候可以考虑使用StringBuffer类中的如下方法:
范例:String与StringBuffer对比
public class JavaAPIDemo {
public static void main(String[] args) {
String string = "Hello";
change(string);
System.out.println(string);
}
public static void change(String temp){ //内容并没有发生改变
temp = temp + "Hello !";
}
}
public class JavaAPIDemo {
public static void main(String[] args) {
StringBuffer string = new StringBuffer("Hello");
change(string);
System.out.println(string);
}
public static void change(StringBuffer temp){ //内容并没有发生改变
temp.append(" World !");
}
}
实际上大部分的情况下,很少会出现有字符串内容的改变,这种改变指的是并不是针对于静态常量池的改变
范例:分析一下已有问题
public class JavaAPIDemo {
public static void main(String[] args) {
String stringA = "www.shenmenglin.com";
String stringB = "www." + "shenmenglin" + ".com";
System.out.println(stringA == stringB);
}
}
这个时候的strB对象的内容并不算是改变,或者更加严格的意义上来讲,对于现在的strB当程序编译之后会变为如下的形式:
StringBuffer buf = new StringBuffer();
buf.append("www.").append("shenmenglin").append(".com");
所有的“+”在编译之后都变为了StringBuffer中的append()方法,并且在程序之中,String类与StringBuffer类本来就可以互相转换
在StringBuffer类里面除了可以支持有字符串中的内容的修改之外,实际上也提供了一些String类不具备的方法
public class JavaAPIDemo {
public static void main(String[] args) {
StringBuffer nuf = new StringBuffer();
buf.append(".cn").insert(0,"www").insert(0,"shenmenglin");
System.out.println(buf);
}
}
public class JavaAPIDemo {
public static void main(String[] args) {
StringBuffer nuf = new StringBuffer();
buf.append("Hello World !").delete(6,12).insert(6,"shenmenglin");
System.out.println(buf);
}
)
public class JavaAPIDemo {
public static void main(String[] args) {
StringBuffer nuf = new StringBuffer();
buf.append("Hello World !").delete(6,12).insert(6,"shenmenglin");
System.out.println(buf.reverse());
}
}
实际上与StringBuffer类还有一个类似的功能了类,StringBuilder类,这个类是在JDK1.5之后提供的,但是与StringBuffer类的功能一样,主要区别在于StringBuffer类中的方法属于线程安全的,全部使用了synchronized关键字进行了标注,而StringBuilder类属于非线程安全的
面试题:请解释String、StringBuffer、StringBuilder的区别?
CharSequence是一个描述字符串结构的接口,在这个接口里面一般发现有三种常用子类:
String类 | StringBuffer类 | StringBuilder类 |
---|---|---|
public final class String extends Object implements Serializable Comparaable,CharSequence | public final class StringBuffer extends Object implements Serializable,CharSequence | public final class StringBuilder extends Object implements Serializable,CharSequence |
现在只要有字符串就可以为CharSequence接口实例化
public class JavaAPIDemo {
public static void main(String[] args) {
CharSequence str = "www.shenmenglin.com";
}
}
CharSequence本身是一个接口,在该接口之中也定义有如下的操作方法;
CharSequence描述的就是一个字符串
AutoCloseable主要是用于日后进行资源开发的处理上,以实现资源的自动关闭(释放资源),例如:在以后进行文件、网络、以及数据库开发的过程之中由于服务器资源有限,所以使用之后一定要关闭资源,这样才可以被更多的使用者所使用
为了更好的说明资源的问题,将通过一个消息的发送处理来完成
范例:手工实现资源处理
interface IMessage{
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;
}
@Override
public void send() {
System.out.println("发送消息:" + msg);
}
public void close() {
System.out.println("OPEN : 关闭消息发送通道");
}
}
public class JavaAPIDemo {
public static void main(String[] args) {
NetMessage netMessage = new NetMessage("www.shenmenglin.com");
if (netMessage.open()){ //是否打开了连接
netMessage.send(); //消息发送
netMessage.close(); //关闭连接
}
}
}
既然所有的资源完成处理之后都必须进行关闭操作,AutoCloseable接口可以实现资源的自动关闭,AutoCloseable访问接口,这个接口是在JDK1.7的时候提供的,并且该接口只提供了一个方法:
要想实现自动关闭处理,除了要使用AutoCloseable之外,还小结合异常处理语句才能正常使调用
interface IMessage{
void send(); //消息发送
}
class NetMessage implements IMessage , AutoCloseable{ //实现消息的处理机制
private String msg;
public NetMessage(String msg) {
this.msg = msg;
}
public boolean open(){ //获取资源连接
System.out.println("OPEN : 获取消息发送连接资源");
return true;
}
@Override
public void send() {
System.out.println("发送消息:" + msg);
}
public void close() throws Exception{
System.out.println("OPEN : 关闭消息发送通道");
}
}
public class JavaAPIDemo {
public static void main(String[] args) throws Exception{
try (NetMessage netMessage = new NetMessage("www.shenmenglin.com")){
netMessage.send();
} catch (Exception e) {}
}
}
在以后的会经常接触资源关闭问题时,往往会见到AutoCloseable接口的使用
Runtime描述的是运行时的状态类,也就是说在整个JVM之中,Runtime类是唯一一个与JVM运行状态有关的类,并且都会默认提供有一个该类的实例化对象
由于在每一个JVM进程里面允许提供一个Runtime类的对象,所以这个类的构造方法被默认私有化了,那么就证明该类使用的是单例设计模式,并且单例设计模式一定会提供偶一个static方法获取本类实例
由于Runtime类属于与单例设计模式,如果想要获取实例化对象,可以依靠类中的getRuntime()方法完成
通过这个类中的availableProcessors()方法可以获取本机的内核数量
范例:获取Runtime类对象
public class JavaAPIDemo {
public static void main(String[] args) throws Exception{
Runtime runtime = Runtime.getRuntime(); //获取实例化对象
System.out.println(runtime.availableProcessors());
}
}
但是除了以上的方法之外,在Runtime类里面还提供有一下四个操作方法:
范例:观察内存状态
public class JavaAPIDemo {
public static void main(String[] args) throws Exception{
Runtime runtime = Runtime.getRuntime(); //获取实例化对象
System.out.println(runtime.availableProcessors());
System.out.println("最大可用空间:" + runtime.maxMemory());
System.out.println("可用空间:" + runtime.totalMemory());
System.out.println("空闲内存空间:" + runtime.freeMemory());
String string = "";
for (int i = 0; i < 100000; i++) {
string = string + i;
}
System.out.println("最大可用空间:" + runtime.maxMemory());
System.out.println("可用空间:" + runtime.totalMemory());
System.out.println("空闲内存空间:" + runtime.freeMemory());
runtime.gc();
}
}
面试题:请问什么是GC?如何处理?
经常用的系统输出就是采用的System类的方法,System类里面也定义有其他的方法:
数组拷贝:public static void arratcopy(Obejct src , int srcPos , Object dest , int destPos , int length)
获取当前的日期时间数值:public static long currentTimeMillis()
进行垃圾回收:public static void gc()
在System类中也提供有一个gc()方法,但是这个gc()方法并不是重新定义的新方法,而是继续执行了Runtime类中的gc()操作
Cleaner是在JDK1.9之后提供的一个对相爱那个清理操作,其主要功能是进行finalize()方法的代替。Java中有两种特殊的函数:构造、析构(对象手工回收),在Java里面所有的垃圾空间都是通过GC自动回收的,所以很多情况下,是不需要使用析构函数的,因此,Java并没有提供这方面的支持
但是Java本身依然提供了给用户收尾的操作,每个实例化对象在回收之前至少给一个喘息的机会,最初实现对象收尾处理的方法是Object类中提供的finalize()方法,
@Deprecated(since=“9”)
protrcted void finalize throws Throwable
该替换指的是不建议继续使用这个方法了,而是说子类可以继续使用这个方法名称。这个方法最大的特征是抛出了一个Throwable异常类型,而这个异常类型分为两个子类型:Error、Exception,平常所处理的都是Exception
范例:观察传统回收
class Member{
public Member(){
System.out.println("构造:出生了");
}
@Override
protected void finalize() throws Throwable {
System.out.println("我还要再活五百年");
throw new Exception();
}
}
public class JavaAPIDemo {
public static void main(String[] args) throws Exception{
Member member = new Member(); //诞生
member = null; //成为垃圾
System.gc();
System.out.println("去世");
}
JDK1.9之后建议开发者使用AutoCloseable或者Cleaner类进行回收处理
class Member implements Runnable{
public Member(){
System.out.println("构造:出生了");
}
@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 JavaAPIDemo {
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 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() + "name = " + name + "、age = " + age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); //调用父类中提供的clone方法
}
}
public class JavaAPIDemo {
public static void main(String[] args) throws Exception{
Member memberA = new Member("沈梦琳" , 18);
Member memberB = (Member) memberA.clone();
System.out.println(memberA);
System.out.println(memberB);
}
}
如果在开发之中不是非常特别的需求下,很少会出现有对象克隆的需求
程序就是一个数学的处理过程,所以在Java语言本身也提供有相应的 妹子处理的类支持
Math类的主要功能是进行数学计算的操作类,提供有基础的计算公式,这个类的构造方法被私有化了,而且该类之中提供的所有方法都是static方法。即:都是可以通过类名直接调用的
在Math类里面提供有四舍五入的处理方法,但是这个四舍五入在进行处理的时候直接将小数点后的所有位数进行了进位处理了,这样肯定不方便,那么现在最方便的做法是可以实现指定位数的保留
范例:
class MathUtil{
private MathUtil() {}
/**
* 实现数据库的四舍五入操作
* @param num 要进行四舍五入操作的数字
* @param scale 四舍五入保留的小数位数
* @return 四舍五入处理后的结果
*/
public static double round(double num , int scale){
return Math.round(num * Math.pow(10 , scale) / Math.pow(10 , scale));
}
}
public class JavaAPIDemo {
public static void main(String[] args) throws Exception{
System.out.println(MathUtil.round(19.86273 , 2));
}
}
Math类里面提供的基本上都是基础的数学公式,需要的时候需要自己重新整合
Random类主要功能是产生随机数的,这个类主要依靠内部提供的方法完成:
产生一个不大于边界的随机正整数:public int nextInt(int bound)
这里的参数bound是产生随机数的范围
在进行数学计算的过程里面还有一个大数字的操作类,可以实现海量数字的计算(只能提供基础的计算)
当一个数很大,超过了double的范围。在以前通常采用String类来保存这种数据,而进行计算的时候,需要逐位拆分,每一位自己计算,而后自己独立控制进位处理,开发难度较高。因此提供了两个大数字类操作类:BigInteger、BigDecimal
范例:观察四则运算
public class JavaAPIDemo {
public static void main(String[] args) throws Exception{
BigInteger bigA = new BigInteger("232322386465465465465465465465466546546232323232323232");
BigInteger bigB = new BigInteger("32323254654654654654654654654654");
System.out.println("加法操作:" + bigA.add(bigB));
System.out.println("减法操作:" + bigA.subtract(bigB));
System.out.println("乘法操作:" + bigA.multiply(bigB));
System.out.println("除法操作:" + bigA.divide(bigB));
}
}
需要注意的是,虽然提供有大数字操作类,但是整体的操作还是需要考虑到一个性能问题
当已经超过支持的范围时,就会报错
在开发中进行计算时,党计算没有超过基本数据类型包含的位数时,还是不建议使用大数字类,因为这种计算性能还是比较差的
范例:观察BigDecimal
public class JavaAPIDemo {
public static void main(String[] args) throws Exception{
BigDecimal bigA = new BigDecimal("123456789123456789");
BigDecimal bigB = new BigDecimal("123456789");
System.out.println("加法计算:" + bigA.add(bigB));
BigDecimal[] result = bigA.divideAndRemainder(bigB);
System.out.println("除法计算:" + result[0] + "、余数:" + result[1]);
}
}
但是在使用BigDecimal的时候有一个数据进位问题,在这个类里面定义有如下的除法计算
范例:使用BigDecimal实现四舍五入处理
class MathUtil{
private MathUtil() {}
/**
* 实现数据库的四舍五入操作
* @param num 要进行四舍五入操作的数字
* @param scale 四舍五入保留的小数位数
* @return 四舍五入处理后的结果
*/
public static double round(double num , int scale){
return new BigDecimal(num).divide(new BigDecimal(1.0) , scale
, RoundingMode.HALF_UP).doubleValue();
}
}
public class JavaAPIDemo {
public static void main(String[] args) throws Exception{
System.out.println(MathUtil.round(19.6352 , 2));
}
Math的处理由于使用的都是基本数据类型,所以性能一定是高于大数字处理类的
从整体的java 来讲一直强调简单Java类的主要设计来自于数据表的结构,在数据表的结构里面常用的类型:数字、字符串、日期
观察Date类中的构造方法:
public Date(){
this.(System.currentTimeMillis());
}
public Date(long date){
fastTime = date;
}
Date类中知识对long数据的一种包装,所以Date类中一定提供由于日期时间与long数据类型的转换方法:
public class JavaAPIDemo {
public static void main(String[] args) {
Date date = new Date();
long current = date.getTime();
current = current + 864000 * 1000; //十天的秒数
System.out.println(new Date(current)); //long转为了Date
}
}
long之中可以保存毫秒的数据皆,这样方便程序处理
日期格式化
虽然Date可以获取当前的日期时间,但是默认情况下Date类输出的日期时间结构,并不能被国人所习惯,因此需要对日期显示的格式进行格式化处理。在java.text包中提供有SimpleDateFormat程序类,该类是DateFormat的子类,在该类汇总提供有如下的方法:
**DateFormat继承 **将日期格式化:public final String format(Date date)
DateFormat继承 将字符串转为日期:public Date parse(String source) throws ParseException
构造方法:public SimpleFateFormat(String pattern)
日期格式:年(yyyy)月(MM)日(dd)时(HH)分(mm)秒(ss)毫秒(SSS)
范例:格式化日期格式
public class JavaAPIDemo {
public static void main(String[] args) {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
String string = sdf.format(date);
System.out.println(string);
}
}
当然,除了可以将日期格式化为字符串之后,也可以实现字符串与日期之间的格式转换
但是,如果所使用的日期时间数字超过了指定的合理范围,则会自动进位处理。当然,可以进行数字的格式化
String字符串可以向所有类型转换,基础类型、日期类型都可以
下一篇:正则表达式