搜索到1篇与笔记的结果

Java-笔记
# Java
- Java 采用全面面向对象
- Java 入口类必须是 main
- 必须 ; 结尾
- 自上而下执行
## 数据类型
程序在运行过程中,根据不同的数据类型分配不同的内存空间
### 基本数据类型
1. 整数型 ( byte、short、int、long )
区别:占用的空间大小不同
2. 浮点型 ( float、double )
3. 布尔型 ( boolean )
4. 字符型 ( char )
| 数据类型 | 占字节数 | 取值范围 | 缺省默认值 |
| ------------------ | -------- | ------------------------------------------------------------ | ---------- |
| byte (字节类) | 1 | [ -2<sup>7</sup> ~ 2<sup>7</sup> -1]、[ -128~127 ] | 0 |
| short (短整类) | 2 | [ -2<sup>15</sup> ~ 2<sup>7</sup> -1]、[ -32768 ~ 32767] | 0 |
| int (整类) | 4 | [ -2<sup>31</sup> ~ 2<sup>31</sup> -1]、[ -2147483648 ~ 214783647 ] | 0 |
| long (长整类) | 8 | [ -2<sup>63</sup> ~ 2<sup>63</sup> -1 ] | 0L |
| float (单精度) | 4 | [ -2<sup>31</sup> ~ 2<sup>31</sup> -1] | 0.0f |
| double (双精度) | 8 | [ -2<sup>63</sup> ~ 2<sup>63</sup> -1 ] | 0.0 |
| boolean (布尔型) | 1 | true、false | false |
| char (字符类) | 2 | [ 0~2<sup>16</sup> -1]、[ 0~65535 ] | '\u0000' |
### 引用数据类型
除了基本数据类型剩下的全部是引用型
## 运算符
| 运算符 | 值 |
| ---------------- | ----------------------------------- |
| 算术运算符 | +、-、*、%(取模)、++、-- |
| 关系运算符 | >、>=、<、<=、、==、!== |
| 逻辑运算符 | &、\|、!、&&、\|\| |
| 赋值运算符 | =、+=、-=、*=、%=、&=、\|、<<=、>>= |
| 位运算符 | &、\|、^、~、<<、>>、<<< |
| 条件运算符 | (三元) |
| 字符串连接运算符 | + |
| 其他运算符 | instanceof、new |
## 面向对象
### 构造方法
构造方法可以完成对象的创建,以及实例变量的初始化
当一个类中没有提供构造方法,系统会默认提供无参数的构造方法,这个无参数的构造方法叫做缺省构造器
构造方法名 必须和 类名 保持一致
[修饰符列表] 构造方法名 (形参列表) { }
明星类
```java
public class Star {
int no;
String name;
/*
构造方法
[修饰符列表] 构造方法名 (形参列表) {}
构造方法名必须和类名一致
*/
public Star (int no, String name)
{
this.no = no;
this.name = name;
}
public static String sendName(String name)
{
return name;
}
}
```
测试对象
```java
public class ObjTest {
public static void main(String[] args){
Star ldh = new Star(1,"刘德华");
Star zxy = new Star(2,"张学友");
System.out.println(ldh.no);
System.out.println(ldh.name);
System.out.println(zxy.no);
System.out.println(zxy.name);
}
}
```
### 继承
Java中,子类继承父类,除构造方法不能继承之外,剩下都可以继承。但是私有的属性无法在子类中直接访问。
Java 不支持多继承,但是有时候可以间接继承的效果
比如:class A,class B extends A,class C extends B,class D extends C。
父类
```java
public class Base {
private int no;
private String username;
static String name = "刘德华";
public static void p(String val)
{
System.out.println("你好:"+val);
}
public Base()
{
}
public Base(int no, String username)
{
this.no = no;
this.username = username;
}
public int getNo() {
return no;
}
public String getUsername() {
return username;
}
public void send(String val)
{
System.out.println("发送成功!"+ val + "Base");
}
}
```
子类
```java
public class BaseTest extends Base {
public static void main(String[] args)
{
BaseTest b = new BaseTest(11,"刘德华");
b.send(b.getUsername());
}
public BaseTest(int no, String username)
{
// 调用父类的 构造方法
super(no,username);
}
public void send(String val)
{
System.out.println("发送成功!"+ val + "Test");
}
}
```
### 方法覆盖
如果子类有一个实例方法和父类的 name 参数 一样则会覆盖(使用子类的方法而不是使用父类的方法)
- 方法覆盖只针对于方法,和属性无关
- 私有方法无法覆盖
- 构造方法不能被继承,所以构造方法不能被覆盖
- 方法覆盖只是针对于 实例方法,静态方法覆盖没意义
什么条件满足的时候构成方法覆盖 ?
1. 有继承关系的两个类
2. 具有相同方法名,返回值类型、形式参数列表
3. 访问权限不能更低。
4. 抛出异常不能更多。
### 多态
多种形态,多种状态
1. 编译阶段 (判断父类型方法)
2. 运行阶段 (动态绑定子类型对象的方法)
#### 基础语法
##### 向上转型
子--->父 父类 a = new 子类();
##### 向下转型
父--->子 子类 c = (子类)a
什么时候进行向下转型?
需要调用或者执行子类对象中特有的方法 必须进行向下转型,才可以调用。
风险:
容易出现ciasscastException(类型转换异常)
怎么避免这个风险?
instanceof运算符,可以在程序运行阶段动态的判断某个引用指向的对象是否为某一种类型。
养成好习惯,向下转型之前一定要使用instanceof运算符进行判断。
#### 作用
面向抽象编程,不要面向具谑编程。降低程序的耦合度。提高程序的扩展力。

