java基础之面向对象

本文详细介绍了Java中的面向对象编程思想,包括类与对象的概念,封装机制如JavaBean规范,构造方法的作用,以及继承的特点和重写与重载的区别。此外,讨论了多态性,抽象类的关键字`abstract`的用途,以及`final`关键字在成员变量、成员方法和类上的应用。最后,讲解了`static`关键字的作用,如静态变量、静态方法和静态代码块在类加载过程中的行为。
摘要由CSDN通过智能技术生成

面向对象

1.面向对象思想

面向对象是一种以对象为中心的编程思想,能让复杂问题简单化。当需要实现某个功能时,程序员不需要了解具体的实现过 程,只需要找一个具有该功能的对象来实现

2.类和对象

类:现实世界中某一种事物具有公共特征,将这些共同特征提取出来形成的一种概念叫做类

类和对象的关系:

​ 类是对一类事物的描述,是抽象的

​ 对象是一类事物的实例,是具体的。

​ 类是对象的模板,对象是类的实例

由类创建对象的过程叫做实例化

3.三大特征
3.1 封装:
3.1.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.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.1.2 构造方法作用
Student stu = new Student();
/*
构造方法作用:
	1. 提供数据类型,构造方法的名称要求必须是类名,JVM 会根据当前构造方法的名称 明确实例化对象的数据类型是哪一个,计算得到对应所需的内存空间
	2. 用于初始化类对象成员变量数据内容

new:
	1. 在内存堆区根据当前数据类型所需申请对应的内存空间
	2. 申请的内存空间进行数据擦除

new + 构造方法 是实例化对象的一种形式,也是最为基础的形式。
【工厂】
*/
3.2 继承
3.2.1 作用和相关特性

继承的作用:
基本作用:子类继承父类,代码可以得到复用。(这个不是重要的作用,是基本作用。)
主要(重要)作用:因为有了继承关系,才有了后期的方法覆盖和多态机制。

继承的相关特性

① B类继承A类,则称A类为超类(superclass)、父类、基类,
		B类则称为子类(subclass)、派生类、扩展类。
			class A{}
			class B extends A{}
			我们平时聊天说的比较多的是:父类和子类。
② java 中的继承只支持单继承,不支持多继承,C++中支持多继承,
这也是 java 体现简单性的一点,换句话说,java 中不允许这样写代码:
	class B extends A,C{ } 这是错误的。

③ 虽然 java 中不支持多继承,但有的时候会产生间接继承的效果,
例如:class C extends B,class B extends A,也就是说,C 直接继承 B,
其实 C 还间接继承 A。

④ java 中规定,子类继承父类,除构造方法不能继承之外,剩下都可以继承。
但是私有的属性无法在子类中直接访问。(父类中private修饰的不能在子类中
直接访问。可以通过间接的手段来访问。--getter setter方法访问)

⑤ java 中的类没有显示的继承任何类,则默认继承 Object类,Object类是 
java 语言提供的根类(老祖宗类),也就是说,一个对象与生俱来就有 
Object类型中所有的特征。

⑥ 继承也存在一些缺点,例如:CreditAccount 类继承 Account 类会导致它
们之间的耦合度非常高,Account 类发生改变之后会马上影响到 CreditAccount 类
3.2.2重写与重载的区别

重写方法 Override method

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

重载方法 Reload

同一个类,或者同一个接口内
重载方法要求
	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);
}

多态

4.abstract 关键字

abstract 关键字首当其冲是针对于方法的约束和修饰,增强方法后期的自主性。abstract 修饰的方法相当于制定了规则,主要是方法的参数**【入参】和返回值【出参】**,后续的子类或者实现类,可以根据实际的开发情况选择合理合适的方式完成代码实现,提升代码的可复用性和特征性。

对于程序员而言,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();
    }
}
3. final 关键字

final 可以修饰类,成员变量,成员方法,局部变量

3.1 final 修饰成员变量

final 修饰的成员变量要求必须进行初始化操作

【解决方案】

  1. 直接初始化赋值
  2. 【有参】数构造方法,实例化对象过程中初始化 final 修饰成员变量
  3. final 修饰的成员变量一旦被赋值无法二次修改
