• 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. 注解

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

  • 相关阅读:
    eclipse环境:把jdk1.6 改 jdk1.7或jdk1.8(改回也可以)(图文详解)
    SVN 将文件还原到之前的指定版本
    用起来很方便的枚举扩展类
    VS2015新功能
    EasyUi 动态列
    基于EasyUi的快速开发框架
    深圳某保险公司招聘职位列表
    考勤系统之计算工作小时数
    考勤系统之状态管理
    第一次裁员
  • 原文地址:https://www.cnblogs.com/JasperZhao/p/14371617.html
Copyright © 2020-2023  润新知