### final
修饰 表示最终的,不可变的
1. 被修饰的类,无法继承
2. 被修饰的方法,无法被覆盖(被重写)
3. 修饰的变量,一旦赋值了,就不可改变了(只能赋值一次)
4. 修饰引用的对象(变量),一旦赋值了,就不可改变引入对象的内存地址,但是可以对象内部的数据可以修改
5. 修饰的,实例变量,系统不会默认赋值,必须手动赋值
6. 修饰的实例变量一般添加 static 修饰(常量)
### 抽象类
抽象类无法实例化,无法创建对象,是因为抽象类和类之间有共同特征,将具有共同特征的类再进一步
抽象形成了抽象类,由于类本身不存在,所以抽象类无法创建对象。
final 和 abstract 不能联合使用,这两个关键字是对立的
抽象类有构造方法,供子类使用
抽象类中不一定有抽象方法,抽象方法必须出现在抽象类中。

抽象类也需要引入类型
**<span style="color:#E02433;">如果抽象类中存在 抽象方法,子类如果是非抽象类,必须进行抽象方法重写</span>**
#### 定义
[ 修饰符列表 ] abstract class 类名 {}
### 接口
- 接口也是一种引入数据类型,编译之后也生成 class 字节码文件
- 接口是完全抽象的(抽象类是半抽象)
- 接口支持继承,一个接口可以继承多个接口
- 接口中只包含两部分内容,一部分是:常量、一部分是:抽象方法
- 接口所有元素都是 public 修饰的
- 接口中定义抽象方法时,public abstract 修饰符可以省略、常量前面的修饰符也可以省略
- 接口中的方法不能有<span style="color:#E02433;">方法体</span>
- 一个类可以继承多个接口
- extends和implements可以共存,extends在前,implements在后。
- 使用接口,写代码的时候,可以使用多态(父类型引用指向子类型对象〉|
#### 定义
[ 修饰符列表 ] interface 接口名 {}
#### 作用
类似于多态在开发中的作用。
接口完全是面向抽象编程。
面向抽象编程这句话以后可以修改为:面向接口编程。
有了接口就有了可插拔。可插拔表示扩展力很强。不是焊接死的。
主板和内存条之间有插槽,这个插槽就是接口,内存条坏了,可以重新买一个换下来。这叫做高扩展性。(低耦合度。)
<span style="color:#E02433;">接口的使用离不开多态</span>
## 控制修饰符
| 修饰符 | 本类 | 同包 | 子类 | 任意位置 |
| --------- | ---- | ---- | ---- | -------- |
| public | 可 | 可 | 可 | 可 |
| protected | 可 | 可 | 不 | 不 |
| 默认 | 可 | 可 | 不 | 不 |
| private | 可 | 不 | 不 | 不 |
从大到小:public > protected > 默认 > private
## 数组
1. 数组是一种引入数据类型,数组的 父类是 Object
2. 数组中,可以存储基本数据类型,和引入数据类型
3. 因为数组是引入类型,所有数组对象存储在堆内存中
4. 数组一旦创建,在java中规定中,不可变
5. Java中的数组要求数组中的元素统一,比如 int 类型的数组只能存储 int 类型的数据。
6. 数组在内存方面存储的时候,数组中的元素内存地址是连续的
7. 数组中第一次元素的内存地址,作为整个数组的内存地址
### 优点
查询/查找/检索某个下标上的元素时效率极高。可以说是查询效率最高的一个数据结构。
1. 每一个元素的内存地址在空间存储上是连续的。
2. 每一个元素类型相同,所以占用空间大小一样。
3. 知道第一个元素内存地址,知道每一个元素占用空间的大小,又知道下标,所以通过一个数学表达式就可以计算出某个下标上元素的内存地址。查接通过内存地址定位元素,所以数组的检索效率是最高的。
数组中存储100个元素,或者存储100万个元素,在元素查询/检索方面,效率是相同的,因为数组中元素查找的时候不会一个一个找,是通过数学表达式计算出来的。(算出一个内存地址,直接定位的。)
### 缺点
1. 由于为了保证数组中每个元素的内存地址连续,所以在数组上随机删除或者增加元素的时候,效率较低,因为随机增删元素会涉及到后面元素统―向前或者向后位移的操作。
2. 数组不能存储大数组量,因为很多在内存空间上找到一块特别大的连续的内存空间
```java
public class ArrayTest04 {
public static void main(String[] args) {
// 一维数组
int[] arr1 = {1,2,3};
// 二维数组
int[][] arr2 = {
{1,2,3},
{4,5,6},
{7,8,9}
};
// 三维数组
int[][][] arr3 = {
{
{1,2,3},
{1,2,3},
{1,2,3}},
{
{1,2,3},
{1,2,3},
{1,2,3}},
{
{1,2,3},
{1,2,3},
{1,2,3}
}
};
}
}
```
```java
public class ArrayTest01 {
public static void main(String[] args) {
// 静态创建数组
int[] arr1 = {100,200,300,400,500};
/*
动态创建数组 这里表示数组元素的个数
初始化一个长度为5的int类型数组,每个元素默认值 0
*/
int[] arr2 = new int[5];
// 循环遍历数组
for (int i = 0; i < arr2.length;i++)
{
// 赋值
arr2[i] = i;
System.out.println(arr2[i]);
}
// 循环遍历数组
for (int value : arr1) {
System.out.println(value);
}
}
}
```
### 扩容
在Java开发中,数组长度一旦确定不可变,那么数组满了怎么办?
Java中对数组的扩容是:
先新建一个大容量的数组,然后将小容量数组中的数据一个一个拷贝到大数组当中
结论:数组扩容效率较低。因为涉及到拷贝的问题。所以在以后的开发中请注意﹔尽可能少的进行数组的拷贝。
```javascript
public class ArrayTest03 {
public static void main(String[] args) {
int[] arr = new int[4];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
int[] maxArr = new int[20];
// 源数组 起始位置 目标 目标起始位置 拷贝数量(长度)
System.arraycopy(arr,0,maxArr,0 ,arr.length);
for (int i = 0; i < maxArr.length ; i++) {
System.out.println(maxArr[i]);
}
}
}
```
### 类库
#### 排序
```java
int[] arr = {550,200,300,45012,3,1};
// 从小到大
Arrays.sort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
```
#### 二分法查找
```java
public class ArrayUtil {
public static void main(String[] args) {
int[] arr = {113,200,257,600,700,985,1300};
// 找 arr 数组中 200所在的下标
int index = binarySearch(arr,1300);
System.out.println(index == -1 ? "该元素不存在" : "该元素下标是:" + index);
}
/**
* 从数组中查找目标元素下标
* @param arr 被查找的数组(必须已经排序的)
* @param dest 目标元素
* @return -1 表示该元素不存在,其他表示该元素的下标
*/
private static int binarySearch(int[] arr, int dest) {
// 开始下标
int begin = 0;
// 结束下标
int end = arr.length -1;
// 开始元素的下标只能要在结束元素下标的左边,就继续循环
while (begin <=end){
// 中间元素下标
int mid = (begin + end) / 2;
if(arr[mid] == dest) {
return mid;
} else if (arr[mid] < dest){
// 目标在中间的右边
begin = mid + 1;
}else{
// arr[mid] > dest
// 目标在中间的左边
end = mid - 1;
}
}
return -1;
}
}
```
## 字符串
### 类库
#### contains
判断前面字符串是否包含后面的子字符串
```java
System.out.printle("Hello World.java").contains(".java"); // true
System.out.printle("https://www.xkbk.top").contains("http"); // false
```
#### endsWith
判断当前字符串是否以某个字符串结尾
```java
System.out.printle("Hello World.java").endWith("a"); // true
System.out.printle("Hello World.java").endWith("bb"); // false
```
#### equals
判断两个字符串是否相等(不能用 == )
```java
String s1 = "abc";
String s2 = "abc";
String s3 = "acd";
System.out.printle(s1.equals(s2)); // true
System.out.printle(s1.equals(s3)); // false
```
#### equalsIgnoreCase
判断两个字符串是否相等,并且忽略大小写
```java
String s1 = "abc";
String s2 = "abc";
String s3 = "Acd";
System.out.printle(s1.equals(s2)); // true
System.out.printle(s1.equals(s3)); // true
```
#### getBytes
接字符串对象转成字节数组,返回值是 byte 数组
```java
byte[] bytes = "adcaadf".getBytes();
```
#### indexOf
判断某个子字符串在当前字符串第一次出现处的索引
```java
System.out.printle("ordermysqlputhoncsshtml".indexOf("mysql")); // 5
```
lasIndexOf
判断某个子字符串在当前字符串最后一次出现处的索引
```java
x System.out.printle("ordermysqlmysql".indexOf("mysql")); // 10
```
#### isEmpty
判断某个字符串是否为空
```java
String s1 = "";
System.out.printle(s1.isEmpty()); // true
```
#### replace
替换字符串,返回新的字符串
```java
String s1 = "http://www.baidu.com".replace("http://","https://");
System.out.printle(s1); // https://www.baidu.com
```
#### split
拆分字符串,返回的是一个字符串数组
```
String[] s1 = "1980-10-11".split("-");
```
#### startsWith
判断当前字符串是否以某个子字符串开始
```java
System.out.printle("abc".startsWith("a")); // true
System.out.printle("abc".startsWith("bb")); // false
```
#### substring
截取字符串,开始位置,结束位置(为空默认最后)
```java
System.out.printle("https://www.baidu.com".substring(7,20)); // www.baidu.com
```
#### toCharArray
将一个字符串转换成 char 数组
```java
char[] c1 = "我是中国人".toCharArray();
```
#### toLowerCase()
转换为小写
```JAVA
System.out.printle("ABCDDAA".toLowerCase()); // abcddaa
```
#### toUpperCase
转换为大写
```java
System.out.printle("abcddaa".toUpperCase()); // ABCDDAA
```
#### trim
去掉当前字符串,前后空格
```java
System.out.printle(" abcddaa ".trim()); // abcddaa
```
#### StringBuffer
创建一个程序量为16个byte[] 数组,(字符串缓冲区对象)( 会自动扩容 )
优化:创建 StringBuffer 对象的时候尽量指定合适的初始容量,避免后期需要扩容
```java
public class stringBuffer01 {
public static void main(String[] args) {
// 默认创建一个 16 的 byte[] 数组容量
StringBuffer stringBuffer = new StringBuffer();
// 添加
stringBuffer.append("你浩");
stringBuffer.append("kkk");
stringBuffer.append(3.14);
stringBuffer.append(true);
System.out.println(stringBuffer);
// 指定初始化 容量 100
StringBuffer stringBuffer2 = new StringBuffer(100);
System.out.println(stringBuffer2);
}
}
```
#### StringBuilder
StringBuilder 和 StringBuilder 的使用方法一样
区别:StringBuilder 中的方法都有 synchronized 关键字修饰
StringBuffer 在多线程环境下运行是安全的
StringBuilder 是不安全 但是可变类,速度更快
## 包装类
8种 包装类型
| 基本数据类型 | 包装类型 | 父类 |
| ------------ | ------------------- | ------ |
| byte | java.Lang.Byte | Number |
| short | java.Lang.Short | Number |
| int | java.Lang.Integer | Number |
| long | java.Lang.Long | Number |
| float | java.Lang.Float | Number |
| double | java.Lang.Double | Number |
| boolean | java.Lang.Boolean | Object |
| char | java.Lang.Character | Object |
### Number
是一个抽象类,无法实例化
```java
public class IntegerTest {
public static void main(String[] args) {
// 123这个是基本数据类型,进行构造方法的包装达到了:基本数据类型向引入数据类型转换
//基本数据类型 ——> 引入数据类型 (装箱)
Integer i = 123;
// 将引入数据类型 -> 基本数据类型 (拆箱)
float b = i.floatValue();
System.out.println(b);
// 将引入数据类型 -> 基本数据类型 (拆箱)
int result = i.intValue();
System.out.println(result);
Integer c = new Integer("456");
System.out.println(c);
Integer d = new Integer(12);
System.out.println(d);
}
}
```
### 常量
```java
public class InegerTest02 {
public static void main(String[] args) {
// 通过访问包装类的常量,来获取最大值和最小值
System.out.println("int的最大值" + Integer.MAX_VALUE);
System.out.println("int的最小值" + Integer.MIN_VALUE);
System.out.println("byte的最大值" + Byte.MAX_VALUE);
System.out.println("byte的最小值" + Byte.MIN_VALUE);
}
}
```
### 自动装/拆箱
在 JDK 5 之后,支持自动装/拆箱
```java
public class IngerTest03 {
public static void main(String[] args) {
// 自动装箱
Integer i = 123;
// 自动拆箱
float b = i;
System.out.println(b);
}
}
```
### 常用类
```java
public class IngerTest03 {
public static void main(String[] args) {
// 字符串 转 int
int retValue = Integer.parseInt("567");
System.out.println(retValue);
// 字符串 转 double
double res = Double.parseDouble("34.15");
System.out.println(res);
// 其它类型 照葫芦画瓢
}
}
```
## 日期
### Date
Date 日期对象
SimpleDateFormat 格式化日期对象
```java
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateTest01 {
public static void main(String[] args) {
// 获取系统时间(精确到毫米)
Date newTime = new Date();
System.out.println(newTime); // Thu Mar 31 10:14:43 CST 2022
/*
* 日期格式化
* yyyy 年
* MM 月
* dd 日
* HH 时
* mm 分
* ss 秒
* SSS 毫米
* */
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(newTime)); // 2022-03-31 10:20:25
}
}
```
### 日期字符串转 Data
```java
import java.util.Date;
import java.text.SimpleDateFormat;
public class DateTest02 {
public static void main(String[] args) throws Exception {
String time = "2002-12-31 12:08:06";
// 注意:格式必须和字符串日期格式一致
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 字符串 转 Date
Date time2 = sdf.parse(time);
System.out.println(time2); // Tue Dec 31 12:08:06 CST 2002
}
}
```
### 时间戳
```java
public class DateTest03 {
public static void main(String[] args) {
// 获取时间戳
long Time = System.currentTimeMillis();
System.out.println(Time); // 1648694403445
// 记录 运行 print() 耗时 时间
long begin = System.currentTimeMillis();
print();
long end = System.currentTimeMillis();
long printTime = (end - begin);
System.out.println("耗时:"+printTime+"毫米");
}
public static void print()
{
for (int i = 0; i < 1000; i++) {
System.out.println(i);
}
}
}
```
时间戳转 Date
```java
import java.util.Date;
public class DateTest04 {
public static void main(String[] args) {
// 获取昨天
Date time = new Date((System.currentTimeMillis() - 1000 *60 * 60 *24));
System.out.println(time);
}
}
```
## 随机数
```java
import java.util.Random;
public class RandomTest01 {
public static void main(String[] args) {
// 创建随机数对象
Random random = new Random();
// nextInt 生成一个 int 类型 范围的随机数
int num1 = random.nextInt();
System.out.println(num1);
// 生成 0~100 之间的随机数
int num2 = random.nextInt(100);
System.out.println(num2);
}
}
```
### 生成不重复的随机数
```java
import java.util.Arrays;
import java.util.Random;
public class RandomTest02 {
public static void main(String[] args) {
Random random = new Random();
int[] arr = new int[5];
for (int i = 0; i < arr.length; i++) {
arr[i] = -1;
}
int index = 0;
while (index < arr.length) {
int num = random.nextInt(5);
if(!contains(arr,num)) {
arr[index] = num;
index++;
}
}
for (int i = 0; i <arr.length ; i++) {
System.out.println(arr[i]);
}
}
public static boolean contains(int[] arr ,int key){
for (int i = 0; i < arr.length; i++) {
if(arr[i] == key) {
return true;
}
}
return false;
}
}
```
## 异常
异常在java中 是以类和对象的形式存在
### 处理
1. 在方法声明的位置上,使用 throws 关键字 抛给上一级
2. 使用 try....catch 语句进行异常捕捉
```java
public class ExceptionTest01 {
public static void main(String[] args) {
try {
System.out.println(100 / 0);
} catch (Exception e) {
System.out.println("发生异常了");
System.out.println(e);
}
}
}
```
```java
public class ExceptionTest02 {
// 上抛 throws ClassNotFoundException
// public static void main(String[] args) throws ClassNotFoundException {
// doSome();
// }
public static void main(String[] args) {
// main方法中调用doSome()方法
// 因为doSome()方法声明位置上有:throws ClassNotFoundException
// 如果不处理,编译器就报错。
// Unhandled exception: java.lang.ClassNotFoundException
// 未处理异常
// doSome();
// 处理异常
// 第一种方式继续上抛异常 在方法声明位置 throws ClassNotFoundException
// 第二种捕捉异常
try {
doSome();
} catch (Exception e) {
}
}
/**
* doSome方法在方法声明的位置上使用了 :throws CLassNotFoundException
* 这个代码表示doSome()方法在执行过程中,有可能会出现cLassNotFoundException异常。
* 叫做类没找到异常。这个异常直接父类是:Exception,所以CLassNotFoundException属于编译时异常。
* @throws ClassNotFoundException
*/
public static void doSome() throws ClassNotFoundException{
}
}
```
### 异常对象主要方法
```java
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class ExceptionTest03 {
public static void main(String[] args) {
try {
new FileInputStream("C:\\User\\xiaoek\\Desktop\\cns.jpg");
} catch (FileNotFoundException e) {
// 获取异常简单的描述信息
String msg = e.getMessage();
System.out.println(msg);
// 打印异常的堆栈信息
e.printStackTrace();
}
}
}
```
### finally
- finally中的代码是最后执行的,并且会一定执行,即使 try 语句中的代码出现异常。
```java
import java.io.FileInputStream;
public class ExceptionTest04 {
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("C:\\User\\xiaoek\\Desktop\\cns.jpg");
System.out.println("Hello World");
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("我是一定会执行");
}
}
}
```
```java
public class ExceptionTest05 {
public static void main(String[] args) {
/* try {
System.out.println("try .....");
return;
// finally 还是会执行
} finally {
System.out.println("finally ...");
}*/
try {
System.out.println("try .....");
// 退出JVM
System.exit(0);
// finally 不会执行
} finally {
System.out.println("finally ...");
}
}
}
```
### 自定义异常类
1. 编写一个继承 Exception(编译时异常)或 RuntimeException (运行时异常)
2. 提供两个构造方法,一个无参,一个带有 String 参数的
```java
public class MyException extends Exception{
public MyException (){
}
public MyException (String s){
super(s);
}
}
```
使用
```java
public class Exception06 {
public static void main(String[] args) {
// // 创建异常对象 (这里只 new了 异常对象,并没抛出去)
// MyException myException = new MyException("用户名不能为空");
// // 获取简单描述信息
// System.out.println(myException.getMessage());
// // 打印异常堆栈信息
// myException.printStackTrace();
// 处理异常
try {
doSome();
} catch (MyException e) {
e.printStackTrace();
}
}
public static void doSome() throws MyException {
// 创建异常
MyException myException = new MyException("用户名不能为空");
// 抛出异常 (上抛)
throw myException;
}
}
```
### 覆盖问题
- 重写之后的方法不能比重写之前的方法抛出更多异常,可以更少
```java
class Animal {
public void doSome(){}
public void doOther() throws Exception{}
}
class Cat extends Animal {
// 编译正常
public void doOther(){}
/* 编译报错
public void doSome() throws Exception{}*/
/* 编译正常
public void doOther(){}*/
}
```
## 集合
数组其实就是一个集合,集合实际上就是一个容器,可以来容纳其它类型的数据。
### 存储
集合不能直接存储基本数据类型,另外集合页也不能直接存储 java 对象,集合当中存储的都是 java 对象的内存地址(或者说集合中存储的是引用)
**集合存储的是引用**
在 java 中每一个不同的集合,底层会对应不同的数据结构,往不同的集合中存储元素,等于将数据放到不同的数据结构中。
### 分类
一类是单个方式存储元素:这一类集合中的超级父接口:java.util.Collection
一类是以键值对的方法存储:这一类集合中的超级父接口:java.util.Map
### Collection
1. Collection 中能放什么元素?
1. 没用使用泛型之前,Collection 中可以存储 Objet 的所有子类型
2. 使用了 泛型 之后,Collection 中只能存储某个具体类型
#### 常用方法
- boolean add (Object e) 向集合中添加元素
- int size() 获取集合中的元素个数
- void clear() 清空集合
- boolean contains(Object o) 判断集合中是否存在某个元素,存在返回 true,不存在返回 false
- boolean remove( Object o) 删除集合中的某个元素
- boolean isEmpty() 判断集合是否为空
- Object[] toArray() 集合转数组
```java
import java.util.ArrayList;
import java.util.Collection;
/*
* java.util.Collection 接口的常用方法
* */
public class CollectionTest01 {
public static void main(String[] args) {
// 创建一个接口对象 (注意:Collection 是一个接口是无法实例化的 可以实例化它下面的子类 多态)
Collection collection = new ArrayList();
// add 向集合中添加元素
// 自动装箱 实际上是放进去一个内存地址( new Integer(1200) )
collection.add(500);
collection.add(new Integer(80));
collection.add("600");
System.out.println(collection);
// size 获取集合中元素的个数
int CollectionSize = collection.size();
System.out.println(CollectionSize);
// 清空集合
collection.clear();
System.out.println(collection.size());
collection.add("小明");
collection.add("小红");
collection.add("小华");
collection.add("小强");
System.out.println(collection);
// contains 判断接口中是否存在某个元素
System.out.println(collection.contains("小明")); // true
System.out.println(collection.contains("小芳")); //
// remove 删除集合中某个元素
collection.remove("小明");
System.out.println(collection);
}
}
```
### 迭代器
```java
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/*
* 集合迭代
* */
public class CollectionTest02 {
public static void main(String[] args) {
Collection c = new ArrayList();
c.add("小明");
c.add("小红");
c.add("小华");
c.add("小强");
/*
* 迭代
* 1.获取集合迭代器
* 2.循环
* */
/*
* 迭代器方法
* boolean hasNext() 如果仍有元素可以迭代,则返回 true
* Object next() 返回迭代的下一个元素
* 迭代器最终并没有指向第一个元素
* */
Iterator it = c.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
```
### List
存储特点:有序可重复
#### 常用方法
- void add (int index, E element) 指定下标添加元素(无第一个参数为在集合末尾添加元素)
- E get(int index) 获取指定下标元素
- int indexOf(Object o) 获取指定元素第一次出现的下标
- int lastIndexOf(Object o) 获取指定元素最后出现的下标
- E remove(int index) 删除指定下标元素
- E set(int index,E element) 修改指定下标元素
```java
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ListTest01 {
public static void main(String[] args) {
List list = new ArrayList();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
list.add(1,"KING");
Iterator it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
// 获取指定下标元素
System.out.println("第三个元素是:"+list.get(2));
// List 接口 特有的循环
for (int i = 0; i < list.size() ; i++) {
System.out.println(list.get(i));
}
// 获取指定元素第一次出现的下标
System.out.println("KING的下标是:" +list.indexOf("KING"));
// 获取指定元素最后一次出现的下标
System.out.println("C最后出现的下标:" +list.lastIndexOf("C"));
System.out.println(list);
// 删除指定下标的元素
list.remove(0);
System.out.println(list);
// 删除指定元素
list.remove("KING");
System.out.println(list);
list.set(1,"Jack");
System.out.println(list);
}
}
```
#### ArrayList
- 默认容量为10(底层先创建一个长度为空0的数组,当添加第一个元素的时候,初始化容量为10)
- 集合底层是一个 Object 数组
- 构造方法
- new ArrayList()
- new ArrayList(指定初始化容量)
- ArrayList集合的扩容:原容量的1.5倍,尽可能少扩容,在创建的时候给定一个初始化容量
521
2022-04-12
312℃
2
3