Java学习 - day003

Exception 异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.hspedu.exception_;

import java.util.Scanner;

public class Test {
public static void main(String[] args) {
// 创建 Scanner 对象
Scanner scanner = new Scanner(System.in);
int num = 0;
String inputStr = "";
while(true) {

System.out.println("Please input a Integer");
inputStr = scanner.next();
try {
num = Integer.parseInt(inputStr);
break;
} catch (NumberFormatException e) {
System.out.println("你输入的不是一个整数");
}
}

System.out.println("你输入的值是 " + num);
}
}


  • 编译异常,程序 必须处理
  • 运行时异常,程序中没有处理,默认就是 throws 方法进行处理(有默认处理机制,最终处理 这个异常的是我们的 JVM 虚拟机,JVM 虚拟机对相关的处理非常简单暴力,直接进行输出该异常

Throws 抛出语句

  • 之前我们使用的都是 try-catch 语句,现在我们使用 throws 抛出异常,让调用该方法的调用者进行异常处理
  • 如果我们在代码中出现了 try - catch 相当于处理了异常,就不用再使用 throws 语句
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Father {
public void method() throws RuntimeException {

}
}


class son extends Father {
// 子类抛出的异常要不与父类一致或者是父类的异常的子类
@Override
public void method() throws RuntimeException {
super.method();
}
}

自定义异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.hspedu.exception_.customexception;

public class Customexception {
public static void main(String[] args) {
int age = 180;

if (!(age >= 18 && age <= 120)) {
throw new AgeException("年龄需要在18 ~120 之间");
}
System.out.println("您的年龄范围正确");
}
}

class AgeException extends RuntimeException {
public AgeException(String message) {
super(message);
}

}

练习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.hspedu.exception_.homework;

public class Ecmdef {
public static void main(String[] args) {

// 先验证输入的个数对不对
try {
if (args.length != 2) {
throw new ArrayIndexOutOfBoundsException("参数个数不对");
}
int n1 = Integer.parseInt(args[0]);
int n2 = Integer.parseInt(args[1]);
double res = cal(n1, n2);
System.out.println("结果为= " + res);
} catch (ArrayIndexOutOfBoundsException e) {
throw new RuntimeException(e);
} catch (NumberFormatException e) {
System.out.println("参数格式不正确, 需要输出整数");
} catch (ArithmeticException e) {
System.out.println("出现了除零的异常");
}
}

public static double cal(int n1, int n2) {
return n1 / n2;
}

}

包装类

image-20250522210827227

自动装箱和手动装箱

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.hspedu.wrapper;
/**
* @author Wiretender
* @version 1.0
*/
public class Integer01 {
public static void main(String[] args) {
//演示int <--> Integer 的装箱和拆箱
//jdk5 前是手动装箱和拆箱
//手动装箱 int->Integer
int n1 = 100;
Integer integer = new Integer(n1);
Integer integer1 = Integer.valueOf(n1);
//手动拆箱
//Integer-> int
int i = integer.intValue();
//jdk5 后,就可以自动装箱和自动拆箱
int n2 = 200;
//自动装箱 int->Integer
Integer integer2 = n2; //底层使用的是 Integer.valueOf(n2)
//自动拆箱 Integer->int
int n3 = integer2; //底层仍然使用的是 intValue()方法
}
}

包装类练习题

1
2
Object obj1 = true ? new Integer(1) : new Double(2.0);
System.out.println(obj1); // 这里进行了一个变量提升的机制 三元运算符要看成一个整体

包装类型和 String 类型的相互转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* @author Wiretender
* @version 1.0
*/

public class WrapperVSString {
public static void main(String[] args) {
Integer i = 100;

String str1 = i + "";
// str1 = "100" 以基本数据类型转换的一个字符串
String str2 = i.toString();
// 包装类直接转换为字符串
String str3 = String.valueOf(i);

String str4 = "12345";
Integer i2 = Integer.parseInt(str4);
Integer i3 = new Integer(str4);// 构造器
}
}

  • 源码解读
1
2
3
4
5
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
  • 源码的 Valueof 方法中,对于传入的 int 类型,如果在范围 -127 ~ 128 就直接返回一个 int 类型,如果超出范围,就返回一个 Integer 对象,所以比较的时候对于 Integer 对象要使用 equals 来进行比较。

String 源码剖析

image-20250522214901662

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
packagecom.hspedu.string_;
/**
*@author韩顺平
*@version1.0
*/
public class String01{
public static void main(String[]args) {
//1.String对象用于保存字符串,也就是一组字符序列
//2."jack"字符串常量,双引号括起的字符序列
//3.字符串的字符使用Unicode字符编码,一个字符(不区分字母还是汉字)占两个字节
//4.String类有很多构造器,构造器的重载
//常用的有String s1=newString();//
//String s2=newString(Stringoriginal);
//String s3=newString(char[]a);
//String s4= newString(char[]a,intstartIndex,intcount)
//Strings5=newString(byte[]b)
//5.String类实现了接口Serializable【String可以串行化:可以在网络传输】
//接口Comparable[String对象可以比较大小]
//6.String是final类,不能被其他的类继承
//7.String有属性privatefinalcharvalue[];用于存放字符串内容
//8.一定要注意:value是一个final类型,不可以修改(需要功力):即value不能指向
//新的地址,但是单个字符内容是可以变化
String name = "jack";
name = "tom";
final char[] value = {'a','b','c'};
char[] v2 = {'t','o','m'};
value[0] = 'H';
//value=v2;不可以修改value地址
}
}

创建 String 的两种方法

image-20250522221133157

1
2
3
4
5
String a = "abc";
String b = "abc";
Sout(a.equals(b)); // true;
sout(a == b) // true
// 因为在创建 a 的时候已经在常量池创建了 "abc" 的数据空间,所以在创建 b 的时候直接指向该空间
  • 对于 intern()方法的文档

    • 当调用 intern 方法时,如果池已经包含与 equals(Object) 方法确定的相当于此 String 对象的字符串,则返回来自池的字符串。否则,此 String 对象将添加到池中,并返回对此 String 对象的引用。

StringBuffer 类

  • StringBuffer 是一个可变的字符串类,是一类容器,支持对字符串的增删查改
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* @author Wiretender
* @version 1.0
*/
package com.hspedu.wrapper_.stringbuffer_;

public class StringBuffer02 {
public static void main(String[] args) {
// String -> StringBuffer
// 1.创建一个大小为 16 的 char[] , 用于存放字符串
StringBuffer stringBuffer = new StringBuffer("hello");
// 2.通过构造器指定char[]大小
StringBuffer stringBuffer1 = new StringBuffer(100);
String str = "hello tom";
StringBuffer stringBuffer2 = new StringBuffer(str);
StringBuffer stringBuffer3 = new StringBuffer();
stringBuffer3 = stringBuffer3.append(str);

// StringBuffer -> String
StringBuffer stringBuffer4 = new StringBuffer("一二三四五");
String s = stringBuffer4.toString();
String s1 = new String(stringBuffer4);
}
}

ArrayList 底层源码和机构分析

  1. ArrayList 维护了一个 object 类型的数组 elementData transient Object[] elementData;
  2. 当创建 ArrayList 对象时,使用的是无参构造器,则初始的 elementData 容量为 0,第 1 次添加,则扩容 elementData 为 10,如需再次扩容,则扩容 elementDate 为 1.5 倍。
  3. 当创建 ArrayList 使用的是指定大小的构造器,则初始 elementData 容量为指定大小,如果需要扩容,指直接扩容 elementData 为 1.5 倍.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
// modCount 显示的是当前被修改的次数,
private void ensureExplicitCapacity(int minCapacity) {
// 防止多线程操作的的异常,记录当前集合被修改的次数
modCount++;

// overflow-conscious code
// 如果elementData大小不够,就调用grow方法去扩容 也就是我们在前文写的扩容1.5倍
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
// old + old / 2 = 1.5 * old (扩容1.5倍)
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 如果现在新的容量还没有开始的最小容量大,那我们就把这个最小的容量给新的
// 也就是当初始化的容量为 0 时
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}

Map接口源码分析

  1. Map 与 Collection 并列存在,用于保存具有映射关系的数据: (key-value)
  2. 当Map 中有相同的Key是,就会等价于替换该value

Map练习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/**
* @author Wiretender
* @version 1.0
*/
package com.hspedu.map_;

import java.security.KeyStore;
import java.util.*;

@SuppressWarnings({"all"})
public class Map01 {
public static void main(String[] args) {
// 使用HashMap添加3个员工对象,要求
// 键:员工id
// 值:员工对象
// 并遍历显示工资>18000的员工(遍历方式最少两种)
// 员工类:姓名、工资、员工d
HashMap employeeHashMap = new HashMap();
employeeHashMap.put(001, new Employee("Mike", 18000, 001));
employeeHashMap.put(002, new Employee("John", 5000, 002));
employeeHashMap.put(003, new Employee("Milan", 19000, 003));

// 1,entrySet
System.out.println("------entrySet for--------------");
Set entrySet = employeeHashMap.entrySet();
for (Object obj : entrySet) {
Map.Entry m = (Map.Entry) obj;
System.out.println(m.getKey() + " - " + m.getValue());
}

// 2.iterator
System.out.println("-----------iterator---------");
Iterator iterator = entrySet.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
// 向下转型
Map.Entry m = (Map.Entry) next;
Employee emp = (Employee) m.getValue();
if (emp.getSalary() > 18000) {
System.out.println(emp);
}
}

// 3.keySet and Collections values
// map.values() -> 这里存储的是一个Collection实现的
// // final class Values extends AbstractCollection<V>
System.out.println("-----------keySet and values---------");
Set keySet = employeeHashMap.keySet();
Collection values = employeeHashMap.values();
// (1) get all keys
Iterator iterator2 = keySet.iterator();
while (iterator2.hasNext()) {
Object next = iterator2.next();
System.out.println(next + " - " + employeeHashMap.get(next));
}
// (2) get all values
Iterator iterator3 = values.iterator();
while (iterator3.hasNext()) {
Object val = iterator3.next();
System.out.println("value" + " - " + val);
}

}
}

class Employee {
private String name;
private double salary;
private int employeeId;

public Employee(String name, double salary, int employeeId) {
this.name = name;
this.salary = salary;
this.employeeId = employeeId;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public double getSalary() {
return salary;
}

public void setSalary(double salary) {
this.salary = salary;
}

public int getEmployeeId() {
return employeeId;
}

public void setEmployeeId(int employeeId) {
this.employeeId = employeeId;
}

@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", salary=" + salary +
", employeeId=" + employeeId +
'}';
}
}



集合类总结(end)

image-20250531175145280