第十五次 java作业

本文详细介绍了Java编程中的包装类,包括自动装箱、拆箱、构造器以及常用方法。同时,文章讲解了日期处理,涉及java.util.Date、java.sql.Date、SimpleDateFormat、Calendar以及JDK1.8新增的日期时间API。此外,还讨论了Math类、Random类和String类的相关知识点,如String的内存分析和StringBuilder与StringBuffer的区别。

目录

包装类

包装类-引用

包装类 - 常用属性 - 常用构造器

包装类 - 自动装箱 - 自动拆箱

包装类 - 常用方法

日期类

日期相关 - java.util.Date

日期相关 - java.sql.Date

日期相关 - SimpleDateFormat

日期相关 - Calendar

日期相关 - Calendar练习需求

日期相关 - JDK1.8新增日期时间API的原因

日期相关 - JDK1.8新增日期时间API - LocaLDate,LocaLTime,LocalDateTime

日期相关 - DateTimeFormatter

Math 类

Random 类

String类

String 的本质

String 的常用方法

String 的内存分析

StrinngBuilder 类

StringBuilder 和 StringBuffer

String、StringBuffer、StringBuilder区别与联系


 包装类

包装类-引用

1. 什么是包装类

以前定义变量,经常使用基本数据类型,对于基本数据类型,它就是一个数。加点属性,加点方法,加点构造器,对基本数据类型对应进行了封装产生了一个新的类,这种类叫包装类(改造基本数据类型的的类)。

int, byte...-->基本数据类型

包装类 -->引用数据类型

2. 基本数据类型对应的包装类 

基本数据类型包装类继承关系
byteByte--->Number--->Object
shortShort--->Number--->Object
intInteger--->Number--->Object
longLong--->Number--->Object
floatFloat--->Number--->Object
doubleDouble--->Number--->Object
charCharacter--->Object
booleanBoolean--->Object

3.为什么要把基本数据类型封装为包装类

1.Java语言,面向对象的语言,最擅长的操作各种各样的类

2.以前学习装数据的---> 数组,int[] String[] double[] Student[]

3.以后学习装数据的---> 集合,有一个特点,只能装引用数据类型的数据

包装类 - 常用属性 - 常用构造器

打开Java api文档,搜索Integer开始学习 

  1. 从属与java.lang包(属于这个包意味着直接使用,不用导入包)

  2. 类的继承关系

    java.lang.Object
    ​java.lang.Number
    java.lang.Integer
  3. 实现接口 

  4. 被final修饰,那么这个类不能有子类,不能被继承

  5. 包装类是对基本数据类型的封装:对int类型封装产生了Integer。

  6. 类的历史

  7. 字段摘要 Field Summary

    public class test1 {
            //这是一个main方法,是程序的人口
            public static void main(String[] args){
                //属性:
                System.out.println(Integer.MAX_VALUE);
                System.out.println(Integer.MIN_VALUE);
                //“物极必反”原理:
                System.out.println(Integer.MAX_VALUE+1);
                System.out.println(Integer.MIN_VALUE-1);
            }
    }

  8. 构造方法摘要,可以在idea上点进去看

public class Test02{
	public static void main(String[] args) {
        Integer i1 = new Integer(12);
        System.out.println(i1.toString());
	}
}

 

(1)int类型作为构造器的参数 

 Integer i1 = new Integer(39);//Integer方法构造

 

(2)String类型作为构造器的参数 

Integer i2 = new Integer("12");
Integer i3 = new Integer("abcdef");

包装类 - 自动装箱 - 自动拆箱

9.包装类特有的机制:自动装箱、自动拆箱 

public class Test03{
public static void main(String[]args){
    Integer i = 12; 
    System.out.println(i);
    //自动拆箱:Integer--->int
        Integer i2 = new Integer(12);
        int num = i2;
        System.out.println(num);
    }
}

(1) 自动装箱   自动拆箱  是从jdk1.5以后新出的特征.

