Java 基础

Java 基础

1 第一个Java程序

  • 创建一个HelloWord.java 文件,编写如下内容:

    package com.fcarey;
    
    /*
    在Java中,每一行实际运行的代码,都必须包含在类的内部。
    这行声明了一个名为类 Main,它是 public 公共的, 这意味着其他任何类都可以访问它。
    注:
      当我们声明一个public类,也必须使用相同的名称(Main.java文件)的文件中声明它,否则编译时,会出错。
    */
    public class HelloWorld {
        
        /*
        这是我们的Java程序的入口点。 main方法有这个确切的签名 main,以便能够运行我们的程序。
        public 意味着任何人都可以访问它.
        static 意味着你可以不创建实例运行此 Main 方法.
        void 意味着此方法不返回任何值。
        main 方法的名称。
        */
        public static void main(String[] args) {
    
            /*
            System 是一个预先定义的类,Java为我们提供,它拥有一些有用的方法和变量
            out 是系统类 System 中的静态变量,可以提供打印输出。
            println 是出一种方法,可用于打印一行。
            */
            System.out.println("Hello World");
    
        }
    }
    
  • 编译程序

    # 格式:javac 文件名.java
    javac HelloWorld.java
    
  • 运行程序

    # java 类名
    java HelloWorld
    
  • JDK11开始支持 java命令直接运行.java文件

    # 格式:java 文件名.java
    java HelloWorld.java
    

2 IDEA中的代码结构

完成HelloWorld案例的基本流程:

  1. 新建一个空项目: java_learning
  2. 新建一个新模块: java_day01
  3. java_day01模块的src下新建一个包: com.fcarey
  4. com.fcarey包下新建一个类: HelloWorld
  5. HelloWorld类中编写代码
  6. IDEA中运行HelloWorld

3 Variables Types

3.1 数据类型

数据类型 关键字 占用内存 取值范围
整数 byte 1 -128 ~ 127
整数 short 2 -32768 ~ 32767
整数 int(default) 4 -2^31 ~ 2^31-1
整数 long 8 -2^63 ~ 2^63-1
浮点数 float 4 1.4E-45 ~ 3.4028E+38
浮点数 double(default) 8 4.9E-324 ~ 1.7976E+308
字符 char 2 0 ~ 65535
布尔 boolean 1 true, false
  • 说明:E+38表示:乘以10的38次方。同理E-45表示:乘以10的负45次方

3.2 变量的注意事项

  • 变量名不能重复

  • 变量未赋值,不能使用

  • 定义long类型变量,数据后面加L

  • 定义float类型变量,数据后面加F

  • 练习:

    package com.fcarey;
    
    public class VariablesTypes {
        public static void main(String[] args) {
            // 声明一个 int 语法
            int myNumber;
            myNumber = 1;
            // 或组合在一起
            int myNumber2 = 2;
            // 定义一个 double 语法
            double d = 3.14;
            // 重新赋值
            d = 3.1415;
            // 定义一个 float 语法
            float f = 3.14f; // 常用
            float f2 = (float) 3.1415;
            // 定义一个 char 语法
            char c = 'g';
            // 使用构造器创建一个字符串
            String s1 = new String("Who let the dogs out?");
            // 使用双引号 "" 创建一个字符串,所以没必要用上面的方法.
            String s2 = "Who who who who!"; // 常用
            // java定义了 + 加号运算两个字符串就是把两个字符串联合起来
            String s3 = s1 + s2;
            // 字符串 + 变更 结果为字符串
            int num = 5;
            String s = "I have " + num + " cookies";
            boolean b = false;
            System.out.println("int1 = " + myNumber);
            System.out.println("int2 = " + myNumber2);
            System.out.println("double = " + d);
            System.out.println("float1 = " + f);
            System.out.println("float2 = " + f2);
            System.out.println("char = " + c);
            System.out.println("string1 = " + s3);
            System.out.println("string2 = " + s);
            System.out.println("boolean = " + b);
        }
    }
    

3.3 关键字

关键字就是被Java语言赋予了特定含义的单词,特点:

  • 关键字的字母全部小写
  • 常用的代码编辑器,针对关键字有特殊的颜色标记,非常直观。
// 48个关键字:
    abstract、assert、boolean、break、byte、case、catch、char、class、continue、default、do、double、else、enum、extends、final、finally、float、for、if、implements、import、int、interface、instanceof、long、native、new、package、private、protected、public、return、short、static、strictfp、super、switch、synchronized、this、throw、throws、transient、try、void、volatile、while

// 2个保留字(现在没用以后可能用到作为关键字):
    goto、const
// 3个特殊直接量:
    true、false、null

3.4 标识符

标识符:就是给类,方法,变量等起名字的符号

标识符的组成规则:由数字、字母、下划线(_)和美元符($)组成,,注意事项:

  • 不能以数字开头
  • 不能是关键字
  • 区分大小写

常用的命名约定:

  • 小驼峰命名法:适用于对方法,变量等起名字
    • 约定1:标识符一个单词的时候,首字母小写
    • 范例1:name
    • 约定2:标识符是多个单词的时候,第一个单词首字母小写,其他单词首字母大写
    • 范例2:firstName
  • 大驼峰命名法:适用于对类,接口等起名字
    • 约定1:标识符一个单词的时候,首字母大写
    • 范例1:Hello
    • 约定2:标识符是多个单词的时候,每个单词首字母大写
    • 范例2:HelloWorld

4 运算符

4.1 算术运算符

操作符 描述 例子(A=10,B=20)
+ 加法 - 相加运算符两侧的值 A + B 等于 30
- 减法 - 左操作数减去右操作数 A – B 等于 -10
* 乘法 - 相乘操作符两侧的值 A * B等于200
/ 除法 - 左操作数除以右操作数 B / A等于2
取余 - 左操作数除以右操作数的余数 B%A等于0
++ 自增: 操作数的值增加1 B++ 或 ++B 等于 21
-- 自减: 操作数的值减少1 B-- 或 --B 等于 19
package com.fcarey;

/*
    算术运算符
*/
public class Conditions {
    public static void main(String[] args) {
        int a = 6;
        int b = 4;
        System.out.println("a + b = " + (a + b));
        System.out.println("a - b = " + (a - b));
        System.out.println("a * b = " + (a * b));
        System.out.println("a / b = " + (a / b));
        // 整数相除只能得到整数,要想得到小数,必须有指定其中一个类型为浮点数
        System.out.println("(float) a / b = " + ((float) a / b));
        System.out.println("a % b = " + (a % b));
    }
}
// a + b = 10
// a - b = 2
// a * b = 24
// a / b = 1
// (float) a / b = 1.5
// a % b = 2
  • 整数相除只能得到整数,要想得到小数,必须有指定其中一个类型为浮点数

4.1.1 不同数字类型相加

在Java程序中,数据参与运算,要求类型一致。这里就涉及到了数据的类型转换。而类型转换又分为两种:

  1. 隐式转换
  2. 强制转换

隐式转换:把一个表示数据范围小的数值或者变量赋值给另一个表示数据范围大的变量

强制转换:把一个表示数据范围大的数值或者变量赋值给另一个表示数据范围小的变量;格式:数据类型 变量名 = (目标数据类型) (数值或者变量)

package com.fcarey;

