01 前言

学校公选课选了Java,所以把Java学一下,每周三更一丢丢


02 环境配置

环境使用的是sdk-9.0.1
IDE使用的是IntelliJ IDEA 2019.3.3


03 Hello World

3.1 程序开发步骤说明

Java程序开发三步骤:编写,编译,运行

其中:
Javac.exe是编译器
Java.exe是解释器

3.2 编写Java源程序

先新建一个HelloWorld.java然后通过cmd先编译再运行

编译:javac HelloWorld.java 这里会生成一个HelloWorld.class文件,就是编译以后运行用的

运行:java HelloWorld 这里运行的是HelloWorld.class文件但是我们不需要再cmd中输入.class

out:Hello World!

3.3 代码注释规则

Java的注释规则和C/C++一样
单行用//多行用/**/

3.4 解释HelloWorld.java

1
2
3
4
5
6
7
public class HelloWorld
{
public static void main(String[] args)
{
System.out.println("Hello world!");
}
}

这里第一行中的第三个单词必须和文件名称完全一样
public class后面定义的是一个类的名称,类是java当中所有源代码的基本组织单位
第三行中public static void main(String[] args)是万年不变的固定写法,代表main方法,这一行代表程序执行的起点
System.out.println("Hello World!")是java的print语句

3.5 标识符

标识符:是指在程序中,我们自己定义内容。比如类的名字、方法的名字和变量的名字等等,都是标识符

  • HelloWorld案例中,出现的标识符有类名字HelloWorld

命名规则:

  • 标识符可以包含英文字母26个(区分大小写)0-9数字$(美元符号)_(下划线)
  • 标识符不能以数字开头
  • 标识符不能是关键字

04 常量

4.1 概述

常量:是指在Java程序运行期间固定不变的数据

4.2 分类

分类和C/C++,python中的基本上都是一样的
分为:

  • 字符串常量:”Hello World”
  • 整型常量:1
  • 浮点型常量:3.3
  • 字符常量:’A’
  • 布尔常量:true、false
  • 空常量:NULL

05 变量和数据类型

5.1 变量概述

变量:常量是固定不变的数据,那么在程序中可以变化的量称为变量

就和C/C++中int a等一样,一个保存数据的变量

5.2 数据类型

5.2.1 数据类型分类

Java的数据类型分为两大类:

  • 基本数据类型:包括整型浮点型字符布尔
  • 引用数据类型:包括数组接口

5.2.2 基本数据类型

Java中默认的数据类型:整型是int,浮点型是double

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Variable {
public static void main(String[] args) {
byte b = 100; // 定义字节变量
System.out.println(b);
short s = 1000; // 定义短整型变量
System.out.println(s);
int i = 123456; // 定义整型变量
System.out.println(i);
long l = 111111111111L; // 定义长整型,注意末尾要加L
System.out.println(l);
float f = 3.14F; // 定义单精度浮点型,注意末尾要加F
System.out.println(f);
double d = 3.1415926; // 定义双精度浮点型
System.out.println(d);
boolean bool = true; // 定义布尔变量
System.out.println(bool);
char c = 'A'; // 定义字符型变量
System.out.println(c);
}
}

5.3 数据类型转换

5.3.1 自动转换

自动转换:将取值范围小的类型自动提升为取值范围大的数据类型

转换规则:

  • 范围小的类型向范围大的类型提升,byte,short,char运算时提升为int

  • byte,short,char--->int--->long--->float--->double--->String

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class DataType {
public static void main(String[] args) {
System.out.println(2020); // 整数类型,默认就是int
System.out.println(3.14); // 浮点数类型,默认为doule

int num1 = 1;
byte num2 = 3;

// byte sum1 = num1 + num2; 会报错,因为num1是int类型,不会自动转换为小的byte类型
int sum2 = num1 +num2; // 自动转换:将取值范围小的类型自动提升为取值范围大的数据类型
// 这里byte只有一个字节,在和int类型运算时,会提升为int类型,自动补充3个字节
System.out.println(sum2);

double num3 = 3.14;
double sum3 = num1 + num3;
System.out.println(sum3);

char c = '1';
int sum = c + num1; // c去ASCII码数字
System.out.println(sum);
}
}

out:

1
2
3
4
5
2020
3.14
4
4.140000000000001
50

5.3.2 强制类型转换

强转类型转换:将字节大的数据类型强转成字节小的数据类型

类似于python中的规则