(2)自动装箱      自动拆箱 :将基本数据类型和包装类进行快速的类型转换.

包装类特有机制,拆箱装箱(底层使用了方法完成,velueOf() 和 intValue() )可以自行断点查看

//自动装箱,int直接变成Integer
Integer i = 3;
//自动拆箱,Interger直接变成int相加
System.out.println(i+1);

包装类 - 常用方法

10.常用方法

 常用方法,主要查看JavaAPI文档自学,下面列举主要几个方法,可以在idea点进方法查看底层

public class Test04 {
    //这是一个main方法,是程序的人口:
    public static void main(String[] args){
        //compareTo:只返回三个值:要么是0,-1,1 
        Integer i1 = new Integer(value:6); 
        Integer i2 = new Integer( value:12);
        System.out.println(i1.compareTo(i2));// return(x<y)?-1:((x==y)?0:1)
        //eauals:Inteaer对Obiect中的eauals方法进行了重写,比较的是底层封装的那个value的值。
        //Integer对象是通过new关键字创建的对象: 
        Integer i3 = new Integer(value: 12); 
        Integer i4 = new Integer(value: 12);
        System.out.println(i3 == i4);//false因为比较的是两个对象的地址 
        boolean flag = i3.equals(i4); 
        System.out.println(flag);
        //Integer对象通过自动装箱来完成: 
        Integer i5 = 130;
        Integer i6 = 130;
        System.out.println(i5.equals(i6));//true 
        System.out.println(i5==i6);
        /*
        如果自动装箱值在-128~127之间,
        那么比较的就是具体的数值否在,比较的就是对象的地址
        */
        //intValue():作用将Integer--->int 
        Integer i7 = 130;
        int i= i7.intValue();
        System.out.println(i);
        //parseInt(String s) :String--->int: 
        int i8=Integer parseInt(s:"12"); 
        System.out.println(i8);
        //toString:Integer--->String 
        Integer i10 = 130;
        System.out.println(i10.toString());
    }
}

1.comperTo() 在数字上比较两个Integer对象。

2.equals()将对象和指定对象进行比较。

3.intValue()以 int 类型返回该Integer的值

4.parseInt()将字符串转成 int 类型

5.toString()返回一个表示该Integer的字符串

日期类

日期相关 - java.util.Date

Date()类

1.基本概念:

java.util.Date类用于描述日期信息:年月日时分秒,可以精确到毫秒。1秒=1000毫秒。

2.常用方法:

Date()

用于无参的方式构造对象,默认使用当前的系统时间。

Date(long date)

根据参数指定的毫秒数来构造对象

其中参数为距离1970年1月1日0时0分0秒的毫秒数(与File类搭配使用)

Date getTime()

获取当前对象距离1970年1月1日0时0分0秒的毫秒数

Date setTime(long time)

用于设置当前对象的时间为参数指定的毫秒数,距离标准时间

import java.util.Date;
	public class Test {
		//这是一个main方法·是程序的人口:
		public static void main(String[] args){
				//java.util.Date:
				Date d=new Date(); 
				System.out.println(d);
				System.out.println(d.toString());
				System.out.println(d.toGMTString());//过期方法·过时方法·废弃方法。 
				System.out.println(d.toLocaleString());
				System.out.println(d.getYear());//122+1900=2022
				System.out.println(d.getMonth());//5:返回的值在日和11之间·值日表示1月
				//返回自1970年1月1日00:00:00GMT以来此Date对象表示的毫秒数。 
				System.out.println(d.getTime());
				System.out.println(System.currentTimeMillis());
	}
}

 

获取时间差用currentTimeMiLLis()因为这个方法是静态的,可以类名,方法名直接调用
public static native long currentTimeMillis();因为这个方法的具体实现不是通过java写的。                 作用:一般会去衡量一些算法所用的时间

