【面向对象扩展篇】详细介绍并编码实现static静态成员、静态代码块、静态导入,abstract(抽象),interface(接口)、implements(实现)及四种内部类【萌新友好版】

一、static静态成员、静态代码块、静态导入

static(静态成员:静态变量、静态方法):

package com.oop.demo07;

/*
    被static修饰的成员均为静态成员。静态成员均属于类,而非对象。
    静态成员和类一起加载(JVM加载class文件时)初始化,存储在堆中的方法区。
    生命周期与类相同,从类加载到JVM卸载。
 */

// static :
public class Student {
    private static int age;  // 静态变量(类变量)。属于类而非对象,所有实例共享同一个静态变量。在类加载时初始化,内存中只有一份拷贝。常用于共享数据或常量。
    private double score;  // 实例变量--对象级别。每个对象独立拥有。

    public void run(){
        go();
    }
    public static void go(){  // 静态方法: 只能访问静态成员(变量、方法)。不能使用this或super关键字。
        
    }

    public static void main(String[] args) {
        Student s1 = new Student();

        System.out.println(Student.age);  // 0。对于static静态变量,建议使用类名访问
        System.out.println(new Student().age);  // 不推荐用对象访问静态变量
        System.out.println(s1.age);  // 0
        System.out.println(s1.score);  // 0.0

        new Student().run();  // 创建匿名对象并调用方法。 对象.方法。

        Student.go();  // 静态方法推荐用类名调用
        go();  // 在同一个类中可以直接调用。静态成员【也叫静态属性】(包括静态变量、静态方法)可直接调用。
    }
}

匿名代码块、静态代码块:

package com.oop.demo07;

public class Person {
    {
        // 匿名代码块(实例初始化块): 用于对象初始化,可替代多个构造方法的公共代码。
        System.out.println("匿名代码块");  // 2. 每次创建对象时都会(自动)执行,在构造方法之前执行。可以有多个,按定义顺序执行。
    }
    static {  // 静态代码块: 用于初始化静态资源(如加载配置文件、静态变量)
        System.out.println("静态代码块");  // 1. 静态代码块在类加载时执行,且只执行一次。执行顺序优先于任何其他代码块和构造方法。
    }
    public Person() {
        System.out.println("构造方法");  // 3.
    }

    public static void main(String[] args) {
        System.out.println("=============================================");  // 这一句上面还会调用并输出静态代码块,因为它是和类一起加载的。
        Person person1 = new Person();  // 输出: 匿名代码块     构造方法
        System.out.println("=============================================");
        Person person2 = new Person();  // 输出: 匿名代码块     构造方法
    }
}

static静态导入:

package com.oop.demo07;

import static java.lang.Math.*;  // 静态导入Math类的所有静态成员。
import static java.lang.Math.random;  // 静态导入方法。导入java.lang包下的Math数学工具类中的random方法。可在调用该方法时无需带类名直接调用。
import static java.lang.Math.PI;  // 静态导入常量

public final class Test {  // 通过final修饰的类不能被继承,也就不会有子类。

    public static void main(String[] args) {
        System.out.println(Math.random());  // Math.random() : 生成[0.0,1.0)之间double类型的随机数
        System.out.println(random());  // 等价于上面的调用。
        System.out.println(PI);
        System.out.println(Math.PI);  // PI -- double类型的圆周率常量
    }
}

二、abstract抽象类、抽象方法

在这里插入图片描述

抽象类、抽象方法:

package com.oop.demo08;

// abstract : 定义抽象类和抽象方法的关键字。
public abstract class Action {  // 被abstract修饰的类不能实例化(不能被new),可以包含抽象方法和具体方法。主要用于继承。
    public abstract void doSometing();  // 抽象方法 : 只有声明没有实现,子类必须实现(除非子类也是抽象类)。

    /* 抽象类的约束:
       对子类的强制要求(必须实现所有抽象方法)。
       对抽象类的使用限制(不能直接实例化)。
       对代码结构的规范。
     */