/*
    不同数字类型相加
*/
public class Conditions03 {
    public static void main(String[] args) {
        int num1 = 123;
        double num2 = 222;
        byte num3 = (byte) (num1 + num2);
        System.out.println(num1 + num2);
        System.out.println(num3);
    }
}
// 345.0
// 89

4.1.2 字符相加

package com.fcarey;

/*
    不同数据类型相加
*/
public class Conditions04 {
    public static void main(String[] args) {
        int num1 = 32;
        char ch1 = 'A';  //'A'的值是65
        System.out.println(num1 + ch1);
    }
}
// 97
  • 字符参与+操作,其实就是拿字符对应ASCII码数值来进行计算。

  • A: 65, A-Z是连续的

  • a: 97, a-z是连续的

  • 0: 48, 0-9是连续的

4.1.3 字符串相加

package com.fcarey;

/*
    字符串相加
*/
public class Conditions05 {
    public static void main(String[] args) {
        System.out.println("Hello" + " " + "World");
        System.out.println("Hello" + " " + "World" + 1 + 2);
        System.out.println(1 + 2 + "Hello" + " " + "World");
    }
}
// Hello World
// Hello World12
// 3Hello World
  • 从左到右:当+操作中有字符串时,此时是字符串连接符,而不是算术运算:"Hello" + " " + "World" + 1 + 2
  • 从左到右:当+操作中均为数字时,此时是算术连接符:1 + 2 + "Hello" + " " + "World"

4.3 赋值运算符

操作符 描述 例子
= 简单的赋值运算符,将右操作数的值赋给左侧操作数 C = A + B将把A + B得到的值赋给C
+ = 加和赋值操作符,它把左操作数和右操作数相加赋值给左操作数 C + = A等价于C = C + A
- = 减和赋值操作符,它把左操作数和右操作数相减赋值给左操作数 C - = A等价于C = C - A
* = 乘和赋值操作符,它把左操作数和右操作数相乘赋值给左操作数 C * = A等价于C = C * A
/ = 除和赋值操作符,它把左操作数和右操作数相除赋值给左操作数 C / = A,C 与 A 同类型时等价于 C = C / A
%= 取模和赋值操作符,它把左操作数和右操作数取模后赋值给左操作数 C%= A等价于C = C%A
<< = 左移位赋值运算符 C << = 2等价于C = C << 2
>> = 右移位赋值运算符 C >> = 2等价于C = C >> 2
&= 按位与赋值运算符 C&= 2等价于C = C&2
^ = 按位异或赋值操作符 C ^ = 2等价于C = C ^ 2
| = 按位或赋值操作符 C | = 2等价于C = C | 2
package com.fcarey;

/*
    赋值运算符
*/
public class Conditions06 {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        int c = 0;
        c = a + b;
        System.out.println("c = a + b = " + c);
        byte d = 30;
        d *= a;
        System.out.println("d += a  = " + d);
    }
}
// c = a + b = 30
// d += a  = 44
  • 扩展的赋值运算符隐含了强制类型转换

4.4 关系运算符

运算符 描述 例子
== 检查如果两个操作数的值是否相等,如果相等则条件为真。 (A == B)为假。
!= 检查如果两个操作数的值是否相等,如果值不相等则条件为真。 (A != B) 为真。
> 检查左操作数的值是否大于右操作数的值,如果是那么条件为真。 (A> B)为假。
< 检查左操作数的值是否小于右操作数的值,如果是那么条件为真。 (A <B)为真。
>= 检查左操作数的值是否大于或等于右操作数的值,如果是那么条件为真。 (A> = B)为假。
<= 检查左操作数的值是否小于或等于右操作数的值,如果是那么条件为真。 (A <= B)为真。

4.5 逻辑运算符

操作符 描述 例子
&& 称为逻辑与运算符。当且仅当两个操作数都为真,条件才为真。 (A && B)为假。
|| 称为逻辑或操作符。如果任何两个操作数任何一个为真,条件为真。 (A || B)为真。
称为逻辑非运算符。用来反转操作数的逻辑状态。如果条件为true,则逻辑非运算符将得到false。 !(A && B)为真。

5 逻辑控制语句

5.1 if

// eg:01
if (b) {
    System.out.println("It's true!");
}

// eg:02
if (a == b) {
    // a and b are equal... 
} else {
    // a and b are not equal... :/
}

// eg:03
if (a == b) {
    // a and b are equal... 
} else if (a == c) {
    // a and c are equal... :/
} else {
    // a is not equal to b and c... :/
}

5.2 三元运算符

variable x = (expression) ? value if true : value if false

示例:

package com.fcarey;

/*
    三元运算符
*/
public class Conditions08 {
    public static void main(String[] args) {
        int a = 3;
        int b = (a > 2) ? a : 1;
        System.out.println(b);
    }
}
  • 如果if语句控制的内容:是用变量记录数据值,可以通过三元运算符替换;

  • 如果if语句控制的内容是:是通过输出语句直接输出数据值,无法使用三元运算符;

    if (a > b) {
        System.out.println("the max is " + a);
    } else {
        System.out.println("the max is " + b);
    }
    

5.3 switch

switch (expression) {
    case value :
       //语句01
       break; //可选
    case value :
       //语句02
       break; //可选
    //你可以有任意数量的case语句
    default : //可选
       //语句
       break;
}
  • 注:在switch语句中,如果case控制的语句体后面不写break,将出现穿透现象,在不判断下一个case值的情况下,向下运行,直到遇到break,或者整个switch语句结束

6 循环语句

6.1 for 循环

for(初始化; 布尔表达式; 更新) {
    //代码语句
}

6.2 while 循环

while( 布尔表达式 ) {
  //循环内容
}

6.3 do..while 循环

do {
       //代码语句
}while(布尔表达式);

  • 三种循环语句的区别:
    • for循环和while循环先判断条件是否成立,然后决定是否执行循环体(先判断后执行)
    • do...while循环先执行一次循环体,然后判断条件是否成立,是否继续执行循环体(先执行后判断)
  • forwhile的区别:
    • 条件控制语句所控制的自增变量,在for循环结束后,就不可以继续使用
    • 条件控制语句所控制的自增变量,在while循环结束后,还可以继续使用

6.4 continuebreak

  • continue: 用在循环中,基于条件控制,跳过某次循环体内容的执行,继续下一次的执行。
  • break: 用在循环中,基于条件控制,终止循环体内容的执行,也就是说结束当前的整个循环。

6.5 综合练习

package com.fcarey;

/*
 *需求:小芳的妈妈每天给她2.5元钱,她都会存起来。
 * 但是,每当这一天是存钱的第5天或者5的倍数的话,她都会花去6元钱.
 * 请问,经过多少天,小芳才可以存到100元钱?
 */
public class loop02 {
    public static void main(String[] args) {
        double wallet = 0;
        int day = 1;
        while (wallet < 100) {
            wallet += 2.5;
            if (day % 5 == 0) {
                wallet -= 6;
            }
            day++;
        }
        System.out.println("Total wallet: " + wallet);
        System.out.println("Total day: " + (day - 1));
    }
}

7 方法

Java方法: 是语句的集合,它们在一起执行一个功能。

  • 方法是解决一类问题的步骤的有序组合
  • 方法包含于类或对象中
  • 方法在程序中被创建,在其他地方被引用

7.1 不带参数方法的定义和调用

/*
    定义格式:
        public static void 方法名() {
           // 方法体
       }
 */