public class Test {   
			public static void main(String[] args){
				long startTime = System.currentTimeMillis(); 
				for (int i = 0; i < 100000; i++) {
					System.out.println(i);
					long endTime=System.currentTimeMillis(); 
					System.out.println(endTime-startTime);
		}
	}
}

 

日期相关 - java.sql.Date

        Java中的java.sql.Date类适用于JDBC(数据库连接)API,如果你需要往java.sql.PreparedStatement中设置日期,或从java.sql.ResultSet中读取日期,你会用到java.sql.Date的。

        其实java.sql.Date是java.util.Date的派生类(继承),所以任何你在java.util.Date上能做的事,你也可以在java.sql.Date上做。

创建一个java.sql.Date对象的代码如下:

long time = System.currentTimeMillis();
java.sql.Date date = new java.sql.Date(time);

  java.sql.Date和java.util.Date最大的不同在于java.sql.Date只记录日期,而没有具体这一天的时间。所以举例来说,如果当前是2009-12-24 23:20,你创建一个java.sql.Date将只记下2009-12-24这个信息。若你需要保留时间进行JDBC操作,请使用java.sql.Timestamp代替。

import java.sql.Date;
public class Text {
    public static void main(String[] args){
        //java.sql.Date:
        Date d = new Date(1592055964263L);
        System.out.println(d);
        java.util.Date date = new Date(1592055964263L);//创建util.Date的对象
        Date date1=(Date) date;
        Date date2 = new Date(date.getTime());
        java.util.Date date3=d;
        Date date4 = Date.valueOf("2020-5-7");
    }
}

 

日期相关 - SimpleDateFormat

从前台过来的日期数据一般都是有格式的String,需要转换成util.Date类型

1.String-->sql.Date

2.sql.Date-->util.Date

1.基本概念:

java.text.SimpleDateFormat类用于格式化和解析日期,也就是实现日期类型和字符串之间的相关转换。

2.常用方法:

SimpleDateFormat(String pattern)

根据参数指定的字符串模式来构造对象。

y代表年,M代表月,d代表日,H代表时,m代表分,s代表秒

public final String format(Date date)

用于将Date类型转换成String类型

public Date parse(String source) throws ParseException

用于将String类型转换成Date类型

public class Test04 {
    public static void main(String[] args) {
    java.sql.Date date = java.sql.Date.valueOf("2022-5-26");
    java.util.Date date2 = date;
    System.out.println(date2.toString());
    }
}

 

 上面的代码有局限性,字符串的格式只能是年-月-日拼接的形式,换成其它类型,就会出现异常: 

 3.引入新类DateFormat

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test {
    //这是一个main方法,是程序的入口:
    public static void main(String[] args){
        //日期转换:
        //SimpleDateFormat(子类) extends DateFormat(父类是一个抽象类)
        //格式化的标准已经定义好了:
        DateFormat df =new SimpleDateFormat("yyyy-MM-ddHH:mm:ss");
        //String--->Date
    try {
        Date d=df.parse("2019-4-6 12:23:54"); 
        System.out.println(d);
    } catch (ParseException e){
        e.fillInStackTrace();
    }
    //Date--->String
    String format=df.format(newDate()); 
    System.out.println(format);
    Date date = new Date();
    System.out.println(date.toString()); 
    System.out.println(date.toGMTString());
    System.out.println(date.toLocaleString());
    }
	private static Date newDate() {
		// TODO Auto-generated method stub
		return null;
	}
}

日期相关 - Calendar

1.基本概念:

java.util.Calendar类用于描述日期信息的,该类中很多方法取代了Date类的过时方法。

该类是一个抽象类,不能实例化对象。

2.常用方法:

static Calendar getInstance()

用户获取当前类的引用

该方法的返回值真正指向的是Calendar类的子类对象,这是多态的第三种用法。

void set(int year, int month, int date, int hourOfDay, int minute, int second)

根据参数设置年月日时分秒。

Date getTime()

