Java 面向对象编程基础 - 学习笔记

模块二 面向对象

任务一: 类和对象

 

第一讲:对象和面向对象的概念

第二讲:面向对象编程的概念

第三讲:类和对象的概念

第四讲:类和对象以及引用的定义

<1>类的定义

class 类名{

类体;

}

<2>成员变量的定义

class 类名{

数据类型 成员变量名 = 初始值;

}

<3>对象的创建

new 类名();

// 这个过程叫做类的实例化

// 创建对象的本质: 在内存空间的堆区申请一块内存区域,用于存放该对象独有特征信息

<4>引用的定义

a. 使用引用数据类型定义的变量叫做引用型变量,简称为 引用

b. 引用变量主要用于记录对象在堆区中的内存地址信息,便于下次访问

c. 语法格式

类名 引用变量名;

引用变量名.成员变量名;

 

第五讲 - 第六讲:Person类的定义

public class Person{

 

//数据类型 成员变量名 = 初始值; 其中 = 初始值 通常都省略不写

String name;

int age;

 

public static void main(String[] args){

// 数据类型(类名) 引用变量名 = new 类名();

Person p = new Person();

 

// 打印对象中的成员变量值

// 引用变量名.成员变量名

. System.out.println("我是" + p,name + ", 今年 "+ p.age + "岁了!") // null 0

 

// 修改成员变量的数值

p.name = "John Lennon";

p.age = 100;

}

}

 

 

 

第七讲:Point类

public class Point{

 

int x;

int y;

 

public static void main(String[] args){

Point p = new Point();

p.x = 1;

p.y = 2;

 

System.out.println("x = "+p.x+", y = " + p.y);

}

}

 

第八讲:成员方法

<1>定义

class 类名{

返回值类型 成员方法名(形参列表){

成员方法体;

}

}

 

 

第九讲 - 第十讲: Person 类中无参无返回值的成员方法

public class Person{

 

//数据类型 成员变量名 = 初始值; 其中 = 初始值 通常都省略不写

String name;

int age;

 

// 成员变量和成员方法都属于类内部的成员,因此可以直接访问成员变量不需要再加 // 引用.的前缀

void show(){

System.out.println("name = " + name +", age = "+age);

}

 

public static void main(String[] args){

// 数据类型(类名) 引用变量名 = new 类名();

Person p = new Person();

 

// 修改成员变量的数值

p.name = " John Lennon";

p.age = 100;

 

// 打印对象中的成员变量值

// 打印方法的调用: 引用变量名.成员方法名(实参列表);

// 实际参数列表主要用于对形式参数列表进行初始化操作,因此参数的个数,类型

// 以及顺序要完全一致

p.show();

}

}

 

第十一讲:Point类中无参无返回值成员方法的定义

public class Point{

 

int x;

int y;

 

// 自定义成员方法,实现成员变量数值的打印

void show(){

System.out.println("x = "+x+", y = " + y);

}

 

public static void main(String[] args){

Point p = new Point();

p.x = 1;

p.y = 2;

}

}

 

第十二讲 - 第十三讲:Person类中有参数值,无返回值的成员方法

public class Person{

 

//数据类型 成员变量名 = 初始值; 其中 = 初始值 通常都省略不写

String name;

int age;

 

// 成员变量和成员方法都属于类内部的成员,因此可以直接访问成员变量不需要再加 // 引用.的前缀

void show(){

System.out.println("name = " + name +", age = "+age);

}

 

// 自定义成员方法,实现将姓名修改为 指定数值

void setName(String name){

this.name = name;

}

 

// 自定义成员方法,实现将年龄修改为 指定数值

void setAge(int age){

this.age = age;

}

 

// 自定义成员方法,修改姓名和年龄(不推荐使用,因为降低了功能之间的耦合性)

void setNameAndAge(String name, int age){

this.name = name;

this.age = age;

}

 

public static void main(String[] args){

 

// 数据类型(类名) 引用变量名 = new 类名();

Person p = new Person();

 

// 修改成员变量的数值

p.name = " John Lennon";

p.age = 100;

p.setName("Joe Biden");

p.setNameAndAge("Obama", 50);

 

// 打印对象中的成员变量值

// 打印方法的调用: 引用变量名.成员方法名(实参列表);

// 实际参数列表主要用于对形式参数列表进行初始化操作,因此参数的个数,类型

// 以及顺序要完全一致

p.show();

}

}

 

第十四讲:Point类有参无返回值成员方法

public class Point{

 

int x;

int y;

 

void setX(int x){

this.x = x;

}

void setY(int y){

this.y = y;

}

 

// 自定义成员方法,实现成员变量数值的打印

void show(){

System.out.println("x = "+x+", y = " + y);

}

 

public static void main(String[] args){

Point p = new Point();

p.x = 1;

p.y = 2;

 

p.setX(10);

p.setY(20);

p.show();

}

}

 

第十五讲:Person类中,可变长参数 的使用

<1>语法规则

返回值类型 方法名(参数的类型... 参数名)

参数个数是可以改变的,也就是0~n个

一个方法的参数列表中最多只能声明一个可变长参数,并且需要放在末尾

<2>代码

public class Person{

 

//数据类型 成员变量名 = 初始值; 其中 = 初始值 通常都省略不写

String name;

int age;

 

// 可变长参数,可看做 一维数组 使用即可

void showArguments(String... args){

for(int i = 0; i< args.length; i++){

System.out.println( "args[" +i+ "] =" + args[i] );

}

}

 

// 成员变量和成员方法都属于类内部的成员,因此可以直接访问成员变量不需要再加 // 引用.的前缀

void show(){

System.out.println("name = " + name +", age = "+age);

}

 

// 自定义成员方法,实现将姓名修改为 指定数值

void setName(String name){

this.name = name;

}

 

// 自定义成员方法,实现将年龄修改为 指定数值

void setAge(int age){

this.age = age;

}

 

// 自定义成员方法,修改姓名和年龄(不推荐使用,因为降低了功能之间的耦合性)

void setNameAndAge(String name, int age){

this.name = name;

this.age = age;

}

 

public static void main(String[] args){

 

// 数据类型(类名) 引用变量名 = new 类名();

Person p = new Person();

 

// 修改成员变量的数值

p.name = " John Lennon";

p.age = 100;

p.setName("Joe Biden");

p.setNameAndAge("Obama", 50);

 

// 打印对象中的成员变量值

// 打印方法的调用: 引用变量名.成员方法名(实参列表);

// 实际参数列表主要用于对形式参数列表进行初始化操作,因此参数的个数,类型

// 以及顺序要完全一致

p.show();

p.showArguments("大","家","好","才","是","真","的","好");

}

}

 

第十六讲:Point类中可变长参数的使用

