【学习打卡】Java高级(三)

学习目标:

Java 高级编程 学习打卡 第三天

学习内容:

1、画出如下几行代码的内容结构:

String s1 = "hello"; 
String s2 = "hello";
String s3 = new String("hello");
s1 +="world";

2、如何理解String类的不可变性?

3、String类可以被继承?为什么?

String s = new String("hello");

在内存中创建了几个对象?请说明

4、String、StringBuffer、StringBuilder三者的对比

5、String的常用方法有哪些?(至少7个)

学习时间:

2021年4月27日

学习产出:

【学习打卡】Java高级 第一天
【学习打卡】Java高级 第二天
【学习打卡】Java高级 第三天

学习总结:

java.lang.String类的使用

1、概述

String:字符串,使用一对""引起来表示。

1、String声明为final的,不可以被继承

2、String实现了Serializable接口:表示字符串是支持序列化的。实现了Comparable接口:表示String可以比较大小

3、String内部定义了final char[] value用于存储字符串数据

4、通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中

5、字符串常量池中是不会存储相同内容(使用String类的equals()比较,返回true)的字符串的。

2、String的不可变性

1、当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值。

String s1 = "abc";//字面量的定义方式
String s2 = "abc";
//比较s1和s2的地址值
System.out.println(s1==s2);//true
s1 = "hello";
System.out.println(s1==s2);//false
System.out.println(s1);//hello
System.out.println(s2);//abc

2、当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。

String s1= "abc";
String s2= "abc";
System.out.println(s1==s2);//true
s1 += "def";
System.out.println(s1==s2);//false
System.out.println(s1);//abcdef

3、当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。

String s1 = "abc";
String s2 = "abc";
System.out.println(s1==s2);//true
String s3 = s1.replace('a', 'm');
System.out.println(s1==s2);//true
System.out.println(s1);//abc
System.out.println(s3);//mbc

【学习打卡】Java高级(三)_第1张图片

3、String实例化的不同方式

1、通过字面量定义的方式

2、通过new + 构造器的方式

//通过字面量定义的方式,此时的s1和s2的数据,
//JavaEE声明在方法区中的字符串常量池中
String s1 = "JavaSE";
String s2 = "JavaSE";

//通过new+构造器的方式,此时的s3和s4保存的是地址值,
//是数据在堆空间中开辟空间以后对应的地址值
String s3 = new String("JavaEE");
String s4 = new String("JavaEE");

System.out.println(s1==s2);//true
System.out.println(s3==s4);//false
System.out.println(s1==s3);//false

3、String s = new String(“abc”);方式创建对象,在内存中创建了几个对象?

两个:一个是堆空间中new的结构,另一个是char[]对应的常量池中的数据:“abc”

【学习打卡】Java高级(三)_第2张图片

4、字符串拼接方式赋值的对比

1、常量与常量的拼接的结果在常量池。且常量池中不会存在相同内容的常量。

2、只要其中一个是变量,结果就在堆中。

3、如果拼接的结果调用intern()方法,返回值就在常量池中。

String s1 = "Java";
String s2 = "EE";
String s3 = "JavaEE";
String s4 = "Java"+"EE";
String s5 = "Java"+s2;
String s6 = s1 + s2;
String s7 = s6.intern();

System.out.println(s3==s4);//true
System.out.println(s3==s5);//false
System.out.println(s3==s6);//false
System.out.println(s3==s7);//true

5、常用方法

String str1=new String();
String str2 = null;
String str3 = "";
String str4 = new String("");
StringBuffer stringBuffer = new StringBuffer();
System.out.println(stringBuffer.length());//0
StringBuilder stringBuilder = new StringBuilder();
System.out.println(stringBuilder.length());//0
System.out.println(str1.length());//0
//System.out.println(str2.length());//java.lang.NullPointerException
System.out.println(str3.length());//0
System.out.println(str4.length());//0
//int length():返回字符串的长度: return value.length
String s1 = "abc";
String s2 = null;
String s3 = "";
System.out.println(s1.length());//3
//System.out.println(s2.length());//java.lang.NullPointerException
System.out.println(s3.length());//0

