Bootstrap

Java学习——面向对象基础

1. 面向对象的基本操作

  1. 类型设计
  2. 类对象实例化操作
  3. 类对象/类名调用方法操作,功能执行和数据操作【重点】
/**
 * 自定义的数组工具类
 *
 * @author Anonymous 2023/2/24 9:45
 */
public class MyArrayUtils {
    /**
     * 自定义方法,实现 int 类型数组数据展示功能
     *
     * @param arr int 类型数组
     */
    public static void printIntArray(int[] arr) {
        /*
        增强 for 循环
            for (int i = 0; i < arr.length; i++) {}
            for (int i : arr) {}

            for (当前数组/集合存储的数据类型 在循环中使用的临时变量 : 数组/集合)
                增强 for 循环自动遍历整个数组/集合,临时变量存储遍历数组对应的数据
         */
        for (int i : arr) {
            System.out.println(i);
        }
    }
}

public class Student<val> {
    private Integer id;
    private String name;
    private Integer age;
    private Boolean gender;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Boolean getGender() {
        return gender;
    }

    public void setGender(Boolean gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", gender=" + gender +
                '}';
    }
}

public class Demo1 {
    public static void main(String[] args) {
        // 实例化 Student 对象 【实体类 数据的载体】
        Student student = new Student();

        // 1. 利用方法对于 Student 对象数据存储进行修改和获取
        student.setId(1);
        student.setName("张三");
        student.setAge(66);
        student.setGender(false);

        System.out.println(student);

        System.out.println();
        System.out.println(student.getId());
        System.out.println(student.getName());
        System.out.println(student.getAge());
        System.out.println(student.getGender());
        System.out.println();

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

        // 通过类调用功能方法,实现目标功能
        MyArrayUtils.printIntArray(arr);
    }
}

2. 面向对象两大任务

1.数据的载体(人和马云)
2. 方法的载体(工具箱和扳手)

3. 面向对象三大特征

3.1 封装

JavaBean 规范实体类要求

  1. 要求所有成员变量全部 private 私有化修饰

  2. 必须提供所有成员变量对应的 getter and setter 方法

  3. 必须提供无参数构造方法

案例:

public class Student {
    // 私有化成员变量 Field
    private Integer id;
    private String name;
    private Integer age;
    // boolean 类型成员变量对应的 getter 方法是 is开头 ==> isGender
    // Boolean 包装类型还是 get 和 set 开头
    private boolean gender; //private Boolean gender;
   	
    
    // 构造方法 Constructor
    public Student() {}
    
    public Student(Integer id, String name, Integer age) {
        // this 关键字目前的作用是区分成员变量和参数变量
        // this 表示 new + 当前构造方法实例化的对象本身
        this.id = id;
        this.name = name;
        this.age = age;
    }
    
    // getter and setter
    public Integer getId() {
        return id;
    }
    
    public void setId(Integer id) {
        this.id = id;
    }
    ...
}
3.2 继承
3.2.1 基本格式和特征
class A extends B {

}
A 类是 B 类的一个子类
B 类是 A 类的唯一父类
    
/*
特征:
	1. 父类中非私有化成员(成员变量和成员方法)都可以继承给子类使用
	2. 父类中私有化成员子类无法获取
	3. 实例化子类对象会默认调用父类的无参数构造方法。
		父类构造方法是用于继承给子类数据内容对应内存空间初始化操作使用的方法。
		JVM 设计规则【先有父,再有子】
*/
3.2.2 重写方法

子类继承父类方法,父类方法无法满足子类的特征需求,可以进行重写操作。
重写操作要求:
1. 要求方法声明完全一致,包括返回值类型,方法名和形式参数列表
2. 权限修饰符子类权限必须大于等于父类
父类 public 子类允许 public
父类 protected 子类允许 public protected
3. 重写方法必须有 @Override 注解

3.2.3 重载方法

同一个类,或者同一个接口内
重载方法要求:
1. 方法名必须一致
2. 方法形式参数列表数据类型必须不同
3. 返回值类型无限制
4. 权限修饰符无限制

/*
方法重载 Reload
 */
public static void test(int num) {
    System.out.println(num);
}
public static void test(int num1, int num2) {
    System.out.println(num1 + num2);
}
private static void test(float num) {
    System.out.println(num);
}
3.3 多态

4. 权限修饰符的作用范围

publicprotectedprivate
同一包×
同一类
子孙类×
不同包××

5. 关键字

5.1 abstract

语法特征:

  1. abstract 修饰的方法有且只有方法声明,没有方法体
  2. abstract 修饰方法有且只能定义在 abstract 修饰的类内或者 interface 接口内
  3. 一个非 abstract 修饰类继承 abstract 类或者 遵从 interface 接口,要求实现在 abstract 类中或 interface 接口中有可能存在的 abstract 修饰方法。
  4. 阿里巴巴开发规约要求(AJCG) abstract 修饰的类推荐使用 Abstract 或者 Base 类名开头

代码示例:

/*
abstract 演示
 */
abstract class BaseTest {
    /**
     * abstract 修饰的成员方法,没有方法体
     */
    public abstract void test();
}

class A extends BaseTest {

    @Override
    public void test() {
        System.out.println("子类继承 abstract 类实现的 abstract 方法");
    }
}

/**
 * @author Anonymous 2023/2/24 10:24
 */
public class Demo3 {
    public static void main(String[] args) {
        /*
         匿名对象,可以用于调用不会重复使用的方法,或者作为其他方法的参数
         提高代码的执行效率和内存的使用效率
        */
        new A().test();

        /*
        正常操作
         */
        A a = new A();
        a.test();
    }
}
5.2 final
5.2.1 final修饰成员变量

final 修饰的成员变量要求必须进行初始化操作
【解决方案】

  1. 直接初始化赋值
  2. 有参数构造方法,实例化对象过程中初始化 final 修饰成员变量
  3. final 修饰的成员变量一旦被赋值无法二次修改
class A {
    /*
    Variable 'msg' might not have been initialized
    msg 变量可能尚未初始化
    【解决方案】
        1. 直接初始化赋值
        2. 【有参】数构造方法,实例化对象过程中初始化 final 修饰成员变量
     */
    public final String msg = "直接赋值 final 修饰成员变量";
}

class B {
    public final String info;

    /**
     * 当前类有且只有有参数构造方法,并且当前有参数构造方法参数内容
     * 是给予当前类内 final 修饰的成员变量 info 进行初始化赋值操作
     * 可以满足在用户使用 info 之前可以已经赋值准备好对应的数据内容。
     *
     * @param info 赋值 final 修饰成员变量对应的参数
     */
    public B(String info) {
        this.info = info;
    }
}

/**
 * @author Anonymous 2023/2/24 10:32
 */
public class Demo1 {
    public static void main(String[] args) {

        A a = new A();
        // final 修饰的成员变量无法进行二次赋值操作。
        // a.msg = "测试";
        System.out.println(a.msg);

        B b = new B("通过有参构造方法赋值 final 修饰成员变量");
        System.out.println(b.info);
    }
}

5.2.1 final修饰成员方法

final 修饰成员方法不允许被子类重写
一般用于框架,业务核心代码内容修饰,不允许修改/重写代码内容

class C {
    public final void test() {
        System.out.println("C 类 test 成员方法");
    }
}

class D extends C {
    /*
    'test()' cannot override 'test()' in 'com.qfedu.b_final.C'; overridden method is final

    final 修饰的成员方法,子类不允许重写。
        一般用于框架,业务核心代码内容修饰,不允许修改/重写代码内容

    @Override
    public void test() {
        System.out.println("D 类继承 C 类重写 test 方法");
    }
    */
}

/**
 * @author Anonymous 2023/2/24 10:44
 */
public class Demo2 {
    public static void main(String[] args) {
        new D().test();
    }
}

5.2.1 final修饰类

final 修饰类没有子类
在开发中基本类型不允许继承重新定义/制定规则。

final class  E {

}

/*
Cannot inherit from final 'com.qfedu.b_final.E'
不能继承一个 final 修饰类
final 修饰类没有子类
   在开发中基本类型不允许继承重新定义/制定规则。
   例如:
        Java 中是 String 类,基本数据类型的包装类 Integer Float Double

 */
//class F extends E {
//
//}

/**
 * @author Anonymous 2023/2/24 10:50
 */
public class Demo3 {
}
5.2.1 final修饰局部变量

final 修饰的局部变量首次赋值允许,后期不允许二次赋值

/**
 * @author Anonymous 2023/2/24 10:54
 */
public class Demo4 {
    public static void main(String[] args) {
        final int num ;
        /*
        final 修饰的局部变量,【首次】赋值没有任何的问题
            1. 定义时候初始化
            2. 后期代码赋值
         */
        num = 10;
        System.out.println(num);

        /*
        Cannot assign a value to final variable 'num'
        不能重新赋值一个 final 修饰的局部变量(local variable) num
         */
        num = 20;
    }
}
5.3 static
5.3.1 类加载

游戏加载:
在游戏开始之前,需要加载游戏的相关资源(地图,角色,角色皮肤,角色特效,网络情况…)。在游戏开始之前完成的工作。

类加载同理:
JVM 会根据当前程序运行所需,加载所有的类文件(.class 文件),程序准备阶段,并且在准备阶段过程中,会执行加载【static】修饰相关内容。

核心:
三个重点:静态成员变量,静态成员方法,静态代码块
一个原则: 类加载过程中 static 修饰内容完成准备工作

5.3.2 static 修饰静态变量