用于将Calendar类型转换为Date类型并返回。

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test {
    public static void main(String[] args){
        DateFormat df =new SimpleDateFormat( pattern:"yyyy-MM-ddHH:mm:ss");
    try {
        Date d=df.parse( source:"2019-4-6 12:23:54"); 
        System.out.println(d);
    } catch (ParseException e){
        e.fillInStackTrace();
    }
    String format=df.format(newDate()); 
    System.out.println(format);
    Date date = new Date();
    System.out.println(date.toString()); 
    System.out.println(date.toGMTString());
    System.out.println(date.toLocaleString());
    }
	private static Date newDate() {
		return null;
	}
}

日期相关 - Calendar练习需求

import java.util.Calendar;
import java.util.Scanner;
public class Test {
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) {
        //录入日期的string:
        Scanner sc=new Scanner(System.in);
        System.out.print("请输入你想要查看的日期:(提示:请按照例如2022-5-26的格式书写)");
        String strDate=sc.next();
        //System.out.println(strDate);
        //String--->Calendar:
        // String-->Date:
        java.sql.Date date = java.sql.Date.valueOf(strDate);
        //Date--->Calendar:
        Calendar cal=Calendar.getInstance(); cal.setTime(date);
        //后续操作:
        // 星期提示:
        System.out.println("日\t一\t二\t三\t四\t五\t六\t");
        //获取本月的最大天数:
        int maxDay=cal.getActualMaximum(Calendar.DATE);//获取当前日期中的日:
        int nowDay=cal.get(Calendar.DATE);
        //将日期调为本月的1号:
        cal.set(Calendar.DATE,1);//获取这个一号是本周的第几天
        int num =cal.get(Calendar.DAY_OF_WEEK);
        //System.out.println(num);
        //前面空出来的天数为:
        int day =num -1;//引入一个计数器:
        int count=0;//计数器最开始值为0//在日期前将空格打印出来:
        for (int i = 1; i <= day; i++) {
            System.out.print("\t");
        }
            //空出来的日子也要放入计数器 count = count + day;
            count = count +day;
            //遍历:从1号开始到maxDay号进行遍历:
            for (int i = 1; i <= maxDay ;i++) {
                if(i==nowDay){//如果遍历的和当前日子一样的话,后面多拼一个*
                    System.out.print(i+"*"+"\t");
                }else{
                    System.out.print(i+"\t");}
                count++;//每在控制台输出一个数字,计数器做加1操作
                if(count%7 == 0){//当计数器的个数是7的倍数的时候,就换行操作
                    System.out.println();
           }
        }
    }
}

日期相关 - JDK1.8新增日期时间API的原因

1.可变性和不可变性不合理(不应该有set方法,不应该可以改日历,一个日历对象仅仅永远只能是一个时间,不可变)

2.偏移性:getYear(),是从1900开始的,有偏移性

3.格式化,格式化只能对Date格式化,而不能对Calendar格式化

日期相关 - JDK1.8新增日期时间API - LocaLDate,LocaLTime,LocalDateTime

get方法

with方法(不可变体现)

加减方法

