Java基础-static关键字和单例模式

栏目: 后端 · 发布时间: 5年前

内容简介:看下输出结果:ok,现在分析下,我第一个对象的那我现在如果把
  • static关键字的特点

    1. 用来修饰类的成员-修饰成员变量的称之为类变量(静态变量),修饰成员方法的称之为类方法(静态方法)。(属性拿static修饰完之后就不叫属性了,他也就不属于任何对象了,而是属于多个对象共享的,就叫类变量或静态变量,方法也一样)

    2. 当类被加载的时候就会被加载,优先于对象的存在。

    3. 用来修饰与语句块-称之为静态代码块。先于构造方法之前执行,只会执行一次。用来对静态成员做初始化

    4. 静态修饰的成员被所有的对象共享

    5. 调用的时候可以直接通过类名.成员来进行访问。

  • static关键字注意事项

    1.静态方法中只能访问外部的静态成员 (为什么?当我们去调用静态方法的时候,对象都没产生,对象没产生怎么可能有属性呢,因为属性是属于某个对象的对吧) 2.静态方法中不能出现this关键字 (为什么?同样的道理,当我们去调用静态方法的时候,对象都没产生,对象没产生this又是指谁呢?)

ok 上代码!

public class StaticDemo {


    public static void main(String[] args)
    {
        Device device1 = new Device();
        device1.showName();
        device1.showEnergy();
        Device device2 = new Device();
        device2.energy++;
        device2.showName();
        device2.showEnergy();
    }
}

class Device
{
    private String name="device1";//普通的属性
    public int energy=2;//普通的属性

    public String getName() {
        return name;
    }

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

    public int getEnergy() {
        return energy;
    }

    public void setEnergy(int energy) {
        this.energy = energy;
    }

    public void showName()
    {
        System.out.println(name);
    }

    public void showEnergy()
    {
        System.out.println(energy);
    }
}
复制代码

看下输出结果:

device1
2
device1
3
复制代码

ok,现在分析下,我第一个对象的 energy 属性初始值时 2 ,第二个对象的 energy 属性我用 public 修饰了,所以我直接可以调用下,然后 加一 了,打印出来的结果两个对象是不一样的。这就说明了什么? 每个对象都有他自己的独立的一份属性 。对不对?~对的哈。。这句话很重要~~

那我现在如果把 name 这个属性改成用 static 来修饰的话,现在会怎么样? public static String name="device1";//静态变量,他现在不属于任何一个对象了,被多个对象共享,他现在是属于类的,他也称为类变量

现在我们把调用方法改成这样

public static void main(String[] args)
    {
        Device device1 = new Device();
        device1.name = "cyy";
        device1.showName();
        device1.showEnergy();
        Device device2 = new Device();
        device2.energy++;
        device2.showName();
        device2.showEnergy();
    }
复制代码

现在 name 不是个属性了,他现在是个静态变量,我在 device1 里面把他设置成 cyy ,现在打印结果来看下。

cyy
2
cyy
3
复制代码

看到没两个 name 都变成 cyy 了。这说明了什么?这是不是说明了,这个 name 大家都共享了呀,不再是每个对象独立拥有的了,对吧! 那既然他都不是共享的了,那我们访问的时候是不是就可以直接 Device.name 就可以了啊,因为他现在不属于对象了,他现在属于类的。 而 age 可不可以直接通过 Device.age 来访问啊,当然不可以,因为他现在并不属于类对吧。

好的,现在如果我们把一个方法改成静态的呢,比如这样:

public static void showName()
{
    System.out.println(energy);
    System.out.println(name);
}
复制代码

如果这么写的话,是不是会报错呀,编译时就会报错,会提示: Non-static field 'energy' cannot be referenced from a static context

什么意思?大概意思就是说,你静态方法不能访问非静态变量~为什么?!因为你静态方法调用的时候,还没有创建对象呢,人家 energy 是个属性,又不是静态变量,你会跑的时候,人家还没出生呢,你咋能去找人家玩儿呢?对吧,所以 静态方法不能访问非静态变量静态方法中不能使用this ,只能访问外部静态的东西。

非静态方法 可不可以访问 静态变量 ?思考一下?答案当然是可以的,想像一下,静态变量在你对象创建之前就已经分配好内存空间了,已经存在了,你对象创建完之后,他已经存在了,所以肯定是可以访问的,对吧。总结就是 静态的只能访问静态的,非静态的都可以访问