    /* 抽象类的意义:
       提取多个类的共性。抽象类用于定义共性行为模板。
       子类可实现差异化行为,需要定义一些公共方法但又希望部分方法由子类决定时。
       作为框架的基础类。
       实现多态基础。
     */

    // 知识小点: 抽象类不可以被new创建对象,实例化。但是可以有构造器,子类实例化时会调用父类(抽象类)的构造器。
}

(实现抽象类的)子类:

package com.oop.demo08;

// 抽象类中的方法,由继承它的子类来实现其所有抽象方法。除非该子类也是一个抽象类,那么由具体子类去实现。
public class A extends Action{  //
    @Override  // 重写
    public void doSometing() {

    }
}

三、interface接口、implements实现

在这里插入图片描述

如图:

在这里插入图片描述

UserService(接口):

package com.oop.demo09;

// 接口定义关键字: interface。  接口都需要有实现类
public interface UserService {  // 一般在接口中定义方法然后通过约束(实现类)来实现它。
    public static final int AGE = 99;  // 接口中的属性,默认为 public static final 【公共静态常量】(一般不建议在接口中定义常量)

    public abstract void run(String name);  // 接口中的方法声明,类型默认为 public abstract。接口方法默认是抽象的(abstract)。
    void run1(String name);

    void add();
    void delete();
    void update();
    void query();
}

TimeService(接口):

package com.oop.demo09;

public interface TimeService {
    void timer();
}

UserServiceImpl(实现接口)类:

package com.oop.demo09;

// 抽象类 : extends--单继承
/* 接口实现类:
   1. 使用 implements(实现) 关键字来实现接口
   2. 必须(重写)实现所有接口方法(除非自身是抽象类)
   3. 可以实现多个接口(伪多继承)
   4. 命名规范: 实现类通常以Impl结尾
 */
public class UserServiceImpl implements UserService,TimeService{
    @Override
    public void run(String name) {

    }

    @Override
    public void run1(String name) {

    }

    @Override
    public void add() {

    }

    @Override
    public void delete() {

    }

    @Override
    public void update() {

    }

    @Override
    public void query() {

    }

    @Override
    public void timer() {

    }
}

JDK8后接口中的默认方法、静态方法:

package com.oop.demo09;

public interface ModernInterface {  // JDK8以后,接口中可以有默认方法和静态方法。
    void abstractMethod();  // 1. 抽象方法(接口方法),隐式默认为 public abstract 类型。子类必须实现。

    // 2. 默认方法(Java 8+)。用default修饰,子类可直接继承或重写。作用:解决接口新增方法时的向后兼容问题。在不破坏现有代码的前提下,扩展接口功能。
    default void defaultMethod() {
        System.out.println("默认方法");
//        privateMethod();  // 调用私有方法
    }

    // 3. 静态方法(Java 8+)。用static修饰,(子类)可直接通过接口名调用。目的: 提供工具方法,避免额外的工具类。
    static void staticMethod() {
        System.out.println("静态方法");
    }

    // 4. 私有方法(Java 9+)。用private修饰,仅在接口内部被默认方法或静态方法调用。目的: 提取接口中重复的代码逻辑(代码复用),提高内聚性。
//    private void privateMethod() {
//        System.out.println("私有方法");
//    }
}

抽象类与接口不同的关键点:

抽象类接口
构造方法
设计理念“是什么”(is–关系)“能做什么”(has–a / can–do关系)
使用场景提取多个相关类的共性定义不相关类共有的行为

接口定义行为,抽象类共享代码。

接口作用:实现多态和解耦。

四、内部类

在这里插入图片描述

如图:

在这里插入图片描述

非静态内部类、静态内部类、局部内部类:

package com.oop.demo10;

public class Outer {
    private int id = 10;  // 外部类私有属性
    public void out(){
        System.out.println("这是外部类的方法");
    }