语法特征:
1. static 修饰的静态成员变量在内存的【数据区】
2. static 修饰的静态成员变量在整个代码的运行周期中有且只有一个。
3. static 修饰的静态成员变量在类文件加载阶段,需要准备就绪,已具备数据提供能力和数据存储能力。
4. static 修饰的静态成员变量别名【类变量】,语法建议直接通过类名操作
例如:
Integer.MAX_VALUE ==> public static final int MAX_VALUE = 0x7FFFFFFF;
5. 【使用建议】
静态成员变量最好不要和类对象有相关性。
静态成员变量生命周期从类加载开始到程序结果
类对象是从实例化对象开始,到 JVM GC 回收结束
可以实例化对象相当于程序开始运行,晚于静态成员变量加载
GC 收回是在程序退出之前,完成内存收回工作之后,静态成员变量销毁。

package com.qfedu.c_static;

class A {
    /*
    static 修饰静态成员变量
     */
    public static int num = 10;
}

/**
 * @author Anonymous 2023/2/24 11:49
 */
public class Demo1 {
    public static void main(String[] args) {
        // 通过类名可以直接调用当前静态成员变量
        System.out.println(A.num);

        // 当前情况下,匿名对象生命周期有且只在当前行,超出对象销毁
        new A();

        /*
        Static member 'com.qfedu.c_static.A.num' accessed via instance reference
        【警告】
            static 修饰的静态内存,通过实例化对象引用,IDE(Eclipse IDEA MyEclipse) 工具不建议

         */
        System.out.println(new A().num);

        // 对象已销毁,但是静态成员变量依然可以通过类名直接调用。
        System.out.println(A.num);
    }
}
5.3.3 static 修饰静态成员方法

语法特征:
1. 静态成员方法使用 static 修饰
2. static 修饰的静态成员方法不允许使用类内的【非静态成员】
static 修饰的静态成员方法在类文件加载阶段已具备执行能力,方法内有非静态相关内容,无法执行,因为
非静态成员需要实例化对象调用操作,加载过程中没有相关的对象存在。
3. static 修饰的静态成员方法可以直接使用类内的其他静态资源。
4. 静态成员方法常用于【工具类】方法封装
静态成员方法是可以通过类名直接调用,可以摆脱类对象的限制,执行效率较高。无需考虑对象实例化过程,以及销毁对象过程的时间和内存空间的占用浪费。
5. 静态成员方法推荐使用类名直接调用,也可以称之为【类方法】

import java.util.Arrays;

class MyArrayUtils {
    int num = 10;

    static int test = 10;

    public void test() {
        System.out.println("测试");
    }

    /**
     * 静态成员方法,降序 int 数据类型选择排序
     *
     * @param arr int 类型数组
     */
    public static void selectSortDesc(int[] arr) {
        /*
        Non-static field 'num' cannot be referenced from a static context
        static 修饰静态内容不可以引用非静态成员变量
         */
        //System.out.println(num);
        // 难兄难弟,互不嫌弃
        System.out.println(test);

        /*
        Non-static method 'test()' cannot be referenced from a static context
        static 修饰静态内容不可以引用非静态成员方法
         */
//        test();

        if (null == arr || 0 == arr.length) {
            return;
        }

        for (int i = 0; i < arr.length - 1; i++) {
            int index = i;

            for (int j = i + 1; j < arr.length; j++) {
                if (arr[index] < arr[j]) {
                    index = j;
                }
            }

            if (index != i) {
                int temp = arr[index];
                arr[index] = arr[i];
                arr[i] = temp;
            }
        }

        showArray(arr);
    }

    public static void showArray(int[] arr) {
        System.out.println(Arrays.toString(arr));
    }
}

/**
 * @author Anonymous 2023/2/24 14:50
 */
public class Demo2 {
    public static void main(String[] args) {
        int[] arr = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};

        // 直接通过类名调用静态成员方法
        MyArrayUtils.selectSortDesc(arr);
        MyArrayUtils.showArray(arr);
    }
}
5.3.4 static 修饰静态代码块
  1. 静态代码块在类文件加载阶段一定执行!!!并且有且只执行一次。
  2. 静态代码块可以调用类内的其他静态资源
  3. 静态代码块不可以调用类内的非静态资源
  4. 静态代码块一般用于程序初始化操作,预处理操作,项目运行前准备工作。
    案例:
    配置资源读取
    配置文件读取
    相关资源加载
public class Demo4 {

    public int num = 10;
    public static String msg = "测试";

    // 静态代码块
    static {
        /*
        Non-static field 'num' cannot be referenced from a static context
        不可以在一个静态区域中引用非静态成员变量
        System.out.println(num);
         */
        System.out.println(msg);
        staticMethod();
        /*
        Non-static method 'test()' cannot be referenced from a static context
        不可以在一个静态区域中引用非静态成员方法
        test();
         */

        System.out.println("静态代码块资源");
    }

    public void test() {
        System.out.println("非静态成员方法");
    }

    public static void staticMethod() {
        System.out.println("静态成员方法");
    }

    public static void main(String[] args) {
        Class cls = Demo4.class;

        new Demo4();
        new Demo4();
        new Demo4();
        new Demo4();
        new Demo4();
        new Demo4();
        new Demo4();
        new Demo4();
        new Demo4();
    }

}
;