第二十章 常用类
1.1 字符串的存储原理
User.java
package com.bjpowernode.javase.string;
public class User {
private int id;
private String name;
public User() {
}
public User(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
UserTest.java
public class UserTest {
public static void main(String[] args) {
User user = new User(111, "xiaohong");
}
}
StringTest01.java
关于Java JDK中内置的一个类:java.lang.String
1、String表示字符串类型,属于引用数组类型,不属于基本数据类型。
2、在java中使用双引号括起来的都是String对象。例如:"abc", "def", "a", 这是三个String对象
3、java中规定,双引号括起来的字符串,是不可变的,也就是说“abc”自出生到最终死亡,不可变,不能变成“abcd”,也不能变成“ab”
4、在JDK当中双引号括起来的字符串,例如:"abc", "def"都是直接存储在“方法区”的“字符串常量池”当中。
为什么SUN公司把字符中存储在一个“字符串常量池”当中呢?因为字符串在实际的开发中使用的太频繁,为了执行效率,把字符串放到了方法区的字符串常量池当中。
public class StringTest01 {
public static void main(String[] args) {
// 这两行代码表示底层创建了3个字符串对象,都在字符串常量池当中。
String s1 = "abcdef";
String s2 = "abcdef" + "xy";
// 分析:这是使用new的方式创建的字符串对象,这个代码中的“xy”是从哪里来的?
// 凡是双引号括起来的都在字符串常量池中有一份。
// new对象的时候一定在堆内存中开辟空间
String s3 = new String("xy");
// i变量中保存的是100这个值。
int i = 100;
// s变量中保存的是字符串对象的内存地址
// s引用中保存的不是"abc"
// 而0x1111是"abc"字符串对象在字符串常量池当中的内存地址
}
}

StringTest02.java
package com.bjpowernode.javase.string;
import java.sql.SQLOutput;
public class StringTest02 {
public static void main(String[] args) {
String s1 = "hello";
// "hello"是存储在方法区的字符串常量池当中
// 所以这个"hello"不会新建。(因为这个对象已经存在了)
String s2 = "hello";
// 分析结果是true还是false?
// == 双等号比较的是不是变量中保存的内存地址?是的。
System.out.println(s1 == s2); // true
String x = new String("xyz");
String y = new String("xyz");
// 分析结果是true还是false?
// == 双等号比较的是不是变量中保存的内存地址?是的。
System.out.println(x == y); // false
// 通过这个案例的学习,我们知道了,字符串对象之间的比较不能使用“==”
// “==”不保险,应该调用String类的equals方法。
// String类已经重写了equals方法,以下的equals方法调用的是String重写之后的equals
System.out.println(x.equals(y)); // true
String k = new String("testString");
// String k = null;
// "testString"是一个String字符串对象。只要是对象都能调用方法。
System.out.println("testString".equals(k)); // 建议使用这种方式,因为这个可以避免空指针异常
System.out.println(k.equals("testString")); // 存在空指针异常的风险,不建议这样写。
}
}
StringTest03.java
package com.bjpowernode.javase.string;
/*
分析以下程序,一共创建了几个对象
*/
public class StringTest03 {
public static void main(String[] args) {
/*
一共3个对象:
方法区字符串常量池中有1个: "hello"
堆内存当中有两个String对象。
一共3个。
*/
String s1 = new String("hello");
String s2 = new String("hello");
}
}
1.2 String类的构造方法
第一个:String s = new String("")
第二个:String s = ""; 最常用
第三个:String s = new String(char数组);
第四个:String s = new String(char数组, 起始下标, 长度);
第五个:String s = new String(byte数组);
第六个:String s = new String(byte数组, 起始下标, 长度);
public class StringTest04 {
public static void main(String[] args) {
// 创建字符串对象最常用的一种方式
String s1 = "hello world";
// s1这个变量中保存的是一个内存地址
// 按说以下应该输出一个地址
// 但是输出一个字符串,说明String类已经重写了toString()方法
System.out.println(s1); // hello world
System.out.println(s1.toString()); // hello world
// 这里只掌握常用的构造方法。
byte[] bytes = {97, 98, 99}; // 97是a,98是b,99是c
String s2 = new String(bytes);
// 输出一个引用的时候,会自动调用toString()方法,默认Object的话,会默认输出内存地址。
// 通过输出结果我们得出一个结论:String类已经重写了toString()方法
// 输出字符串对象的话,输出的不是对象的内存地址,而是字符串本身
System.out.println(s2); // abc
// String(字节数组,数组元素下标的起始位置,长度)
// 将byte数组中的一部分转换成字符串
String s3 = new String(bytes, 1, 2);
System.out.println(s3);
// 将char数组全部转换成字符串
char[] chars = {'我', '是', '中', '国', '人'};
String s4 = new String(chars);
System.out.println(s4);
// 将char数组的一部分转换成字符串
String s5 = new String(chars, 2, 3);
System.out.println(s5);
String s6 = new String("helloworld");
System.out.println(s6);
}
}
1.3 String常用方法
package com.bjpowernode.javase.string;
public class StringTest05 {
public static void main(String[] args) {
// String类当中常用方法
// 1(掌握). char charAt(int index)
char c = "中国人".charAt(1); // "中国人"是一个字符串String对象,只要是对象就能“点”
System.out.println(c);
// 2(了解).int compareTo(String anotherString)
// 字符串之间比较大小不能直接使用 > <,需要使用compareTo方法
int result = "abc".compareTo("abc");
System.out.println(result); // 0(等于0) 前后一致
int result2 = "abcd".compareTo("abce");
System.out.println(result2); // -1(小于0) 前小后大
int result3 = "abce".compareTo("abcd");
System.out.println(result3); // 1(大于0) 前大后小
// 拿着字符串第一个字母和后面字符串的第一个字母比较,能分胜负就不比较了。
System.out.println("xyz".compareTo("yxz")); // -1
// 3(掌握). boolean contains(CharSequence s)
// 判断前面的字符串中是否包含后面的子字符串
System.out.println("helloWorld.java".contains(".java")); // true
System.out.println("http://www.baidu.com".contains("https://")); // false
// 4(掌握). boolean endsWith(String suffix)
System.out.println("test.txt".endsWith(".java")); // false
System.out.println("test.txt".endsWith(".txt")); // true
System.out.println("fdsjkfaj;sdfjaksdfkjasd;fjasdk;fjkasdff".endsWith("ff")); // true
// 5(掌握). boolean equals(Object anObject)
// 比较两个字符串必须使用equals方法,不能使用"=="
// equals方法有没有调用compareTo方法?JDK13中并没有调用compareTo方法
// 6(掌握). boolean equalsIgnoreCase(String anotherString)
// 判断两个字符串是否相等,并且同时忽略大小写
System.out.println("AbC".equalsIgnoreCase("abC"));
// 7(掌握). byte[] getBytes()
// 将字符串对象转换成字节数组
byte[] bytes = "abcdef".getBytes();
for(int i = 0; i < bytes.length; i++){
System.out.println(bytes[i]);
}
// 8(掌握). int indexOf(String str)
// 判断某个子字符串在当前字符串中第一次出现处的索引。
System.out.println("oraclejavac++.netc#pythonphpjavaoraclec++".indexOf("java")); // 6
// 9(掌握). boolean isEmpty()
// 判断某个字符串是否为“空字符串”,底层源代码调用的应该是字符串的length()方法。
String s = "";
System.out.println(s.isEmpty());
String s1 = "1";
System.out.println(s1.isEmpty());
// 10(掌握). int length();