3.2 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 方法");
    }
    */
}


public class Demo2 {
    public static void main(String[] args) {
        new D().test();
    }
}
3.3 final 修饰类

final 修饰类没有子类
在开发中基本类型不允许继承重新定义/制定规则。
例如:
Java 中是 String 类,基本数据类型的包装类 Integer Float Double


final class  E {

}

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

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

public class Demo3 {
}
3.4 final 修饰局部变量

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

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;
    }
}
3.5 final 小面试题
class Person {
    public String name;
    public Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
}

/**
 * @author Anonymous 2023/2/24 10:58
 */
public class Demo5 {
    public static void main(String[] args) {
        final Person person = new Person("张三", 66);

        System.out.println(person.name);
        System.out.println(person.age);
        /*
        以下代码错误的是:
            person.age = 20;
            person.name = "李四";
            person = new Person();
        答案
            全错
            1 2 错 3 对 
            1 2 对 3 错 【正确答案】
            【注意】
                final 修饰引用数据类型变量,指向不可变,指向数据空间内容可变
             从底层逻辑分析,final 修饰的为引用数据类型变量,当前变量存储数据不可变,变量存储
             内容是一个【地址】,表示地址无法修改,但是对应地址指向的数据空间内容,没有被 final 
             修饰,可以修改数据内容。
         */
    }
}
3.6 final 使用总结
1. final 修饰类一般是架构中的底层核心代码,基本数据类型
2. final 修饰成员变量一般用于常量使用,并且在开发中大量存在,例如: 订单状态,用户状态,设备状态
3. final 修饰局部变量一般用于常量数据使用,同时是为了避免【生命周期问题】。
4. final 修饰成员方法是核心业务逻辑方法
4. static【重点 难点】
4.1 类加载【重点】

程序所需资源加载过程

游戏加载:
	在游戏开始之前,需要加载游戏的相关资源(地图,角色,角色皮肤,角色特效,网络情况...)。在游戏开始之前完成的工作。
	
类加载同理
	JVM 会根据当前程序运行所需,加载所有的类文件(.class 文件),程序准备阶段,并且在准备阶段过程中,会执行加载【static】修饰相关内容。

【核心】

三个重点:静态成员变量,静态成员方法,静态代码块

一个原则: 类加载过程中 static 修饰内容完成准备工作

【没有对象】

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

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);
    }
}
4.4 static 修饰静态代码块
4.4.1 补充知识点

代码块有三种形式

  1. 构造代码块【不多见】
  2. 局部代码块【已淘汰】
  3. 静态代码块【目前还有很大作用】

构造代码块

package com.qfedu.c_static;

/**
 * @author Anonymous 2023/2/24 15:13
 */
public class Demo3 {
    /*
     构造代码块
     Java 编译器在编译代码的过程中,会将构造代码块内容放入到每一个构造方法的【第一行】
     first statement
     */
    {
        System.out.println("构造代码块");
    }

    public Demo3() {
        System.out.println("无参数构造方法");
    }

    public Demo3(int num) {
        System.out.println(" int 参数构造方法");
    }

    public Demo3(String message) {
        System.out.println("String 参数构造方法");
    }

    public static void main(String[] args) {
        new Demo3();
        System.out.println();
        new Demo3(10);
        System.out.println();
        new Demo3("字符串");
        System.out.println();
    }
}

局部代码块

int num = 10;

/*
 局部代码块,利用 Java 局部变量特征,压缩局部变量生存空间。
 num2 作用范围和生命周期都在 大括号范围以内。
 提高内存的复用度,加快 GC 垃圾回收。
 */
{
    int num2 = 20;
}

System.out.println(num);
System.out.println(num2);
4.4.2 静态代码块特征
1. 静态代码块在类文件加载阶段一定执行!!!并且有且只执行一次。
2. 静态代码块可以调用类内的其他静态资源
3. 静态代码块不可以调用类内的非静态资源
4. 静态代码块一般用于程序初始化操作,预处理操作,项目运行前准备工作。
	案例:
		配置资源读取
		配置文件读取
		相关资源加载
/**
 * 静态代码块
 *
 * @author Anonymous 2023/2/24 15:41
 */
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();
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值