public class MethodDemo {
    public static void main(String[] args) {
        //调用方法
        isEvenNumber();
    }

    // 需求:定义一个方法,在方法中定义一个变量,判断该数据是否是偶数
    public static void isEvenNumber() {
        // 在方法中定义一个变量
        int number = 3;
        number = 4;

        // 判断该数据是否是偶数
        if (number % 2 == 0) {
            System.out.println(number + "是偶数");
        } else {
            System.out.println(number + "不是偶数");
        }
    }
}
    • 方法定义完毕后,需要调用才能执行
    • 方法必须先定义后调用,否则程序将报错

7.2 带参数方法的定义和调用

package com.fcarey;

/*
    带参数方法的定义和调用

    定义格式:
        public static void 方法名(数据类型 变量名,数据类型 变量名) { … … }
 */
public class Fun01 {
    public static void main(String[] args) {
        System.out.println(sum(10));
    }

    public static int sum(int num) {
        int count = 0;
        for (int i = 1; i <= num; i++) {
            count +=i;
        }
        return count;
    }
}

  • 带参方法定义时,参数中的数据类型变量名都不能缺少,缺少任意一个程序将报错
  • 带参方法定义时,多个参数之间使用逗号(,)分隔
  • 带参方法调用时,参数的数量与类型必须与方法定义中的设置相匹配,否则程序将报错
  • 方法定义时return后面的返回值与方法定义上的数据类型要匹配,否则程序将报错
  • 方法的返回值通常会使用变量接收,否则该返回值将无意义
  • void表示无返回值,可以省略return,也可以单独的书写return,后面不加数据

7.3 方法的通用格式

public static 返回值类型 方法名(参数) {
    方法体;
    return 数据;
}
  • public static: 修饰符,目前先记住这个格式,告诉编译器如何调用该方法。定义了该方法的访问类型。

  • 返回值类型 :方法可能会返回值。returnValueType 是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType 是关键字void

  • 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。

  • 参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。

  • 方法体:方法体包含具体的语句,定义该方法的功能。

  • 定义方法时,要做到两个明确

    • 明确返回值类型:主要是明确方法操作完毕之后是否有数据返回,如果没有,写void;如果有,写对应的数据类型
    • 明确参数:主要是明确参数的类型和数量

7.4 方法重载

方法重载:指同一个类中定义的多个方法之间的关系,满足下列条件的多个方法相互构成重载

  • 多个方法在同一个类中
  • 多个方法具有相同的方法名
  • 多个方法的参数不相同,类型不同或者数量不同
package com.fcarey;

public class Fun04 {
    public static void main(String[] args) {
        System.out.println(ifEqual(4,3));
    }

    public static boolean ifEqual(int a, int b) {
        return a == b;
    }
    public static boolean ifEqual(byte a, byte b) {
        return a == b;
    }
    public static boolean ifEqual(short a, short b) {
        return a == b;
    }
    public static boolean ifEqual(long a, long b) {
        return a == b;
    }
}

8 数组

8.1 一维数组

8.1.1 数组定义

  • 格式1:数据类型[] 变量名;

    // 定义了一个int类型的数组,数组名是arr
    int[] arr;
    
  • 格式2:数据类型 变量名[];

    // 定义了一个int类型的变量,变量名是arr数组
    int arr[];
    

8.1.2 数组的初始化

  • Java中的数组必须先初始化,然后才能使用。

  • 所谓初始化:就是为数组中的数组元素分配内存空间,并为每个数组元素赋值

  • 数组中的每一个数据,我们称之为数组中的元素

  • 数组的初始化分为两种方式:

    • 静态初始化: 开始就存入元素值,适合一开始就能确定元素值的业务场景

    • 动态初始化: 指定数组长度,后期赋值,适合开始知道数据的数量,但是不确定具体元素值的业务场景

数组静态初始化

  • 初始化时指定每个数组元素的初始值,由系统决定数组长度

  • 格式:数据类型[] 变量名 = new 数据类型[]{数据1,数据2,数据3,…};

    int[] arr = new int[]{1,2,3};
    
  • 简化格式:数据类型[] 变量名 = {数据1,数据2,数据3,…};

    int[] arr = {1,2,3};
    

数组动态初始化

  • 初始化时只指定数组长度,由系统为数组分配初始值

  • 格式:数据类型[] 变量名 = new 数据类型[数组长度];

    int[] arr = new int[3];
    
  • **注: **两种初始化的方式是独立的,不可以混用,如下的声明是错误的:int[] arr = new int[3]{30,40,50};

8.1.3 综合练习

package com.fcarey;

import java.util.Random;
import java.util.Scanner;

/*
 * 需求:定义一个可以存储5个元素的int数组,数据来自于键盘录入,
 * 遍历数组,将元素输出
 * 将元素打散后遍历数组,将元素输出
 */
public class Arry04 {
    public static void main(String[] args) {
        int[] arr = new int[5];
        for (int i = 0; i < arr.length; i++) {
            Scanner sc = new Scanner(System.in);
            System.out.println("Enter number: ");
            arr[i] = sc.nextInt();
        }
        System.out.println();
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
        Random rand = new Random();
        for (int i = 0; i < arr.length; i++) {
            int random = rand.nextInt(arr.length);
            int temp = arr[i];
            arr[i] = arr[random];
            arr[random] = temp;
        }
        System.out.println();
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
}

8.2 二维数组

8.2.1 数组定义

  • 二维数组:元素为一维数组的数组。

  • 定义二维数组:

    1. 数据类型[][] 变量名;

      int[][] arr;
      
    2. 数据类型 变量名[][];

      int arr[][];
      
    3. 类型[] 变量名[];

      int[] arr[];
      

8.2.2 二维数组初始化

  • 二维数组初始化也有两种格式:
    1. 静态初始化: 适合一开始就能确定元素值的业务场景
    2. 动态初始化: 适合开始知道数据的数量,但是不确定具体元素值的业务场景

静态初始化

  • 格式:数据类型[] [] 变量名 = new 数据类型[] []{{元素…},{元素…},{元素…},…};

    int[] [] arr = new int[] []{{1,2,3},{4,5,6},{7,8,9}};
    
  • 简化格式:数据类型[][] 变量名 = {{元素…},{元素…},{元素…},…};

    int[] [] arr = {{1,2},{3,4,5},{6,7,8,9}};
    

**动态初始化: **

  • 格式:数据类型[] [] 变量名 = new 数据类型[m] [n];

    int[] [] arr = new int[2] [3];
    

8.2.3 综合练习

package com.fcarey;

import java.util.Random;
import java.util.Scanner;


public class Arry05 {
    public static void main(String[] args) {
        int[][] arr = {{1,2,3},{4,5,6},{7,8,9}};
        System.out.println(arr);
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                System.out.print(arr[i][j] + " ");
            }
            System.out.println();
        }
        System.out.println("--------------------------");
        Random rand = new Random();

        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                int x = rand.nextInt(arr.length);
                int y = rand.nextInt(arr[x].length);

                int temp = arr[i][j];
                arr[i][j] = arr[x][y];
                arr[x][y] = temp;
            }
        }
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                System.out.print(arr[i][j] + " ");
            }
            System.out.println();
        }
        System.out.println("--------------------------");
    }
}

8.2.4 图像分片展示

package com.fcarey;

