包装类
包装类 - 引用
【1】什么是包装类:
以前定义变量,经常使用基本数据类型
对于基本数据类型来说,它就是一个数,加点属性,加点方法,加点构造器将基本数据类型对应进行了一个封装,产生了一个新的类,---》包装类。
int,byte..--->基本数据类型
包装类--->引用数据类型
【2】对应关系:
【3】已经有基本数据类型了,为什么要封装为包装类?
(1)java语言面向对象的语言,最擅长的操作各种各样的类。
(2)以前学习装数据的---》数组,int0]Stringldoublel StudentD
以后学习的装数据的---》集合,有一个特点,只能装引用数据类型的数据
【4】是不是有了包装类以后就不用基本数据类型了?
不是
包装类 - 常用属性 - 常用构造器
【1】直接使用,无需导包:
java. lang
类Integer
【2】类的继承关系:
jara. lang. object
jaya.lang.Number
java. lang. integer
【3】实现接口:
所有已实现的接口;
Serializable,Comparable<Integer)
【4】这个类被final修饰,那么这个类不能有子类,不能被继承:
pubilc final class Integer
extends Number
implements Cosparable<Integer>
【5】包装类是对基本数据类型的封装:
对int类型封装产生了Integer
Integer类在对象中包装了一个基本类型int的值。
Integer类型的对象包含一个int类型的字段。
【6】类的历史:
从以下版本开始:
JDK1.0
【7】属性:
public class test01 {
//这是一个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】构造器(发现没有空参构造器)
(1)int类型作为构造器的参数
(2)String类型作为构造器的参数
Integer i1 = new Integer(12);
public class test02 {//创建类
public static void main(String[] args) {//主方法
Integer i1=new Integer(12);//构造器
System.out.println(i1.toString());//输出信息
Integer i2= new Integer("12");//构造器
System.out.println(i2);//输出
}
}
运行结果
【9]包装类特有的机制:自动装箱、自动拆箱:
public class Test03 {//创建类
public static void main(String[] args) {//主方法
//自动装箱:int--->Integer
Integer i=12;//定义一个Integer对象并赋值
System.out.println(i);//输出
//自动拆箱:Integer --->int
Integer i2=new Integer(12);//创建构造器并传入值
int num=i2;//定义一个int类型的变量并赋值
System.out.println(num);//输出
}
}
运行结果
1.自动装箱 自动拆箱是从JDK1.5以后新出的特性
2.自动装箱 自动拆箱:将基本数据类型和包装类进行快速的类型转换。
public class W10 {//创建类
public static void main(String[] args) {//主函数
// TODO Auto-generated method stub
//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);
}
}
包装类-常用方法
包装类常用的方法如下: 包装类主要是两种方法,一种是本类型和其它类型之间进行转换,另一种是字符串和本类型以及基本类型之间的转换的方法前五种是本类型和其他类型之间的转换,后三种是字符串和本类型以及基本类型之间的转换。
/*
* 返回一个表示指定的 int 值的 Integer 实例。如果不需要新的 Integer 实例,则
* 通常应优先使用该方法,而不是构造方法 Integer(int),因为该方法有可能通过
* 缓存经常请求的值而显著提高空间和时间性能。
* @param i an <code>int</code> value.
* @return a <tt>Integer</tt> instance representing <tt>i</tt>.
* @since 1.5
*/
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i); }
可以看到对于范围在-128到127的整数,valueOf方法做了特殊处理。
采用IntegerCache.cache[i + offset]这个方法
/*
* IntegerCache内部类
* 其中cache[]数组用于存放从-128到127一共256个整数
*/
private static class IntegerCache {
private IntegerCache(){}
static final Integer cache[] = new Integer[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Integer(i - 128);
}
}
这就是valueOf方法真正的优化方法,当-128=<i<=127的时候,返回的是IntegerCache中的数组的值;当 i>127 或 i<-128 时,返回的是Integer类对象
三、日期相关类
在 Java 中获取当前时间,可以使用 java.util.Date 类和 java.util.Calendar 类完成。 其中, Date 类主要封装了系统的日期和时间的信息,Calendar 类则会根据系统的日历来解释 Date 对象 。
package com.imooc.collection;
import java.util.Date;
public class Test041 {
//这是一个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());//1592055964263
System.out.println(System.currentTimeMillis());
/*
(1)疑问:以后获取时间差用:getTime()还是currentTimeMiLLis()
答案:currentTimeMillis()--》因为这个方法是静态的,可以类名,方法名直接调用
(2)public static native long currentTimeMillis();本地方法
为什么没有方法体?因为这个方法的具体实现不是通过java写的。
*/
}}
从前台过来的日期数据一般都是有格式的String,需要转换成util.Date类型
String-->sql.Date
sql.Date-->util.Date
局限性:日期必须是规定格式!
引入新类DateFormat
package com.imooc.collection;
/*
(3)这个方法的作用:
一般会去衡量一些算法所用的时间
*/
public class test {
//这是一个main方法·是程序的人口:
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的。
long time = System.currentTimeMillis();
java.sql.Date date = new java.sql.Date(time);
package com.imooc.collection;
import java.sql.Date;
public class test {
public static void main(String[] args){
//java.sql.Date:
Date d = new Date(1592055964263L);
System.out.println(d);
/*
(1)java.sql.Date和java.util.Date的区别:
java.util.Date: 年月日 时分秒
java.sql.Date: 年月日
(2)java.sql.Date和java.utilDate的联系:
java.sql.Date(子类) extends java.util.Date(父类)
*/
//java.sql.Date和java.util.Date相互转换:
//【1】util--->sqL:
java.util.Date date = new Date(1592055964263L);//创建util.Date的对象
//方式1:向下转型
Date date1=(Date) date;
/*
父类:Animal 子类:Dog
Animal an =new Dog();
bog d=(Dog)an;*/
//方式2:利用构造器
Date date2 = new Date(date.getTime());
//【2】sql-->util:
java.util.Date date3=d;
//[3]String--->sqL.Date:
Date date4 = Date.valueOf("2020-5-7");
}
}
Calendar
Calendar是一个抽象类,不能直接创建对象,使用子类实现
可以使用静态方法Calendar.getInstance()创建。
常用方法:get(),set()
一个Calendar的实例是系统时间的抽象表示,通过get(int field)方法来取得想要的时间信息。比如YEAR、MONTH、DAY_OF_WEEK、HOUR_OF_DAY 、MINUTE、SECOND。
java.text.SimpleDateFormat类
Date类的API不易于国际化,大部分被废弃了,java.text.SimpleDateFormat类是一个不与语言环境有关的方式来格式化和解析日期的具体类。其允许进行①格式化:日期—>字符串、②解析:字符串—>日期。
String---》java.util.Date类型转换:
分解:
(1)String--->java.sql.Date
(2)java.sql.Date--->java.util.Date
插入数据库时,存入当前日期,需要格式转换
import java.text.SimpleDateFormat;
formatter = new SimpleDateFormat( "yyyy-MM-dd ");
String date = formatter.format(new Date());//格式化数据,取当前时间结果为 2014-10-30
String格式的数据转化成Date格式
import java.text.SimpleDateFormat;
formatter = new SimpleDateFormat( "yyyy-MM-dd ");
String s = "2011-07-09 ";
Date date = formatter.parse(s);
String直接转sql.Date——valueOf()
java.sql.Date类的方法接受以JDBC转义格式(yyyy-mm-dd)表示日期的String值,并进行转换
将给定的String值转换为Date对象。
package com.imooc.collection;
public class Test04 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) {
// (1)string--->java.sql.Date
java.sq1.Date date = java.sq1.Date.valueOf("2015-9-24");
//(2)java.sgl.Date--->java.util.Date
java.util.Date date2 = date;
System.out.println(date2.toString());
}
}
DateTimeFormatter 自定义格式
用于转换LocalDateTime等与String转换的定义和规范.
引入新的类
package com.imooc.collection;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test05 {
//这是一个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;
}
}
package com.imooc.collection;
import java.sql.Date;
import java.util.Calendar;
import java.util.Scanner;
public class deta {
public static void main(String[] args) {
//获取日期
System.out.println("请输入你想要查看的日期(提示:格式为1990-2-5):");
Scanner sc = new Scanner(System.in);
String strDate = sc.next();
Date date = Date.valueOf(strDate);
Calendar cal = Calendar.getInstance();
cal.setTime(date);
//打印信息
int nowday = cal.get(Calendar.DAY_OF_MONTH);
System.out.println("日\t一\t二\t三\t四\t五\t六");
for (int i = 0; i < cal.get(Calendar.DAY_OF_MONTH); i++) {//对齐一号是星期几
System.out.print("\t");
}
for (int i = 1; i <= cal.getActualMaximum(Calendar.DATE); i++) {//遍历该月
String day = i+"";
if(i<=9){ //为了对齐一位数两位数
day = i+" ";
}
if (i==nowday){ //在指定日期打星号
day = i+"";
System.out.print(day+"*"+"\t");
continue;
}
cal.set(Calendar.DATE,i);
if (cal.get(Calendar.DAY_OF_WEEK)==7){ //在换行时换行
System.out.println(day+"\t");
continue;
}
System.out.print(day+"\t"); //正常日期
}
}
}
JDK1.8新增日期时间API的原因
1、java.util.Date 是从 JDK 1.0 开始提供,易用性差
默认是中欧时区(Central Europe Time)
起始年份是 1900 年 起始月份从 0 开始 对象创建之后可修改
2、JDK 1.1 废弃了 Date 中很多方法,新增了并建议使用 java.util.Calendar 类
相比 Date 去掉了年份从 1900 年开始 月份依然从 0 开始 选用 Date 或 Calendar,让人更困扰
3、为了解决 JDK 中时间与日期较难使用的问题,JDK 1.8 开始,吸收了 Joda-Time 很多功能,新增 java.time 包,加了新特性:
区分适合人阅读的和适合机器计算的时间与日期类
日期、时间及对比相关的对象创建完均不可修改 可并发解析与格式化日期与时间 支持设置不
同的时区与历法
DK1.1引入Calendar类--》第二批日期时间API
缺陷:
可变性:像日期和时间这样的类应该是不可变的。偏移性:Date中的年份是从1900开始的,而月份都从0开始。
格式化:格式化只对Date有用,Calendar则不行。
JDK1.8新增日期时间API--》第三批日期时间API
JDK1.8新增日期时间API - LocaLDate,LocaLTime,LocalDateTime
LocaLDate:日期
LocaLTime:时间
LocalDateTime:日期+时间
package com.imooc.collection;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
public class test09 {
//这是一个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
使用旧的Date对象时,我们用**SimpleDateFormat**进行格式化显示。使用新的LocalDateTime或ZonedLocalDateTime时,我们要进行格式化显示,就要使用DateTimeFormatter。
和SimpleDateFormat不同的是,DateTimeFormatter不但是不变对象,它还是线程安全的。
因为SimpleDateFormat不是线程安全的,使用的时候,只能在方法内部创建新的局部变量。
而DateTimeFormatter可以只创建一个实例,到处引用。
ava 8使用线程安全类对date / Time API进行了大修,该类替换了笨拙的date和calendar类。这也向我们介绍了DateTimeFormatter类,这与旧API中的simpledateFormat相反
package com.imooc.collection;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.TemporalAccessor;
public class test010 {
//这是一个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);
//方式二:本地化相关的格式。如:ofLocalizedDateTime()
//参数:FormatStyle.LONG/FormatStyle.MEDIUM/FormatStyle.SHORT
// FormatStyle.LONG:2020年6月15日下午03时17分13秒
// FormatStyle.MEDIUM:2022年5月7日 下午9:13:25
// FormatStyle.SHORT:2022/5/7 下午9:02
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类
Math的概念
类包含用于执行基本数学运算的方法
Math 类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。
Math所有类都是静态的。可以直接类名。调用。
Math类特点
由于Math类在java.lang包下,所以不需要导包。
因为它的成员全部是静态的,所以私有了构造方法
Java中的 +、-、*、/ 和 % 等基本算术运算符不能进行更复杂的数学运算,例如,三角函数、对数运算、指数运算等。于是 Java 提供了 Math 工具类来完成这些复杂的运算
Math 类中包含 E 和 PI 两个静态常量,正如它们名字所暗示的,它们的值分别等于 e(自然对数)和 π(圆周率)
常用方法
System.out.println("随机数:"+Math.random());
System.out.println("绝对值:"+Math.abs(-5.6));
System.out.println("进一:"+Math.ceil(9.1));
System.out.println("舍一:"+Math.floor(9.9));
System.out.println("四舍五入:"+Math.round(9.9));
System.out.println("取最大:"+Math.max(3,9));
System.out.println("取最小:"+Math.min(9,28));
直接使用,无需导包:
package java.lang;
final修饰类,这个类不能被继承:
public final class Math {
}
构造器私有化,不能创建Math类的对象:
/**
* Don't let anyone instantiate this class.
*/
private Math() {}
Math内部的所有的属性,方法都被static修饰:类名.直接调用,无需创建对象:
package com.imooc.collection;
public class test010 {
//这是一个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));
}
}
package com.imooc.collection;
import static java.lang.Math.*;
public class test010 {
//这是一个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);
再次强调:种子数只是随机算法的起源数字,和生成的随机数字的区间无关。
Random类中的常用方法
Random类中的方法比较简单,每个方法的功能也很容易理解。需要说明的是,Random类中各方法生成的随机数字都是均匀分布的,也就是说区间内部的数字生成的几率是均等的。下面对这些方法做一下基本的介绍:
(1)public boolean nextBoolean()
该方法的作用是生成一个随机的boolean值,生成true和false的值几率相等,也就是都是50%的几率。
(2)public double nextDouble()
该方法的作用是生成一个随机的double值,数值介于[0,1.0)之间。
(3)public int nextInt()
该方法的作用是生成一个随机的int值,该值介于int的区间,也就是-231到231-1之间。
如果需要生成指定区间的int值,则需要进行一定的数学变换,具体可以参看下面的使用示例中的代码。
(4)public int nextInt(int n)
该方法的作用是生成一个随机的int值,该值介于[0,n)的区间,也就是0到n之间的随机int值,包含0而不包含n。
如果想生成指定区间的int值,也需要进行一定的数学变换,具体可以参看下面的使用示例中的代码。
(5)public void setSeed(long seed)
该方法的作用是重新设置Random对象中的种子数。设置完种子数以后的Random对象和相同种子数使用new关键字创建出的Random对象相同。
package com.imooc.collection;
import java.util.Random;
public class Test02 {
//这是一个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 值。
}
}
自行在API文档中初步了解Random类
不管是无参数构造Random,还是Math类的random方法,最后底层都是到Random类的有参构造中。
六、string类
String表示字符串类型,属于引用数据类型,不属于基本数据类型
tring是C++标准库的一个重要的部分,主要用于字符串处理。可以使用输入输出流方式直接进行string操作,也可以通过文件等手段进行string操作。同时,C++的算法库对string类也有着很好的支持,并且string类还和c语言的字符串之间有着良好的接口
我们知道输出格式化数字可以使用 printf() 和 format() 方法。
String 类使用静态方法 format() 返回一个String 对象而不是 PrintStream 对象。
String 类的静态方法 format() 能用来创建可复用的格式化字符串,而不仅仅是用于一次打印输出
String 的常用方法
length()字符串的长度
charAt()截取一个字符
getchars()截取多个字符并由其他字符串接收
getBytes()将字符串变成一个byte数组
toCharArray()将字符串变成一个字符数组
equals()和equalsIgnoreCase()比较两个字符串是否相等,前者区分大小写,后者不区分
startsWith()和endsWith()判断字符串是不是以特定的字符开头或结束
toUpperCase()和toLowerCase()将字符串转换为大写或小写
concat() 连接两个字符串
trim()去掉起始和结束的空格
substring()截取字符串
indexOf()和lastIndexOf()前者是查找字符或字符串第一次出现的地方,后者是查找字符或字符串最后一次出现的地方
compareTo()和compareToIgnoreCase()按字典顺序比较两个字符串的大小,前者区分大小写,后者不区分
replace() 替换
String类实现了Comparable,里面有一个抽象方法叫compareTo,所以String中一定要对这个方法进行重写:
String s8 = new string("abc");
String s9 = new string("abc");
System.out.println(s8.compareTo(s9));
其他常用方法
String 中常见 的方法 》字符串 的其他 用法: *length (): 获取当前字符串 的 长度 (返回整数) 例子: String str = "I love java!"; int count = str.length (); System.out.println (num);
//字符串的截取:
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 的内存分析
String在常量池中放置了一个变量,如果后续有结果相同的变量那就不会在增加一个变量,比如String s = "abc";后续如果再来了一个String s1 = "ab"+"c",常量池中也只会有一个"abc",不会有两个。但是注意使用String(String original)构造的String对象则不同。
StringBuilder类
可变字符串类有:StringBuilder类,StringBuffer类
不可变字符串类:String类
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
拼接字符串
public class Test02 {
//这是一个main方法,是程序的入口:
public static void main(string[] args) {
String s1 = "a"+"b"+"c";
String s2 = "ab"+"c"; string s3 = "a"+"bc";
String s4 = "abc";
String s5 = "abc"+"".
}
}
上面的字符串,会进行编译器优化,直接合并成为完整的字符串,我们可以反编译验证
然后在常量池中,常量池的特点是第一次如果没有这个字符串,就放进去,如果有这个字符串,就直接从常量池中取
new关键字创建对象
String s6 = new string("abc");
public class Test03 {
//这是一个main方法,是程序的入口:
public static void main(string[] args) {
String a ="abc".
String b = a + "def";
System.out.println(b);
}
}
StrinngBuilder 类
String内容是不可变的,StringBuilder内容是可变的
StringBuilder又称为可变字符序列(不再创建新的String对象),它是一个类似于 String 的字符串缓冲区,通过某些方法调用可以改变该序列的长度和内容。
原来StringBuilder是个字符串的缓冲区,即它是一个容器,容器中可以装很多字符串。并且能够对其中的字符串进行各种操作。
它的内部拥有一个数组用来存放字符串内容,进行字符串拼接时,直接在数组中加入新内容。StringBuilder会自动维护数组的扩容。默认16字符空间,超过自动扩充)
StringBuilder底层:非常重要的两个属性
package com.imooc.collection;
public class Test02 {
//这是一个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"));
}
}
String 和 StringBuilder
package com.imooc.collection;
public class Test02 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
System.out.println(sb.append("abc")==sb.append("def"));
}
}
常用方法
package com.imooc.collection;
public class Test02 {
//这是一个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);
}
}
package com.imooc.collection;
public class Test02 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) {
StringBuffer sb=new StringBuffer("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,对StringBuffer没有影响
System.out.println(str);
System.out.println(sb3);
}
}
String、StringBuffer、StringBuilder区别与联系
StringBuffer与StringBuilder虽也是final,但都是继承自AbstractStringBuilder,其append实现方法都是重写AbstractStringBuilder里的
而StringBuilder的方法没有加synchronized,在多线程下是不安全的。
线程安全与不安全造成了StringBuilder与StringBuffer在效率方面有区别。
这三者的速度排序是这样的:
String<StringBuffer<StringBuilder
所以,在经常要操作字符串的情况下,多线程下,尽量用StringBuffer,单线程下,则尽量使用StringBuilder
1、tring类是不可变类,即一日一个String对象被创建后,包含在这个对象中的字符序列是不可改变的,直至这个对象销毁。
2、StringBuffer类则代表一个字符序列可变的字符串,可以通过append、insert、reverse、setChartAt、setLength等方法改变其内容。一旦生成了最终的字符串,调用toString方法将其转变为String。
3、JDK1.5新增了一个StringBuilder类,与StringBuffer相似,构造方法和方法基本相同。不同是StringBuffer是线程安全的,而StringBuilder是线程不安全的,所以性能略高。通常情况下,创建一个内容可变的字符串,应该优先考虑使用StringBuilder
三者共同之处:都是final类,不允许被继承,主要是从性能和安全性上考虑的,因为这几个类都是经常被使用着,且考虑到防止其中的参数被参数修改影响到其他的应用
StringBuffer是线程安全,可以不需要额外的同步用于多线程中;
StringBuilder是非同步,运行于多线程中就需要使用着单独同步处理,但是速度就比StringBuffer快多了;
StringBuffer与StringBuilder两者共同之处:可以通过append、indert进行字符串的操作。
String实现了三个接口:Serializable、Comparable、CarSequence
StringBuilder只实现了两个接口Serializable、CharSequence,相比之下String的实例可以通过compareTo方法进行比较,其他两个不可以。
StringBuilder:JDK1.5开始 效率高线程不安全
StringBuffer:JDK1.0开始效率低线程安全