java 类与对象-静态方法和实例方法区别,静态代码块、静态嵌套(内部)类

对象是类的实例化

静态方法

·  调用方式:

静态方法通过类名直接调用,如 ClassName.staticMethod()。

实例方法通过对象实例调用,如 object.instanceMethod()。

·  访问权限:

静态方法可以访问类的静态成员(静态变量和静态方法),但不能直接访问类的非静态成员(实例变量和实例方法)。

实例方法可以直接访问类的静态和非静态成员。

·  内存分配:

静态方法在类加载时被加载到内存中,不依赖于类的实例化对象。

实例方法需要在对象实例化后才能调用

示例

public class Example {
    // 静态变量
    static int staticVar = 10;
    
    // 实例变量
    int instanceVar = 20;

    // 静态方法
    public static void staticMethod() {
        // 可以访问静态变量
        System.out.println("静态变量 staticVar: " + staticVar);
        
        // 无法直接访问实例变量或实例方法
        // System.out.println("实例变量 instanceVar: " + instanceVar);  // 错误,静态方法无法直接访问实例变量

        // 无法直接调用实例方法
        // instanceMethod();  // 错误,静态方法无法直接调用实例方法
    }

    // 实例方法
    public void instanceMethod() {
        // 可以访问静态变量
        System.out.println("静态变量 staticVar: " + staticVar);
        
        // 可以访问实例变量
        System.out.println("实例变量 instanceVar: " + instanceVar);
        
        // 可以调用静态方法
        staticMethod();
    }

    public static void main(String[] args) {
        // 通过类名调用静态方法
        Example.staticMethod();
        
        // 创建实例对象
        Example example = new Example();
        
        // 通过对象调用实例方法
        example.instanceMethod();
    }
}

简单点说,

类就好比于一个模板,对象就是根据模板制造的器物,静态变量和静态方式是属于模板的,不依赖于器物。静态变量和静态方式是被所有对象所共享的,修改静态变量和静态方法,所有的对象都会发生相应的变化。

但是,是可以通过实例来修改静态变量的值的,但是这种修改影响的不只是这一个对象,影响的是根据这个类实例化出来的所有的对象。不建议这样操作。

静态代码块

是用于在类加载时执行的一段代码,主要用于在类加载时进行静态变量的初始化或执行某些只需一次的操作。静态代码块随着类的加载而执行,并且只执行一次,无论创建多少实例,都不会再次执行。

静态代码块的特性:

  1. 类加载时执行

    • 静态代码块在类加载时自动执行,不依赖于对象的创建。即使没有创建对象,只要类被加载,静态代码块就会执行。
  2. 执行顺序

    • 静态代码块的执行顺序遵循在类中定义的顺序。如果有多个静态代码块,它们会按出现顺序依次执行。
  3. 只执行一次

    • 静态代码块只在类加载时执行一次,适合用来进行静态变量的初始化或执行一些只需要做一次的操作(如数据库连接初始化、资源加载等)。
  4. 只能访问静态成员

    • 静态代码块只能访问类的静态变量和静态方法,不能访问实例变量或实例方法,因为它在类加载时执行,不依赖于任何对象

public class Example {
    // 静态变量
    public static int staticVar;

    // 实例变量
    public int instanceVar;

    // 静态代码块
    static {
        System.out.println("静态代码块执行");
        staticVar = 100;  // 静态变量的初始化
    }

    // 构造函数
    public Example() {
        System.out.println("构造函数执行");
        instanceVar = 200;  // 实例变量的初始化
    }

    public static void main(String[] args) {
        // 类加载时静态代码块已经执行
        System.out.println("StaticVar: " + Example.staticVar);

        // 创建实例,静态代码块不会再次执行,只会执行构造函数
        Example example1 = new Example();
        Example example2 = new Example();
    }
}

静态嵌套(内部)类

它是指在另一个类中定义的静态类。静态嵌套类和普通的内部类不同,它不依赖于外部类的实例,可以直接通过外部类的类名来访问和实例化。