    /*
       成员内部类(非静态内部类):
       1. 可以访问外部类的所有成员(包括private私有成员)
       2. 不能有静态成员(除非是final常量)
       3. 必须先有外部类实例才能创建内部类实例
     */

    public class Inner{  // 成员内部类
        public void in(){
            System.out.println("这是内部类的方法");
            }
        public void getID(){
            System.out.println(id);

            // 内部类中访问外部类实例的两种方式:
            System.out.println("外部类引用方式1: " + Outer.this.id);  // 成员内部类隐式持有外部类实例的引用(即Outer.this机制):
            System.out.println("外部类引用方式2: " + Outer.this);  // 当创建成员内部类实例时,它自动持有创建它的外部类实例的引用。Outer.this:java的特殊语法,表示:当前内部类关联的外部类实例
        }

        /*
           静态内部类
           1. 不依赖外部类实例,可以直接创建
           2. 不能直接访问外部类的非静态成员
           3. 可以有静态和非静态成员
         */
    }public static class Inner1{  // 静态内部类: 静态内部类不会持有外部类实例的引用
        public void in(){
            System.out.println("这是静态内部类的方法");
            }
    }

    /*
       局部内部类(方法内部类)
       1. 定义在方法或作用域内
       2. 只能在该方法或作用域内使用
       3. 该类不能有访问修饰符(public/private等)
       4. 可以访问外部类所有成员,但只能访问所在方法中的final或有效final局部变(即该方法中初始化后不再修改的局部变量)
    */

    public void method(){

        final String localVar = "局部变量";
        class Inner{  // 局部内部类,和局部变量差不多,外部无法访问
            public void in(){
                System.out.println("访问外部类私有id: " + id);
                System.out.println("访问局部变量: " + localVar);  // 只能访问所在方法中的final或有效final的局部变量
            }
        }
        // 在方法内部使用局部内部类
        Inner inner = new Inner();
        inner.in();
    }
}

class A{
    public static void main(String[] args) {  // 同一个文件中的其他类(不是内部类)。java文件中允许有多个类,但只能有一个public类。

    }
}

匿名内部类:

package com.oop.demo10;

/*
    匿名内部类是没有名字的内部类,它同时完成类的定义和实例化。
    通常用于只需要使用一次的类实现,比如事件监听器、线程创建等场景。
    可以是实现接口或继承父类的形式。
 */

public class Test {
    public static void main(String[] args) {

        // 创建一个Apple对象并立即调用其eat方法,但不保留对象引用
        new Apple().eat();  // 1. 匿名对象的创建和使用

        // 2. 匿名内部类的使用(接口实现)
        // 直接创建并实现UserService接口,不定义具体类名。适合一次性使用。
        new UserService(){  // 匿名内部类: 匿名内部类会隐式持有外部类的引用(如果是非静态上下文)
            @Override
            public void hello() {
                System.out.println("hello");
            }
        };

        // 3. 将匿名内部类赋值给接口变量
        // 这种形式允许我们后续通过变量名调用匿名内部类的方法,适合多次调用。
        UserService userService = new UserService(){  // 也是匿名内部类
            @Override
            public void hello() {
                System.out.println("Hello");
            }
        };

        userService.hello();  // 调用匿名内部类的方法
    }
}
class Apple{
    public void eat(){
        System.out.println("eat");
    }
}

interface UserService{
    void hello();
}

成员内部类(非静态内部类)的创建:

package com.oop.demo10;

public class Application {
    public static void main(String[] args) {

        // 成员内部类的使用:
        Outer outer = new Outer();  // 1、必须先创建外部类实例

        // 通过外部类来实例化内部类
        Outer.Inner inner = outer.new Inner();  // 2、成员内部类的声明创建。创建的Inner实例会自动持有outer的引用(即Outer.this)。
        inner.in();
        inner.getID();

        Outer.Inner1 inner1 = new Outer.Inner1();  // 静态内部类不需要外部类实例,可直接创建
        inner1.in();

        outer.method();  // 方法内部会创建和使用局部内部类
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值