import javax.swing.*;
import java.util.Random;

public class Arry07 {
    public static void main(String[] args) {
        // 创建窗体对象
        JFrame frame = new JFrame();
        frame.setTitle("图片展示");
        frame.setSize(960, 532);
        frame.setDefaultCloseOperation(3);
        frame.setLocationRelativeTo(null);
        frame.setAlwaysOnTop(true);
        frame.setLayout(null);
/*

        JLabel label = new JLabel(new ImageIcon("java_day01\\imgs\\1.jpg"));
        label.setBounds(0, 0, 320, 177);
        frame.add(label);
        JLabel label02 = new JLabel(new ImageIcon("java_day01\\imgs\\2.jpg"));
        label02.setBounds(320, 0, 320, 177);
        frame.add(label02);
        JLabel label03 = new JLabel(new ImageIcon("java_day01\\imgs\\3.jpg"));
        label03.setBounds(320*2, 0, 320, 177);
        frame.add(label03);

        JLabel label04 = new JLabel(new ImageIcon("java_day01\\imgs\\4.jpg"));
        label04.setBounds(0, 177, 320, 177);
        frame.add(label04);
        JLabel label05 = new JLabel(new ImageIcon("java_day01\\imgs\\5.jpg"));
        label05.setBounds(320, 177, 320, 177);
        frame.add(label05);
        JLabel label06 = new JLabel(new ImageIcon("java_day01\\imgs\\6.jpg"));
        label06.setBounds(320*2, 177, 320, 177);
        frame.add(label06);

        JLabel label07 = new JLabel(new ImageIcon("java_day01\\imgs\\7.jpg"));
        label07.setBounds(0, 177*2, 320, 177);
        frame.add(label07);
        JLabel label08 = new JLabel(new ImageIcon("java_day01\\imgs\\8.jpg"));
        label08.setBounds(320, 177*2, 320, 177);
        frame.add(label08);
        JLabel label09 = new JLabel(new ImageIcon("java_day01\\imgs\\9.jpg"));
        label09.setBounds(320*2, 177*2, 320, 177);
        frame.add(label09);
*/
        int[][] imgs = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
        /*for (int i = 0; i < imgs.length; i++) {
            for (int j = 0; j < imgs.length; j++) {
                JLabel label = new JLabel(new ImageIcon("java_day01\\imgs\\" + imgs[i][j] + ".jpg"));
                label.setBounds(320 * j, 177 * i, 320, 177);
                frame.add(label);
            }
        }
        frame.setVisible(true);*/
        Random rand = new Random();
        for (int i = 0; i < imgs.length; i++) {
            for (int j = 0; j < imgs.length; j++) {
                int x = rand.nextInt(imgs.length);
                int y = rand.nextInt(imgs[i].length);
                int tmp_img = imgs[i][j];
                imgs[i][j] = imgs[x][y];
                imgs[x][y] = tmp_img;
            }
        }
        for (int i = 0; i < imgs.length; i++) {
            for (int j = 0; j < imgs.length; j++) {
                JLabel label = new JLabel(new ImageIcon("java_day01\\imgs\\" + imgs[i][j] + ".jpg"));
                label.setBounds(320 * j, 177 * i, 320, 177);
                frame.add(label);
            }
        }
        frame.setVisible(true);
    }
}

9 Java API

9.1 包和导包

  • 包其实就是文件夹,用于对类进行分类管理

  • 包的定义格式:

    • 格式:package 包名;

    • 包名一般是公司域名反写,并且多级包用.分开

      // 例:example.com
      package com.example;
      
  • 导包的格式:

    • 格式:import 包名;
    • 范例:import com.example.demon;

9.2 Scanner

  • 一个简单的文本扫描程序,可以获取基本类型数据和字符串数据
package com.fcarey;

import java.util.Scanner;

/*
 * 需求:定义一个可以存储5个元素的int数组,数据来自于键盘录入,
 * 遍历数组,将元素输出
 * 将元素打散后遍历数组,将元素输出
 */
public class Scanner01 {
    public static void main(String[] args) {
        // 创建 Scanner 对象, System.in 对应的是 `InputStream` 类型,可以表示键盘输入
        Scanner sc = new Scanner(System.in);
        System.out.println("please enter a number: ");
        // 获取一个 int 类型的数据
        int num = sc.nextInt();

        System.out.println("please enter a number: ");
        int num2 = sc.nextInt();

        System.out.println("the number is " + (num + num2));

    }
}

9.2 Random

该类的实例用于生成随机数

package com.fcarey;

import java.util.Random;
import java.util.Scanner;

/*
 *    需求:系统自动产生一个1-100之间的整数,使用程序实现猜这个数字是多少?
 *     猜的时候根据不同情况给出相应的提示
 *     如果猜的数字比真实数字大,提示你猜的数据大了
 *     如果猜的数字比真实数字小,提示你猜的数据小了
 *     如果猜的数字与真实数字相等,提示恭喜你猜中了
 * 分析:
 *     1:使用Random获取一个1-100之间的整数
 *     2:使用Scanner实现键盘录入猜的数据值
 *     3:使用if…else if…else 的格式实现猜数字,并给出对应的提示
 */
public class Random01 {
    public static void main(String[] args) {
        // Random():创建一个新的随机数生成器
        Random rand = new Random();
        // 获取一个int类型的随机数,参数bound表示获取到的随机数在[0,bound)之间
        int num = rand.nextInt(100) + 1;
        Scanner sc = new Scanner(System.in);
        System.out.println("Enter a number between 1 and 100");
        int num1 = sc.nextInt();
        do {
            if (num > num1) {
                System.out.println("The number is greater than the number");
                num1 = sc.nextInt();
            } else {
                System.out.println("The number is less than the number");
                num1 = sc.nextInt();
            }
        } while (num != num1);
        System.out.println("The number is the same");
    }
}

9.3 GUI

  • GUI:Graphical User Interface(图形用户接口),即用图形的方式,来显示计算机操作的界面。

  • 而Java为GUI提供的API都存在java.awt和javax.Swing两个包中,区别如下:

    • java.awt 包:
      • awt是这抽象窗口工具包三个单词首字母的缩写,该包的API需要调用本地系统方法实现功能,和本地系统有关联,不利于代码移植,属重量级控件
    • javax.swing 包:
      • 它是在awt的基础上,建立的一套图形界面系统,提供了更多的组件,而且完全由Java实现。增强了移植性,属轻量级控件
  • 组件是具有图形表示的对象,该图形表示可以显示在屏幕上并且可以与用户交互

  • GUI组件:

    • 容器组件:是可以添加组件的组件。也就是在容器中可以通过add方法添加组件,既可以添加基本组件,也可以添加容器组件。
      • Window
        • Frame
          • JFrame:是一个顶层窗口
      • Panel
        • Jpanel
    • 基本组件:具有图形表示的对象
      • JButton:按钮
      • JLable:显示文本内容,或者展示图片
      • JTextField:文本框,用来输入单行内容的
      • JTextArea:文本域,用来输入多行多列的数据的
package com.fcarey;

import javax.swing.*;
import java.awt.*;
import java.util.Random;

