首页 > 编程语言 >【Java难点解析-9】static

【Java难点解析-9】static

时间:2025-01-08 11:28:41浏览次数:3  
标签:count 难点 Java 变量 子类 实例 static 抽象类 方法

在 Java 中,abstract 关键字用于定义抽象类和抽象方法。抽象类和抽象方法是 Java 中实现抽象化的机制,旨在让开发者通过继承来实现特定的功能,同时隐藏不需要关心的实现细节。

1. 抽象类(Abstract Class)

抽象类是不能被实例化的类。它可以包含抽象方法(没有实现的方法)以及普通方法(有实现的方法)。抽象类的目的是为了提供一个基类,供其他类继承,并在此基础上完成具体的实现。

语法:

abstract class MyAbstractClass {
    // 普通成员变量
    int x;
    
    // 构造方法
    public MyAbstractClass(int x) {
        this.x = x;
    }

    // 普通方法(有实现)
    public void printX() {
        System.out.println("Value of x: " + x);
    }

    // 抽象方法(没有实现)
    abstract void myAbstractMethod();
}

2. 抽象方法(Abstract Method)

抽象方法是没有实现的方法,它只声明了方法的签名(方法名、返回类型、参数类型等),但没有提供具体的实现。抽象方法必须出现在抽象类中,而不能在普通类中出现。

语法:

abstract class MyAbstractClass {
    abstract void myAbstractMethod();
}

3. 继承抽象类

当一个类继承抽象类时,它必须实现所有的抽象方法,除非它本身也声明为抽象类。否则,这个子类也会变成抽象类。

示例:

abstract class Animal {
    abstract void sound();  // 抽象方法

    public void sleep() {  // 普通方法
        System.out.println("This animal is sleeping.");
    }
}

class Dog extends Animal {
    // 实现抽象方法
    @Override
    void sound() {
        System.out.println("Bark");
    }
}

class Cat extends Animal {
    // 实现抽象方法
    @Override
    void sound() {
        System.out.println("Meow");
    }
}

public class TestAbstract {
    public static void main(String[] args) {
        Animal dog = new Dog();
        dog.sound();  // 输出: Bark
        dog.sleep();  // 输出: This animal is sleeping.

        Animal cat = new Cat();
        cat.sound();  // 输出: Meow
        cat.sleep();  // 输出: This animal is sleeping.
    }
}

在这个例子中,Animal 是一个抽象类,包含了一个抽象方法 sound() 和一个普通方法 sleep()DogCat 类继承自 Animal,并实现了 sound() 方法。

4. 抽象类的特点

  • 不能实例化: 你不能直接创建一个抽象类的实例,必须通过其子类来实例化。

  • 可以有构造方法: 抽象类可以有构造方法,这些构造方法可以由子类调用。

  • 可以有普通方法: 抽象类不仅可以包含抽象方法,还可以包含具体的方法,即已实现的方法。

  • 可以有成员变量: 抽象类可以定义成员变量,并且可以对其进行初始化。

  • 可以继承多个接口,但只能继承一个类: 一个抽象类可以实现多个接口,但只能继承一个类(无论是普通类还是抽象类)。

5. 为什么使用抽象类

  1. 提供通用模板: 抽象类允许在子类中共享通用行为,同时让子类实现具体的细节。

  2. 防止实例化: 如果某个类无法有完整的实现,或者只是为了提供基础结构,使用抽象类可以防止被错误地实例化。

  3. 实现多态: 抽象类能够通过继承为子类提供统一的接口,使得程序更具可扩展性。子类可以以不同的方式实现抽象类的方法,从而实现多态。

  4. 代码复用: 抽象类可以包含普通方法,这些方法可以在所有子类中共享,从而减少代码重复。

6. 抽象类与接口的区别

虽然抽象类和接口都有类似的作用,都是为了实现某些抽象行为的定义,但它们之间有一些重要的区别:

特性抽象类(Abstract Class)接口(Interface)
方法可以包含抽象方法和普通方法所有方法默认是抽象方法(Java 8 之后可以有默认方法)
字段可以有实例字段(成员变量)所有字段默认是 public static final 常量
继承方式类只能继承一个抽象类(单继承)类可以实现多个接口(多重继承)
构造方法可以有构造方法不能有构造方法
实现子类必须实现所有抽象方法,除非子类本身也是抽象类子类必须实现所有接口中的方法
使用场景更适用于提供一个公共基类,并允许共享代码实现更适用于定义契约(行为规范),各类可以不同实现

