静态变量与成员变量的区别、代码块、单列模式

本文详细介绍了Java中静态变量与成员变量的区别,通过实例解释了为何会出现栈溢出错误,并讨论了代码块的作用,包括局部代码块、构造代码块和静态代码块。此外,还深入探讨了单例模式的设计思想,如何实现单例以确保对象的唯一性,并提供了具体的Java代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

静态变量与成员变量的区别

代码块

单例模式


静态变量与成员变量的区别

1、两个变量的生命周期不同
成员变量随着对象的创建而存在,随着对象被回收而释放。
静态变量随着类的加载而存在,随着类的消失而消失。
2、调用方式不同
成员变量只能被对象调用。
静态变量可以被对象调用,还可以被类名调用。
3、别名不同
成员变量也称为实例变量,成员变量-对象的特有属性
静态变量也称为类变量,静态变量-对象的共有属性 类成员
4、数据存储位置不同
成员变量存储在堆内存的对象中,所以也叫对象的特有数据。
静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据。

 举个例子:

public class Test {
	public static void main(String[] args) {
		A a=new A();
		System.out.println(a==a.a);
		System.out.println(a.a==a.a.a);
	}
}
class A{
	A a=new A();
}

编译不报错,但是运行报错:

这是“栈溢出”的错误,原因是构造函数一直在进栈

 

public class Test {
	public static void main(String[] args) {
//		A a=new A();
//		System.out.println(a==a.a);
//		System.out.println(a==a.a.a);
		B b=new B();
		System.out.println(b==b.b);//false
		System.out.println(b.b==b.b.b);//true
	}
}
class B{
	static B b=new B();
}
class A{
	A a=new A();
}

没有报错,结果是: 

解析:

b中没有成员变量,只有静态变量。主函数进栈,创建b,将0x456给b。

b.b是通过对象调用成员,先去堆中的对象空间找,没有找到,再去静态区找,找到了,为0x123;那么结果就是false。

b.b.b是0x123,b.b.b先去这个对象当前的所属空间里面去找成员变量b,没有找到,再去静态区找,找到了b,是它本身。结果就是true。

所以b.b.b==b.b.b.b.b.b.b.b.b.b.b,结果也是true。


代码块

代码块 { ... }就是一对{},里面有代码

  1. 局部代码块:存在于函数当中(包括函数) for(){...}   if () {...}
  2. 构造代码块:直接在类中出现的{...}   当对象创建一次,构造代码块执行一次。作用等同于构造函数。
  3. 静态代码块:直接在类中出现的static{...}    当类被加载的时候,仅且只执行一次。作用于对类进行一些初始化操作 JDBC
class CodeBlock{
    {
        System.out.println("构造代码块");
    }
    static{
        System.out.println("静态代码块");
    }
    public static void main(String[] args){
        CodeBlock c1=new CodeBlock();
        CodeBlock c2=new CodeBlock();
        CodeBlock c3=new CodeBlock();
    }
}

结果:

静态代码块
构造代码块
构造代码块
构造代码块

 


单例模式

设计模式:就是我们的前辈们总结出来的一些编码技巧,它并不是随着Java的诞生而诞生的,它是由Java的广大使用者总结出来的一套编码经验,常见有26种。

比如某一个朝代的皇帝 只能是唯一的

 1.既然只能创建一个对象的话,就得不能让外界去创建对象。限制使用new不现实,只能从对象的创建流程中考虑 只要有一个步骤不行,对象就创建不出来。开辟空间分配地址,是由计算机底层决定,我们也控制不了。构造函数执行,只需要将构造函数私有化即可。

class SingleTest{
    public static void main(String[] args){
        Single s1=Single.getInstance();
        Single s2=Single.getInstance();
        //s2=null;
        Single s3=Single.getInstance();
        System.out.println(s1==s2);
        System.out.println(s2==s3);
    }
}

2.既然外界不能创建对象,我们还得保证对象的创建,所以我们只能在类内部创建对象   Single s=new Single();
   但不能写成成员变量的形式,因为成员变量存在的前提是创建对象,但是外界创建不了对象,无法将成员变量向外提供。所以private static

3.内部创建出对象,还得向外界提供。因为private,外界不能直接访问。所以间接访问,向外界提供一个函数,外界通过调用函数获取对象。

//饿汉式 比较急 所以直接返回对象
/*
class Single{
    private static Single s=new Single();
    private Single(){}
    public static Single getInstance(){
        return s;
    }
}
*/
//饱汗式 比交满 不急 判断一下
class Single{
    private static Single s;
    private Single(){}
    public static Single getInstance(){
        if(s==null){
            s=new Single();
        }
        return s;
    }
}

结果:

true
true

 如果s2=null,对s3没有影响。

 

 

 

 

 

 

 

 

JSI框架提供一个无侵入的脚本库管理解决方案,和一个全面的前端开发调试、文档解析、模版编译、打包导出环境支持。 作为一个开发期间的脚本管理工具,让开发者在开发期间享受JSI带来的种种便捷,也可以作为一个运行时的脚本管理框架,让类库编写者能够自己管理好自己编写的类库的相关依赖,让类库的最终用户从繁琐的依赖管理中解脱出来,提高类库的易用性。 JSI 拥有一套完善有效的模块隔离机制,方便重用、组织第三方脚本,避免它们带来的命名污染问题。JSI极力追求简单,不加入特殊语法,被管理的脚本无框架依赖。 开发便捷 * 自动隔离 不用自己编写闭包隔离脚本冲突,JSI自动处理。 * 无需名称空间 JSI有隐式的名称空间,既有名称空间的好处,又没有名称空间的麻烦和性能损失,还可以方便重构(修改报名无需修改代码)。即:你的脚本放在哪个目录下,他就自动属于哪个名称空间 * 优化脚本组织 可以按包(目录)组织您的脚本,划分模块。 * 增量定义依赖 支持功能全面的依赖管理,同时,依赖增量定义。如果有新的类库需求,只许吧新的程序包扔进相关目录,不需修改已有代码。 * 打包部署 部署的内容可以不再是零碎的文件,你可以部署程序包(zip文件) * 自动化导出合并 文件合并,自动隔离冲突,自动压缩等等,都可以自动化,你只许指定你需要到处的元素即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值