方式一:通过字面量定义的方式

方式二:通过new + 构造器的方式

@Test
public void test2(){
// 通过字面量定义的方式:此时的s1和s2的数据javaEE声明在方法区中的字符串常量池中。
String s1 = "javaEE";
String s2 = "javaEE";
// 通过new + 构造器的方式:此时s3和s4的数据保存的地址值,是数据在堆空间中开辟空间以后对应的地址值。
String s3 = new String("abc");
String s4 = new String("abc");
System.out.println(s1 == s2); //true
System.out.println(s1 == s3); //false
System.out.println(s1 == s4); //false
System.out.println(s3 == s4); //false
}
面试题:String s = new String(“abc”),方式创建对象,在内存中创建了几个对象?
答:两个:一个是堆空间中new结构,另一个是char[]对应的常量池中的数据:“abc”。
@Test
public void test3(){
String s1 = "javaEE";
String s2 = "hadoop";
String s3 = "javaEEhadoop";
String s4 = "javaEE" + "hadoop";
String s5 = s1 + "hadoop";
String s6 = "javaEE" + s2;
String s7 = s1 + s2;
System.out.println(s3 == s4); //true
System.out.println(s3 == s5); //false
System.out.println(s3 == s6); //false
System.out.println(s5 == s6); //false
System.out.println(s5 == s7); //false
System.out.println(s6 == s7); //false
String s8 = s5.intern(); //返回值得到的s8使用常量值中已存在的"javaEEhadoop"
System.out.println(s3 == s8); //true
}
@Test
public void test4(){
String s1 = "javaEEhadoop";
String s2 = "javaEE";
String s3 = s2 + "hadoop";
System.out.println(s3 == s1); // false
final String s4 = "javaEE";
String s5 = s4 + "hadoop";
System.out.println(s1 == s5); // true,原因:final定义的是常量
}
注:indexOf和lastIndexOf方法如果未找到都是返回-1
@Test
public void test2(){
String s1 = "abc123";
char[] charArr = s1.toCharArray();
for (int i = 0; i < charArr.length; i++) {
System.out.println(charArr[i]);
}
String s2 = new String(charArr);
System.out.println(s2);
char[] ch = new char[]{'a', 'b', 'c'};
s1 = new String(ch);
System.out.println(s1);
}
编码:字符串 --> 字节(看得懂 --> 看不懂的二进制数据)
解码:字节 --> 字符串(看不懂的二进制数据 --> 看得懂)
说明:解码时,要求使用的编码的字符集必须与编码时使用的字符集一致,否则会出现乱码
@Test
public void test3(){
// 编码
String s1 = "abc123中国";
byte[] bytes = s1.getBytes(); // 无参数,则使用默认字符集,进行编码
System.out.println(Arrays.toString(bytes));
byte[] gbks;
try {
gbks = s1.getBytes("gbk");
System.out.println(Arrays.toString(gbks)); // 使用gbk字符集进行编码
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
// 解码
String s2 = new String(bytes); // 使用默认字符集,进行解码
System.out.println(s2);
String s3 = new String(gbks);
System.out.println(s3); // 出现乱码,原因:编码集和解码集不同
try {
String s4 = new String(gbks, "gbk");
System.out.println(s4); // 不会出现乱码,原因:编码集和解码集一致
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
源码分析:
// 注释为底层源码
String str1 = new String(); //char[] value = new char[0];
String str2 = new String("abc"); //char[] value = new new char[]{'a', 'b', 'c'};
StringBuffer sb1 = new StringBuffer(); //char[] value = new new char[16];
sb1.append('a'); //value[0] = 'a';
sb1.append('b'); //value[1] = 'b';
StringBuffer sb2 = new StringBuffer("abc"); //char[] value = new char["abc".length() + 16];
问题1:System.out.println(sb2.length())? 答:3
问题2:扩容问题:如果添加的底层数组满了,那就需要扩容底层数组。
答:默认情况下,扩容为原来容量的2倍 + 2,同时将原有数组中的元素复制到新的数组中。
指导意见:开发中建议大家使用:StringBuffer(int capacity)或StringBuilder(int capacity)
总结:
- 增:append(XXX)
- 删:delete(int start,int end)
- 改:setCharAt(int n ,char ch)、StringBuffer replace(int start, int end, String str)
- 查:char charAt(int n )
- 插:insert(int offset, xxx)
- 长度:length()
- 遍历:for() + charAt()、toString()
从高到低排列:StringBuilder > StringBuffer > String
@Test
public void test2(){
//初始设置
long startTime = 0L;
long endTime = 0L;
String text = "";
StringBuffer buffer = new StringBuffer("");
StringBuilder builder = new StringBuilder("");
//开始对比
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
buffer.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuffer的执行时间:" + (endTime - startTime));
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
builder.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuilder的执行时间:" + (endTime - startTime));
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
text = text + i;
}
endTime = System.currentTimeMillis();
System.out.println("String的执行时间:" + (endTime - startTime));
}
@Test
public void test1(){
long time = System.currentTimeMillis(); //返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差(称为时间戳)。
System.out.println(time);
}
@Test
public void test2(){
//构造器1:Date():创建一个当前时间的Date对象
Date date1 = new Date(); //Mon Sep 19 20:33:02 CST 2022
System.out.println(date1);
System.out.println(date1.getTime()); //1663590882297
//构造器2:创建一个指定毫秒数的Date对象
Date date2 = new Date(1663590882297L);
System.out.println(date2.toString());
//创建java.sql.Date对象
java.sql.Date date3 = new java.sql.Date(1663590882297L);
System.out.println(date3.toString());
//如何将java.util.Date对象转换为java.sql.Date对象
//情况1:
Date date4 = new java.sql.Date(1663590882297L);
java.sql.Date date5 = (java.sql.Date)date4;
System.out.println(date5.toString());
//情况2:
Date date6 = new Date();
java.sql.Date date7 = new java.sql.Date(date6.getTime());
System.out.println(date7.toString());
}
/**
* SimpleDateFormat的使用:
*/
@Test
public void test3() throws ParseException {
//实例化SimpleDateFormat:使用默认构造器
SimpleDateFormat sdf = new SimpleDateFormat();
//格式化:日期 --> 字符串
Date date = new Date();
System.out.println(date);
String s = sdf.format(date);
System.out.println(s);
//解析:格式化的逆过程,字符串 --> 日期
String s1 = "22-9-22 下午5:19";
Date date1 = sdf.parse(s1);
System.out.println(date1);
// 按照指定的方式格式化和解析:调用带参数的构造器
//格式化
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String s2 = sdf1.format(date);
System.out.println(s2);
//解析:要求字符串必须是符合SimpleDateFormat识别的格式(通过构造器参数体现),否则会抛异常
String s3 = "2022-09-22 05:25:18";
Date date2 = sdf1.parse(s3);
System.out.println(date2);
/**
* 练习一:字符串"2020-09-08"转换为java.sql.Date
*/
System.out.println("****************************");
String s5 = "2020-09-08";
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");
Date date4 = sdf2.parse(s5);
System.out.println(date4);
java.sql.Date date5 = new java.sql.Date(date4.getTime());
System.out.println(date5);
/**
* 练习二:“三天打鱼两天晒网” 1990-01-01 xxxx-xx-xx 打鱼?晒网?
* 举例:2020-09-08
*/
System.out.println("******************************");
Date d1 = sdf2.parse("1990-01-01");
Date d2 = sdf2.parse("2020-09-08");
long t = d2.getTime() - d1.getTime();
long day;
if(t % (1000 * 24 * 60 * 60) == 0){
day = t / 1000 / 24 / 60 / 60 % 5;
}else {
day = t / 1000 / 24 / 60 / 60 % 5 + 1;
}
System.out.println(day);
if(day <= 3 && day != 0){
System.out.println("打鱼");
}else {
System.out.println("晒网");
}
}
/**
* calendar日历类(抽象类)的使用
*/
@Test
public void test4(){
//1. 实例化
//方式一:创建七子类(GregorianCalendar)的对象
//方式二:调用其静态方法getInstance()
Calendar calendar = Calendar.getInstance();
//2. 常用的方法
//get()
int days = calendar.get(Calendar.DAY_OF_MONTH); //获得一个月的第几天
System.out.println(days);
System.out.println(calendar.get(Calendar.DAY_OF_YEAR)); //获得一年的第几天
//set()
calendar.set(Calendar.DAY_OF_YEAR, 200); //设置一年第几天
System.out.println(calendar.get(Calendar.DAY_OF_YEAR));
//add()
calendar.add(Calendar.DAY_OF_YEAR, 3); //在原来的一年的第几天上加了3天
System.out.println(calendar.get(Calendar.DAY_OF_YEAR));
//getTime():日历类 --> Date
Date date = calendar.getTime();
System.out.println(date);
//setTime():Date --> 日历类
Date date1 = new Date();
calendar.setTime(date1);
System.out.println(calendar.get(Calendar.DAY_OF_YEAR));
}
说明:大多数开发者只会用到基础包和format包,也可能会用到temporal包。因此,尽
管有68个新的公开类型,大多数开发者,大概将只会用到其中的三分之一。

@Test
public void test2(){
//now():获取当前的日期、时间、日期 + 时间
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDate);
System.out.println(localTime);
System.out.println(localDateTime);
//of():
LocalDateTime localDateTime1 = LocalDateTime.of(2022, 9, 22, 22, 39, 7);
System.out.println(localDateTime1);
//getXxx():获取相关属性
System.out.println(localDateTime.getDayOfMonth());
System.out.println(localDateTime.getDayOfYear());
System.out.println(localDateTime.getDayOfWeek());
System.out.println(localDateTime.getMonth());
System.out.println(localDateTime.getMonthValue());
System.out.println(localDateTime.getMinute());
//体现不可变性:本身不变,返回值变
//withXxx():设置相关属性
LocalDate localDate1 = localDate.withDayOfMonth(23);
System.out.println(localDate);
System.out.println(localDate1);
LocalDateTime localDateTime2 = localDateTime1.withHour(4);
System.out.println(localDateTime1);
System.out.println(localDateTime2);
//
LocalDateTime localDateTime3 = localDateTime1.plusMonths(4);
System.out.println(localDateTime1);
System.out.println(localDateTime3);
LocalDateTime localDateTime4 = localDateTime1.minusDays(5);
System.out.println(localDateTime1);
System.out.println(localDateTime4);
}

/**
* Instant的使用
* 类似于java.util.Date类
*/
@Test
public void test3(){
//now():获取本初子午线对应的标准时间
Instant instant = Instant.now();
System.out.println(instant); //2022-09-23T07:12:22.421Z
//添加偏移量
OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
System.out.println(offsetDateTime);
//获取自1970年1月1日0时0分0秒(UTC)开始的毫秒数
long milli = instant.toEpochMilli();
System.out.println(milli);
//ofEpochMilli():通过给定毫秒数,获取Instant实例 --> Date(long millis)
Instant instant1 = Instant.ofEpochMilli(milli);
System.out.println(instant1);
}


/**
* DateTimeFormatter:格式化解析时间、日期
* 类似于SimpleDateFormat
*
*/
@Test
public void test4(){
//方式一:预定义的标准格式。如:ISO_LOCAL_ DATE_TIME、ISO_LOCAL_DATE、ISO_LOCAL_TIME...
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
//格式化:日期 --> 字符串
LocalDateTime localDateTime = LocalDateTime.now();
String s1 = formatter.format(localDateTime);
System.out.println(localDateTime);
System.out.println(s1);
//解析:字符串 --> 日期
TemporalAccessor parse = formatter.parse("2022-09-23T15:32:19.853");
System.out.println(parse);
//方式二:
//本地化相关的格式。如:ofLocalDateTime()
//适用于ofLocalDateTime:FormatStyle.LONG 、FormatStyle.MEDIUM、FormatStyle.SHORT
DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
String s2 = formatter1.format(localDateTime);
System.out.println(s2);
//本地化相关的格式。如:ofLocalDate()
//适用于ofLocalDate:FormatStyle.FULL、FormatStyle.LONG 、FormatStyle.MEDIUM、FormatStyle.SHORT
DateTimeFormatter formatter2 = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL);
LocalDate localDate = LocalDate.now();
String s3 = formatter2.format(localDate);
System.out.println(s3);
//方式三:自定义格式。如:ofPattern("yyyy-MM-dd hh:mm:ss E")
DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss E");
//格式化
String s4 = formatter3.format(localDateTime);
System.out.println(s4);
//解析
TemporalAccessor parse1 = formatter3.parse("2022-09-23 03:52:26 星期五");
System.out.println(parse1);
}
说明: Java中的对象,正常情况下,只能进行比较:== 或 != ;不能使用 > 或 < 的,但是在开发场景中,外面需要对多个对象进行排序,言外之意,就需要比较对象的大小。如何实现?使用两个接口中的任何一个:Comparable 或 Comparator
@Test
public void test1(){
String[] arr = new String[]{"AA", "CC", "KK", "MM", "GG", "JJ", "DD"};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
@Test
public void test2(){
Goods[] goods = new Goods[4];
goods[0] = new Goods("联想",34);
goods[1] = new Goods("罗技",78);
goods[2] = new Goods("小米",12);
goods[3] = new Goods("华为",45);
Arrays.sort(goods);
System.out.println(Arrays.toString(goods));
}
/**
* Comparator接口的使用:定制排序
* 1. 背景:
* z
* 2. 重写Compare(Object o1, Object o2)方法,比较o1和o2的大小:
* o1 > o2:返回正整数
* o1 < o2:返回负整数
* o1 == o2:返回零
*/
@Test
public void test3(){
// 俺按照字符串从大到小排序
String[] arr = new String[]{"AA", "CC", "KK", "MM", "GG", "JJ", "DD"};
Arrays.sort(arr, new Comparator<String>() { //泛型
@Override
public int compare(String o1, String o2) {
return -o1.compareTo(o2);
}
});
System.out.println(Arrays.toString(arr));
}
@Test
public void test4(){
Goods[] goods = new Goods[5];
goods[0] = new Goods("联想",34);
goods[1] = new Goods("罗技",78);
goods[2] = new Goods("小米",12);
goods[3] = new Goods("华为",45);
goods[4] = new Goods("华为", 56);
Arrays.sort(goods, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof Goods && o2 instanceof Goods){
Goods g1 = (Goods) o1;
Goods g2 = (Goods) o2;
if(g1.getName().equals(g2.getName())){
return -Double.compare(g1.getPrice(), g2.getPrice());
}else {
return g1.getName().compareTo(g2.getName());
}
}
throw new RuntimeException("输入数据不一致");
}
});
System.out.println(Arrays.toString(goods));
}
@Test
public void test1(){
String javaVersion = System.getProperty("java.version");
System.out.println("java的version:" + javaVersion);
String javaHome = System.getProperty("java.home");
System.out.println("java的home:" + javaHome);
String osName = System.getProperty("os.name");
System.out.println("os的name:" + osName);
String osVersion = System.getProperty("os.version");
System.out.println("os的version:" + osVersion);
String userName = System.getProperty("user.name");
System.out.println("user的name:" + userName);
String userHome = System.getProperty("user.home");
System.out.println("user的home:" + userHome);
String userDir = System.getProperty("user.dir");
System.out.println("user的dir:" + userDir);
}


说明:要求数字精度比较高,故用到java.math.BigDecimal类。
//BigInteger 和 BigDecimal
@Test
public void test2(){
BigInteger bi = new BigInteger("1243324112312387618726361218471784812");
BigDecimal bd = new BigDecimal("12435.351");
BigDecimal bd2 = new BigDecimal("11");
System.out.println(bi);
// System.out.println(bd.divide(bd2));
System.out.println(bd.divide(bd2, BigDecimal.ROUND_HALF_UP));
System.out.println(bd.divide(bd2, 15, BigDecimal.ROUND_HALF_UP));
}