还有个static语句块

他什么时候执行呢?

在类被加载的时候就会执行,只会执行一次,用来对静态变量进行初始化。优先于 构造方法 的执行。

上代码:

class Device
{
    public static String name;//普通的属性
    public int energy=2;//普通的属性

    //static语句块
    static {

        name = "device1";
        System.out.println("===我是静态语句块里的"+name);
    }

    //构造方法
    public Device(String name)
    {
        this.name = name;
        System.out.println("===我是构造方法里的"+name);
    }


    public static void showName()
    {
        System.out.println(name);
    }

    public void showEnergy()
    {
        System.out.println(energy);
    }
}

复制代码

我们现在使用下:

Device device1 = new Device("cyy");
        Device device2 = new Device("cyy513");
复制代码

看下打印结果:

===我是静态语句块里的device1
===我是构造方法里的cyy
===我是构造方法里的cyy513
复制代码

发现了吧,我 new 了两个对象,但是静态语句块里的 system.out.println 只打印了一次,说明啥 static语句块只执行一次,不管你创建多少次对象。 而且我是先于构造方法执行的。

那会有人说,那我以后都不用属性了,我全部用static变量,多好,多方便,其实这样有很多缺点:

  • 破坏了 java 面向对象的封装性
  • static变量的生命周期比较长,程序结束的时候,他的内存才会释放,而属性呢,这个对象运行完了他的属性内存是不是就释放了呀。

那我们什么时候用static呀?

当我们一个类里面,没有任何属性,只有方法 ,而这个方法是为其他的类服务的,这个时候适合用static的。

接下来我们了解下单例模式

定义:

顾名思义,单例模式的意思就是只有一个实例,单例模式确保某一个类只有一个实例,而且自行实例化并为整个系统提供这个实例,这个类称为单例类。

通俗的说,就是我有一个类,整个系统就一个实例,而且他是自己创建自己,他必须对外提供个方法,把我自己给你。

上代码:

class SingleTon
{

    private SingleTon singleTon = new SingleTon();

    /**
     * 构造方法一定不能是公开的,不然别人就可以随便构造了。
     * 所以构造方法必须是private,对吧
     */
    private SingleTon()
    {

    }
    //如果我这么写,会出现什么问题
    public static SingleTon getInstance()
    {
        return singleTon;
    }
}
复制代码

是不是会出现之前说的那种错误呀, 静态方法不能引用非静态变量 。对不对。所以要怎么做?是不是给前面 singleton 加上个 static 就可以了是吧。因为这个SingleTon是静态的在内存里只有一份对吧~正确写法,

class SingleTon
{

    public static SingleTon singleTon = new SingleTon();
    private SingleTon()
    {}
 
    public static SingleTon getInstance()
    {
        return singleTon;
    }
}
复制代码

这种方式称之为 饿汉式 。为什么?因为我在调用 getInstance() 之前这个对象是不是就已经产生了呀,因为它是静态的嘛,在类加载时候,就已经 new SingleTon() 了呀。那我们现在有没有更好的方法呢? 比如在 getInstance() 的时候再去创建这个对象呀?当然可以呀~这么写就可以了.

class SingleTon
{

    public static SingleTon singleTon = null;

    /**
     * 构造方法一定不能是公开的,不然别人就可以随便构造了。
     * 所以构造方法必须是private,对吧
     */
    private SingleTon()
    {

    }
    //如果我这么写,会出现什么问题
    public static SingleTon getInstance()
    {
        if (singleTon==null)
        {
            singleTon = new SingleTon();
        }
        return singleTon;
    }
}
复制代码

这种就是 懒汉式 加载。

不管是 懒汉式 还是 饿汉式 ,是不是目的就是一个,让他整个系统中只有一个实例。

ok,结束~ 后续我会继续更新,Android自定义View,Android NDK,音视频方向的文章,欢迎大家关注,共同进步。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Spring in Action

Spring in Action

Craig Walls / Manning Publications / 2011-6-29 / USD 49.99

Spring in Action, Third Edition has been completely revised to reflect the latest features, tools, practices Spring offers to java developers. It begins by introducing the core concepts of Spring and......一起来看看 《Spring in Action》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

URL 编码/解码
URL 编码/解码

URL 编码/解码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具