toString() (无偏移性体现

LocaLDate:日期

LocaLTime:时间

LocalDateTime:日期+时间

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
public class Test {
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) {
        //1.完成实例化:
        // 方法1:now()--获取当前的日期,时间    日期+时间
        LocalDate localDate=LocalDate.now();
        System.out.println(localDate);
        LocalTime localTime = LocalTime.now();
        System.out.println(localTime);
        LocalDateTime localDateTime=LocalDateTime.now();
        System.out.println(localDateTime);
        //方法2:of()--设置指定的日期,时间,日期+时间
        LocalDate of = LocalDate.of(2010,5,6);
        System.out.println(of);
        LocalTime of1 = LocalTime.of(12,35,56);
        System.out.println(of1);
        LocalDateTime of2 = LocalDateTime.of(1890,12,23,13,24,15);
        System.out.println(of2);
        //LocaLDate,LocaLTime用的不如LocalDateTime多
        // 下面讲解用LocaLDateTime:
        // 一系列常用的get***
        System.out.println(localDateTime.getYear());//年
        System.out.println(localDateTime.getMonth());//月(英语)
        System.out.println(localDateTime.getMonthValue());//月(数字)
        System.out.println(localDateTime.getDayOfMonth());//日
        System.out.println(localDateTime.getDayOfWeek());//星期
        System.out.println(localDateTime.getHour());//时
        System.out.println(localDateTime.getMinute());//分
        System.out.println(localDateTime.getSecond());//秒
        //不是set方法,叫with//体会:不可变性
        LocalDateTime localDateTime2=localDateTime.withMonth(8);
        System.out.println(localDateTime);
        System.out.println(localDateTime2);
        //提供了加减的操作:
        // 加:
        LocalDateTime localDateTime1=localDateTime.plusMonths(4);
        System.out.println(localDateTime);
        System.out.println(localDateTime1);
        //减:
        LocalDateTime localDateTime3=localDateTime.minusMonths(5);
        System.out.println(localDateTime);
        System.out.println(localDateTime3);
    }
}

 

日期相关 - DateTimeFormatter

 用于转换LocalDateTime等与String转换的定义和规范.

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.TemporalAccessor;
public class Test {
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) {
        //格式化类:DateTimeFormatter
        //方式一:预定义的标准格式。如:ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
        DateTimeFormatter df1 = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
        //df1就可以帮我们完成LocalDateTime和string之间的相互转换:
        // LocalDateTime-->String:
        LocalDateTime now=LocalDateTime.now();
        String str = df1.format(now);
        System.out.println(str);//2020-06-15T15:02:51.29
        //String--->LocalDateTime
        TemporalAccessor parse = df1.parse("2020-06-15T15:02:51.29");
        System.out.println(parse);
        DateTimeFormatter df2 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
        //LocalDateTime-->String:
        LocalDateTime now1 = LocalDateTime.now();
        String str2 = df2.format(now1);
        System.out.println(str2);
        //String--->LocalDateTime
        TemporalAccessor parse1 = df2.parse("2022/5/7 下午9:02");
        System.out.println(parse1);
        //方式三:自定义的格式。如:ofPattern("yyyy-MM-dd hh:mm:ss")---》重点,以后常用
        DateTimeFormatter df3 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm;ss");
        //LocalDateTime-->String:
        LocalDateTime now2 = LocalDateTime.now();
        String format = df3.format(now2);
        System.out.println(format);//2020-06-15 03:22:03
        //String--->LocalDateTime
        TemporalAccessor parse2 = df3.parse("2022-05-07 09:15;34");
        System.out.println(parse2);
    }
}

Math 类

1.直接使用,无需导包:

package java.lang;

2.final修饰类,这个类不能被继承:

public final class Math { 
}

3.构造器私有化,不能创建Math类的对象:

/**
* Don't let anyone instantiate this class.
*/
private Math() {
}

不能:

public static void main(String[] args) {
    Math m=new Math();
}

4.Math内部的所有的属性,方法都被static修饰:类名.直接调用,无需创建对象:

public static final double PI = 3.14159265358979323846;
/**
* Returns the trigonometric sine of an angle. Special cases:<ul><li>If the argument is NaN * * or an infinity, then the* result is NaN.
* <li>If the argument is zero, then the result is a zero with the same sign as the argument.    * </ul>
*
* <p>The computed result must be within 1 ulp of the exact result.* Results must be semi-
* monotonic.
*
* @param        a        an angle, in radians. 
* @return the sine of the argument.
*/
@Contract(pure=true) public static double sin(double a) { return StrictMath.sin(a)}
public class Test {
    //这是一个main方法,是程序的入口: 
    public static void main(String[] args) {
        //常用属性:
        System.out.println(Math.PI);//常用方法:
        System.out.println("随机数:"+Math.random());//[0.0,1.0)
        System.out.println("绝对值:"+Math.abs(-80));
        System.out.println("向上取值:"+Math.ceil(9.1));
        System.out.println("向下取值:"+Math.floor(9.9));
        System.out.println("四舍五入:"+Math.round(3.5));
        System.out.println("取大的那个值:"+Math.max(3,6));
        System.out.println("取小的那个值:"+Math.min(3,6));
 
    }
}