//char charAt(int index): 返回某索引处的字符return value[index]
System.out.println(s1.charAt(1));//b

//boolean isEmpty():判断是否是空字符串:return value.length == 0
System.out.println(s1.isEmpty());//false
System.out.println(s3.isEmpty());//true

//String toLowerCase():使用默认语言环境,将 String 中的所字符转换为小写
//String toUpperCase():使用默认语言环境,将 String 中的所字符转换为大写
String s4 = "JavaEE";
System.out.println(s4.toLowerCase());//javaee
System.out.println(s4.toUpperCase());//JAVAEE

//String trim():返回字符串的副本,忽略前导空白和尾部空白
String s5="   string method ";
System.out.println(s5.length());//17
String s6 = s5.trim();
System.out.println(s6);//"string method"
System.out.println(s6.length());//13

//boolean equals(Object obj):比较字符串的内容是否相同
System.out.println(s4.equals("JavaEE"));

//boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大小写
System.out.println(s4.equalsIgnoreCase("javaee"));

//String concat(String str):将指定字符串连接到此字符串的结尾。 等价于用“+”
String s7 = "hello";
String s8 = "world";
System.out.println(s7.concat(s8));//"helloworld"

//int compareTo(String anotherString):比较两个字符串的大小
System.out.println(s7.compareTo(s8));//-15

//String substring(int beginIndex):返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。
System.out.println(s7.substring(2));//"llo"

//String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。
System.out.println(s8.substring(2,4));//"rl"
String s1="hello world";

//boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束
System.out.println(s1.endsWith("d"));//true

//boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始
System.out.println(s1.startsWith("a"));//false

//boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始
System.out.println(s1.startsWith("e",1));//true
boolean contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列时,返回 true
int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引
int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始
int lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引
int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索
注:indexOf和lastIndexOf方法如果未找到都是返回-1
替换:
String replace(char oldChar, char newChar):返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所 oldChar 得到的。
String replace(CharSequence target, CharSequence replacement):使用指定的字面值替换序列替换此字符串所匹配字面值目标序列的子字符串。
String replaceAll(String regex, String replacement):使用给定的 replacement 替换此字符串所匹配给定的正则表达式的子字符串。
String replaceFirst(String regex, String replacement):使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
匹配:
boolean matches(String regex):告知此字符串是否匹配给定的正则表达式。
切片:
String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。
String[] split(String regex, int limit):根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中。

6、String与其它结构的转换

1、String与基本数据类型、包装类之间的转换

String ——> 基本数据类型、包装类:调用包装类的静态方法:parseXxx(str)

基本数据类型、包装类 ——> String:调用String重载的valueOf(xxx)

String s1 = "123";

//int n = (int)s1;错误
int i = Integer.parseInt(s1);

String s = String.valueOf(i);

2、String与字符数组之间的转换

String ——> char[]:调用String的toCharArray()

char[] ——> String:调用String的构造器

String str1 = "abc123";
char[] charArray = str1.toCharArray();
for (int i = 0; i < charArray.length; i++) {
     
	System.out.println(charArray[i]);
}

char[] arr = new char[]{
     'h','e','l','l','o'};
String str2 = new String(arr);
System.out.println(str2);

3、String与字节数组之间的转换

编码:String ——> byte[]:调用String的getBytes()
解码:byte[] ——> String:调用String的构造器

编码:字符串 ——>字节 (看得懂 —>看不懂的二进制数据)
解码:编码的逆过程,字节 ——> 字符串 (看不懂的二进制数据 —> 看得懂)

说明:解码时,要求解码使用的字符集必须与编码时使用的字符集一致,否则会出现乱码。

String str1 = "helloworld你好";
byte[] bytes = str1.getBytes();//使用默认的字符集,进行编码
System.out.println(Arrays.toString(bytes));
//[104, 101, 108, 108, 111, 119, 111, 114, 108, 100, -28, -67, -96, -27, -91, -67]
byte[] gbks = str1.getBytes("gbk");//使用gbk字符集进行编码
System.out.println(Arrays.toString(gbks));
//[104, 101, 108, 108, 111, 119, 111, 114, 108, 100, -60, -29, -70, -61]
String str2 = new String(bytes);//使用默认字字符集,进行解码
System.out.println(str2);//helloworld你好
String str3 = new String(gbks);
System.out.println(str3);//出现乱码。原因:编码集和解码集不一致
String str4 = new String(gbks,"gbk");
System.out.println(str4);//helloworld你好。编码集和解码集一致
}