/*
* 用户登录界面
*/
public class GUI01 {
    public static void main(String[] args) {
        // 创建窗体对象
        JFrame frame = new JFrame("用户登录");
       // 设置窗体关闭时默认操作,窗口关闭时退出应用程序
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // 取消窗体的默认布局
        frame.setLayout(null);
        // 设置窗体大小
        frame.setSize(400, 300);
        
        // 设置此窗口是否应始终位于其他窗口之上
        frame.setAlwaysOnTop(true);
        // 设置位置,值为null时,窗体位于屏幕中央
        frame.setLocationRelativeTo(null);

        // 显示用户名文本
        JLabel userLabel=new JLabel("用户名");
        // 设置位置和大小
        userLabel.setBounds(50,50,50,20);
        // 把按钮添加到窗体
        frame.add(userLabel);

        JTextField userTextField= new JTextField();
        userTextField.setBounds(150,50,180,20);
        frame.add(userTextField);

        // 密码输入框
        JLabel passLable = new JLabel("密码");
        passLable.setBounds(50,100,50,20);
        frame.add(passLable);

        JPasswordField passField= new JPasswordField();
        passField.setBounds(150,100,180,20);
        frame.add(passField);
		
        // 创建一个带文本的按钮
        JButton submitButton = new JButton("登录");
        // 设置位置和大小
        submitButton.setBounds(50,200,280,20);
        frame.add(submitButton);
		
        submitButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("提交成功");
            }
        });

        // 设置窗体可见
        frame.setVisible(true);

    }
}

9.4 String

String类表示字符串。 Java程序中的所有字符串文字(例如"abc" )都被实现为此类的实例。

构造方法:

  • String():初始化新创建的 String 对象,使其表示空字符序列
  • String(String original):初始化新创建的String对象,使其表示与参数相同的字符序列; 换句话说,新创建的字符串是参数字符串的副本。

属性方法

  • public int length(): 返回此字符串的长度。 长度等于字符串中的数字Unicode code units
  • public boolean equals(Object anObject): 将此字符串与指定对象进行比较。 其结果是true当且仅当该参数不是null并且是String对象,表示相同的字符序列作为该对象。
  • public boolean equalsIgnoreCase(String anotherString): 将此String与其他String比较,忽略案例注意事项。 如果两个字符串的长度相同,并且两个字符串中的相应字符等于忽略大小写,则两个字符串被认为是相等的。
  • public String trim(): 返回一个字符串,其值为此字符串,并删除任何前导和尾随空格。
  • String replace(CharSequence target, CharSequence replacement): 将当前字符串中的 target 内容,使用replacement 进行替换,返回新的字符串

  • String 这个类比较特殊, 打印其对象名的时候, 不会出现内存地址,而是该对象所记录的真实内容.

创建字符串对象的区别

  • 通过构造方法创建

    ​ 通过 new 创建的字符串对象,每一次 new 都会申请一个内存空间,虽然内容相同,但是地址值不同

  • 直接赋值方式创建

    ​ 以“”方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM 都只会建立一个 String 对象,并在字符串池中维护

字符串的比较

  • == 比较基本数据类型:比较的是具体的值
  • == 比较引用数据类型:比较的是对象地址值
public class StringDemo01 {
    public static void main(String[] args) {
        String s1 = "abc";
        String s2 = "ab";
        String s3 = "c";
        String s4 = s2 + s3;
        System.out.println(s1); // abc
        System.out.println(s4); // abc
        System.out.println(s1 == s4); // false
    }
}

字符串遍历

import java.util.Scanner;

public class TraverseString {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("Enter a string: ");
        String myString = sc.nextLine();
        for (int i = 0; i < myString.length(); i++) {
            // public char charAt(int index):返回指定索引处的char值,字符串的索引也是从0开始的
            System.out.println(myString.charAt(i));
        }
        // public char[] toCharArray( ):将当前字符串拆分为字符数组并返回
        char[] myChar = myString.toCharArray();
        for (int i = 0; i < myChar.length; i++) {
            System.out.println(myChar[i]);
        }
    }
}

字符串截取

import java.util.Scanner;

/*以字符串的形式从键盘接受一个手机号,将中间四位号码屏蔽*/
public class HidePhoneNum {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("Enter Phone Number: ");
        String phone = sc.nextLine();
        char[] chars = phone.toCharArray();

        for (int i = 0; i < chars.length; i++) {
            if (2 < i && i < 7) {
                chars[i] = '*';
            }
            System.out.print(chars[i]);
        }
        System.out.println();
        // substring(0,3)截取字符串前三位
        System.out.println(phone.substring(0, 3) + "****" + phone.substring(7));
        ;
    }
}

字符串替换

import java.util.Scanner;

public class HideTMD {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("Enter a string: ");
        String s = sc.nextLine();

        // 将当前字符串中的target内容,使用replacement进行替换,返回新的字符串
        System.out.println(s.replace("TMD", "***"));
    }
}

字符串分割

import java.util.Scanner;

public class SplitString {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("Enter a splited by , string: ");
        String myString = sc.nextLine();
        // 根据传入的字符串作为规则进行切割,将切割后的内容存入字符串数组中,并将字符串数组返回
        String[] myStringArray = myString.split(",");
        System.out.println(myStringArray[0]);
        System.out.println(myStringArray[1]);
    }
}

9.5 Integer

  • Integer类包装一个对象中的原始类型int的值。 类型为Integer的对象包含一个单一字段,其类型为int

  • 构造方法:

    • Integer(int value) :构造一个新分配的 Integer对象,该对象表示指定的 int值。
    • Integer(String s):构造一个新分配 Integer对象,表示 int由指示值 String参数。
  • 属性方法

    • public static Integer valueOf(int i): 返回一个Integer指定的int值的Integer实例。
    • public static Integer valueOf(String s): 返回一个Integer对象,保存从指定的String String的值
  • int 转换为 String

    • public static String valueOf(int i):返回 int 参数的字符串表示形式。该方法是 String 类中的方法
  • String 转换为 int

    • public static int parseInt(String s):将字符串解析为 int 类型。该方法是 Integer 类中的方法
  • Integer 自动装箱和拆箱

    • 装箱:把基本数据类型转换为对应的包装类类型

      // 装箱
      Integer i = 100; 
      // 同于
      Integer i = Integer.valueOf(100);
      
    • 拆箱:把包装类类型转换为对应的基本数据类型

      // 拆箱
      i += 2
      i = i + 2;
      // 自动拆箱
      i = i.intValue() + 2;
      i = 3;
      

9.6 Date和SimpleDateFormat

9.6.1 Date

Date类表示特定的时刻,精度为毫秒

构造方法:

  • Date():分配 Date对象并对其进行初始化,使其表示分配时间,测量 Date到毫秒
  • Date(long date):分配 Date对象并初始化它以表示自标准基准时间以来的指定毫秒数,即1970年1月1日00:00:00
package com.fcarey;

import java.util.Date;

/*
 * Date
 */
public class date01 {
    public static void main(String[] args) {
        // Date():分配 Date对象并对其进行初始化,使其表示分配时间,测量 Date到毫秒
        Date date = new Date();
        System.out.println(date);

        // Date(long date):分配 Date对象并初始化它以表示自标准基准时间以来的指定毫秒数,即1970年1月1日00:00:00
        Date date1 = new Date(1000 * 60 * 60 * 24);
        System.out.println(date1);
    }
}