import static java.lang.Math.*;
public class Test {
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) {
        //常用属性:
        System.out.println(PI);//常用方法:
        System.out.println("随机数:"+random());//[0.0,1.0)
        System.out.println("绝对值:"+abs(-80));
        System.out.println("向上取值:"+ceil(9.1));
        System.out.println("向下取值:"+floor(9.9));
        System.out.println("四舍五入:"+round(3.5));
        System.out.println("取大的那个值:"+max(3,6));
        System.out.println("取小的那个值:"+min(3,6));
    }
    //如果跟Math中方法重复了,那么会优先走本类中的方法(就近原则)
    public static int random(){
        return 100;
    }
}

 

Random 类

       Random类中实现的随机算法是伪随机,也就是有规则的随机。在进行随机时,随机算法的起源数字称为种子数(seed),在种子数的基础上进行一定的变换,从而产生需要的随机数字。相同种子数的Random对象,相同次数生成的随机数字是完全相同的。也就是说,两个种子数相同的Random对象,第一次生成的随机数字完全相同,第二次生成的随机数字也完全相同。这点在生成多个随机数字时需要特别注意。 

Random对象的生成

Random类包含两个构造方法,下面依次进行介绍:
(1)public Random()
该构造方法使用一个和当前系统时间对应的相对时间有关的数字作为种子数,然后使用这个种子数构造Random对象。
(2)public Random(long seed)
该构造方法可以通过制定一个种子数进行创建。
示例代码:

Random r = new Random();
Random r1 = new Random(10);

再次强调:种子数只是随机算法的起源数字,和生成的随机数字的区间无关。

import java.util.Random;
public class Test{
	//这是一个main方法,是程序的入口:
	public static void main(String[] args) {
		//返回带正号的 double 值,该值大于等于0.0 且小于 1.0。 
		System.out.println("随机数:"+Math.random());
		//学习Random类
		//(1)利用带参数的构造器创建对象:
		Random r1 =new Random(System.currentTimeMillis()); 
		int i=r1.nextInt();
		System.out.println(i);
		//(2)利用空参构造器创建对象:
		Random r2 =new Random();//表面是在调用无参数构造器,实际底层还是调用了带参构造器
		System.out.println(r2.nextInt(10));//在0(包括)和指定值(不包括)之间均匀分布的 int值。 
		System.out.println(r2.nextDouble());//在0.0和 1.0之间均匀分布的 double 值。
	}
}

 

String类

String 的本质

1.将字符串起来,就是字符串,是不可变类

2所有的字符串都是一个实例化出来的对象,例如"abc","你好世界","helloworld"等。

3.字符串内容不可变,类比LocalDateTime类的不可变性。

4.String底层是一个char类型的数组

String 的常用方法

1.String()空参构造器,给出一个空的value。

2.String(String original),将original的value和hash给到正构造的String对象。

3.String(char value[]),将value数组中的值复制到正构造的String对象的属性value中。

4.length(),字符串底层数组长度。

5.isEmpty(),字符串底层数组是否为空。

6.charAt(int index),字符串中底层数组相对应下标的对应值。

7.equals(Object object),比较两个字符串是否值相等,已被重写。

8.compareTo(String anotherString),对比两个字符串,实现了一个Comparable接口,需要重写compareTo方法,已被重写。

构造器:底层就是给对象底层的value数组进行赋值操作。
通过构造器来创建对象: 

String s1 = new String();
String s2 = new String("abc");
String s3 = new String(new char[] {'a' 'b' 'c'});

常用方法