1
2
3
4
5
6
7
8
9
10
11
12
public class DataType {
public static void main(String[] args) {
// 将字节大的数据类型强转成字节小的数据类型
int i = (int)3.14; // 类似于python中的强转,这里取整
System.out.println(i);

short s = 1;
//s = s + 1; error,因为1默认为int类型,所以s的字节无法存储1
s = (short)(s+1);
System.out.println(s);
}
}

浮点转成整数,直接取消小数点,可能造成数据损失精度

int强制转成short砍掉2个字节,可能造成数据丢失、数据溢出

对于byte/short/char三种类型来说,如果右边复制的数值没有超过范围,那么编译器会自动隐含的为为我们补上强转符号(byte)(short)(char),超过范围就会报错

在给变量进行赋值的时候,如果右侧的表达式中全都是常量,没有任何变量,那么编译器将会直接将若干个常量表达式计算得到结果

06 运算符

6.1 算数运算符

算数运算符:
+ 加法运算
- 减法运算
* 乘法运算
/ 除法运算
% 取余运算
++ 自增运算
自减运算
1
2
3
4
5
6
7
8
9
10
11
12
13
public class draft {
public static void main(String[] args)
{
double a = 5.0 / 3.0;
System.out.println(a);
System.out.println(5 + 3);
System.out.println(5 - 3);
System.out.println(5 / 3);
System.out.println(5.0 / 3.0);
System.out.println(5 % 3);
System.out.println("Hello" + "World");
}
}

字符串相加即为字符串拼接,与python规则一样

自增自减和cpp、python一样,不详细讲了

字符串在Java中的定义为String使用的是双引号""

6.2 赋值运算符

赋值运算符:
= 右边向左边赋值
+= 加等于
-= 减等于
*= 乘等于
/= 除等于
%= 取模等于

6.3 比较运算符

比较运算符:
== 判断相等
> 大于
< 小于
>= 大于等于
<= 小于等于
!= 不等于

6.4 逻辑运算符

逻辑运算符:
&&
ll
! 取反

6.5 三元运算符

数据类型 变量名 = 布尔类型表达式? 结果1 : 结果2

和Cpp规则一样

三元运算符计算方式:

  • 布尔类型表达式结果是true,三元运算符整体结果为结果1,赋值给变量。

  • 布尔类型表达式结果是false,三元运算符整体结果为结果2,赋值给变量。

1
2
3
4
5
6
7
public class draft {
public static void main(String[] args)
{
int i = (1 == 2? 123:567);
System.out.println(i);
}
}

07 方法

我们在学习运算符的时候,都为每个运算符单独的创建一个新的类和main方法,我们会发现这样编写代码非常的繁琐,而且 重复的代码过多。能否避免这些重复的代码呢,就需要使用方法来实现。

  • 方法:就是将一个功能抽取出来,把代码单独定义在一个大括号内,形成一个单独的功能。

当我们需要这个功能的时候,就可以去调用。这样即实现了代码的复用性,也解决了代码冗余的现象。

就是cpp和python中的函数

必须要在class中定义

1
2
3
4
5
修饰符 返回值类型 方法名(参数列表) {
代码

return 返回值;
}
  • 修饰符:目前先固定写成public static

  • 返回值类型:int,void…..

  • 方法名:符合命名规范即可

  • 参数列表:形参

注意:

  • 方法定义的先后顺序无所谓

  • 方法的定义不能产生嵌套包含关系

1
2
3
4
5
6
7
8
9
public class draft {
public static void main(String[] args) {
HelloJava();
}

public static void HelloJava() {
System.out.println("Hello world and Hello Java");
}
}

7.1 方法定义格式

1
2
3
4
修饰符 返回值类型 方法名(参数列表){
//代码部分
return 结果;
}
  • 修饰符: public static 固定写法

  • 返回值类型: 表示方法运行的结果的数据类型,方法执行后将结果返回到调用者

  • 参数列表:方法在运算过程中的未知数据,调用者调用方法时传递

  • return:将方法执行后的结果带给调用者,方法执行到return,整体方法运行结束

7.2 调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Draft {
public static void main(String[] args) {
print();
int c = getSum(3, 2);
System.out.println(getSum(3, 6));
}

public static int getSum(int a, int b) {
return a + b;
}

public static void print() {
System.out.println("Hello world, Hello Java!");
}
}

out:

1
2
Hello world, Hello Java!
9