4、String与StringBuffer、StringBuilder之间的转换

String ——>StringBuffer、StringBuilder:

调用StringBuffer、StringBuilder构造器

StringBuffer、StringBuilder ——>String:

①调用String构造器;

②StringBuffer、StringBuilder的toString()

String str1 = "helloworldABC";
StringBuilder stringBuilder = new StringBuilder(str1);
System.out.println(stringBuilder);//helloworldABC
StringBuffer stringBuffer = new StringBuffer(str1);
System.out.println(stringBuffer);//helloworldABC
String str2 = new String(stringBuffer);
System.out.println(str2);
String str3 = stringBuffer.toString();
System.out.println(str3);
String s4 = new String(stringBuilder);
System.out.println(s4);
String s5 = stringBuilder.toString();
System.out.println(s5);

7、JVM中字符常量池存放位置说明:

jdk 1.6 (jdk 6.0 ,java 6.0):字符串常量池存储在方法区(永久区)

jdk 1.7:字符串常量池存储在堆空间

jdk 1.8:字符串常量池存储在方法区(元空间)

String、StringBuffer、StringBuilder

1、String、StringBuffer、StringBuilder三者的对比

String:不可变的字符序列;底层使用char[]存储

StringBuffer:可变的字符序列;线程安全的,效率低;底层使用char[]存储

StringBuilder:可变的字符序列;jdk5.0新增的,线程不安全的,效率高;底层使用char[]存储

2、StringBuffer与StringBuilder的内存解析

String str = new String();//char[] value = new char[0];
String str1 = new String("abc");//char[] value = new char[]{'a','b','c'};
StringBuffer sb1 = new StringBuffer();//char[] value = new char[16];底层创建了一个长度是16的数组。
System.out.println(sb1.length());//0
sb1.append('a');//value[0] = 'a';
sb1.append('b');//value[1] = 'b';
StringBuffer sb2 = new StringBuffer("abc");//char[] value = new char["abc".length() + 16];
System.out.println(sb2.length());//3
/*
扩容问题:如果要添加的数据底层数组盛不下了,那就需要扩容底层的数组。
默认情况下,扩容为原来容量的2倍 + 2,同时将原数组中的元素复制到新的数组中。
*/
//开发中建议使用:StringBuffer(int capacity) 或 StringBuilder(int capacity)

3、对比String、StringBuffer、StringBuilder三者的执行效率

从高到低排列:StringBuilder > StringBuffer > String

4、StringBuffer、StringBuilder中的常用方法

 StringBuilder stringBuilder = new StringBuilder("abc");
//增:append(xxx)
stringBuilder.append("def");
System.out.println(stringBuilder);//abcdef

//删:delete(int start,int end)
stringBuilder.delete(1,3);//adef
System.out.println(stringBuilder);

//改:setCharAt(int n ,char ch) / replace(int start, int end, String str)
stringBuilder.setCharAt(1,'g');
System.out.println(stringBuilder);//agef

stringBuilder.replace(2,3,"sss");
System.out.println(stringBuilder);//agsssf

//查:charAt(int n )
char c = stringBuilder.charAt(1);
System.out.println(c);//g

//插:insert(int offset, xxx)
stringBuilder.insert(1,"xxx");
System.out.println(stringBuilder);//axxxgsssf

//长度:length();
System.out.println(stringBuilder.length());//9

//遍历:for() + charAt() / toString()
for (int i = 0; i < stringBuilder.length(); i++) {
     
	char charAt = stringBuilder.charAt(i);
	System.out.println(charAt);
}

JDK8之前日期时间API

1、获取系统当前时间:System类中的currentTimeMillis()

long time = System.currentTimeMillis();
//返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差。
//称为时间戳
System.out.println(time);