String s4 = "abc";
System.out.println("字符串的长度为:"+s4.length());
String s5 =new String("abc");
System.out.println("字符串是否为空:"+s5.isEmpty());
System.out.println("获取字符串的下标对应的字符为:"+s5.charAt(1));

equals:

String s6 = new String("abc");
String s7 = new String("abc");
System.out.println(s6.equals(s7));

String类实现了Comparable,里面有一个抽象方法叫compareTo,所以String中一定要对这个方法进行重写:

String s8 = new string("abc");
String s9 = new string("abc");
System.out.println(s8.compareTo(s9));

其他常用方法

//字符串的截取:
String s10 = "abcdefhijk";
System.out.println(s10.substring(3));
System.out.println(s10.substring(3,6));//[3,6)
//字符串的合并/拼接操作:
System.out.println(s10.concat("pppp"));
//字符串中的字符的替换:
String s11 = "abcdeahija";
System.out.println(s11.replace( oldChar: 'a', newChar: 'u'));
//按照指定的字符串进行分裂为数组的形式:
String s12 = "a-b-c-d-e-f";
String[] strs = s12.split( regex: "-");
System.out.println(Arrays.toString(strs));
//转大小写的方法:
String s13 = "abc";
System.out.println(s13.toUpperCase());
System.out.println(s13.toUpperCase().toLowerCase())
//去除收尾空格:
String s14 =" abc "; 
System.out.println(s14.trim());//tostring()
string s15="abc";
System.out.println(s15.tostring());
//转换为string类型:
System.out.println(string.valueOf(false));

String 的内存分析

        String在常量池中放置了一个变量,如果后续有结果相同的变量那就不会在增加一个变量,比如String s = "abc";后续如果再来了一个String s1 = "ab"+"c",常量池中也只会有一个"abc",不会有两个。但是注意使用String(String original)构造的String对象则不同。

String s = "1"+"23";
String s1 = "12"+"3";
String s2 = "1"+"2"+"3";
String s3 = "123";
String s4 = "123"+"";
System.out.println(s4 == s1);//true
System.out.println(s2 == s3);//true

上面的字符串会进行编译优化,合并成完整的字符串,可使用反编译工具查看class文件如下:

 

 然后在常量池中,常量池的特点是第一次如果没有这个字符串,就放进去,如果有这个字符串,就直接从常量池中取:

​ 使用new 创建String: 

String s6 = new String("123");System.out.println(s6 == s4);//false

 拼接字符串分析:

String s = "abc";
String b = s + "def";
System.out.println(b);

反汇编,借助反汇编来分析整个底层做的事情:

进行反汇编命令后得到反汇编代码,我们观察:

        在观察中知道用了两次append,所以在使用变量a和"def"进行拼接的时候,不会进行编译优化,不会直接变成"abcdef",而是会使用StringBuilder类中的方法进行追加。

StrinngBuilder 类

可变字符串类有:StringBuilder类,StringBuffer类

不可变字符串类:String类

分析构造器与append()

StringBuilder sb = new StringBuilder();//表面是空的构造器,底层对value数组初始化长度为16
StringBuilder sb1 = new StringBuilder(3);//底层对value数组初始化长度为3
StringBuilder sb2 = new StringBuilder("abc");//底层对value数组初始化长度为3
sb2.append("aaa").append("bbbbbb").append("ccccccccc").append("ddddddddddddd");//链式调用  return this

        构造器中的StringBuilder(String str)底层调用的是append的方法,我们着重分析append方法。

        在使用StringBuilder(String str)时,首先会根据str的长度,在后面加上16,以这个长度构成StringBuilder的value长度,比如str="abc",则StringBuilder的value长度就会使3+16=19 。

        在一个StringBuilder的对象中使用append(String str)的时候,父类抽象类AbstractStringBuilder类的底层代码会观察你追加的长度是否已经超过当前StringBuilder对象的value长度。

        如果长度没有超过,则直接将str中的char value[]中的值 从开头 复制到 StringBuilder对象中的char value[]最后一个字符后。

        如果长度超过了,则会先对StringBuilder中的char value[]进行扩容至充足,过程:创建一个新的足够长度的char value[],并且将原有(还没有追加的)字符串复制到新的char value[]中,然后就将str中的char value[]中的值 从开头 复制到 StringBuilder对象中的char value[]最后一个字符后。