public class Point{

 

int x;

int y;

 

void showArguments(int... args){

for(int i = 0; i< args.length; i++){

System.out.println( "args[" +i+ "] =" + args[i] );

}

}

 

void setX(int x){

this.x = x;

}

void setY(int y){

this.y = y;

}

 

// 自定义成员方法,实现成员变量数值的打印

void show(){

System.out.println("x = "+x+", y = " + y);

}

 

public static void main(String[] args){

Point p = new Point();

p.x = 1;

p.y = 2;

 

p.setX(10);

p.setY(20);

p.showArguments(1,2,3,4,5,6,7);

}

}

 

第十七讲:Person类中 无参 有返回值 的方法 (get方法)

第十八讲:Point类中 无参 有返回值 的方法 (get方法)

第十九讲:方法的传参过程

 

 

 

 

 

 第二十讲 - 第二十二讲: 参数传递的注意事项

/*
    编程实现参数传递的测试 
 */
public class ArgumentTest {
    
    // 自定义成员方法打印参数传入的整数数据
    // int ia = ib = 10;
    void show1(int ia) {
        ia = 200;
        System.out.println("show方法中:ia = " + ia); // 10  200
    }
    // 自定义成员方法打印参数传入的数组内容
    void show2(int[] arr1) {
        arr1 = new int[2];  // 加上改行代码后,相当于在堆区中又重新申请一块内存空间
        arr1[0] = 200;
        System.out.println("show方法中:arr1[0] = " + arr1[0]); // 10  200  200
    }
    
    public static void main(String[] args) {
        
        // 1.声明ArgumentTest类型的引用指向该类型的对象
        ArgumentTest at = new ArgumentTest();
        // 2.使用引用变量调用show1方法进行测试
        int ib = 10;
        at.show1(ib);
        System.out.println("main方法中:ib = " + ib); // ib = 10 
        
        System.out.println("-----------------------------------");
        // 3.调用show2方法进行测试
        int[] arr2 = new int[]{10, 20};
        at.show2(arr2);
        System.out.println("main方法中:arr2[0] = " + arr2[0]); // 10 200 10
    }
}

 

 

 

第二十三讲:任务总结

 

1.面向对象编程的概念(理解)

对象,面向对象,面向对象编程

  1. 类和对象以及引用(重中之重)

    类和对象,类的定义,成员变量的定义,对象的创建,引用的定义等

  2. 成员方法(重中之重)

    语法格式,调用格式,传参的过程等

 

任务二: 方法和封装

 

第一讲:构造方法的概念和使用

class类名{

类名 (形参列表){

方法体;

}

}

第二讲:构造方法的作用

第三讲:Point类的定义

public class Point{

 

int x;

int y;

 

// 自定义无参构造方法

Point() {}

// 自定义有参构造方法

Point(int i, int j){

x = i;

y = j;

}

 

public static void main(String[] args){

Point p1 = new Point();

Point p2 = new Point(100,200);

}

}

第四讲:重载的概念和体现形式

<1> 重载

方法名相同,参数列表不同,这样的方法之间构成重载关系(Overload)。

 

<2> 代码

/*
    编程实现方法重载主要形式的测试
 */
public class OverloadTest {
    
    // 自定义成员方法
    void show() {
        System.out.println("show()");
    }
    void show(int i) { // ok  体现在方法参数的个数不同
        System.out.println("show(int)");
    }
    void show(int i, double d) { // ok  体现在方法参数的个数不同
        System.out.println("show(int, double)");
    }
    void show(int i, int j) { // ok  体现在方法参数的类型不同
        System.out.println("show(int, int)");
    }
    void show(double d, int i) { // ok  体现在方法参数的顺序不同
        System.out.println("show(double, int)");
    }
    /*
    void show(double a, int b) { // error 与参数变量名无关
        System.out.println("show(double, int)");
    }
    */
    /*
    int show(double d, int i) { // error, 与返回值类型无关
        System.out.println("show(double, int)");
    }
    */
    
    public static void main(String[] args) {
        
        // 1.声明OverloadTest类型的引用指向该类型的对象
        OverloadTest ot = new OverloadTest();
        // 2.调用show方法
        ot.show();
        ot.show(66);
        ot.show(66, 3.14);
        ot.show(66, 118);
        ot.show(3.14, 118);
        //ot.show(3.14, 66);
    }
}

第五讲:Person类中重载的使用

void grow(){

age++;

}

 

void grow(int i){

age += i;

}

 

第六讲:Point类中重载的使用

第七讲:重载的实际意义

调用者只需要记住一个方法名,就可以调用不同的方法,实现不同的功能

第八讲 - 第十二讲:this关键字

<1> 在成员变量前加上 this. 的前缀,明确了该变量是成员变量 (重点)

<2> 可以通过this. 的方式调用成员变量和成员方法 (重点)

<3> this可以作为方法的返回值 (重点)

例子:

// 自定义成员方法,实现 Person类型对象 的获取 并返回

Person getPerson(){

return this;

}

// 调用

Person p2 = p1.getPerson();

 

<4> 在构造方法的第一行,可以使用this()的方式来调用 本类中的其他构造方法 (了解)

 

public class Boy {
    
    String name; // 用于描述姓名的成员变量
    
    // 自定义构造方法
    Boy() {
        // 调用本类中的有参构造方法
        //this("无名");
        System.out.println("无参构造方法!");
    }
    Boy(String name) {
        // 调用本类中的无参构造方法
        this();
        System.out.println("=========有参构造方法!");
        this.name = name;
    }
    // 自定义成员方法实现特征的打印
    void show() {
        System.out.println("我的名字是:" + name);
    }
    
    public static void main(String[] args) {
        
        // 1.使用无参方式构造对象并打印特征
        Boy b1 = new Boy();
        b1.show(); // null
        
        System.out.println("-----------------------------------");
        // 2.使用有参方式构造对象并打印特征
        Boy b2 = new Boy("张飞");
        b2.show(); // 张飞
    }
}

第十三讲:引用对象的注意事项

第十四讲 - 第十六讲: 递归 - 阶乘

/*
    编程实现累乘积的计算并打印
 */
public class FacTest {
    
    // 自定义成员方法实现将参数n的阶乘计算出来并返回
    // 1! = 1;     2! = 1*2;   3! = 1*2*3;   ...   n! = 1*2*3*...*n;
    int show(int n) { // int n=5; int n = 4; int n = 3; int n = 2;  int n = 1;
        // 递推的方式 
        /*
        int num = 1;
        for(int i = 1; i <= n; i++) {
            num *= i;
        }
        return num;
        */
        /*
            5! = 5 * 4 * 3 * 2 * 1;
            4! = 4 * 3 * 2 * 1;
            3! = 3 * 2 * 1;
            2! = 2 * 1;
            1! = 1;
            
            5! = 5 * 4!;
            4! = 4 * 3!;
            3! = 3 * 2!;
            2! = 2 * 1!;
            1! = 1;
            
            n! = n * (n-1)!;
          
        */
        // 递归的方式
        // 当n的数值为1时,则阶乘的结果就是1
        /*
        if(1 == n) {
            return 1;
        }
        */
        if(1 == n) return 1;
        // 否则阶乘的结果就是 n*(n-1)!
        return n*show(n-1);
        // show(5) => return 5*show(4); => 120
        // show(4) => return 4*show(3); => 24 
        // show(3) => return 3*show(2); => 6
        // show(2) => return 2*show(1); => 2
        // show(1) => return 1;         => 1
    }
    
