# java

 

# 基础概念

JDK：java开发环境，java开发工具

1. javac：编译成.class字节码文件
2. java：运行.class文件

JRE：java运行环境，Java核心类库

JVM：java虚拟机，跨平台兼容

关系：JVM>>JRE>>JVM

# 常用DOS指令

| 指令                  | 说明                  |
| --------------------- | --------------------- |
| d:                    | 切换盘符              |
| cd/cd..               | 切换文件夹/进入上一级 |
| dir                   | 文件列表              |
| md                    | 创建文件夹            |
| rd                    | 删除空文件夹          |
| del                   | 删除文件              |
| echo 内容>文件名.后缀 | 创建文件              |
| chcp                  | jdk编码格式           |

# 基本语法

## 关键字

- 电脑语言中事先定义，有特别意义的标识符
- 小写

## 保留字

- 特殊的关键字，无语义，未被java语言使用

## 标识符

- 由字母，数字，_，$组成

- 数字不能开头

- 不能使用关键字和保留字，但可以包含

- 区分大小写

- 不能包含空格

## 命名规范

- 包名：小写

- 类名，接口名：大驼峰命名（首字母大写） 

- 变量名&&方法名：小驼峰命名（首字母小写）

- 常量名：所有字母大写，_连接

## 注释

单行：//

多行：/* */

文本：/** */

## 变量

变量概念：在内存中的一个存储区域，可以在同一类型范围内变换值，内存存储的最小单元

==注意==：先声明（数据类型 变量名 = 值），后使用，仅在自身作用域有效，不能重名

## 数据类型

### 基本数据类型

| 类型    | 占用存储空间                              | 范围         |
| ------- | ----------------------------------------- | ------------ |
| byte    | 1字节=8bit（bit是计算机中最小的存储单位） | -128-127     |
| short   | 2字节                                     | -2^15-2^15   |
| int     | 4字节                                     | -2^31-2^31-1 |
| long    | 8字节（加L）                              | -2^63-2^63-1 |
| float   | 4字节（加F）                              | 小数点后7位  |
| double  | 8字节（默认浮点类型）                     | 小数点后14位 |
| char    | 1字节（单引号）                           | 单个字符     |
| boolean |                                           | true/false   |

### 引用数据类型

| 类型   | 说明     |
| ------ | -------- |
| String | 多个字符 |

### 数据类型转换

#### 自动类型转换

不同数据类型运算时，取数范围小的类型会自动转为取数范围大的类型