public class Test {
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) {
        //创建StrinqBullder的对象:
        StringBuilder sb3 = new StringBuilder();
        //表面上调用StrinqBuilder的空构造器,实际底层是对value数组进行初始化,长度为16
        StringBuilder sb2 =new StringBuilder(3);
        //表面上调用StringBuilder的有参构造器,传入一个int类型的数,实际底层就是对 ivalue数组进行初始化,长度为你传入的数字
        StringBuilder sb = new StringBuilder("abc");
        sb.append("def") . append("aaaaaaaa"). append("bbb").append("ooooooo");//链式调用方式: return this
        System.out.println(sb.append("def") . append("aaaaaaaa"). append("bbb").append("ooooooo"));
    }
}

理解可变和不可变的含义

StringBuilder sb = new StringBuilder();
System.out.println(sb.append("abc") == sb.append("def"));//true

StringBuilder 和 StringBuffer

 StringBuillder可变,在地址不变的情况下,内容是可变的。

StringBuffer概述

1.基本方法和StringBuilder基本一样,包括追加和构造基本一样。

2synchronized,按下不表,多线程部分重点。

public class Test{
    //这是一个main方法,是程序的入口: 
    public static void main(String[] args) { 
    StringBuilder sb = new StringBuilder();
    System.out.println(sb.append("abc")==sb.append("def"));
    }
}

 

public class Test{
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) {
        StringBuilder sb=new StringBuilder("nihaojavawodeshijie");
        //增
        sb.append("这是梦想");
        System.out.println(sb);//nihaojavawodeshijie这是梦想
        // 删
        sb.delete(3, 6);//删除位置在[3,6)上的字符
        System.out.println(sb);//nihavawodeshijie这是梦想
        sb.deleteCharAt(16);//删除位置在16上的字符
        System.out.println(sb);//nihavawodeshijie是梦想
        //改-->插入
        StringBuilder sb1=new StringBuilder("$23445980947");
        sb1.insert(3, ",");//在下标为3的位置上插入,
        System.out.println(sb1);
        StringBuilder sb2=new StringBuilder("$2你好吗5980947");
        //改-->替换
        sb2.replace(3,5,"我好累");//在下标[3,5)位置上插入字符串
        System.out.println(sb2);
        sb.setCharAt(3,'!');
        System.out.println(sb);
        //查
        StringBuilder sb3=new StringBuilder("asdfa");
        for (int i = 0; i<sb3.length(); i++) {
            System.out.print(sb3.charAt(i)+"\t");
        }
        System.out.println();
        //截取
        String str=sb3.substring(2,4);//截取[2,4)返回的是一个新的String,对StringBuilder没有影响
        System.out.println(str);
        System.out.println(sb3);
    }
}

 

String、StringBuffer、StringBuilder区别与联系

1.String类是不可变类,即一旦一个String对象被创建后,包含在这个对象中的字符序列是不可改变的,直至这个对象销毁。

2.StringBuffer类则代表一个字符序列可变的字符串,可以通过append、insert、reverse、setChartAt、setLength等方法改变其内容。一旦生成了最终的字符串,调用toString方法将其转变为String

3.JDK1.5新增了一个StringBuilder类,与StringBuffer相似,构造方法和方法基本相同。

4.不同是StringBuffer是线程安全的,而StringBuilder是线程不安全的,所以性能略高。通常情况下,创建一个内容可变的字符串,应该优先考虑使用StringBuilder

5.StringBuilder:JDK1.5开始效率高线程不安全

6.StringBuffer:JDK1.0开始效率低瞭线程安全

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值