7.3 方法重载

  • 方法重载:指在同一个类中,允许存在一个以上的同名方法,只要它们的参数列表不同即可,与修饰符和返回值类型无关。

  • 参数列表:个数不同,数据类型不同,顺序不同。

  • 重载方法调用:JVM通过方法的参数列表,调用不同的方法。

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
public class Draft {
public static void main(String[] args) {
byte a = 10;
byte b = 20;
short c = 20;
short d = 20;
int e = 10;
int f = 10;
long g = 10;
long h = 20;

System.out.println(compare(a, b));
System.out.println(compare(c, d));
System.out.println(compare(e, f));
System.out.println(compare(g, h));
}

public static boolean compare(byte a, byte b) {
System.out.println("type : ");
return a == b;
}

public static boolean compare(short a, short b) {
System.out.println("short : ");
return a == b;
}

public static boolean compare(int a, int b) {
System.out.println("int : ");
return a == b;
}

public static boolean compare(long a, long b) {
System.out.println("long : ");
return a == b;
}
}

08 判断语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Draft {
String name;
int score;
public static void main(String[] args){
Draft xiaoming = new Draft();
xiaoming.name = "小明";
xiaoming.score = 88;
Draft laoming = new Draft();
laoming.name = "老明";
laoming.score = 99;
if(laoming.score > xiaoming.score){
System.out.println("老明分高");
}else if(xiaoming.score > laoming.score){
System.out.println("小明分高");
}else{
System.out.println("相等");
}
}
}

09 选择语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Draft
{
public static void main(String[] args)
{
int week = 2;
switch (week)
{
case 1:
System.out.println("星期一");
break;
case 2:
System.out.println("星期二");
break;
case 3:
System.out.println("星期三");
break;
default:
System.out.println("no");
break;
}
}
}

在switch语句中,如果case的后面不写break,将出现穿透现象,也就是不会在判断下一个case的值,直接向后运行,直到遇到break,或者整体switch结束。

10 循环语句

10.1 for

1
2
3
4
5
6
7
8
9
public class Draft{
public static void main(String[] args){
int sum = 0;
for(int i = 1; i <= 100; i++){
sum += i;
}
System.out.println(sum);
}
}

10.2 while

1
2
3
4
5
6
7
8
9
10
public class Draft{
public static void main(String[] args){
int sum = 0, i = 1;
while(i != 101 ){
sum += i;
i++;
}
System.out.println(sum);
}
}

10.3 do while

1
2
3
4
5
6
7
8
9
10
public class Draft {
public static void main(String[] args) {
int sum = 0, i = 1;
do {
sum += i;
i++;
} while (i != 101);
System.out.println(sum);
}
}

10.4 break

同C/C++

10.5 continue

同C/C++

11 数组

11.1 初始化数组

11.1.1 动态初始化

数组存储的数据类型[] 数组名字 = new 数组存储的数据类型[长度];

1
2
3
4
5
6
7
public class Draft {
public static void main(String[] args) {
int[] Array = new int[100];
double[] ArrayA = new double[19];
String[] ArrayB = new String[3];
}
}

11.1.2 静态初始化

数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3…};

1
2
3
4
5
6
public class Draft {
public static void main(String[] args) {
int[] ArrayA = new int[]{1, 2, 3, 4};
String[] ArrayB = new String[]{"Hello", "World", "Java"};
}
}

11.1.2.1 省略格式

1
2
3
4
5
public class Draft {
public static void main(String[] args) {
int[] ArrayA = {1, 2, 3, 4};
}
}

11.1.3 初始化中的拆分格式

1
2
3
4
5
6
7
8
9
10
11
public class Draft {
public static void main(String[] args) {
int[] ArrayA;
ArrayA = new int[]{1, 2, 3};
int[] ArrayB;
ArrayB = new int[4];
// 但是不能这样写
// int[] ArrayC;
// ArrayC = {1,2,3,4};
}
}

11.2 使用数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Draft {
public static void main(String[] args) {
//静态
int[] Array = {1, 2, 3, 4, 5};
System.out.println(Array); //内存地址哈希值:[I@5fd0d5ae
System.out.println(Array[3]);
int num = Array[0];
System.out.println(Array[0]);
//动态
int[] ArrayA = new int[3];
System.out.println(ArrayA[0]);
System.out.println(ArrayA[1]);
System.out.println(ArrayA[2]);
ArrayA[0] = 222;
System.out.println(ArrayA[0]);
}
}

out:

1
2
3
4
5
6
7
[I@5fd0d5ae
4
1
0
0
0
222

  • 使用动态初始化数组的时候,其中的元素将会自动拥有一个默认值,规则如下:
    • 如果是整数类型,那么默认为0
    • 如果是浮点类型,那么默认为0.0
    • 如果是字符类型,那么默认为’\u0000’
    • 如果是布尔类型,那么默认为false
    • 如果是引用类型,那么默认为null

直接打印数组名称会打印出它的内存地址的哈希值

使用格式和C/C++中一样

11.3 内存

Java的内存需要划分为5个部分:

  • 1.栈(Stack):存放的都是方法中的局部变量,方法的运行一定要在栈当中。
    • 局部变量:方法的参数,或者是方法{}内部的变量
    • 作用域:一旦超出作用域,立刻从栈内存中消失
  • 2.堆(Heap):凡是new出来的东西,都在堆当中
    • 堆内存里面的东西都是有一个地址值:16进制
    • 堆内存里面的数据,都有默认值,规则:
      • 如果是整数:默认为0
      • 如果是浮点数:默认为0.0
      • 如果是字符:默认为’\u0000’
      • 如果是布尔:默认为false
      • 如果是引用类型:默认为null
  • 3.方法区(Method Area):存储.class的相关信息,包含方法的信息
  • 4.本地方法栈(Native Method Stack):与操作系统相关
  • 5.寄存器(pc Register):与CPU相关


11.4 两个引用指向同一块数组内存地址

1
2
3
4
5
6
7
8
9
public class Draft {
public static void main(String[] args) {
int[] arrayA = {1,4,5,6,7,3};
System.out.println(arrayA[2]);
int[] arrayB = arrayA;
arrayB[2] = 888;
System.out.println(arrayB[2]);
}
}

11.5 获取数组的长度

1
2
3
4
5
6
7
public class Draft {
public static void main(String[] args) {
int[] arrayA = {1, 4, 5, 6, 7, 3};
int len = arrayA.length;
System.out.println(len);
}
}

数组在程序运行中长度是不可改变的

12 类

12.1 类与对象

  • 类:是一组相关属性和行为的集合。可以看成是一类事物的模板,使用事物的属性特征和行为特征来描述该类事物。

    • 属性:就是该事物的状态信息。
    • 行为:就是该事物能够做什么。
  • 对象:是一类事物的具体体现。对象是类的一个实例(对象并不是找个女朋友),必然具备该类事物的属性和行为。

12.2 类的定义

格式:

1
2
3
4
public class ClassName {
//成员变量
//成员方法
}

  • 定义类:就是定义类的成员,包括成员变量和成员方法。
  • 成员变量:和以前定义变量几乎是一样的。只不过位置发生了改变。在类中,方法外。
  • 成员方法:和以前定义方法几乎是一样的。只不过把static去掉,static的作用在面向对象后面课程中再详细讲解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Student {
String name;
int age;

public void eat() {
System.out.println("吃饭");
}

public void sleep() {
System.out.println("睡觉");
}

public void study() {
System.out.println("学习");
}
}

类中是不需要static

12.3 类的调用

在刚刚的那个Student.class的同级目录下

1、导包

1
2
import 包名称.类名称;
import ash.Student;

当前类和使用的类在同一个包下时,可以省略导包语句不写

2、创建

类名称 对象名 = new 类名称()

3、使用

对象名.成员变量名
对象名.成员方法名(参数)

1
2
3
4
5
6
7
8
9
10
11
12
public class Draft{
public static void main(String[] args) {
Student bao = new Student();
bao.age = 20;
bao.name = "包";
System.out.println(bao.age);
System.out.println(bao.name);
bao.eat();
bao.sleep();
bao.study();
}
}

out:

1
2
3
4
5
20

吃饭
睡觉
学习

12.3.1 内存

12.4 使用对象类型作为参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Draft {
public static void main(String[] args) {
Phone one = new Phone();
one.brand = "苹果";
one.price = 8388.0;
one.color = "土豪金";
method(one);
}

public static void method(Phone param) {
System.out.println(param.brand);
System.out.println(param.price);
System.out.println(param.color);
}
}

12.4.1 内存

当对象作为参数时,传递到方法当中时,实际上是传递进去的是对象的地址值

12.5 使用对象类型作为返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Draft {
public static void main(String[] args) {
Phone two = getPhone();
System.out.println(two.color);
System.out.println(two.brand);
System.out.println(two.price);
}

public static Phone getPhone() {
Phone one = new Phone();
one.brand = "苹果";
one.price = 8388.0;
one.color = "玫瑰金";
return one;
}
}

当使用一个对象类型作为方法的返回值时,返回值其实就是对象的地址值

12.5.1 内存

13 局部变量和成员变量

局部变量和成员变量的区别:

  • 1、定义的位置不一样

    • 局部变量:在方法的内部
    • 成员变量:在方法的外部
  • 2、作用范围不一样

    • 局部变量:只有在定义的方法内部才能使用,在方法外部不可使用
    • 成员变量:整个类中都可以使用
  • 3、默认值不一样

    • 局部变量:没有默认值,如果想要使用,必须手动进行赋值
    • 成员变量:如果没有赋值,会有默认值,规则和数组一样
  • 4、内存的位置不一样

    • 局部变量:位于栈内存
    • 成员变量:位于堆内存
  • 5、生命周期不一样:

    • 局部变量:随着方法进栈而诞生,随着方法出栈而消失
    • 成员变量:随着对象创建而诞生,随着对象被回收而消失

14 封装

14.1 定义

面向对象三大特性:封装,继承,多态

  • 1、方法就是一种封装
  • 2、private也是一种封装

14.2 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Draft {
public static void main(String[] args) {
int[] array = {12, 2, 4, 5, 22, 42, 1, 2, 4};
int max = getMax(array);
System.out.println("最大值:" + max);
}

public static int getMax(int[] array) {
int max = array[0];
for (int i = 1; i <= array.length - 1; i++) {
if (array[i] > max) {
max = array[i];
}
}
return max;
}
}

14.3 private

一旦使用private进行修饰,那么本类中仍可访问,但是超出本类后不可访问

间接方位private成员变量,就是定义一对Getter/Setter方法

必须叫setXxx或是getXxx命名规则

  • 对于Getter来说,不能有参数,返回值类型和成员变量对应

  • 对于Setter来说,不能有返回值,参数类型必须和成员变量对应

Person.class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Person {
String name;
private int age;

public void setAge(int num) {
if(num > 0 && num < 100>) {
age = num;
}else{
System.out.println("数据错误");
}
}

public int getAge() {
return age;
}
}

Graft.class

1
2
3
4
5
6
7
8
public class Draft {
public static void main(String[] args) {
Person one = new Person();
one.name = "GEM";
one.setAge(18);
System.out.println(one.getAge());
}
}

对于boolean数据类型,getXxx要更换成isXxx,而setXxx规则不变

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
public class Person {
String name;
private int age;
boolean male;

public void setAge(int num) {
age = num;
}

public int getAge() {
return age;
}

public String getName() {
return name;
}

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

public void setMale(boolean bool) {
male = bool;
}

public boolean isMale() {
return male;
}
}

14.4 this

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
public class Person {
String name;
private int age;
boolean male;

public void setAge(int num) {
age = num;
}

public int getAge() {
return age;
}

public String getName() {
return name;
}

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

public void setMale(boolean bool) {
male = bool;
}

public boolean isMale() {
return male;
}
}

14.5 构造方法

构造方法是专门用来创建对象的方法,当我们通过关键字nuw来创建对象时,其实就是在调用构造方法

  • 1、构造方法的名称必须和所在类的名称完全一样
  • 2、构造方法不用写返回值,不用写void
  • 3、如果没有编写任何构造方法,编译器会自动创建一个空的构造方法
  • 4、构造方法也是可以重载的
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
public class Person {
private String name;
private int age;
boolean male;

public Person(){
System.out.println("无参构造");
}

public Person(String name,int age){
System.out.println("有参构造");
this.name = name;
this.age = age;
}

public void setAge(int num) {
age = num;
}

public int getAge() {
return age;
}

public String getName() {
return name;
}

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

public boolean isMale() {
return male;
}

public void setMale(boolean bool) {
male = bool;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
package ash;

public class Draft {
public static void main(String[] args) {
Person one = new Person();
System.out.println("==============");
Person two = new Person("GEM",18);
System.out.println(two.getAge());
System.out.println(two.getName());
two.setAge(19);
System.out.println(two.getAge());
}
}

out:

1
2
3
4
5
6
无参构造
==============
有参构造
18
GEM
19

如果对象需要重新修改成员变量数据内容,仍需要setXxx

14.6 标准类(Java Bean)

一个标准的类通常需要满足以下四点:

  • 1、所有的成员变量都要使用private进行私有化修饰
  • 2、为每一个成员变量编写一对Getter/Setter
  • 3、编写一个无参的构造方法
  • 4、编写一个全参的构造方法

15 常用API

传送门:

🖱点我传送