目录
一:字符串相关的类:
1)String 类 及 常用方法:
a:String:字符串概念:
-1.String 类 声明为 FInal 的,不可被继承的。
-2.String 类 实现了 Serializable 接口,表示 字符串是支持序列化的
Comparable 接口,表示 字符串 可比较大小
-3.内部定义了:(private final char value[];)数组,存储字符串。一旦创建长度不可变。
-4.字符串常量池中(方法区中),不会储存相同内容的字符串。
b:String 对象的创建:
String str = "张三";
String str2 = new String("张三");
char[] chars = {123, 567};
String str3 = new String(chars);
c:String 在内存中 存储结构:
new:在堆里开辟新地址,堆里面的value值,指向 常量池里面的地址 )
方法区(堆永久区):用于虚拟机加载的:类信息 + 普通常量 + 静态变量 + 编译器编译后的代码 等。
常量池:方法区的一部分,运行时常量池。
d:测试 新建字符串的 存储位置:
public class test_02 {
public static void main(String[] args) {
String s1 = "张三";
String s2 = "张三";
//true
System.out.println(s1 == s2);
/** ********************************* */
Person p1 = new Person("张三", 18);
Person p2 = new Person("张三", 18);
//false
System.out.println(p1 == p2);
//true
System.out.println(p1.getName() == p2.getName());
//true
System.out.println(p1.getAge() == p2.getAge());
}
}
@Data
class Person {
private String name;
private int age;
}
e:面试题:用 String str = new String("123");,创建对象,在内存中一共创建了几个对象。
-1.答:两个对象,一个是 堆空间中的 new 结构;
另一个是 char value[] 对应的,方法区常量池中的数据,“123”。
如果常量池中声明过了,就可以直接指向,因为常量池中不回有两个相同的数据。
f:字符串拼接操作对比:
public static void main(String[] args) {
String s1 = "java";
String s2 = "bb";
String s3 = "javabb";
String s4 = "java" + "bb";
String s5 = s1 + "bb";
final String s6 = "java";
String s7 = s6 + "bb";
//true (java 预编译,字符串和s3相同,存储在常量池中。且常量池不会存储相同内容的常量)
System.out.println(s3 == s4);
//false (只要有变量,就在堆 开辟空间,类似于 new )
System.out.println(s3 == s5);
//true final 修饰的变量,就会看作为是常量,也会进行 Java预编译。
System.out.println(s7 == s3);
//true (拼接的 结果,调用 intern() 方法,返回的结果就在 常量池里面)
String intern = s5.intern();
System.out.println(s3 == intern);
}
g:面试题:
-1.因为:String 是不可变形(基本数据类型传的是数据,引用数据类型传的是地址值)
g:String 常用方法:
public static void main(String[] args) {
String str = "张三";
int length = str.length();//f返回字符串长度
char c = str.charAt(1); //返回某索引处的字符
boolean empty = str.isEmpty();//判断字符串是否为空
String s = str.toLowerCase();//转换为小写
String s1 = str.toUpperCase();//转换为大写
String trim = str.trim();//去除两边的空白格
boolean equals = str.equals("123");//比较字符串内容是否相等
boolean b = str.equalsIgnoreCase("123");//和上类似,忽略大小写
String concat = str.concat("123");//将字符串连接到末尾,等价于 +
int i = str.compareTo("123");//比较两个字符串大小
String substring = str.substring(1, 2);//截取字符串(含头不含尾)
}
h:String 和 其他转换
-1.String <--> int
public static void main(String[] args) {
//String -> int
int i = Integer.parseInt("13");
//int -> String
String s = String.valueOf(13);
String s2 = 14 + "";
}
-2.String <--> char (题:改变字符串内部文字)
public static void main(String[] args) {
String str = "张三";
//String -> char[]
char[] chars = str.toCharArray();
//char[] -> String
String s = new String(chars);
}
-3.String <--> byte[]
public static void main(String[] args) {
/** 默认 UFTF-8 */
String str = "abc123";
// String -> byte[]
byte[] bytes = str.getBytes();
// byte[] -> String
String s = new String(bytes);
/** 指定 转换 编码集 */
// String -> byte[]
byte[] bytes = str.getBytes("GBK");
System.out.println(Arrays.toString(bytes));
// byte[] -> String
String s = new String(bytes, "GBK");
System.out.println(s);
}
i:String 常见 算法题目:(475~478)
2)StringBuilder,StringBuffer:
a:基本介绍:
-1.StringBuffer 代表可变的字符串序列,可以对字符串内容进行增删。
-2.很多方法与 String 相同,StringBuffer 中也是使用 字符数组 保存字符串,
但 char[]value 但是没有用 final 关键字修饰,StringBuffer 是可变长度的。
-3.StringBuffer 是一个容器。
-4.StringBuffer 实现了 Serializable 接口,即对象可进行序列化的。
-5.父类中 有属性 char[] value,不是 final,该 value 数组存放字符串内容,存放在堆中,不在常量池。
-6.StringBuffer 是一个 Final 类,不能被继承。
a:他俩和 String 三者 异同:
b:面试题1:System.out.println(new StringBuilder().length()):输出几?
-1.输出0,因为 获取StringBuilder 的长度,获取的是它内部的真实长度。
c:面试题2:扩容问题,如果要添加的数组底层数组放不下,数组地层数组如何扩容?
-1.append();如果数组长度不够,扩容为原来长度 2倍+2,同时将原数组中的元素复制到新数组中。
-2.开发中,为了避免频繁的地层数组频繁扩容,最好在创建时指定长度。
d:常用方法:(支持链式操作)
public static void main(String[] args) {
StringBuffer stringBuffer = new StringBuffer();
// 后面追加
StringBuffer append = stringBuffer.append("123");
// 从 * 删除到 *
StringBuffer delete = stringBuffer.delete(1, 6);
// 从 * 到 * 位置处(含头不含尾),替换为 aa,
StringBuffer aa = stringBuffer.replace(1, 3, "aa");
// 在指定位置插入
StringBuffer insert = stringBuffer.insert(1, "123");
// 把当前 字符序列 逆转
StringBuffer reverse = stringBuffer.reverse();
}
d:效率对比:
-1.String 最慢,StringBuilder 最快。
e:如何使用:
-1.字符串大量修改,使用 StringBuffer 或 StringBuilder
-2.字符串大量修改,在单线程情况下,使用 StringBuilder
-3.字符串大量修改,在多线程情况下,使用 StringBuffer。
-4.字符串很少修改,使用 String ,比如配置信息。
一:JVM 示意图
a:内存示意图:
b:新生区:类的诞生,成长,消亡的区域。(一个类在这里产生,应用,最后被垃圾回收器收集,结束生命)
新生区又存在两部分:伊甸园区:
幸存区:(幸存0区 和 幸存1区)
c:堆内运行流程:
d:永久区内介绍(方法区):
二:JDK 8 之前的 日期时间 API:
1)时间戳:(常用于计算时间差)
public static void main(String[] args) {
long l1 = System.currentTimeMillis();
// 程序执行
long l2 = System.currentTimeMillis();
System.out.println(l2 - l1);
}
2)java.util.Date:
public static void main(String[] args) {
// 创建当前时间对应的 date 对象
Date date = new Date();
//根据 当前毫秒数,创建 Date 对象
Date date1 = new Date(1619426002107L);
//显示当前 年月日,时分秒
System.out.println(date.toString());//Mon Apr 26 16:33:22 CST 2021
// 获取 当前 Date 对象,对应的时间戳
long time = date.getTime();
System.out.println(time);//1619426002107
}
3)java.sql.Date:(继承于 java.util,Date 类,父子关系)
a:对应数据库中的日期。数据库中(birth -> date),转换为 Date 类。
// 新建 sql.Date();
java.sql.Date date = new java.sql.Date(1619426002107L);
b:java.sql.Date 和 java.util.Date 互相转换,通过 时间戳转换。
4)simpleDateFormat:
a:两个常用方法:(日期和字符串转换)
public static void main(String[] args) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
Date date = new Date();
// 操作1:将日期 格式化为 字符串
String format = sdf.format(date);
System.out.println(format);
//2021-04-26 17-23-18
// 操作2:解析字符串为日期
Date parse = sdf.parse("2021-04-26 17-21-07");
System.out.println(parse.toString());
//Mon Apr 26 17:21:07 CST 2021
}
b:练习:将字符串 "2020-09-08" 转换为 java.sql.Date
5)Calendar 日历类的使用:(JDK1.1)
public static void main(String[] args) throws ParseException {
Calendar calendar = Calendar.getInstance();
//1.get() //获取 这是这个月第几天
int i = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(i);//26
//2.set() //更改 月份为 10
calendar.set(Calendar.MONTH, 10);
System.out.println(calendar.get(Calendar.MONTH));//10
//3.getTime() //获取 当前时间
Date time = calendar.getTime();
System.out.println();
//4.setTime() //设置指定的时间
calendar.setTime(new Date());
}
三:JDK 8 之后的 日期时间 API
1)新的 日期时间 API:
a:java.time. ->包含值对象的基础包
b:java.time.format -> 格式化和解析时间和日期
2)LocalDate,API的使用:
a:创建对象:
public static void main(String[] args) {
// 获取当前的 日期 + 时间
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime);//2021-04-26T19:01:25.840
// 生成指定的 日期 + 时间,没有偏移量
LocalDateTime of = LocalDateTime.of(2020, 1, 1, 20, 20, 20, 20);
System.out.println(of); //2020-01-01T20:20:20.000000020
}
b:获取:
public static void main(String[] args) {
// 获取当前的 日期 + 时间
LocalDateTime localDateTime = LocalDateTime.now();
int dayOfMonth = localDateTime.getDayOfMonth(); //26
DayOfWeek dayOfWeek = localDateTime.getDayOfWeek(); //MONDAY
int dayOfYear = localDateTime.getDayOfYear(); //116
int minute = localDateTime.getMinute();
int monthValue = localDateTime.getMonthValue();
}
c:修改时间:(with)
public static void main(String[] args) {
// 获取当前的 日期 + 时间
LocalDateTime localDateTime = LocalDateTime.now();
// 修改时间
LocalDateTime localDateTime1 = localDateTime.withMonth(1);
}
d:加减时间:(plus / minus)
public static void main(String[] args) {
// 获取当前的 日期 + 时间
LocalDateTime localDateTime = LocalDateTime.now();
//加 1天
LocalDateTime localDateTime1 = localDateTime.plusDays(1);
//减 1天
LocalDateTime localDateTime2 = localDateTime.minusDays(1);
}
3)DateTimeFormatter:
public static void main(String[] args) {
// 获取当前时间
LocalDateTime localDateTime = LocalDateTime.now();
// 进行 格式化 操作
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String format = dtf.format(localDateTime);
System.out.println(format);
//输出 : 2021-04-26 19:28:55
}
四:Java 比较器(自然排序,自定义排序)
1)说明:
a:Java 中的对象,正常情况下,只能进行比较:== 或 != ,不能使用 > < 等比较。
b:如何实现?实现两个接口中的,任意一个。
2)java.lang.Comparable<T> 接口:自然排序
a:类:public interface Comparable<T> { }
b:重写方法:public int compareTo(Object obj);
c:重写规则:如果 当前对象 this 大于 形参对象 obj,则返回正整数;
-1.如果 当前对象 this 小于 形参对象 obj,则返回负整数;
-2.如果 当前对象 this 等于 形参对象 obj,则返回 0;
d:自定义类 继承 Comparable 接口,实现自定义排序:
/**
* 实现 Comparable 接口,比较年龄大小
* 当前实例 的年龄 > 形参实例的 年龄,返回 1
*/
@Override
public int compareTo(Object o) {
if (o instanceof Person) {
Person person = (Person) o;
return this.name.compareTo(person.getName());
}else {
throw new RuntimeException("传入参数不对,排序类型不正确");
}
// //或使用 方法二:
// if (o instanceof Person) {
// Person p = (Person) o;
// if (this.name > p.getName()) {
// return 1;
// } else if (this.name < p.getName()) {
// return -1;
// } else {
// return 0;
// }
// } else {
// throw new RuntimeException("传入参数不对,排序类型不正确");
// }
}
3)java.util.Comparator<T> 接口:自定义排序
a:类:@FunctionalInterface //函数式接口
-1.public interface Comparator<T> { }
b:重写方法: int compare(T o1, T o2);
c:重写规则:如果方法 返回正整数,则表示 o1 > o2;
-1.如果方法 返回负整数,则表示 o1 < o2;
-2.如果方法 返回 0,则表示 o1 = o2;
d:使用:
public static void main(String[] args) {
// java 比较器
A a1 = new A("张三", 12);
A a2 = new A("fd", 13);
A a3 = new A("ffff", 4);
A[] arr = new A[]{a1, a2, a3};
List<A> collect = Arrays.asList(arr).stream().sorted(new Comparator<A>() {
@Override
public int compare(A o1, A o2) {
return o1.getAge() - o2.getAge();
}
}).collect(Collectors.toList());
System.out.println(collect);
}
4)使用比较:
a:java.lang.Comparable<T> : 类 实现这个接口,重写比较方法。
b:java.util.Comparator<T> :调方法时候,临时给一个排序的方式。
五:System 类
1)常用方法:
public static void main(String[] args) {
long l = System.currentTimeMillis();
System.out.println(l);
System.gc();
}
六:Math 类
1)Math 类 API:
七:BigInteger 与 BigDecimal
1)BigInteger:常用来表示 比较大的整数时 使用。
2)BigDecimal:对于精度要求比较高的小数,使用这个计算。
a:构造器:
b:常用方法:
c:案例:
public static void main(String[] args) {
BigDecimal b1 = new BigDecimal("1.1");
BigDecimal b2 = new BigDecimal("2.2");
//保留 15位小数,使用 四舍五入
BigDecimal divide = b1.divide(b1, 15, BigDecimal.ROUND_HALF_UP);
}
八:Object 类详解
1)== 比较运算符 :
a:== :既可以判断基本类型,又可以判断引用类型。
b:==:如果判断基本类型,判断的是 值是否相等。(例:int i = 10 ;double j = 10.0,他俩 ==)
c:==:如果判断引用类型,判断的是 地址是否相等,即判定是不是同一个对象。
2)equals() 方法:
a:是 Object 类中的方法,只能判断引用类型。如何看 JDK 原码
b:默认判断的是地址是否相等,也就是判断两个对象是不是同一个对象,
子类中往往重写该方法,用于判断内容是否相等。
c:子类 重写 equals:(变成比较两个字符串的值,是否相同)
3)hashCode() 方法:返回该对象的 哈希码值
a:提高 具有 哈希结构的容器的效率。
b:两个引用,如果指向同一个对象,则 hash 值肯定相同。
c:两个引用,如果指向的是不同的对象,则 hash 值是不一定。(反之:哈希值一样,不一定是一个对象)
d:哈希值 主要根据地址号来的,不能完全将 哈希值 等价于 内存地址。
e:后面再集合中,hashCode 如果需要的话,也会重写。(集合时,继续讲解)
4)toString() 方法:默认返回:全类名 + @ + 哈希值的十六进制,一般都会进行重写
5)finalize() 方法:
a:当对象被回收时,系统自动调用该对象的 fianlize 方法。子类可以重写该方法,做一些释放资源的操作。
b:什么时候被回收:当某个对象没有任何引用时(堆中),则 jvm 就认为这个对象是一个垃圾对象,就会使用该对象的垃圾回收机制 来销毁该对象,在销毁该对象前,会先由 该对象的 垃圾回收器,调用 finalize() 方法。
c:垃圾回收机制的调用,是由系统来决定的;也可以通过 System.gc() 方法,主动触发垃圾回收机制。