静态嵌套类的特性:

  1. 无需外部类的实例

    • 静态嵌套类与外部类不直接关联,无法访问外部类的非静态成员(非静态变量和方法),但可以访问外部类的静态成员。
  2. 通过外部类的类名访问

    • 可以通过 OuterClass.StaticNestedClass 的方式直接访问静态嵌套类,而不需要实例化外部类。
  3. 用于逻辑上的分组

    • 静态嵌套类通常用于逻辑上与外部类密切相关,但并不需要外部类实例的情况。它可以帮助将相关类组织在一起,增加代码的可读性和可维护性。
  4. 嵌套类可以是静态或非静态

    • 非静态的内部类可以访问外部类的所有成员(包括静态和非静态成员),但静态嵌套类只能访问外部类的静态成员
public class OuterClass {
    // 外部类的静态变量
    public static int outerStaticVar = 100;

    // 外部类的实例变量
    public int outerInstanceVar = 200;

    // 静态嵌套类
    public static class StaticNestedClass {
        public void display() {
            // 访问外部类的静态变量
            System.out.println("Outer static variable: " + OuterClass.outerStaticVar);

            // 无法访问外部类的实例变量
            // System.out.println("Outer instance variable: " + outerInstanceVar); // 错误
        }
    }

    // 普通内部类
    public class InnerClass {
        public void display() {
            // 访问外部类的静态变量和实例变量
            System.out.println("Outer static variable: " + outerStaticVar);
            System.out.println("Outer instance variable: " + outerInstanceVar);
        }
    }

    public static void main(String[] args) {
        // 直接通过外部类的类名实例化静态嵌套类
        OuterClass.StaticNestedClass nested = new OuterClass.StaticNestedClass();
        nested.display();  // 输出:Outer static variable: 100

        // 必须实例化外部类后才能实例化非静态的内部类
        OuterClass outer = new OuterClass();
        OuterClass.InnerClass inner = outer.new InnerClass();
        inner.display();  // 输出:Outer static variable: 100, Outer instance variable: 200
    }
}

静态嵌套类的加载:

静态嵌套类的加载和初始化是懒加载的,只有在首次引用或实例化时才会进行。外部类的加载并不会导致静态嵌套类的立即加载和初始化,这和静态变量是不同的,和静态方法是类似的。

public class OuterClass {
    static {
        System.out.println("OuterClass loaded");
    }

    // 静态嵌套类
    public static class StaticNestedClass {
        static {
            System.out.println("StaticNestedClass loaded");
        }
    }

    public static void main(String[] args) {
        System.out.println("Main method executed");
        
        // 实例化静态嵌套类
        StaticNestedClass nested = new StaticNestedClass();
    }
}

执行结果:

OuterClass loaded
Main method executed
StaticNestedClass loaded

应用场景

静态方法与静态变量:

在构建类时,有些参数和方法是不会根据对象的不同而发生变化的,那么这些变量和方法就可以写成静态变量和方法的。

静态代码块:

静态变量的复杂初始化

public class Config {
    public static final Map<String, String> CONFIG_MAP = new HashMap<>();

    static {
        CONFIG_MAP.put("url", "http://example.com");
        CONFIG_MAP.put("timeout", "5000");
        CONFIG_MAP.put("retries", "3");
    }
}

加载外部资源

public class DatabaseConnector {
    static {
        try {
            // 加载数据库驱动
            Class.forName("com.mysql.jdbc.Driver");
            System.out.println("数据库驱动加载成功");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

静态嵌套(内部)类:

表示外部类的组件。例如,外部类可能代表一个复杂的实体对象,而静态嵌套类可以表示这个实体的某个静态部分,如配置、工具类、内部算法等。

构建器模式总比较常见

public class Product {
    private String name;
    private double price;

    // 静态嵌套类:构建器类
    public static class Builder {
        private String name;
        private double price;

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

        public Builder setPrice(double price) {
            this.price = price;
            return this;
        }

        public Product build() {
            Product product = new Product();
            product.name = this.name;
            product.price = this.price;
            return product;
        }
    }
}

通过 Builder 模式,可以一步一步地设置每个属性,最终调用 build() 方法来创建对象。这样可以避免多参数构造函数的复杂性。如果你只想设置某些属性而不设置其他属性,Builder 模式可以很容易实现,

Product product = new Product.Builder()
        .setName("Laptop")
        .setPrice(999.99)
        .build();

 Product{name='Laptop', price=999.99}

Product product = new Product.Builder()
        .setName("Laptop")
        .build();
System.out.println(product);

 Product{name='Laptop', price=0.0}  会给个默认值

链式调用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值