7. 抽象类的应用场景

  • 设计模板方法模式: 通过抽象类定义框架,具体步骤在子类中实现。例如,在处理文件读取、数据处理等流程时,抽象类可以提供步骤框架,具体实现由子类负责。

  • 实现代码复用: 在多个子类之间共享代码和行为。抽象类可以提供一些已实现的方法,子类可以继承这些方法,减少代码重复。

  • 提供标准接口: 如果你有一组类需要提供统一的接口(比如实现一些特定的算法),你可以通过抽象类来强制子类实现这些接口。


总结

2. 内存分配

3. 生命周期

4. 访问方式

5. 访问范围

6. 默认值

7. 示例代码

类变量示例:

class Counter {
    static int count = 0;  // 类变量

    Counter() {
        count++;  // 每创建一个实例,count 值增加
    }
}

public class TestClassVariable {
    public static void main(String[] args) {
        Counter obj1 = new Counter();
        Counter obj2 = new Counter();
        Counter obj3 = new Counter();
        
        System.out.println("Count: " + Counter.count);  // 输出: 3
    }
}

在此例中,count 是类变量,它记录了 Counter 类的实例化次数。obj1obj2obj3 实际上共享同一个 count 变量,所以它们的修改会影响同一个值。

实例变量示例:

class Counter {
    int count = 0;  // 实例变量

    Counter() {
        count++;  // 每创建一个实例,count 值增加
    }
}

public class TestInstanceVariable {
    public static void main(String[] args) {
        Counter obj1 = new Counter();
        Counter obj2 = new Counter();
        Counter obj3 = new Counter();

        System.out.println("obj1 count: " + obj1.count);  // 输出: 1
        System.out.println("obj2 count: " + obj2.count);  // 输出: 1
        System.out.println("obj3 count: " + obj3.count);  // 输出: 1
    }
}

在此例中,count 是实例变量,每个对象 obj1obj2obj3 都有自己的 count 变量,因此它们的值互不影响。

8. 主要区别总结