![](https://raw.githubusercontent.com/yzuxqz/pic-bed/master/notes-img/%E8%87%AA%E5%8A%A8%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2.png)

==注意==：

1. byte，short类型做运算，结果自动转为int类型
2. char类型在与数值类型做运算时取得AscII码值做运算，结果为int类型

#### 强制类型转换

将取数范围大的数据类型转为取数范围小的数据类型

float a = (float) 2.9；

==注意==：会损失精度

#### String类型转数值类型

int  i = Integer.parseInt(str)；

## 运算符

### 算术运算符

| 算术运算符 |      | 说明                                     |      |
| ---------- | ---- | ---------------------------------------- | ---- |
| +          |      | 加（字符串拼接）                         |      |
| -          |      | 减                                       |      |
| *          |      | 乘                                       |      |
| /          |      | 取整                                     |      |
| %          |      | 取余                                     |      |
| ++         |      | 自增（后缀：先赋值，再自增，前缀：相反） |      |
| --         |      | 自减（后缀：先赋值，再自减，前缀：相反） |      |

### 赋值运算符

| 赋值运算符 | 说明            |
| ---------- | --------------- |
| =          | 赋值            |
| +=         | i+=2相当于i=i+2 |
| -=         |                 |
| *=         |                 |
| /=         |                 |

### 比较运算符

| 比较运算符 | 说明 |
| ---------- | ---- |
| ==         | 相等 |
| !=         | 不等 |
| </<=       |      |
| >/>=       |      |

### 逻辑运算符

| 逻辑运算符 | 说明                          |
| ---------- | ----------------------------- |
| &          | 左边为flase会继续执行右边     |
| &&         | 短路，左边为false不会执行右边 |
| \|         | 左边为true会继续执行右边      |
| \|\|       | 短路，左边为true不会执行右边  |
| !          | 非                            |
| ^          | 异或，相同为false，不同为true |

### 位运算符

二进制

1. 正数

- 源码，反码，补码相同

1. 负数

- 反码：符号位不变，源码取反

- 补码：符号位不变，源码取反加一

| 位运算符 | 说明                                                         |
| -------- | ------------------------------------------------------------ |
| <<       | 左移x位(<<x),相当于原数*2^x                                  |
| >>       | 右移x位(<<x),相当于原数/2^x ，==注意==：高位为0补0，高位为1补1 |
| >>>      | 无符号右移，无论最高位是什么都补0                            |
| &        | 二进制各个位相与                                             |
| \|       | 二进制各个位相或                                             |
| ^        | 二进制各个位相异或                                           |
| ~        | 非                                                           |

区别逻辑运算符：位运算符操作数值，逻辑运算符操作布尔值

### 三元运算符

条件表达式 ？语句1（表达式为true）：语句2（表达式为false）;

==注意==：必须根据返回值类型接收结果

## Scanner类

1. 导入jar包

   java.util.Scanner;

2. 创建Scanner实例

   new Scanner(System.in);

3. 使用Scanner类中的方法

   next(),nextInt(),nextDouble(),next().charAt(0)

## Arrays类

java.util.Arrays;

## 流程控制语句

### 流程分支语句

- if else

```java
if(){
}else if(){
}else{
}
```

- switch case

```java
switch(表达式){
	case 常量1:语句1;
        break;
	case 常量2:语句2;
        break;
	case 常量3:语句3;
        break;
    default:语句4;
        break;
}
```

​		==注意==：表达式的类型只能是byte，short，int，char，String

​					 当没有break关键字时，匹配条件之后的代码都会去执行

### 循环控制语句

####  for

```java
for(初始;条件(布尔表达式);代代){
语句;
}
```

#### break

用于switch：结束当前switch

用于循环：结束循环，不继续下一次循环

#### continue

跳出本次循环，继续下一次循环

#### while

```java
初始
while(条件){
迭代
语句
}
```

​	随机数：

1. java.util.Random
2. new Random.nextInt(范围);

##### do while

```
初始
do{
迭代
语句
}while(条件)
```

==区别==：先执行再判断，至少会执行一次

## 数组

1. 数组是引用数据类型，数组元素不一定
2. 数组的长度一旦确定，就不能更改
3. 数组的创建会在内存开辟一连串连续的空间
4. 数组引用的是连续内存空间的首地址

### 一维数组

#### 声名和初始化

```java
//1.静态初始化：声名与初始化同时进行
int[] arr = new int[]{1,2,3}
//或者
int[] arr = {1,2,3}//类型推断
//2.动态初始化
String[] arr = new String[3];
double[] arr6 = new double[3];
```

#### 添加和获取元素

```java
//通过下标添加
arr6[0]=12.3;
arr6[3]=12;//编译通过，运行出错，索引越界
```

#### 遍历数组

```java
for(int i=0;i<arr.length;i++){
    System.out.println(arr[i]);
}
```

#### 数组元素的默认初始值

##### 基本数据类型

- 整形：0

- 浮点型：0.0

- char：0（ASCII码值）
- boolean：false

##### 引用数据类型

- null

#### 数组的内存解析

### 二维数组

#### 声名和初始化

```java
//1.静态初始化
//String[][] arrs = new String[][]{{"123","456"}}
//2.动态初始化
int[][] arrs1 = new int[5][2]
```

#### 添加和获取元素

```java
int[][] arr6 = {{1,2}}//类型推断
arr6[1][1];
arr6.length//二位数组的长度
arr6[0].length//一维数组的长度
```

#### 遍历二维数组

嵌套循环

#### 二维数组的默认初始值

外层数组：null

内层数组：与一维数组元素默认初始值相同

#### 二维数组内存解析

# 面向对象

## 属性

### 成员变量vs局部变量

相同点：

1. 声名赋值的方式一样
2. 先声明再使用
3. 都有自身的作用域

不同点：

1. 成员变量可以使用权限修饰符：public protected 缺省 private

   局部变量不能使用权限修饰符，修饰可以用static final关键字

2. 成员变量可以不用显示初始化

   局部变量必须进行显示初始化

3. 内存的存放：

   局部变量存放在栈中

   成员变量存放在堆中

4. 成员变量声名在类中

   局部变量可以存放在方法中，方法的参数

## 方法

### 声名

权限修饰符 返回类型 方法名（参数类型 参数1，...）{}

1. 权限修饰符

   用来限定对象对该类成员（属性，方法）的一个访问权限

   修饰属性

   修饰方法

   修饰类：只能使用public和缺省

   | 权限修饰符      | 类内部 | 同一个包 | 不同包的子类 | 同一个工程 |
   | --------------- | ------ | -------- | ------------ | ---------- |
   | public          | yes    | yes      | yes          | yes        |
   | protected       | yes    | yes      | yes          |            |
   | 缺省（default） | yes    | yes      |              |            |
   | private         | yes    |          |              |            |

2. 返回类型

   1. 有返回值

      返回值可以是变量，也可以是常量：return 返回数据；既返回值又结束方法

   2. 无返回值

      void关键字，也可以用return;表示结束方法

3. 方法名

   小驼峰

4. 参数（形参）

   局部变量 

5. 在同一个类中，方法1可以继续调用方法1（递归）

6. 方法中不能再声名方法

### 重载

1. 在同一个类中
2. 方法名相同
3. 参数列表不同（参数个数，参数类型）

### 值传递机制

基本数据类型：方法传递的是变量本身的值，方法的形参会开辟新的内存空间

引用数据类型：方法参数传递的是地址值

## 匿名对象

 	new Person().name = "Linc"

==注意==：只能使用一次

## 对象数组

Student[] s1 =  new Student[]

## 构造器

```java
//无参构造器
权限修饰符 类名(){
}
//有参构造器
权限修饰符 类名(形参){
	this.xxx = 参数;
}
```

==注意==：构造器没有返回类型，构造器可以重载。每一个类都会提供一个默认的无参构造器，当我们在类中定义了一个有参的构造器，类中就不会再有无参构造器

## this关键字

可以放在方法中

构造器中

还可以在构造器中去调用其他的构造器

```java
//调用当前对象的无参构造器
public Constructor(String name){
	this();
	this.name = name;
}
//调用当前对象的有参构造器
public Constructor(String name,int age){
	this("xqz");
	this.name = name;
  	this.age = age;
}
```

## 封装

表现

- 属性私有化
- 通过公共的方法去操作私有的属性

```java
public class Person {
    private int age;

    public void setAge(int age) {
        if (age >= 0 && age <= 130){
            this.age = age;
        }else{
            this.age = 20;
        }
    }

    public int getAge(){
        return age;
    }
}
```

## package

1. 为了更好的实现项目中类的管理，提供包的概念

2. 使用package声名类或接口所属的包，声名在源文件的首行

3. 包，属于标识符，遵循标识符的命名规则，规范，见名知意

4. 每”.“一次，就代表一层文件目录

   ==注意==：同一个包下，不能命名同名的接口和类

### jdk包介绍

![](https://raw.githubusercontent.com/yzuxqz/pic-bed/master/notes-img/jdk%E5%8C%85%E4%BB%8B%E7%BB%8D.png)

## import

1. 在源文件中显示的使用import结构导入指定包下的类，接口
2. 声名在包的声名和类的声名之间
3. 如果需要导入多个结构，则并列写出即可
4. 可以使用xxx.*的方式，表示可以导入xxx包下的所有结构
5. 如果使用的类或接口是java.lang包下定义的，则可以省略import
6. 如果使用的类或接口是本包下定义的，则也可以省略
7. 如果同时引入不同的包里有同名的类，其中一个要com.xxx.xxx.类名来使用，import中只能有一个
8. 使用”xxx.*“方式可以调用xxx包下的所有结构，但如果是xxx子包下的结构，仍需要显示导入
9. import static: 导入指定类或接口==里面==的静态结构

## 继承

extends&&super

## 重写

子类覆盖父类的方法

前提：有继承关系

1. 子类的访问修饰符权限不能小于父类重写方法的访问修饰符权限

   ==注意==：父类中的private方法不能被重写

2. 引用数据类型：子类重写的方法的返回值类型不能大于父类被重写的方法的返回值类型

3. 基本数据类型：子类重写的方法的返回值类型（比如：double）必须和父类被重写的方法的返回值类型一模一样

4. 对于方法名和参数列表：子类必须和父类相同

```java
访问修饰符 返回类型  方法名(参数列表){
     方法体
}
```

==区别==：方法的重写和重载

## super

1. 理解为：父类的

2. 可以用来调用：属性，方法，构造器

   ### super的使用

   1. 可以在子类的方法或者构造器中中显式的调用父类的属性和方法，用super.属性或super.方法,但是通常会省略该super
   2. 特殊情况==：
      1. 当子类和父类定义了同名属性时，要想在子类中调用父类中的属性，不能省略super
      2. 当子类重写了父类的方法时，要想在子类中调用父类中方法，不能省略super

   ### super调用构造器

   1. 在子类的构造器中显示的使用super（形参列表）的方式，调用父类中声名的指定的构造器

   2. super(形参列表)的使用，必须声名在子类构造器的首行

   3. 注意：在类的构造器中，this(形参列表):调用本类中其他的构造器

      和super(形参列表)只能二选一，如果什么都没写，默认会有super()，即父类的无参构造

## 多态

前提：

- 继承关系
- 方法重写

1. 编译时看左边：编译时的类型看声名变量的类型，运行时看右边：new出来的类型
2. 子类必须重写了父类的方法才能使用多态
3. 子类中具有父类同名的属性和方法，在多态的情况下，使用的是父类的属性和子类的方法

### 向下转型

Cat cat = (Cat) animal

这样才能使用子类中独有的属性和方法

### instance of

```java
if(animal instance of Cat（这里是类型）{}
```

## ==和equals的区别

1. ==：运算符 进行比较的

2. 基本数据类型（除了boolean）间的比较,比较的是值

   ```java
   int a = 10;
   int b = 20;
   a==b//false
       
   double c = 12.5;
   a==c//false,int会自动转为double
       
   char d = 10;//10代表的是ascii码值为10的字符
   a==d//true(char类型的运算是用ascii码值进行计算的)
   char e = 'a';
   char f = 97;
   e==f//true
   ```

3. 引用数据类型

   比较的是地址

   equals方法是java.lang.Object类提供的一个方法,内部还是用的==,String类对equals方法进行了重写，所以String类型的可以用equals进行比较

   ```java
   Person person1/3 = new Person("xqz",21)
   person1==person2//false
   person1.equals(person3)//false，因为这里equals内部还是用的==，Person并没有进行重写
   
   String str1 = "123";
   String str2 = "123";
   str1 == str2//true，123属于方法区中的常量池，所以str1和str2都指向常量池中的123，String是个较为特殊的包装类型，直接用=“”创建的数据是存放在常量池
   ```

4. 一般来说，对于引用类型调用equals方法进行比较的时候，是调用Object类提供的equals方法，执行的==，比较的地址值

5. 特殊情况：String，Date，File里重写了equals方法，比较的是值

## 重写toString方法

toString

- java.lang.Object类提供

- 返回的是当前类的全类名+@+地址值（十六进制）
- 重写后输出实体值

```java
Person person = new Person("xqz",21)
sout(person)//输出地址，println()方法会先调用valueof()，然后在该方法里面再调用object的toString()
   
String str = new String("123");
sout(str);//输出123，str重写了toString方法
```

==注意：==

```java
        char[] arr1 = new char[]{'a','b','c'};
        System.out.println(arr1);//abc
        int[] arr2 = new int[]{'a','b','c'};
        System.out.println(arr2);//地址
        double[] arr3 = new double[]{12.4,3.6,5.6};
        System.out.println(arr3);//地址
```

==解释==：println()方法中有char[]特有的重载方法，会打印char数组中的元素，其他类型的数组则没有重载方法，会进入valueof方法，然后调用object类中的toString方法，输出地址值。

## 包装类

基本数据类型，包装类，String类的数据类型转

![](https://raw.githubusercontent.com/yzuxqz/pic-bed/master/notes-img/%E5%8C%85%E8%A3%85%E7%B1%BB%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2.png)

### 基本数据类型转包装类

调用包装类的构造器

### 包装类转基本数据类型

调用包装类的xxxValue()

==注意：==

1. new Integer("xxx")，会自动转为int类型，但前提是xxx都是数字，否则会报错
2. Boolean中只要是和true不一样的都为false
3. 包装类作为其他类的成员变量时默认值为null，因为它已经是一个类了

### 自动装箱与自动拆箱

1. 自动装箱

   基本数据类型-->包装类

2. 自动拆箱

   包装类-->基本数据类型

```java
int a = 10;
Integar in = a;//自动装箱

Integar in = new Integar(12);
int b = in;//自动拆箱
```

### 基本数据类型包装类转String类型

1. 连接运算
2. String类型的valueof方法

```java
int num1 = 10;
String str1 = num1 +""
    
String str2 = String.valueof(num1)
    

```

### String类型转基本数据类型包装类

1. 调用包装类的parseXxx方法

   转化之前必须保证这个数是可以转的

```java
String str1 = "123"
int num2 = Integar.parseInt(str1)
```

注意：Integar的值在-128到127则是在常量池中直接取值，地址相同。>127或者<-128则会开辟新的地址。

## static关键字

修饰属性，方法，代码块，内部类

![](https://raw.githubusercontent.com/yzuxqz/pic-bed/master/notes-img/static.png)

1. 非静态属性：属于类的对象，需要new创建对象才能调用，独立于每一个对象

   静态属性：属于类，随着类的加载而加载，优先于对象创建，被类的所有对象所共享，当修改其中一个对象中的静态属性时，会改变其他对象的该属性，因为静态属性在静态域中，多个对象的该属性指向的是同一个静态域中的地址。调用方式：类名.属性

2. 静态方法中，只能调用静态的方法和静态的属性，非静态方法中，都可以调用

   静态方法中不能使用this，super关键字

   通过类名.静态方法名，调用

3. 开发中，属性是多个对象所共享的，不会随着对象的不同而改变，则声名为static。

   类中的常量也声名为static

### 类的生命周期

类加载 .class 文件进行加载，未涉及到jvm

## 代码块

也是类的结构                                                                                                                                                                                                                                                                                    

1. 只能用static修饰，用来初始化类，对象

2. 静态代码块：随着类的加载而执行，只执行一次，不能调用非静态的结构

   ​					  作用：初始化类的信息

   非静态代码块：随着对象的创建而执行，每创建一个对象就执行一次非静态代码块。

   ​						 作用：可以在创建对象时，对对象的属性进行初始化
   
3. 代码块可以存在多个按先后顺序执行

4. 顺序：

   由父及子，静态先行

   1. 父类静态代码块
   2. 子类静态代码块
   3. 父类非静态代码块
   4. 父类无参构造器
   5. 子类的非静态代码块
   6. 属性
   7. 子类的无参构造器

5. 对属性赋值

   1. 默认赋值
   2. 显示赋值/代码块
   3. 构造器
   4. 对象属性或方法

## final关键字

1. 修饰类：不能被继承

2. 修饰方法：不能再被重写

3. 修饰变量：

   - 修饰变量：常量

   - 修饰属性：能显示初始化，在代码块中初始化，构造器中初始化

   - 修饰局部变量：方法体中：常量

     ​						  形参：实参进行赋值后只能调用不能改变值	

4. static final 用来修饰属性：全局常量

## 抽象类

1. 不能实例化
2. 抽象类中一定有构造器，便于子类实例化时调用
3. 开发中，都会提供抽象类的子类，让子类对象实例化

## 抽象方法

1. 抽象方法只有方法的声名，没有方法体

2. 包含抽象方法的类，一定是一个抽象类。反之，抽象类中可以没有抽象方法

3. 子类重写了父类所有的抽象方法，方可实例化。如果子类没有重写父类所有的抽象方法，则子类是一个抽象类

   ==注意：==

   1. abstract不能修饰属性，构造器
   2. 不能修饰私有方法，静态方法（静态方法不能被覆盖）

## 接口

1. 在jdk7.0之前，接口中可以声名全局常量和抽象方法
2. 接口没有提供构造器，不能进行实例化操作
3. 在jdk8.0还可以在接口中声名静态方法和默认方法
4. 使用i
5. mplements实现接口
6. 如果不实现接口，类用abstract修饰
7. 一个类实现了接口需要重写接口中所有的抽象方法
8. 接口可以继承接口，且支持多继承

## 静态方法和默认方法

1. 静态方法：public static void play(){}
2. 默认方法：public default void sing(){}
3. 调用静态方法：接口名.方法名
4. 调用默认方法：需要创建子类对象，通过子类去调用

## 内部类

### 成员内部类

1. 一方面作为外部类的成员

   - 可以调用外部类的结构
   - 可以被static修饰
   - 可以被4中不同的权限修饰

2. 另一方面，作为一个类

   - 类内可以定义属性，方法，构造器

   - 可以用final修饰，表示此内部类无法继承。
   - 可以被abstract修饰，表示不能被实例化

```java
//实例化静态成员内部类
Person.Dog dog = new Person.Dog();
dog.show();
//实例化非静态成员内部类
Person p = new Person();
Person.Bird bird = p.new Bird();
bird.sing();
//内部类的方法调用同名参数
name//方法形参
this.name//内部类的属性
Person.this.name//外部类的属性
```

#### static成员内部类

static class

#### 非static成员内部类

### 局部内部类

方法内

代码块内

构造器内

# 异常

1. error

   jvm无法解决的严重性问题

   比如：stackoverflowError超出栈内存空间，oom超出堆内存空间

2. exception

异常处理：

1. try（可能出现异常的代码）-catch（出现异常后的逻辑）-finally（一定会执行的代码）
2. throws+异常类型，放在方法名之前。逐层向上抛出，子类继承父类时，父类抛出了异常，子类抛出的异常不大于父类抛出的异常
3. 在方法中存在多个方法的调用，并且有多个方法存在递进关系的时候，一般在这几个方法中使用throws，最后在方法中使用try-catch

自定义异常

1. 需继承于目前存在的异常，通常使用RuntimeException/Exception

# String类

1. final修饰的类，不能被继承
2. 实现了Serializable接口，表示String类能够被序列化
3. 实现了Cinparable接口，表示String类可以比较大小
4. 实现了CharSequence接口：字符序列
5. String定义了一个final char[]数组存放字符内容
6. 根据final的特性，推断出String是一个不可变的字符序列
7. 通过字面量的方式给字符串赋值，会在字符串的常量池中开辟空间
8. 字符串常量池不会存储相同的内容
9. 改变字符串的内容时，不会改变原有的，而是重新开辟空间
10. 两个字面量相加，在常量池中
11. 有变量相加，都在堆中开辟空间，堆中有指向常量池中的地址，等同于new操作

常用方法：

![](https://raw.githubusercontent.com/yzuxqz/pic-bed/master/notes-img/%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%B8%B8%E7%94%A8%E6%96%B9%E6%B3%951.png)

![](https://raw.githubusercontent.com/yzuxqz/pic-bed/master/notes-img/%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%B8%B8%E7%94%A8%E6%96%B9%E6%B3%952.png)

![](https://raw.githubusercontent.com/yzuxqz/pic-bed/master/notes-img/%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%B8%B8%E7%94%A8%E6%96%B9%E6%B3%953.png)

# StringBuffer类

可变的字符序列，线程安全的但是效率低

![](https://raw.githubusercontent.com/yzuxqz/pic-bed/master/notes-img/StringBuffer%E5%B8%B8%E7%94%A8%E6%96%B9%E6%B3%95.png)

# StringBuilder类

可变的字符序列，线程不安全但是效率高
