1. String
1.1 相关介绍
-
基本特性:不可变性。如果修改了String对象的内容,那么其实是重新开辟空间并赋上新值
-
如果是通过字面量的方式赋值,那么赋值后字符串保存在方法区的常量池中。在常量池中,不会保存相同内容的字符串,所以如果两个String对象的内容相同,那么它们指向的是同一个地址
public class Test { public static void main(String[] args) { String s1 = "abc"; String s2 = "abc"; System.out.println(s1 == s2); // 输出结果为true } } -
如果是通过new来创建,则是保存在堆中,但是对象中的value是指向常量池的
public class Test { public static void main(String[] args) { String s1 = "abc"; String s2 = "abc"; 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 } }
-
关于字符串拼接,如果涉及到变量的拼接,则是在堆中开辟新的空间
public class Test { public static void main(String[] args) { String s1 = "Hello"; String s2 = "World"; final String s3 = "World"; String s4 = "HelloWorld"; // 字面量赋值,直接指向常量池 String s5 = s1 + "World"; // 涉及到变量的拼接,会在堆中开辟新的空间 String s6 = "Hello" + s2; // 同上 String s7 = s1 + s2; // 同上 String s8 = "Hello" + s3; // s3是final修饰的常量,两个常量的拼接,指向常量池 String s9 = "Hello" + "World"; // 常量与常量的拼接,指向常量池 String s10 = (s1 + s2).intern(); // intern()返回的是在常量池中的地址 System.out.println(s4 == s5); // false System.out.println(s4 == s6); // false System.out.println(s4 == s7); // false System.out.println(s4 == s8); // true System.out.println(s4 == s9); // true System.out.println(s4 == s10); // true } }
1.2 类型准换
-
String转换为基本类型:调用基本类型对应包装类的parseXXX()方法
-
基本类型转换为String:调用String.valueOf()方法
-
String转换为char[]:调用String对象的toCharArray()方法
-
char[]转换为String:把char[]放进String的构造器中
-
String转换为字节数组:调用String对象的getBytes()方法
-
字节数组转换为String:把字节数组放进String的构造器中
public class Test { public static void main(String[] args) throws UnsupportedEncodingException { byte[] bytes = "Java学习".getBytes("gbk"); // 按gbk字符集编码,默认是utf-8 String str = new String(bytes, "gbk"); // 按gbk字符集解码 System.out.println(str); // 输出"Java学习" } }
1.3 String、StringBuffer、StringBuilder异同
相同点:
- 都是用char[]存储
不同点:
- String:不可变的字符序列
- StringBuffer:可变的字符序列,线程安全(方法都是synchronized修饰的),效率低。如何实现可变:先创建默认长度字符数组,当追加的字符过多就会扩容,即创建一个新的字符数组大小为原来的2倍加2,再把旧数组的内容复制过去
- StringBuilder:可变的字符序列,线程不安全,效率高
- 三者效率:StringBuilder > StringBuffer > String
1.4 例题
获取两个字符串的一个最大子字符串
/**
* 获取两个字符串的一个最大子字符串
* @param str1 字符串1
* @param str2 字符串2
* @return 返回两个字符串的一个最大子字符串
*/
public String findMaxSameString(String str1, String str2) {
if (str1 == null || str2 == null || str1.equals("") || str2.equals("")) {
return null;
}
String maxStr;
String minStr;
if (str1.length() >= str2.length()) {
maxStr = str1;
minStr = str2;
} else {
maxStr = str2;
minStr = str1;
}
int length = minStr.length();
for (int flag = length; flag > 0; flag--) {
for (int start = 0, end = flag - 1; end < length; start++, end++) {
String temp = minStr.substring(start, end + 1);
if (maxStr.contains(temp)) {
return temp;
}
}
}
return null;
}
2. 时间类相关
2.1 java.util.Date
| 构造器 | 解释 |
|---|---|
| Date() | 创建一个当前**时间戳(从1970年1月1日0时0分到现在的毫秒数)**的Date对象 |
| Date(long date) | 创建一个指定时间戳的Date对象 |
| 方法 | 解释 |
|---|---|
| toString() | 显示对应时间 |
| getTime() | 获取对应时间戳 |
(注:java.sql.Date对应数据库中的date类型)
2.2 java.text.SimpleDateFormat
用于对日期Date类的格式化和解析。
public class Test {
public static void main(String[] args) {
// 创建特定格式的SimpleDateFormat
// 格式化:日期-->字符串
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = new Date();
String result = sdf.format(date);
System.out.println(result);
// 解析:字符串-->日期
String str = "2019-09-08";
try {
Date parse = sdf.parse(str);
System.out.println(parse);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
常用字母代表的意思如下图所示(JDK 1.6 API)
2.3 java.util.Calendar
日历类,是一个抽象类。
public class Test {
public static void main(String[] args) {
// 方法1:通过其子类实例化
Calendar calendar = new GregorianCalendar();
// 方法2:通过静态方法实例化
Calendar calendar2 = Calendar.getInstance();
// get()方法
System.out.println(calendar.get(Calendar.DAY_OF_MONTH)); // 输出8
// set()方法
calendar.set(Calendar.DAY_OF_MONTH, 10);
System.out.println(calendar.get(Calendar.DAY_OF_MONTH)); // 输出10
// add()方法
calendar.add(Calendar.DAY_OF_MONTH, 5);
System.out.println(calendar.get(Calendar.DAY_OF_MONTH)); // 输出15
// 转换为Date对象
Date time = calendar.getTime();
System.out.println(time);
// 使用Date对象为Calendar类设置时间
Date date = new Date();
calendar.setTime(date);
System.out.println(calendar.get(Calendar.DAY_OF_MONTH)); // 输出8
}
}
2.4 LocalDate、LocalTime、LocalDateTime
Java 8 引入的关于时间的类。
public class Test {
public static void main(String[] args) {
// 三个类的方法都类似
// 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 localDateTime2 = LocalDateTime.of(2019, 9, 8, 15, 8);
System.out.println(localDateTime2);
// getXXX()
System.out.println(localDateTime.getDayOfWeek());
// withXXX()设置相关属性,注意会返回一个新的对象,旧对象内容不变
LocalDateTime newLocalDateTime = localDateTime.withDayOfMonth(20);
System.out.println(newLocalDateTime);
// plusXXX()给属性增加值
LocalDateTime newLocalDateTime2 = localDateTime.plusDays(5);
System.out.println(newLocalDateTime2);
// minus()给属性减少值
LocalDateTime newLocalDateTime3 = localDateTime.minusDays(3);
System.out.println(newLocalDateTime3);
}
}
2.5 java.time.Instant
public class Test {
public static void main(String[] args) {
// now()创建的Instant对象比东八区慢8小时
Instant instant = Instant.now();
System.out.println(instant);
// 添加时间偏移量
OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
System.out.println(offsetDateTime);
// 获取时间戳
long millis = instant.toEpochMilli();
System.out.println(millis);
// 根据时间戳创建Instant对象
Instant instant2 = Instant.ofEpochMilli(millis);
System.out.println(instant2);
}
}
2.6 DateTimeFormatter
public class Test {
public static void main(String[] args) {
// 方式一:预定义的标准格式
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
// 格式化:日期-->字符串
LocalDateTime localDateTime = LocalDateTime.now();
String str = formatter.format(localDateTime);
System.out.println(str);
// 解析:字符串-->日期
TemporalAccessor parse = formatter.parse(str);
System.out.println(parse);
// 方式二:本地化相关格式
// FormatStyle.LONG, FormatStyle.MEDIUM, FormatStyle.SHORT 适合LocalDateTime
DateTimeFormatter formatter2 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
String str2 = formatter2.format(localDateTime);
System.out.println(str2);
// FormatStyle.FULL, FormatStyle.LONG, FormatStyle.MEDIUM, FormatStyle.SHORT 适合LocalDate
LocalDate localDate = LocalDate.now();
DateTimeFormatter formatter3 = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL);
String str3 = formatter3.format(localDate);
System.out.println(str3);
// 方法三:自定义格式,常用
DateTimeFormatter formatter4 = DateTimeFormatter.ofPattern("yyyy-MM-dd kk:mm:ss");
System.out.println(formatter4.format(LocalDateTime.now()));
}
}
3. 比较器
用于对对象进行比较。
3.1 实现Comparable
1、编写一个People类实现Comparable接口,重写compareTo(obj)方法。如果当前对象大于比较对象obj,返回正整数,等于返回0,小于则返回负整数。
public class People implements Comparable<People> {
private int age;
private float height;
@Override
public int compareTo(People o) {
if (this.age > o.age) {
return 1;
} else if (this.age == o.age) {
return 0;
}
return -1;
}
public People(int age, float height) {
this.age = age;
this.height = height;
}
@Override
public String toString() {
return "People{" +
"age=" + age +
", height=" + height +
'}';
}
}
2、编写测试类,使用Arrays.sort()或Collections.sort()进行排序
public class Test {
public static void main(String[] args) {
People[] peoples = new People[3];
peoples[0] = new People(18, 1.7F);
peoples[1] = new People(20, 1.8F);
peoples[2] = new People(14, 1.5F);
// 数组排序
Arrays.sort(peoples);
System.out.println(Arrays.toString(peoples));
// 输出[People{age=14, height=1.5}, People{age=18, height=1.7}, People{age=20, height=1.8}]
List<People> list = new ArrayList<>();
list.add(new People(30, 1.9F));
list.add(new People(35, 1.6F));
list.add(new People(25, 1.7F));
// 集合排序
Collections.sort(list);
System.out.println(list);
// 输出[People{age=25, height=1.7}, People{age=30, height=1.9}, People{age=35, height=1.6}]
}
}
3.2 使用Comparator实现类
1、编写普通的People类
public class People {
private int age;
private float height;
public int getAge() {
return age;
}
public People(int age, float height) {
this.age = age;
this.height = height;
}
@Override
public String toString() {
return "People{" +
"age=" + age +
", height=" + height +
'}';
}
}
2、编写测试类,使用Comparator匿名实现类来排序
public class Test {
public static void main(String[] args) {
People[] peoples = new People[3];
peoples[0] = new People(18, 1.7F);
peoples[1] = new People(20, 1.8F);
peoples[2] = new People(14, 1.5F);
// 数组排序
Arrays.sort(peoples, new Comparator<People>() {
@Override
public int compare(People o1, People o2) {
return o1.getAge() - o2.getAge();
}
});
System.out.println(Arrays.toString(peoples));
// 输出[People{age=14, height=1.5}, People{age=18, height=1.7}, People{age=20, height=1.8}]
List<People> list = new ArrayList<>();
list.add(new People(30, 1.9F));
list.add(new People(35, 1.6F));
list.add(new People(25, 1.7F));
// 集合排序
Collections.sort(list, new Comparator<People>() {
@Override
public int compare(People o1, People o2) {
return o1.getAge() - o2.getAge();
}
});
System.out.println(list);
// 输出[People{age=25, height=1.7}, People{age=30, height=1.9}, People{age=35, height=1.6}]
}
}
4. 枚举类
4.1 自定义枚举类
1、Java 5 之前制作枚举类的步骤如下:
public class Season {
// 1.使用final修饰属性
private final String seasonName;
private final String seasonDetail;
// 2.私有化构造器
private Season(String seasonName, String seasonDetail) {
this.seasonName = seasonName;
this.seasonDetail = seasonDetail;
}
// 3.提供当前枚举类的多个常量对象
public static final Season SPRING = new Season("春天", "春暖花开");
public static final Season SUMMER = new Season("夏天", "烈日炎炎");
public static final Season AUTUMN = new Season("秋天", "秋高气爽");
public static final Season WINTER = new Season("冬天", "冰天雪地");
// 4.提供获取属性方法
public String getSeasonName() {
return seasonName;
}
public String getSeasonDetail() {
return seasonDetail;
}
@Override
public String toString() {
return "Season{" +
"seasonName='" + seasonName + '\'' +
", seasonDetail='" + seasonDetail + '\'' +
'}';
}
}
2、测试效果如下:
public class Test {
public static void main(String[] args) {
Season spring = Season.SPRING;
System.out.println(spring);
// 输出Season{seasonName='春天', seasonDetail='春暖花开'}
}
}
4.2 使用enum关键字
1、Java 5 引入enum关键字,使用该关键字定义枚举类
// 使用该关键字定义的枚举类继承于java.lang.Enum
public enum Season {
// 提供当前枚举类的对象,放在最开头
SPRING("春天", "春暖花开"),
SUMMER("夏天", "烈日炎炎"),
AUTUMN("秋天", "秋高气爽"),
WINTER("冬天", "冰天雪地");
private final String SeasonName;
private final String SeasonDetail;
Season(String seasonName, String seasonDetail) {
SeasonName = seasonName;
SeasonDetail = seasonDetail;
}
}
2、测试效果以及Enum类的常用方法如下
public class Test {
public static void main(String[] args) {
Season spring = Season.SPRING;
System.out.println(spring); // 输出SPRING
// Enum的values()方法
Season[] values = Season.values(); // 返回该枚举类的所有对象
for (Season s : values) {
System.out.println(s);
}
// Enum的valueOf()方法
Season winter = Season.valueOf("WINTER"); // 根据对象名获取枚举类的特定对象
System.out.println(winter);
}
}
3、实现某接口时的情况
比如有如下接口时,如果枚举类实现了该接口,那么可在类中重写方法,也可在对象中重写方法
public interface Info {
void show();
}
public enum Season implements Info {
// 在对象中重写方法,则每个对象输出内容不同
SPRING("春天", "春暖花开") {
@Override
public void show() {
System.out.println("这是春天");
}
},
SUMMER("夏天", "烈日炎炎") {
@Override
public void show() {
System.out.println("这是夏天");
}
},
AUTUMN("秋天", "秋高气爽") {
@Override
public void show() {
System.out.println("这是秋天");
}
},
WINTER("冬天", "冰天雪地") {
@Override
public void show() {
System.out.println("这是冬天");
}
};
private final String SeasonName;
private final String SeasonDetail;
Season(String seasonName, String seasonDetail) {
SeasonName = seasonName;
SeasonDetail = seasonDetail;
}
// 如果在类中重写接口的方法,那么每个对象都输出相同内容
// @Override
// public void show() {
// System.out.println("这是一个季节");
// }
}
public class Test {
public static void main(String[] args) {
Season spring = Season.SPRING;
spring.show(); // 这是春天
Season winter = Season.valueOf("WINTER");
winter.show(); // 这是冬天
}
}