特性类变量 (Static Variable)实例变量 (Instance Variable)
定义使用 static 修饰的变量,属于类而非实例没有 static 修饰的变量,属于类的实例
内存分配存储在方法区,所有实例共享一份数据存储在堆内存中,每个对象有一份独立副本
生命周期类加载时初始化,类卸载时销毁对象创建时初始化,对象销毁时销毁
访问方式可以通过类名或对象访问,但推荐通过类名访问必须通过对象访问
默认值自动初始化为默认值(如 0falsenull自动初始化为默认值(如 0falsenull
作用范围类的所有实例共享,修改一个实例的类变量会影响所有实例每个对象实例有自己独立的副本,互不影响

9. 何时使用类变量和实例变量

通过理解类变量和实例变量的差异,你可以根据需求来决定如何定义和使用这些变量。

  • 抽象类 是一种特殊的类,它不能直接实例化,可以包含抽象方法和普通方法,通常用于作为基类提供通用的行为和属性。
  • 抽象方法 是没有实现的方法,它只提供方法签名,由子类来实现具体的功能。
  • 使用抽象类可以帮助我们提供代码的复用、封装通用行为,并确保子类实现特定的功能。
  • 在 Java 中,类变量static 变量)和 实例变量(普通变量)是类中的两种主要成员变量。它们在内存中的分配、生命周期和访问方式上有很大的区别。以下是两者的详细比较:

    1. 定义和声明

  • 类变量(Static Variable)

    • 使用 static 关键字修饰的变量,属于类,而不属于任何一个具体的对象。
    • 所有类的实例共享同一个类变量。
  • 实例变量(Instance Variable)

    • 没有 static 修饰符的变量,属于对象(实例)。
    • 每个对象有自己独立的实例变量副本。
  • 类变量:

    • 类变量存储在 方法区(或称为类的静态存储区)中。
    • 无论创建多少个对象,类变量只有一份,所有对象共享同一份内存。
  • 实例变量:

    • 实例变量存储在 堆内存 中,每个对象都有一份独立的副本。
    • 每个对象的实例变量是不同的,每个对象创建时都会在堆内存中分配内存空间来存储这些实例变量。
  • 类变量:

    • 类变量随着类的加载而被初始化,并且在类加载时就存在,直到类卸载为止。
    • 无论多少个对象实例化,类变量都只会被初始化一次。
  • 实例变量:

    • 实例变量随着对象的创建而被初始化,随着对象的销毁而释放。
    • 每个对象都有自己独立的实例变量副本,当对象被销毁时,这些实例变量会被释放。
  • 类变量:

    • 类变量可以通过类名直接访问,无需创建类的实例。
    • 也可以通过对象访问,但这种方式不推荐,因为类变量是属于类的,应该通过类名来访问。

    示例:

    class MyClass {
        static int count = 0;  // 类变量
    }
    
    public class Test {
        public static void main(String[] args) {
            System.out.println(MyClass.count);  // 通过类名访问类变量
        }
    }
    
  • 实例变量:

    • 实例变量必须通过对象来访问,因为每个对象有自己的实例变量。

    示例:

    class MyClass {
        int count = 0;  // 实例变量
    }
    
    public class Test {
        public static void main(String[] args) {
            MyClass obj1 = new MyClass();
            obj1.count = 5;  // 通过对象访问实例变量
            System.out.println(obj1.count);
        }
    }
    
  • 类变量:
    • 类变量对所有对象实例都是共享的。如果一个对象修改了类变量的值,其他对象的类变量值也会被修改。
  • 实例变量:
    • 实例变量在每个对象中都是独立的。一个对象修改了实例变量的值,其他对象的实例变量不受影响。
  • 类变量:

    • 类变量在类加载时会自动初始化为默认值。例如,数值类型为 0,布尔类型为 false,引用类型为 null
  • 实例变量:

    • 实例变量也会在对象创建时被初始化为默认值,但只有当对象被创建并且实例化时,实例变量才会获得这些值。
  • 使用类变量
    • 当你需要共享一个变量的值,所有类的实例都应该访问同一个变量时,使用类变量。比如计数器、常量等。
  • 使用实例变量
    • 当你希望每个对象实例有独立的数据时,使用实例变量。比如每个对象的属性、状态等。

标签:count,难点,Java,变量,子类,实例,static,抽象类,方法
From: https://blog.csdn.net/m0_69378371/article/details/144998835

相关文章

  • java 服务cpu 100%解决
    online环境发现有个task的微服务白天使用高峰期一直cpu非常高98%-99%用 如下命令在cpu非常高的时候生成了多个dump文件jstack<PID>>thread_dump1.txtjstack<PID>>thread_dump2.txtjstack<PID>>thread_dump3.txtjstack<PID>>thread_dump4.txtjstack<PID>......
  • 【Java】自定义字符串方法——根据开始和结束字符串,截取字符串
    1/**2*根据开始和结束字符串,截取字符串3*@paramstr被截取的字符串4*@paramstartStr起始字符串(最后一次出现的起始值)5*@paramendStr结束字符串(最后一次出现的结束值)6*@return7*/8publicstaticStringsubstring(Stringstr,Stringstar......
  • java中反射的基本使用
    一、参考文档:https://www.cnblogs.com/chanshuyi/p/head_first_of_reflection.htmlchatgpt问答 二、前言反射是java的一个特性,是java提供的一种机制。反射允许程序在运行时查询和操作类的信息。反射对很多高级功能(框架设计、动态代理等)都很有用。反射提供了很多......
  • Java实现回文排列问题的探讨
    Java实现回文排列问题的探讨在编程的世界里,解决一个具体问题往往有多种方法,而选择合适的方法不仅能提高代码的效率,还能让代码更加优雅易懂。今天,我们就来探讨一下如何使用Java语言来解决一个有趣的问题——回文排列问题。问题描述回文排列问题源自LeetCode的第266题,它要求我们......
  • Java中将特征向量转换为矩阵的实现
    哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。  我是一名后端开发爱好者......
  • Java实现《七星传说》游戏开发详解
    哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。  我是一名后端开发爱好者......
  • JAVA线程池有哪些队列? 以及它们的适用场景案例
    大家好,我是V哥。在高并发应用场景下,线程池的使用是必然的,那在线程中的队列都有哪些呢?下面V哥整理的几种常见的线程池队列以及适用场景案例,分享给大家。线程池中的队列主要用于存放等待执行的任务,以下是几种常见的线程池队列:1.无界队列(UnboundedQueue)LinkedBlockingQueue......
  • “Java岗八股文”2025版史上最新最全超详细易理解,面试必备(一)Spring篇
    Spring篇文章目录Spring篇1、Spring框架中的单例bean是线程安全的吗?2、什么是AOP,你们项目中有没有使用到AOP?3、Spring中的事务是如何实现的?4、什么是AOP5、你们项目中有没有使用到AOP6、Spring中的事务是如何实现的7、Spring中事务失效的场景有哪些8、Spring的bean的生......
  • JavaWeb—Servlet详解
    前言:        本章节主要学习Servlet基础知识点,收录于JavaWeb系列,该系列主要讲解Servlet、JSP、Filter过滤器、Session、分层开发概念等知识点,欢迎童鞋们互相交流。觉得不错可以三连订阅喔。 目标:一、概念二、入门程序        1.创建Servlet类    ......
  • 理解JAVA封装.继承.多态
    JAVA面向对象的三大特征:封装,继承,多态。1.封装(1)封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现的细节,仅通过公开的接口和对象交互。封装使类成为一个具有内部属性的有隐藏功能的代码模块。通俗的理解就是将类内部的一些属性和方法隐藏起来,屏蔽细节。(2)JAVA中......