2、java.util.Date类与java.sql.Date类

java.util.Date类
		|---java.sql.Date类

1、两个构造器的使用

构造器一:Date():创建一个对应当前时间的Date对象

构造器二:创建指定毫秒数的Date对象

2、两个方法的使用

toString():显示当前的年、月、日、时、分、秒

getTime():获取当前Date对象对应的毫秒数。(时间戳)

//构造器一:Date():创建一个对应当前时间的Date对象

Date date1 = new Date();
System.out.println(date1);//Tue May 04 08:35:56 CST 2021
System.out.println(date1.toString());//Tue May 04 08:35:56 CST 2021
System.out.println(date1.getTime());//1620088556182

//构造器二:创建指定毫秒数的Date对象

Date date2 = new Date(1620088556182L);
System.out.println(date2);//Tue May 04 08:35:56 CST 2021

3、java.sql.Date对应着数据库中的日期类型的变量

如何实例化?

如何将java.util.Date对象转换为java.sql.Date对象?

 java.sql.Date date1 = new java.sql.Date(35235325345L);
System.out.println(date1);//1971-02-13

//将java.util.Date对象转换为java.sql.Date对象

//情况一
Date date2 = new java.sql.Date(2343243242323L);
System.out.println(date2);
java.sql.Date date3 = (java.sql.Date)date2;
System.out.println(date3);

//情况二
Date date4 = new Date();
java.sql.Date date5 = new java.sql.Date(date4.getTime());
System.out.println(date5);

3、java.text.SimpleDataFormat类

SimpleDateFormat对日期Date类的格式化和解析

1、两个操作:

1.1、格式化:日期 ——>字符串

1.2、解析:格式化的逆过程,字符串 ——> 日期

2、SimpleDateFormat的实例化:new + 构造器

//按照指定的方式格式化和解析:调用带参的构造器
//SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyy.MMMMM.dd GGG hh:mm aaa");
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
//格式化
String format1 = sdf1.format(date);
System.out.println(format1);//2021-05-04 08:51:21
//解析:要求字符串必须是符合SimpleDateFormat识别的格式(通过构造器参数体现),
//否则,抛异常
Date date2 = sdf1.parse("2021-05-04 08:49:52");
System.out.println(date2);//Tue May 04 08:49:52 CST 2021

小练习:

/*
    练习一:字符串"2020-09-08"转换为java.sql.Date

    练习二:"天打渔两天晒网"   1990-01-01  xxxx-xx-xx 打渔?晒网?

    举例:2020-09-08 ? 总天数

    总天数 % 5 == 1,2,3 : 打渔
    总天数 % 5 == 4,0 : 晒网

    总天数的计算?
    方式一:( date2.getTime() - date1.getTime()) / (1000 * 60 * 60 * 24) + 1
    方式二:1990-01-01  --> 2019-12-31  +  2020-01-01 -->2020-09-08
     */
    @Test
    public void testExer() throws ParseException {
     
        String birth = "2020-09-08";

        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
        Date date = sdf1.parse(birth);
//        System.out.println(date);

        java.sql.Date birthDate = new java.sql.Date(date.getTime());
        System.out.println(birthDate);
    }

4、Calendar类:日历类、抽象类

		//1.实例化
        //方式一:创建其子类(GregorianCalendar的对象
        //方式二:调用其静态方法getInstance()
        Calendar calendar = Calendar.getInstance();
//        System.out.println(calendar.getClass());

        //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可变性
        calendar.set(Calendar.DAY_OF_MONTH,22);
        days = calendar.get(Calendar.DAY_OF_MONTH);
        System.out.println(days);

        //add()
        calendar.add(Calendar.DAY_OF_MONTH,-3);
        days = calendar.get(Calendar.DAY_OF_MONTH);
        System.out.println(days);

        //getTime():日历类---> Date
        Date date = calendar.getTime();
        System.out.println(date);

        //setTime():Date ---> 日历类
        Date date1 = new Date();
        calendar.setTime(date1);
        days = calendar.get(Calendar.DAY_OF_MONTH);
        System.out.println(days);

你可能感兴趣的:(Java高级)