9.6.2 SimpleDateFormat

  • SimpleDateFormat是一个具体的类,用于以区域设置敏感的方式格式化和解析日期。 它允许格式化(日期文本),解析(文本日期)和归一化。

  • 日期和时间格式由日期和时间模式字符串指定。

    Letter Date or Time Component Presentation Examples
    G Era designator Text AD
    y Year Year 1996; 96
    Y Week year Year 2009; 09
    M Month in year (context sensitive) Month July; Jul; 07
    L Month in year (standalone form) Month July; Jul; 07
    w Week in year Number 27
    W Week in month Number 2
    D Day in year Number 189
    d Day in month Number 10
    F Day of week in month Number 2
    E Day name in week Text Tuesday; Tue
    u Day number of week (1 = Monday, ..., 7 = Sunday) Number 1
    a Am/pm marker Text PM
    H Hour in day (0-23) Number 0
    k Hour in day (1-24) Number 24
    K Hour in am/pm (0-11) Number 0
    h Hour in am/pm (1-12) Number 12
    m Minute in hour Number 30
    s Second in minute Number 55
    S Millisecond Number 978
    z Time zone General time zone Pacific Standard Time; PST; GMT-08:00
    Z Time zone RFC 822 time zone -0800
    X Time zone ISO 8601 time zone -08; -0800; -08:00
  • 构造方法:

    • SimpleDateFormat():构造一个 SimpleDateFormat使用默认模式和日期格式符号为默认的 FORMAT区域设置。
    • SimpleDateFormat(String pattern):使用给定模式 SimpleDateFormat并使用默认的FORMAT语言环境的默认日期格式符号。
  • 格式化(从 Date 到 String ):

    • String format(Date date):将日期格式化成日期/时间字符串
  • 解析(从 String 到 Date ):

  • Date parse(String source):从给定字符串的开始解析文本以生成日期

package com.fcarey;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/*
 * Date
 */
public class Date01 {
    public static void main(String[] args) throws ParseException {
        // Date():分配 Date对象并对其进行初始化,使其表示分配时间,测量 Date到毫秒
        Date date = new Date();
        System.out.println(date);

        // Date(long date):分配 Date对象并初始化它以表示自标准基准时间以来的指定毫秒数,即1970年1月1日00:00:00
        Date date1 = new Date(1000 * 60 * 60 * 24);
        System.out.println(date1);

        // 格式化从 Date 到 String
        Date date2 = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        System.out.println(sdf.format(date2));

        // 格式化从 String 到 Date
        String dateStr = "1997/01/01 17:00:00";
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        Date date3 = sdf1.parse(dateStr);
        System.out.println(date3);

    }
}

9.8 StringBuilder

StringBuilder 是一个可变的字符串类,我们可以把它看成是一个容器,这里的可变指的是 StringBuilder 对象中的内容是可变的

  • StringBuilder类和String类的区别

    • String类:内容是不可变的
    • StringBuilder类:内容是可变的
  • 构造方法

    方法名 说明
    public StringBuilder() 创建一个空白可变字符串对象,不含有任何内容
    public StringBuilder(String str) 根据字符串的内容,来创建可变字符串对象
  • 成员方法

    方法名 说明
    public StringBuilder append(任意类型) 添加数据,并返回对象本身
    public StringBuilder reverse() 返回相反的字符序列
  • StringBuilder和String相互转换

    • public String toString():通过 toString() 就可以实现把 StringBuilder 转换为 String
    • public StringBuilder(String s):通过构造方法就可以实现把 String 转换为 StringBuilder
  • import java.util.Scanner;
    
    public class StringDemo02 {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            System.out.println("Enter a string: ");
            String s = sc.nextLine();
            StringBuilder sb = new StringBuilder(s);
            System.out.println(sb);
    
            String s1 = sb.reverse().toString();
            System.out.println(s1);
            if (s.equals(s1)) {
                System.out.println("Yes");
            } else {
                System.out.println("No");
            }
        }
    }
    
    

9.7 综合练习

9.7.1 用户登录界面

package com.fcarey;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/*
 * 用户登录界面
 * 用户名的长度是5-12位,密码6-12位
 * 先判断输入的用户名和密码是否符合要求,再判断用户登录是否成功
 * 
 */
public class GUI06 {
    public static void main(String[] args) {
        JFrame frame = new JFrame("用户登录");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(null);
        frame.setSize(400, 300);
        frame.setLocationRelativeTo(null);

        JLabel userLabel = new JLabel("用户名");
        userLabel.setBounds(50, 50, 50, 20);
        frame.add(userLabel);

        JTextField userTextField = new JTextField();
        userTextField.setBounds(150, 50, 180, 20);
        frame.add(userTextField);

        JLabel passLable = new JLabel("密码");
        passLable.setBounds(50, 100, 50, 20);
        frame.add(passLable);

        JPasswordField passField = new JPasswordField();
        passField.setBounds(150, 100, 180, 20);
        frame.add(passField);

        JButton submitButton = new JButton("登录");
        submitButton.setBounds(50, 200, 280, 20);
        frame.add(submitButton);

        submitButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String username = userTextField.getText();
                String password = new String(passField.getPassword());
                String user = "admin";
                String pass = "123456";
                if (username.length() >= 5 && username.length() <= 12 && password.length() > 5 && password.length() <= 12) {
                    if (username.equals(user) && password.equals(pass)) {
                        System.out.println("登录成功");
                        JOptionPane.showMessageDialog(frame, "登录成功");
                    } else {
                        System.out.println("用户名或密码错误");
                        JOptionPane.showMessageDialog(frame, "用户名或密码错误");
                    }
                } else {
                    System.out.println("用户名长度登录是5~12位,请重新输入:");
                    JOptionPane.showMessageDialog(frame, "用户名长度登录是5~12位,请重新输入:");
                    userTextField.setText("");
                }

            }
        });
        frame.setVisible(true);

    }
}

9.7.2 聊天室

package com.fcarey;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/*
* 聊天室
* 把文本框的内容发送到文本域中
* 每次发送的文本内容不带前后空格
* 多次发送的内容在文本域以追加的方式呈现
* 清空聊天就是把文本域的内容设置为空
*/
public class GUI07 {
    public static void main(String[] args) {
        JFrame frame = new JFrame("聊天室");
        frame.setLayout(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400,300);
        frame.setLocationRelativeTo(null);

        JTextArea textArea = new JTextArea();
        textArea.setEditable(true);
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        textArea.setBounds(10,10,360,200);
        frame.add(textArea);

        JTextField msgField = new JTextField();
        msgField.setBounds(10,230,180,20);
        frame.add(msgField);

        JButton sendButton = new JButton("发送");
        sendButton.setBounds(200,230,70,20);
        frame.add(sendButton);

        JButton clearButton = new JButton("清空聊天");
        clearButton.setBounds(280,230,100,20);
        frame.add(clearButton);

        sendButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 多次发送的内容在文本域以追加的方式呈现
                textArea.append(msgField.getText().trim()+"\n");
                // 把空的内容发送到文本域中
                msgField.setText("");
            }
        });
        clearButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                textArea.setText("");
            }
        });
        frame.setVisible(true);
    }
}

10 面向对象基础

面向过程 :是一种以过程为中心的编程思想,实现功能的每一步,都是自己实现的

面向对象 :是一种以对象为中心的编程思想,通过指挥对象实现具体的功能,即:以什么形式组织代码;以什么思路解决问题。