    public static void main(String[] args) {
        
        // 1.声明FacTest类型的引用指向该类型的对象
        FacTest fct = new FacTest();
        // 2.调用方法进行计算并打印
        int res = fct.show(5);
        System.out.println("最终的计算结果是:" + res); // 120
    }
}

 

 第十七讲: 斐波那契数列 - 递归法

/*
    编程实现费氏数列的计算并打印  功能类/封装类
 */
public class Fee {
    
    // 自定义成员方法实现费氏数列中第n项数值的计算并返回,n由参数指定
    // 1 1 2 3 5 8 13  21 ....
    int show(int n) { // int n = 5; int n = 4; int n = 3; int n = 2; int n = 1;
        // 1.使用递归的方式进行计算
        
        // 当n=1或者n=2时,结果是1
        if(1 == n || 2 == n) {
            return 1;
        }
        // 否则结果是前两项的和
        return show(n-1) + show(n-2);
        // show(5) => return show(4) + show(3); => 5
        // show(4) => return show(3) + show(2); => 3
        // show(3) => return show(2) + show(1); => 2
        // show(2) => return 1;                 => 1
        // show(1) => return 1;                 => 1
    }    
}

 

 

 第十八讲: 斐波那契数列 - 递推法

 

 

 

// 使用递推的方式进行计算
int show(int n) {
        int ia = 1;
        int ib = 1;
        for(int i = 3; i <= n; i++) {
            int ic = ia + ib;
            ia = ib;
            ib = ic;
        }
        return ib;
}

 

第十九讲:代码的拆分实现

main()方法应放置入一个独有的类(测试类)中,而不应在功能类(封装类)中。

 

第二十讲 - 第二十二讲:封装

/*
    编程实现Student类的封装  封装类
 */
public class Student {
    
    // 1.私有化成员变量,使用private关键字修饰
    // private关键字修饰表示私有的含义,也就是该成员变量只能在当前类的内部使用
    private int id;       // 用于描述学号的成员变量
    private String name;  // 用于描述姓名的成员变量 
    
    // 3.在公有的构造方法中调用set方法进行合理值的判断
    public Student() {}
    public Student(int id, String name) {
        //this.id = id;
        //this.name = name;
        setId(id);
        setName(name);
    }
    
    // 2.提供公有的get和set方法,并在方法体中进行合理值的判断
    // 使用public关键字修饰表示公有的含义,也就是该方法可以在任意位置使用
    public int getId() {
        return id;
    }
    public void setId(int id) {
        if(id > 0) {
            this.id = id;
        } else {
            System.out.println("学号不合理哦!!!");
        }
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
    // 自定义成员方法实现特征的打印
    // 什么修饰符都没有叫做默认的访问权限,级别介于private和public之间
    public void show() {
        //System.out.println("我是" + name + ",我的学号是" + id);
        System.out.println("我是" + getName() + ",我的学号是" + getId());
    }
}
/*
    编程实现Student类的测试
 */
public class StudentTest {
    