10.1 类与对象

  • 类与对象的关系

    • :类是对一类具有共同属性和行为的事物的抽象,确定对象将会拥有的属性和行为。例如:房子, 车子

    • 对象:是能够看得到摸的着的真实存在的实体

    • 类是对象的抽象,对象是类的实体。

10.1.1 类

  • 类的组成

    • 属性:对象具有的各种特征,每个对象的每个属性都拥有特定的值;在类中通过成员变量来体现(类中方法外的变量)
    • 行为:对象能够执行的操作,在类中通过成员方法来体现(和前面的方法相比去掉static关键字即可)
  • 类的定义

    • 属性:在类中通过成员变量来体现(类中方法外的变量)
    • 行为:在类中通过成员方法来体现(和前面的方法相比去掉static关键字即可)
    package com.fcarey;
    
    // 定义一个学生类
    public class ClassStudent01 {
        // 成员变量
        String name;
        int age;
        // 成员方法
        public void study(){
            System.out.println("Study study");
        }
        public void doHomework(){
            System.out.println("Do homework");
        }
    }
    
    

10.1.2 对象

  • 创建对象的格式:
    • 类名 对象名 = new 类名();
  • 调用成员的格式:
    • 对象名.成员变量
    • 对象名.成员方法();
package com.fcarey.class;

public class TestStudent {
    /*
        创建对象的格式:
                类名 对象名 = new 类名();
        调用成员变量的格式:
                对象名.变量名
        调用成员方法的格式:
                对象名.方法名();
     */
    public static void main(String[] args) {
        // 类名 对象名 = new 类名();
        Student stu = new Student();
        // 对象名.变量名
        // 默认初始化值
        System.out.println(stu.name);  // null
        System.out.println(stu.age);   // 0

        stu.name = "张三";
        stu.age = 22;

        System.out.println(stu.name);  // 张三
        System.out.println(stu.age);   // 22

        // 对象名.方法名();
        stu.study();
        // 全类名(包名 + 类名)
        System.out.println(stu);
    }
}

10.2 Java 内存分配

Java 程序在运行时,需要在内存中分配空间。为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。

image-20240806201812656

以代码Student s = new Student();为例:

  • 栈(虚拟机栈):所有局部变量都会在栈内存中创建,此处的Student s

    • 局部变量:定义在方法中的变量或者方法声明上的变量
    • 方法执行都会加载到栈中进行
    • 局部变量特点:随着方法的调用而存在,随着方法的调用完毕而消失
  • :所有对象及其对应的实例变量和数组都将存储在此处,此处的new Student()

    • 简单理解为:new出来的东西,都存储在堆内存
    • 每一个new出来的东西都有一个地址值,使用完毕,会在垃圾回收器空闲时被回收
    • 实例变量(成员变量)有初始化值:
      • 基本数据类型:整数:0,浮点数:0.0,布尔:false,字符:空字符
      • 引用数据类型:null
  • 成员变量和局部变量的区别

    区别 成员变量 局部变量
    类中位置不同 类中方法外 方法内或者方法声明上
    内存中位置不同 堆内存 栈内存
    生命周期不同 随着对象的存在而存在,随着对象的消失而消失 随着方法的调用而存在,随着方法的调用完毕而消失
    初始化值不同 有默认的初始化值 没有默认的初始化值,必须先定义,赋值,才能使用

10.3 private 关键字

  • 是一个权限修饰符
  • 可以修饰成员(成员变量和成员方法)
  • 作用是保护成员不被别的类使用,被 private 修饰的成员只在本类中才能访问
  • 针对 private 修饰的成员变量,如果需要被其他类使用,提供两个相应的操作:
    • 提供get变量名()方法,用于获取成员变量的值,方法用 public 修饰
    • 提供set变量名(参数)方法,用于设置成员变量的值,方法用 public 修饰

10.4 this 关键字

  • this限定的变量用于指代成员变量
    • 方法的形参如果与成员变量同名,不带this修饰的变量指的是形参,而不是成员变量
    • 方法的形参没有与成员变量同名,不带this修饰的变量指的是成员变量
  • 用于解决局部变量隐藏成员变量
  • 注:方法被哪个对象调用,this就代表哪个对象

10.4 封装

  • 封装概述
    • 是面向对象三大特征之一(封装,继承,多态
    • 是面向对象编程语言对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界是无法直接操作的
  • 封装原则
    • 将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问
    • 成员变量private,提供对应的getX()/setX()方法
  • 封装好处
    • 通过方法来控制成员变量的操作,提高了代码的安全性
    • 把代码用方法进行封装,提高了代码的复用性

10.5 构造方法概述

  • 构造方法是一种特殊的方法

  • 作用:创建对象

  • 功能:主要是完成对象数据的初始化

  • 构造方法的创建

    • 如果没有定义构造方法,系统将给出一个默认无参数构造方法
    • 如果定义了构造方法,系统将不再提供默认的构造方法
    • 格式注意 :
      • 方法名与类名相同,大小写也要一致
      • 没有返回值类型,连void都没有
      • 没有具体的返回值(不能由retrun带回结果数据)
    • 执行时机 :
      • 创建对象的时候调用,每创建一次对象,就会执行一次构造方法
      • 不能手动调用构造方法
  • 构造方法的重载

    • 如果自定义了带参构造方法,还要使用无参数构造方法,就必须再写一个无参数构造方法
  • 推荐的使用方式

    • 永远提供无参数构造方法
  • 例:

    // 一个简单的构造函数
    public class MyClass {
      int x;
     
      // 以下是构造函数
      public MyClass() {
        x = 10;
      }
    }
    

10.6 JavaBean

  • 就是一个Java中的类,其对象可以用于在程序中封装数据
  • 标准 JavaBean 须满足如下要求:
    • 成员变量使用 private 修饰
    • 提供每一个成员变量对应的 setX()/getX()
    • 提供一个无参构造方法

10.7 综合练习

package com.fcarey;

/*
 * 设置一个手机的JavaBean
 */
public class Class01 {
    // 本类访问的成员变量
    private String brand;
    private int price;
    // 公共访问的成员变量
    String color = "Red";

    // 设置本类成员变量的值
    public void setBrand(String brand) {
        this.brand = brand;
    }

    // 获取本类成员变量的值
    public String getBrand() {
        return brand;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public Integer getPrice() {
        return price;
    }

    // 系统默认的无参数的构造方法
    public void phone() {
    }

    // 构造方法重载
    public void phone(String color) {
        // this 指代成员变量,color 输出的是对象调用的引入的值
        System.out.println(this.color + " " + this.brand + " is worth " + this.price);
        // 输出:Red
        System.out.println(color + "是引用的");
    }
}

11 继承

  • 继承是面向对象三大特征之一(封装,继承和多态)

  • 可以使得子类具有父类的属性和方法,还可以在子类中重新定义,追加属性和方法。即通过继承,可以把父类中能够被访问到的成员变量和成员方法拿过来直接使用。

  • 提高了代码的复用性

  • 继承格式:

    class 父类 {
    }
     
    class 子类 extends 父类 {
    }
    

12 综合练习

编写流程

  1. 绘制游戏界面
  2. 图片打乱
  3. 给按钮注册事件
  4. 移动业务实现
  5. 求助业务实现
  6. 重置业务实现
  • PicFrame.java

    package extend02.fcarey;
    
    import javax.swing.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.Random;
    
    public class PicFrame extends JFrame {
        // 定义一个二维数组用于存储图片的编号
        private int[][] imgArray = {{1, 2, 3}, {4, 5, 6}, {7, 8, 0}};
        private int[][] winImgArray = {{1, 2, 3}, {4, 5, 6}, {7, 8, 0}};
        private int x0, y0;
        private JButton upButton, downButton, leftButton, rightButton, helpButton, resetButton;
        private JPanel imgPanel = new JPanel();
    
        public PicFrame() {
            // 初始化窗体
            initFrame();
    
            // 打散图片,需要在绘制窗体组件前调用
            randomPic();
    
            // 绘制窗体组件
            paintView();
    
            addButtonEvent();
            // 设置窗体可见
            this.setVisible(true);
    
        }
    
        // 拼图完成
        public boolean win() {
            for (int i = 0; i < winImgArray.length; i++) {
                for (int j = 0; j < winImgArray[i].length; j++) {
                    if (winImgArray[i][j] != imgArray[i][j]) {
                        return false;
                    }
                }
            }
            return true;
        }
    
        // 更新事件后的图片
        public void newPic() {
            // 移除所有窗体
            imgPanel.removeAll();
            for (int i = 0; i < imgArray.length; i++) {
                for (int j = 0; j < imgArray[i].length; j++) {
                    JLabel imageLabel = new JLabel(new ImageIcon("java_day01\\imgs\\" + imgArray[i][j] + ".jpg"));
                    imageLabel.setBounds(320 * j, 177 * i, 320, 177);
                    imgPanel.add(imageLabel);
                    if (imgArray[i][j] == 0) {
                        x0 = i;
                        y0 = j;
                    }
                }
            }
            if (win()) {
                JOptionPane.showMessageDialog(this, "你赢啦");
                upButton.setEnabled(false);
                downButton.setEnabled(false);
                leftButton.setEnabled(false);
                rightButton.setEnabled(false);
            }
            // 重新绘制窗体
            imgPanel.repaint();
        }
    
        // 添加按钮事件
        public void addButtonEvent() {
            upButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.println(x0 + "," + y0);
                    for (int i = 0; i < imgArray.length; i++) {
                        for (int j = 0; j < imgArray[i].length; j++) {
                            System.out.print(imgArray[i][j] + ", ");
                        }
                    }
                    if (x0 == 2) {
                        return;
                    } else {
                        int imgTmp = imgArray[x0 + 1][y0];
                        imgArray[x0 + 1][y0] = imgArray[x0][y0];
                        imgArray[x0][y0] = imgTmp;
                        newPic();
                    }
                }
            });
            downButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (x0 == 0) {
                        return;
                    } else {
                        int imgTmp = imgArray[x0 - 1][y0];
                        imgArray[x0 - 1][y0] = imgArray[x0][y0];
                        imgArray[x0][y0] = imgTmp;
                        newPic();
                    }
                }
            });
            leftButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
    
                    if (y0 == 2) {
                        return;
                    } else {
                        int imgTmp = imgArray[x0][y0 + 1];
                        imgArray[x0][y0 + 1] = imgArray[x0][y0];
                        imgArray[x0][y0] = imgTmp;
                        newPic();
                    }
                }
            });
            rightButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (y0 == 0) {
                        return;
                    } else {
                        int imgTmp = imgArray[x0][y0 - 1];
                        imgArray[x0][y0 - 1] = imgArray[x0][y0];
                        imgArray[x0][y0] = imgTmp;
                        newPic();
                    }
                }
            });
    
            helpButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    imgArray = new int[][]{{1, 2, 3}, {4, 5, 6}, {7, 8, 0}};
                    newPic();
                }
            });
            resetButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    randomPic();
                    newPic();
                    upButton.setEnabled(true);
                    downButton.setEnabled(true);
                    leftButton.setEnabled(true);
                    rightButton.setEnabled(true);
                }
            });
        }
    
        // 打散图片
        public void randomPic() {
            // 打散图片,使用不存在的0去替换9,以做空格
            Random rand = new Random();
            for (int i = 0; i < imgArray.length; i++) {
                for (int j = 0; j < imgArray[i].length; j++) {
                    // 数组的列索引
                    int x = rand.nextInt(imgArray.length);
                    // 数组的行索引
                    int y = rand.nextInt(imgArray[i].length);
                    int imgTmp = imgArray[i][j];
                    imgArray[i][j] = imgArray[x][y];
                    imgArray[x][y] = imgTmp;
                }
            }
        }
    
        // 绘制窗体组件
        public void paintView() {
            // 绘制标题图片
            JLabel titleLabel = new JLabel(new ImageIcon("java_day01\\imgs\\title.png"));
            titleLabel.setBounds(800, 27, 232, 57);
            this.add(titleLabel);
    
            // 添加参照图片
            JLabel referImg = new JLabel(new ImageIcon("java_day01\\imgs\\refer.jpg"));
            referImg.setBounds(320 * 4 - 100, 177, 288, 160);
            this.add(referImg);
    
            // 添加方向按钮
            upButton = new JButton(new ImageIcon("java_day01\\imgs\\up.png"));
            upButton.setBounds(320 * 4, 370, 57, 57);
            this.add(upButton);
            downButton = new JButton(new ImageIcon("java_day01\\imgs\\down.png"));
            downButton.setBounds(320 * 4, 430, 57, 57);
            this.add(downButton);
            leftButton = new JButton(new ImageIcon("java_day01\\imgs\\left.png"));
            leftButton.setBounds(320 * 4 - 70, 430, 57, 57);
            this.add(leftButton);
            rightButton = new JButton(new ImageIcon("java_day01\\imgs\\right.png"));
            rightButton.setBounds(320 * 4 + 70, 430, 57, 57);
            this.add(rightButton);
    
            // 添加请求与重围按钮
            helpButton = new JButton(new ImageIcon("java_day01\\imgs\\help.png"));
            helpButton.setBounds(320 * 4 - 70, 570, 80, 32);
            this.add(helpButton);
            resetButton = new JButton(new ImageIcon("java_day01\\imgs\\reset.png"));
            resetButton.setBounds(320 * 4 + 30, 570, 80, 32);
            this.add(resetButton);
    
            // 创建面板
            imgPanel.setBounds(150, 144, 320 * 3, 177 * 3);
            imgPanel.setLayout(null);
    
            newPic();
            this.add(imgPanel);
    
            // 添加背景图
            JLabel backgroundImg = new JLabel(new ImageIcon("java_day01\\imgs\\background.png"));
            backgroundImg.setBounds(0, 0, 1920, 1080);
            this.add(backgroundImg);
        }
    
    
        // 初始化窗体
        public void initFrame() {
            // 设置标题
            this.setTitle("拼图");
            // 设置窗体大小
            this.setSize(1360, 720);
            // 设置窗体居中
            this.setLocationRelativeTo(null);
            // 取消窗体默认布局
            this.setLayout(null);
            // 设置窗体关闭时退出程序
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            // 设置窗体保持最前
            this.setAlwaysOnTop(true);
        }
    }
    
    
  • APP.java

    package extend02.fcarey;
    
    public class APP {
        public static void main(String[] args) {
            PicFrame frame = new PicFrame();
        }
    }
    
posted @ 2024-08-08 11:34  f_carey  阅读(4)  评论(0编辑  收藏  举报