    public static void main(String[] args) {
        
        // 1.声明Student类型的引用指向Student类型的对象
        Student s1 = new Student();
        // 2.对成员变量进行赋值并打印
        //s1.id = -1001;
        //s1.name = "张飞";
        s1.setId(-1001);
        s1.setName("张飞");
        s1.show(); // 1001 张飞
        
        System.out.println("----------------------------------------------------");
        // 3.使用有参方式构造对象并打印特征
        Student s2 = new Student(-1001, "张飞");
        s2.show(); 
    }
}

 

 

 

第二十三讲:

<1>

/* 编程实现学生信息的录入和打印 */ import java.util.Scanner; public class StudentTest2 { public static void main(String[] args) { // 1.提示用户输入学生的人数并使用变量记录 System.out.println("请输入学生的人数:"); Scanner sc = new Scanner(System.in); int num = sc.nextInt(); // 2.根据学生的人数准备对应的一维数组 // int[] arr = new int[3]; - 表示声明一个长度为3元素类型为int类型的一维数组 // 数组中的每个元素都是int类型,也就是说数组中的每个元素都可以看做是一个int类型的变量,使用整数数据进行初始化 arr[0] = 10; // 下面的代码是声明一个长度为num元素类型为Student类型的一维数组 // 数组中的每个元素都是Student类型,也就是说数组中的每个元素都可以看做Student类型的变量,arr[0] = new Student(); Student[] arr = new Student[num]; // 3.提示用户输入每个学生的信息(学号 姓名)并记录到一维数组中 for(int i = 0; i < num; i++) { System.out.println("请输入第" + (i+1) + "个学生的信息(学号 姓名):"); arr[i] = new Student(sc.nextInt(), sc.next()); } System.out.println("-----------------------------------------------"); // 4.打印所有学生信息 System.out.println("该班级的所有学生信息有:"); for(int i = 0; i < num; i++) { //System.out.println(arr[i]); arr[i].show(); } } }

 

<2> JavaBean的概念

JavaBean本质上就是符合以下标准的Java类:

类是公共的

有一个无参的公共构造器

有属性,且有对应的get,set方法

 

第二十四讲:任务总结

1.构造方法(重中之重)

语法格式,默认构造方法,实现成员变量的初始化

2.方法重载(重点)

概念,体现形式,实际意义

3.this关键字(原理)

概念,原理,使用方式

4.递归(难点)

概念,使用原则

5.封装(重中之重)

 

概念,实现流程

 

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

1.定义的位置不一样【重点】

  • 局部变量:在方法的内部

  • 成员变量:在方法的外部,直接写在类当中

2.作用范围不一样【重点】

  • 局部变量:只有方法当中才可以使用,出了方法就不能再用了

  • 成员变量:整个类都可以通用

 

任务三:static 关键字和继承

第一讲:People类和测试类的实现

<1> 实现People类的封装,特征有:姓名,年龄,国籍

<2> 编程实现PeopleTest类,main方法中使用有参方式构造两个对象并打印

<3> 代码:

public class People{

 

private String name;

private int age;

private String country;

 

//构造方法

public People(){}

public People(String name, int age, String country){

setName(name);

setAge(age);

setCountry(country);

}

 

public void show(){

System.out.println("name = " +name+ " age = " + age + " country = "+country);

}

 

public String getName(){

return name;

}

public void setName(String name){

this.name = name;

}

public int getAge(){

return age

}

public void setAge(int age){

if(age > 0 && age < 150){

this.age = age;

}else{

System.out.println("年龄不合理哦!!!");

}

}

public String getCountry(){

return country;

}

public void setCountry(String country){

this.country = country;

}

}

 

// 编程实现People类的测试

public class PeopleTest{

 

public static void main(String[] args){

    

    // 1.使用有参方式构造两个People类型的对象并打印特征
    People p1 = new People("zhangfei", 30, "China");
    p1.show(); // zhangfei 30 China
    
    People p2 = new People("guanyu", 35, "China");
    p2.show(); // guanyu 35 China

}

}

第二讲:static关键字的基本概念

<1> 使用static修饰后, 成员变量由 对象层级 提升为 类层级

也就是,整个类 只有一份 并 被所有对象共享,

该成员变量 随着类的加载 准备就绪,与 是否 创建对象 无关

 

 

 

  <2>

// 3.验证static关键字修饰的静态成员(类成员)是否与创建对象无关  类名.的方式 => 无关
//System.out.println("获取到的国籍信息是:" + People.country); // null
System.out.println("获取到的国籍信息是:" + People.getCountry()); // null
        
    // 2.验证static关键字修饰的静态成员(类成员) 是否被所有对象共享  => 共享
    //p1.country = "蜀国";
    p1.setCountry("蜀国");
    //System.out.println("第一个对象的国籍是:" + p1.country); // 蜀国
    //System.out.println("第二个对象的国籍是:" + p2.country); // 蜀国
    System.out.println("第一个对象的国籍是:" + p1.getCountry()); // 蜀国
    System.out.println("第二个对象的国籍是:" + p2.getCountry()); // 蜀国
    
    People p3 = new People();
    //System.out.println("第三个对象的国籍是:" + p3.country); // 蜀国
    System.out.println("第三个对象的国籍是:" + p3.getCountry()); // 蜀国

<3> static关键字修饰的成员,可以使用 引用. 的方式访问, 但 推荐 类名. 的方式

 

第三讲:static关键字的使用方式

<1>

public class StaticTest {
    
    private int cnt = 1; // 隶属于对象层级,也就是每个对象都拥有独立的一份
    private static int snt = 2; // 隶属于类层级,也就是所有对象都共享同一份
    
    // 自定义非静态的成员方法  需要使用引用.的方式访问
    public void show() {
        System.out.println("cnt = " + this.cnt); // 1
        System.out.println("snt = " + this.snt); // 2  
        // 静态成员被所有对象共享,this关键字可以省略
    }
    public static void main(String[] args) {
        
        StaticTest st = new StaticTest();
        st.show();
    }
}

使用方式

在 非静态成员方法中 既能访问非静态的成员,又能访问 静态的成员

(成员:成员变量+成员方法,静态成员被所有对象共享)

 

<2>

在static方法中,只能访问static成员, 不能访问 非静态 成员。

 

(这一特点,体现了Java语言的安全性)

 

 

 <3>只有隶属于类层级并被所有对象共享的内容才可以使用static修饰(不能滥用static 关键词)

<4> 静态成员变量的get(),set()方法 (规范)

public class People {
    private static String country;
    
    public static String getCountry() {
        return country;
    }
    public static void setCountry(String country) {
        //this.country = country;
        People.country = country;
    }
}
/*
    编程实现构造块和静态代码块的使用
 */
public class BlockTest {
    
    // 当需要在执行构造方法体之前做一些准备工作时,则将准备工作的相关代码写在构造块中即可,比如:对成员变量进行的统一初始化操作
    {
        System.out.println("构造块!"); // (2)
    }
    
    // 静态代码块会随着类的加载而准备就绪,会先于构造块执行
    // 当需要在执行代码块之前随着类的加载做一些准备工作时,则编写代码到静态代码块中,比如:加载数据库的驱动包等
    static {
        System.out.println("#####################静态代码块!");   // (1)
    }
    
    // 自定义构造方法
    public BlockTest() {
        System.out.println("====构造方法体!"); // (3)
    }
    
    public static void main(String[] args) {
        
        BlockTest bt = new BlockTest();
        
        
        BlockTest bt2 = new BlockTest();
        
        // 静态代码块执行了一次, 构造块执行了两次
    }
}

第五讲 main方法详解

<1> 向main(String[] args)方法中传递参数:

javac MainTest.java

java MainTest 变量1 变量2 变量3

 

第六讲 - 第八讲:Singleton 和SingletonTest类

要求:Singleton 只能被实例化一次 ==> Singleton的构造方法私有化

 

public class Singleton{
    
    private static Singleton s = new Singleton();
    
    private Singleton(){}
    
    public static Singleton getInstance(){
        return s;
    }
    
}

public class SingletonTest{

    public static void main(String[] args){

        // <1> 不符合单例的要求
        //Singleton s1 = new Singleton();
        //Singleton s2 = new Singleton();
        //System.out.println(s1 == s2); // false
        // <2> 需要封装变量Singleton s的原因:
        // Singleton.s = null; // 可以使得引用变量无效
        // <3>正确:
        Singleton s1  = Singleton.getInstance(); 
        Singleton s2  = Singleton.getInstance(); 
        // 此时:s1 == s2

    }

}

图解:

 

 

 第九讲:单例设计模式

<1> 对外只提供一个对象的类 ==> 单例类

<2> 实现流程

 

 

 <3>应用:

Windows的任务管理器,只能打开一个

<4>单例的两种实现模式: 饿汉式 / 懒汉式

public class Singleton {
    
    // 2.声明本类类型的引用指向本类类型的对象,使用private static关键字共同修饰
    //private static Singleton sin = new Singleton();  // 饿汉式
    private static Singleton sin = null;               // 懒汉式
    
    // 1.私有化构造方法,使用private关键字修饰
    private Singleton() {}
    
    // 3.提供公有的get方法负责将对象返回出去,使用public static关键字共同修饰
    public static Singleton getInstance() {
        //return sin;
        if(null == sin) {
            sin = new Singleton();
        }
        return sin;
    }
}

第十讲:继承的由来和概念

<1>

 

 

 <2> 使用extends表示继承关系

 

第十一讲:继承的意义

public class Person{

    private String name;
    private int age;
    
    Person(){
        System.out.println("Person()");
    }
    Person(String name, int age){
        System.out.println("Person(String,int)");
        setName(name);
        setAge(age);
    }
    
    public String getName(){
        return name;
    }
    
    public void setName(String name){
        this.name = name;
    }
    
    public int getAge(){
        return age;
    }
    
    public void setAge(int age){
        if( age > 0 && age < 150){
            this.age = age;
        } else{
            System.out.println(“年龄不合理哦!”);
        }     
    }
    
    public void show(){
        System.out.println("name = "+ name + " age = " + age);
    }
    
    public void eat(String food){
        System.out.println(food + "真好吃!");
    }
    
    public void play(String game){
        System.out.println(game +"真好玩!");
    }
}
// Worker

public class Worker extends Person {
    
    private int salary;
    
    public Worker() {
        super(); // 表示调用父类的无参构造方法, 若没有加,则编译器 自动添加
        System.out.println("Worker()");
    }
    public Worker(String name, int age, int salary){
        super(name,age); // 表示调用父类的有参构造方法
        System.out.println("Worker(String,int,int)");
        setSalary(salary);
    }
    
    public int getSalary(){
        return salary;
    }
    
    public void setSalary(int salary){
        if(salary >= 2200){
            this.salary = salary;
        }else{
            System.out.println("薪水不合理哦!");
        }
    }
    
    // 自定义成员方法表述工作行为
    public void work(){
        System.out.println("今天的砖头有点烫手...");
    }
    
}
public class Teacher extends Person {
    
}

// WorkerTest
public class WorkerTest{
    
    public static void main(String[] args){
        
        Worker w1 = new Worker();
        // 调用顺序 Person() ==> Worker()
        w1.show(); // 正确: null 0 
        // 注意: Worker类中没有 show 方法
        // 说明: Worker类的引用可以调用Person类的 show 方法   
        
        Worker w2 = new Worker("张飞",30,3000);
        // 调用顺序 Person(String,int,int) ==> Worker(String,int,int)
        w2.show(); // 正确: null 0 
        // 注意: Worker类中没有 show 方法
        // 说明: Worker类的引用可以调用Person类的 show 方法
        w2.eat("豆芽");
        w2.play("王者荣耀");
        w2.work();
    }    
}

继承提高了代码的复用性,可维护性和扩展性, 是多态的前提条件。

 

第十二讲 - 第十四讲: 继承的特点

<1> 子类 不能继承 父类的 构造方法 和 private 方法

<2> 私有成员变量 可以被继承 只是不能直接访问

<3> super()

 

 

 <4> 使用继承必须满足逻辑关系: 子类 is a 父类,也就是不能滥用继承

<5> Java只支持单继承: 一个孩子只能有一个父亲, 一个父亲可以有多个孩子

<6> 若, 编程实现 计算机老师类 继承自 Teacher类,则:

 

 

 第十五讲:方法的重写 (Override)

<1> 父类方法不满足子类需求 ===> 重新写一个一样的方法,将父类的版本覆盖掉

public class Person{

    public void show(){
        System.out.println("name = "+ name + " age = " + age);
    }
}

public class Worker extends Person {
    
    @Override // 标注/注解,用于说明下面的方法是对父类方法的重写,若没有构成重写,则编译报错
    public void show(){
        super.show(); //表示调用父类的show()方法
           System.out.println( "salary = " + getSalary());
    }
}

第十六讲:方法重写的原则

<1> 要求方法名相同, 参数列表相同 以及 返回值类型 相同,

从Java5开始 允许 返回子类类型

 

<2> 方法的访问权限不能变小,可以相同或者变大

错误:父类 public 子类 private

正确:父类 private 子类public

可以这样理解: 子类继承父类,是一种扩展的实现

<3> 子类不能抛出更大的异常

 

第十八讲- 第十九讲:IDEA的安装和初始化

第二十讲 - 第二十一讲:Animal类,Dog类,DogTest类的实现

第二十二讲: 构造块与静态代码块(笔试考点)

<1> 先执行父类的静态代码块,再执行子类的静态代码块

先执行父类的构造块,执行父类的构造方法体

先执行子类的构造块,执行子类的构造方法体

<2> 例子:

package com.lagou.task08;
public class SuperTest {
    {
        System.out.println("SuperTest类中的构造快!"); 
    }
    static {
        System.out.println("SuperTest类中的静态代码块!"); 
    }
    public SuperTest(){
        System.out.println("SuperTest中的构造方法体!"); 
    }
}


package com.lagou.task08;

public class SubSuperTest extends SuperTest {
    {
        System.out.println("========= SubSuperTest类中的构造快!");   
    }
    static {
        System.out.println("========= SubSuperTest类中的静态代码块!");  
    }
    public SubSuperTest(){
        System.out.println("========= SubSuperTest类中的构造方法体!");  
    }
    public static void main(String[] args) {
        // 使用无参方式构造子类的对象
        SubSuperTest sst = new SubSuperTest();
    }
}

运行结果:
SuperTest类中的静态代码块!
========= SubSuperTest类中的静态代码块!
SuperTest类中的构造快!
SuperTest中的构造方法体!
========= SubSuperTest类中的构造快!
========= SubSuperTest类中的构造方法体!

 

二十三讲:权限修饰符和包的定义

<1>

 

 

 <2> private成员只能在本类内部使用

成员方法都用public关键字修饰,成员变量都使用private关键词修饰

<3> package语句的由来

为了实现项目管理,解决命名冲突,以及权限控制的效果

在指定包名的时候,也按照一定的规范

<4>import

  1. 导入包

  2. 导入类中的成员: import static java.lang.System.out; (很少使用)

 

第二十四讲:final修饰类和方法的作用

<1> final 修饰类 ==> 该类不能被继承

--- 主要用于防止滥用继承,如: java.lang.String类 等

<2> final修饰方法 ==> 方法不能被重写,但可以被继承

--- 主要用于防止不经意间造成重写,如: java.text.Dateformat类中format方法等

<3>

多行注释快捷键: ctrl + shift + /

单行注释快捷键: ctrl + /

 

第二十五讲: final修饰成员变量的作用

<1> final修饰成员变量 ==> 该变量必须初始化,且不能改变

--- 主要用于防止不经意间造成改变,如: java.lang.Thread类中MAX_PRIORITY等

<2> final变量的3 种初始化方式

package com.lagou.task08;

public class FinalMemberTest {
//    private final int cnt = 1; // 显式初始化
    private final int cnt;

    /*{
        cnt = 2;  // 构造块中进行初始化
    }*/

    public FinalMemberTest() {
        cnt = 3; // 构造方法体中进行初始化
    }

    public static void main(String[] args) {

        // 声明FinalMemberTest类型的引用指向该类的对象
        FinalMemberTest fmt = new FinalMemberTest();
        // 打印成员变量的数值
        System.out.println("fmt.cnt = " + fmt.cnt); // 0  1  2  3
    }
}

<3>在以后的开发中很少单独使用final关键字来修饰成员变量, 通常使用public static final关键字共同修饰成员变量来表达常量的含义,常量的命名规范要求所有字母都要大写,不同的单词之间采用下划线连。

 

第二十六讲:任务总结

1.static关键字

概念使用方式构造块 和 静态代码块单例设计模式(饿汉式和懒汉式)等

2.继承

概念特点方法方法的重写重写的原则IDEA的使用等

3.访问控制

publicprivatepackage导入等

4.final关键字

概念修饰类修饰成员方法修饰成员变量常量的概念等

 

任务四:多态和特殊类

第一讲:多态的概念和语法格式

<1>多态的概念

多态主要指 同一事物 表现出来的 多种形态

饮料:可乐,雪碧,红牛...

人:学生,教师,工人,保安...

图形:矩形,圆形,梯形...

<2>多态的语法格式

父类类型 引用 = new 子类类型(); // 父类引用指向子类对象

如: Shape s = new Rect();

s.show();

 

第二讲 - 第三讲:Shape类和Rect类

<0> 快捷键 ctrl + d : 复制并粘贴当前行

快捷键alt + shift + 上/下方向键: 移动当前行

<1> 代码

package com.lagou.class09;

public class ShapeRectTest {
    public static void main(String[] args) {
        
        // 父类 ===> 父类
        Shape s = new Shape(1,2);
        s.show(); // 1 2

        // 子类 ===> 子类
        Rect r = new Rect(3,4,5,6);
        r.show(); // 3 4 (子类中没有show方法)
        
        // 父类 ===> 子类
        Shape s2 = new Rect(7,8,9,10);
        s2.show(); // 7 8 (子类中没有show方法)
    }
}

<2> 代码

         // 父类 ===> 父类
        Shape s = new Shape(1,2);
        s.show(); // 1 2

        // 子类 ===> 子类
        Rect r = new Rect(3,4,5,6);
        r.show(); // 3 4 5 6 (子类中有show方法)

        // 父类 ===> 子类
        // 披着 "羊皮"(Shape) 的 ”狼“(Rect)
        Shape s2 = new Rect(7,8,9,10);
        s2.show(); // 7 8 9 10 (子类中有show方法)

第四讲:多态的特点

<1> Shape 的引用能否直接调用 父类 和 子类中独有的方法呢?

Shape s2 = new Rect(7,8,9,10);

int X = s2.getX(); // 1. 可以直接调用 父类独有的方法

// 2. 不能直接调用 子类独有的方法

 

<2> 父子类都有的 非静态 方法, 编译阶段调用父类版本,运行阶段调用子类重写的版本(动态绑定)

<3>父子类都有的 静态 方法, 编译阶段 & 运行阶段 都调用 父类版本

 

第五讲:引用数据类型之间转换的方式

<1> 使用父类类型的引用,调用子类独有方法 的方式

Shape s2 = new Rect(7,8,9,10);

( (Rect) sr ).getLen(); // Shape 父大 ===> Rect 子小 (向下转型,显示类型扎转换)

<2> 自动类型转换: 子类 ===> 父类 (向上转型, 小 ===> 大)

例子:

Shape s2 = new Rect(7,8,9,10);

 

第六讲:引用数据类型 转换 的 注意事项

<1>

Shape s2 = new Rect(7,8,9,10);

Circle c1 = (Circle) s2; // 运行报错:Rect 不能转换为 Circle (ClassCastException)

// 羊皮 (Shape) 揭掉变成狼 (Rect)

<2>

为了避免上述错误的发生,应该在强转之前进行判断,格式如下:

if (引用变量 instanceof 数据类型){ // 判断引用变量 指向的 对象 是否为 后面的 数据类型

}

<3> 例子

if (s2 instanceof Circle){

System.out.println("可以放心地转换了");

Circle c1 = (Circle) s2;

}else{

System.out.println("强转有风险,操作需谨慎!");

}

 

第七讲:Rect对象特征的打印

 

 

 第八讲:多态的实际意义

<1>

 

 

 <2>

 

 <3> 解析

// 自定义成员方法实现既能打印矩形对象又能打印圆形对象的特征,对象由参数传入 子类 is a 父类// Shape s = new Rect(1, 2, 3, 4); 父类类型的引用指向子类类型的对象,形成了多态// Shape s = new Circle(5, 6, 7); 多态// 多态的使用场合一:通过参数传递形成了多态public static void draw(Shape s) { // 编译阶段调用父类的版本,运行阶段调用子类重写以后的版本 s.show();}

 

 

 第九讲:抽象方法 和 抽象类 的概念

<1>抽象方法: 不能具体实现的方法,使用abstract关键字修饰,并且没有方法体

<2> 语法格式

访问权限 abstract 返回值类型 方法名(形参列表);

<3> 例子

public abstract void cry();

"方法体没法写,但这个方法还得存在" ===> 写成抽象方法

 

<4> 抽象类: 不能具体实例化的类,也就是不能创建对象,使用abstract关键字修饰

<5>例子

package com.lagou.task09;

public abstract class AbstractTest {
    private int cnt;

    public AbstractTest() {
    }

    public AbstractTest(int cnt) {
        setCnt(cnt);
    }

    public int getCnt() {
        return cnt;
    }

    public void setCnt(int cnt) {
        this.cnt = cnt;
    }

    // 自定义抽象方法
    public abstract void show();

    public static void main(String[] args) {

        // 错误:
        // 声明该类类型的引用指向该类类型的对象
        //AbstractTest at = new AbstractTest();
       
    }
}

<6> 抽象方法 必须 放在 抽象类 中

<7> 抽象类 应该(不是必须) 具有 抽象方法

 

第十讲:抽象类的实际意义

<1>抽象类的实际意义,不在于自身创建对象,而在于,被继承

<2>例子

public abstract class AbstractTest {

// 自定义抽象方法 public abstract void show();

}

public class SubAbstractTest extends AbstractTest { @Override public void show() { System.out.println("其实我是被迫重写的,否则我也得变成抽象的呀!"); }

 

<3> 继承抽象类,则必须重写 抽象方法, 否则, 该类也得是 抽象类。

<4> 抽象类对子类具有强制性和规范性, 因此 叫做 模板设计 模式

 

第十一讲: 多态在抽象类中的应用

<1> 多态的另一种形式:

抽象类的引用 指向 子类类型的对象

<2>例子:

// 方式一:

SubAbstractTest s = new SubAbstractTest();

AbstractTest a = new SubAbstractTest();

// 方式二(多态):AbstractTest 是抽象类,SubAbstractTest是抽象类的实现类

 

第十二讲:抽象类的应用

<1>例子

银行有 定期账户(Saving Account) 和 活期账户(Checking Account)。

继承自 账户类。

账户类中:

public abstract class Account{

private double money;

public abstract double getInterest();

}

 

<2> 代码

 

Account.java

 

 

 FixedAccount.java

 

 

 第十三讲:笔试考点

// private 和 abstract 关键字不能共同修饰一个方法// 错误:private abstract double getLixi();

// final 和 abstract 关键字不能共同修饰一个方法// 错误:public final abstract double getLixi();

// static 和 abstract 关键字不能共同修饰一个方法// 错误:public static abstract double getLixi();

 

第十四讲:接口的基本概念

<1>

接口是一种 比 抽象类 还 抽象的类,体现在 所有方法 都为 抽象方法

<2>

定义接口的关键字是: interface

<3>

代码

public interface InterfaceTest{

/ * public static final 可以省略*/ int CNT = 1; // 里面只能有常量

// private void show(){}// 从JAVA9开始允许接口中出现私有方法

/ * public abstract 可以省略 */ void show(); //里面只能有抽象方法 (新特性除外)

// 注释中的关键字可以省略,但建议写上

}

 

第十五讲:接口的实际意义

<1> 定义类的关键字是class,定义接口的关键字是interface,如:

金属接口,货币接口,黄金类

<2> 支持 “继承”多个接口

黄金类 实现 货币接口

黄金类 实现 金属接口

<3> 代码

 

 

 

 

 第十六讲 - 第十七讲:类和接口之间的关系 - 抽象类和接口的主要区别

<1> Runner 接口 ------ Hunter接口 extends Runner接口 --- Man类 implements Hunter

 

 

 

 

 只要涉及到接口,都支持: 多继承,多实现

接口和接口直接:多继承

接口和类之间:多实现

弥补了JAVA中不支持多继承的不足

 

<2> 抽象类 和 接口 区别

  1. 抽象类关键字: abstract class , 接口关键字: interface

  2. 继承抽象类: extends, 实现接口:implements

  3. 抽象类:可以有构造方法, 接口:不可以

  4. 抽象类:可以有成员变量, 接口:不可以

  5. 抽象类:可以有成员方法, 接口:只能有抽象方法 (JAVA8以前)

  6. 在接口中,增加方法时,类一定需要重写(JAVA8 以前)

  7. 接口中,允许出现非抽象方法 和 静态方法, 非抽象方法需要使用default 关键词修饰 (JAVA8 新特性)

  8. 接口中,允许出现私有方法(JAVA9 新特性)

 

第十八讲:任务总结

  1. 多态(重中之重)

    基本形态, 语法格式, 多态的特点, 类型转换, instanceof,实际意义等

  2. 抽象类(重点)

    抽象方法,抽象类,抽象类和抽象方法的关系,实际意义等

  3. 接口(重点)

    基本概念,常量,抽象方法,弥补不能多继承的不足,接口和类之间的关系,抽象类和接口的主要区别等

 

任务五:特殊类

第一讲:内部类的概念和分类

<1> 基本概念

当 一个类的定义 出现在 另外一个类的 类体中 时,这个类 叫做 内部类, 而这个内部类所在的类叫做 外部类

<2>类中的内容: 成员变量,成员方法,构造方法,静态成员,构造快和静态代码块,内部类

<3>实际作用

当 一个类 存在的价值 仅仅是为 某一个类 单独服务时, 那么 就可以将 这个类定义为 所服务类中的 内部类, 这样 可以隐藏 该类的 实现细节 并且 可以方便的访问 外部类的私有成员, 而不再需要 共有的 get 和 set方法。

<4>内部类的分类

普通内部类 - 直接将一个类的定义放在另外一个类的类体中

静态内部类 - 使用static 关键字修饰的内部类,隶属于类层级

局部内部类 - 写在方法体内部 的类

匿名内部类 - 就是指没有名字的内部类

 

第二讲:普通内部类的定义

<1> 普通(成员)内部类的格式

访问修饰符 class 外部类类名{

访问修饰符 class 内部类类名{

内部类类体;

}

}

<2> 示例

public class NormalOuter {

private int cnt = 1;

 

// 定义普通内部类,隶属于外部类的成员,并且是对象层级

public class NormalInner{

private int ia = 2;

 

public NormalInner(){

System.out.println("普通内部类的构造方法");

}

 

public void show(){

System.out.println("外部类中变量cnt的数值为:" + cnt); // 1

System.out.println(" ia = " + ia); // 2

}

}

}

 

public class NormalOuterTest{

public static void main(String[] args){

// 1.声明NormalOuter类型的引用 指向该类型的对象

NormalOuter outer = new NormalOuter();

//2. 声明NormalOuter类中,内部类的引用,指向内部类的对象

NormalOuter.NormalInner inner = outer.new NormalInner();

// 3.调用内部类中的show方法

inner.show();

}

}

 

第三讲:普通内部类的使用方式

<1>

普通内部类和普通类一样可以定义成员方法变量,成员方法以及构造方法等。

<2>

普通内部类和普通类一样可以使用final或者abstract关键字修饰

<3>

普通内部类还可以使用private或protected关键字进行修饰

<4>

普通内部类需要使用外部类来创建对象

<5>

如果内部类 访问 外部类中 与本类内部同名的 成员变量 或 方法时, 需要使用 this 关键字

例子:

 

 

 public class NormalOuterTest{

public static void main(String[] args){

NormalOuter outer = new NormalOuter();

NormalOuter.NormalInner inner = outer.new NormalInner();

inner.show(4);

}

}

 

 

第四讲 - 第五讲:静态内部类的定义 & 静态内部类的使用方式

<1> 语法格式

访问修饰符 class 外部类类名{

访问修饰符 static class 内部类类名{

内部类类体;

}

}

 

<2>代码

public class StaticOuter {

private int cnt = 1;// 隶属于对象层级

private static int snt = 2; // 隶属于类层级

 

public void show(){

System.out.println("外部类中的 show()方法! " );

}

 

private static class StaticInner{

private int ia = 3;

public StaticInner(){

System.out.println("静态内部类的构造方法哦!");

}

 

public void show(){

System.out.println("静态内部类的show方法! ia = " + ia);

System.out.println("外部类的 snt = " + snt);

// 不能访问外部类的cnt: System.out.println("外部类的 cnt = " + cnt);

}

 

public void show2(int snt){

System.out.println(" snt = " + snt); // 5

System.out.println(" 内部类中的成员snt = " + StaticInner.snt); // 4

System.out.println(" 外部类中的成员snt = " + StaticOuter.snt); // 2

// 调用外部类中的show方法

new StaticOuter().show();

}

}

}

public class StaticOuterTest {

    public static void main(String[] args) {

        // 1.声明StaticInner类型的引用指向该类型的对象
        StaticOuter.StaticInner si = new StaticOuter.StaticInner();
        // 2.调用show方法进行测试
        si.show();

        System.out.println("---------------------------------------");
        si.show2(5);
    }
}

<3>静态内部类的使用方式

静态内部类不能直接访问外部类的非静态成员

静态内部类可以直接创建对象

如果内部类 访问 外部类中 与本类内部同名的 成员变量 或 方法时, 需要使用 类名. 的方式访问

 

第六讲:局部内部类的定义

<1> 局部(方法)内部类的格式

访问修饰符 class 外部类的类名{

方法(){

class 内部类的类名{

内部类的类体;

}

}

}

 

<2> 局部内部类

public class AreaOuter{

private int cnt = 1;

 

public void show(){

 

// 定义一个局部变量进行测试

// 从Java8开始,直接默认理解为 final关键字 修饰的变量

// 虽然可以省略final,但是建议加上

/*final */ int ic = 4;

 

// 定义局部内部类,只在当前方法体的内部好使

class AreaInner{

private int ia = 2;

 

public AreaInner(){

System.out.println("局部内部类的构造方法!");

}

 

public void test(){

System.out.println(" ia = " + ia);// 2

System.out.println(" cnt = " + cnt);// 1

 

}

 

// 声明局部内部类的引用,指向局部内部类的对象

AreaInner ai = new AreaInner();

ai.test();

}

}

}

 

public class AreaOuterTest{

 

public static void main (String[] args){

 

// 1. 声明:外部类类型的引用,指向外部类的对象

AreaOuter ao = new AreaOuter();

// 2. 通过show方法的调用,实现局部内容类的定义和使用

ao.show();

}

}

 

<3> 使用方式

只能在方法内部使用

可以在方法体内部直接创建对象

不能使用访问控制符和static关键字修饰符

可以使用外部方法的局部变量,但必须是final的。 由局部内部类和局部变量的声明周期不同所致。

 

第八讲:回调模式 - 第九讲:匿名内部类的使用

<1>概念

回调模式是:如果一个方法的参数,是接口类型,则,在调用该方法时,需要创建,并,传递一个实现此接口类型的对象; 而,该方法,在运行时,会调用到,参数对象中,所实现的方法

 

<2>

public interface AnonymousInterface{

// 自定义抽象方法

public abstract void show();

}

 

public interface AnonymousInterfaceTest{

// 假设已有下面的方法, 则:

// AnonymousInterface ai = new AnonymousInterfaceImps() ;

// 接口类型的引用指向实现类型的对象,形成了多态

public static void test(AnonymousInterface ai){

// 编译阶段调用父类版本,运行调用实现类重写的版本

ai.show();

}

 

public static void main(String[] args){

// 请问如何调用 test(AnonymousInterface ai)?

AnonymousInterfaceTest.test (new AnonymousInterfaceImps() );

 

// 第九讲:如果AnonymousInterfaceImps()中的方法只需要使用一次? 有没有更好的方法?

 

// 方法一: 使用匿名内部类的语法格式来得到接口类型的引用,

// 格式为: 接口/父类类型引用变量名 = new 接口/父类类型() {方法的重写};

AnonymousInterface ait = new AnonymousInterface(){

@Override

public void show(){

System.out.println("匿名内部类");

}

AnonymousInterfaceTest.test(ait);

 

// 二:从Java8开始提出新特性: Lamda表达式,可以简化上述代码, 格式为:

// (参数列表) -> {方法体}

AnonymousInterface ait2 = () -> System.out.println("Lamda表达式是如此简单!");

AnonymousInterfaceTest.test(ait2);

}

}

}

 

public class AnonymousInterfaceImps implements AnonymousInterface{

@Override

public void show(){

System.out.println("实现了show方法");

}

}

 

<3> 匿名内部类的语法格式(重点)

接口/父类类型引用变量名=new 接口/父类类型() {方法的重写};

 

第十讲:枚举类的概念 和 自定义实现

<1> 为什么需要枚举?

季节: 春,夏,秋,冬

性别: 男,女

键盘上的所有方向键: 上,下,左,右

这类事物,只有几个明确的固定值,可以一一列举出来

 

<2>代码:

// 编程实现所有方向的枚举:上,下,左,右

public class Direction {

private final String description; // 用于表述方向字符串的成员变量

 

// 通过构造方法实现成员变量的初始化,更加灵活

private Direction (String description){

this.description = description;

}

 

public String getDescription(){

return description;

}

 

public static final Direction UP = new Direction("向上");

public static final Direction DOWN = new Direction("向下");

public static final Direction LEFT = new Direction("向左");

public static final Direction RIGHT = new Direction("向右");

}

 

public class DirectionTest {

public static void main(String[] args){

Direction d1 = Direction.UP;

System.out.println("获取到的方向是:" + d1.getDescription());

}

}

 

第十一讲:枚举类型的定义

<1>

使用public static final表示的常量描述较为繁琐,使用enum关键字来定义枚举类型取代常量,枚举类型是从Java5开始增加的一种引用数据类型。

<2> 代码

 

public static final enum DirecitionEnum{

// 枚举类型要求所有枚举值必须放在枚举类型的最前面

UP("向上"), DOWN("向下"), LEFT("向左"), RIGHT("向右");

private final String description;

 

private DirectionEnum(String description){

this.description = description;

}

 

public String getDescription(){

return Description;

}

}

 

public class DirectionTest{

DirectionEnum de = DirectionEnum.DOWN;

System.out.println("获取到的方向是:"+ de.getDescription());

}

 

<3> 枚举值就是当前类的类型,也就是指向本类的对象,默认使用public static final 关键字共同修饰, 因此采用枚举类型. 的方式调用

<4> 枚举类可以自定义构造方法,但是构造方法的修饰必须是 private, 默认也是私有的

 

第十二讲:自定义类和枚举类型在switch结构的使用

public class DirectionUseTest{

 

// 自定义静态方法,实现根据参数 指定的 字符串内容,来打印 具体的 方向信息.

public static void test1(String str){

switch (str){

case "向上":

System.out.println("抬头望明月"); break;

case "向下":

System.out.println("低头思故乡"); break;

case "向左":

System.out.println("左牵黄 ");break;

case "向右":

System.out.println("右擎苍 ");break;

deafult:

System.out.println("没有这样的方向哦");

 

}

}

 

// 接收枚举类型的变量

public static void test2(DirectionEnum de){

switch (de){

case UP:

System.out.println("抬头望明月"); break;

case DOWN:

System.out.println("低头思故乡"); break;

case LEFT:

System.out.println("左牵黄 ");break;

case RIGHT:

System.out.println("右擎苍 ");break;

deafult:

System.out.println("没有这样的方向哦");

 

}

}

 

public static void main(String[] args){

DirectionUseTest.test1(Direction.UP.getDescription());

 

DirectionUseTest.test2(DirectionEnum.DOWN)

}

}

 

 

第十三讲:Enum类的概念和方法

<1>  所有的枚举类都继承自 java.lang.Enum类, 常用方法如下:

 

 

 <2> 代码示例

 

 

第十四讲:Enum类的常用方法

 

 

 

 

 

 第十五讲:枚举类实现接口的方式

 

 

调用重写后的show方法

 

 

 

 

 

 

 

 

第十六讲:注解的概念

Annotation, 是一种引用数据类型。

可以把注解看做是一种 特殊的接口。 (比喻为: 超市货架上的标签)

注解,本质上是 代码中的特殊标记, 通过标记,可以在编译,运行,类加载时, 执行指定的处理。

 

第十七讲:注解的定义和使用

<1> 格式

访问修饰符 @interface 注解名称{

    注解成员;

 

<2>

 

 <3> 代码示例

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

第十八讲:元注解之 Retention

元注解 - “标签的标签”

 

 

 

 

 

 

 

 

 

 代码示例

 

 

 

第十九讲:元注解之Documented

 

 

 

示例

 

 

 

 

 

 

 

 

 

 

 

 示例

 

 

 

 

 

 

 

 

 

第二十讲: @Target 和 @Inherited 

 

 

 

 

 

 示例

 

 

 

在 Person.java 中:

 

 

 

 

 

 

 

 

 

示例 

 

 

 

 

 

 

 

 

 

第二十一讲:@Repeatable 

 

 

 

 

 

 

 

================================================================================

 

 

 

 

 

 

 

Plus:

 

 

 

 

 

 

 

第二十二讲: 常见的预制注解

 

 

 

 

 第二十三讲:任务总结

1. 内部类

   概念,普通内部类,静态内部类,局部内部类,匿名内部类,回调模式

2. 枚举类型

   概念,自定义枚举类,enum关键字,继承Enum类,实现接口等

3. 注解

   概念,自定义注解,使用,元注解,预制注解等

posted @ 2021-02-04 11:22  Jasper2003  阅读(104)  评论(0编辑  收藏  举报