探秘static——类不需实例化就能用?

简介: 一般情况下,需要用到某个类的时候,都必须先实例化这个类,才能对其进行调用。在编程过程中发现,有些类不用实例化就可以直接拿来使用,使用它的字段、方法等等。

      一般情况下,需要用到某个类的时候,都必须先实例化这个类,才能对其进行调用。在编程过程中发现,有些类不用实例化就可以直接拿来使用,使用它的字段、方法等等。


      这时候,靠的就是static作用。static英文意思为“静止的,静态的”,在OOP中可以作为修饰符,类、字段、属性、方法等被static修饰后,变为静态类、静态字段、静态属性、静态方法……


      static修饰的类成为静态类,静态类中只能包含静态成员(被static修饰的字段、属性、方法),不能被实例化,不能被继承;非静态中可以包含静态成员。  


     1、被调用时必须先实例化的情况:


      被调用成员为非静态成员(此时它所属的类肯定为非静态类)。如下小例子:


    public class ClassA      //ClassA类(非静态类)
    {
        public ClassA() { }  //构造函数
        public void Fun() { }//ClassA类中的方法(非静态方法)
    }
    public class ClassB     //需要调用ClassA类中方法的ClassB类
    {
        public ClassB() { }  //构造函数
        public void Fun()  
        {
            ClassA a = new ClassA();//调用ClassA类中的方法需要先实例化
            a.Fun();
        }
    }


     说明:ClassA类为非静态类,其中的方法Fun()也为非静态方法,所以在ClassB中调用时需要先实例化ClassA类。


      2、被调用时不需要实例化的情况:

      被调用成员为静态成员(此时它所属的类为静态类或非静态类)。如下小例子:


      (1)被调用类为非静态类:

    public class ClassA      //ClassA类(非静态类)
    {
        public ClassA() { }  //构造函数
        public static void Fun() { }//ClassA类中的方法(静态方法)
    }
    public class ClassB     //需要调用ClassA类中方法的ClassB类
    {
        public ClassB() { }  //构造函数
        public void Fun()  
        {
            ClassA.Fun();  //调用ClassA类中的方法直接调用:类名.成员
        }
    }


      说明:ClassA类为非静态类,但其中的方法Fun()为非静态方法,所以在ClassB中调用时不实例化ClassA类(而且不能实例化),直接调用其成员,语法为“类名.成员”。


      (2)被调用类为静态类:


    public static class ClassA      //ClassA类(静态类)
    {
        //当然静态类中不能存在构造函数
        public static void Fun() { }//ClassA类中的方法(静态方法)
    }
    public class ClassB     //需要调用ClassA类中方法的ClassB类
    {
        public ClassB() { }  //构造函数
        public void Fun()  
        {
            ClassA.Fun();  //调用ClassA类中的方法直接调用:类名.成员
        }
    }

     说明:ClassA类为静态类,其中的方法也Fun()为非静态方法,所以在ClassB中调用时不实例化ClassA类(而且不能实例化),直接调用其成员,语法为“类名.成员”。


      3、static修饰符(拓展):


       (1) 用来修饰类或类的成员,这时不需要创建实例就能访问(而且不能实例化),在被调用的时候自动实例化,且在内存中产生一个实例。当含有静态成员的非静态类实例化出对象后,这些对象公用这些静态成员,通过类名或对象名都能访问它们。

       在网上看到两个有趣的小例子:

       人是一个非静态类。人有脑子,这是一个用static修饰的属性。

这个属性是针对所有的人,是人的共同特征。而不是某个特点对象所特有的(比如张三有脑子,李四没脑子),因为只要是个人,他都有脑子(虽然卡洛斯·罗德里格兹只有半个脑子,还有些人比较脑残→_→,那也算是有脑子),既然是人类共有的,那么他就不能被实例化。


32.jpg


      另外一个能被实例化的例子,还是人这个类,人的身高,就是一个非static的属性。因为每个人的身高是不同的。比如我身材魁梧,高达1.55米,这个1.55米是描述我的身高,是跟我这个特定的对象有联系的。姚明才2.26米,这是姚明这个对象的数据。不管是1.55还是2.26,这都和特定的对象有联系,而不是人类所共有的特征。所以非static的可以被实例化,而static不能被实例化。


33.jpg


      (2) 修饰方法内部的静态变量:

      我们的代码都是从硬盘加载到内存中才能运行的,在内存中主要分为三个区域,来存放我们的代码,分别是堆、栈和静态存储区。堆中存放的是代码中的引用类型变量,如类的实例、数组等;栈中存放的是代码中的值类型,如整型、浮点型、布尔型等;静态存储区中存放静态变量和全局变量、常亮。


      整个程序运行时,代码都是共用静态存储区中的静态变量的,例如定义存款余额为静态变量,同一个银行卡号,无论你是在银行取钱、在ATM机取钱,还是网银消费,用的都是这个静态的余额。


      所以,方法内部的静态变量,执行完静态变量值不消失,再次执行此对象的方法时,值仍存在,它不是在堆和栈中分配的,是在静态区非配的, 这是与局部变量最大的区别。关于内存分配问题可参考《静态存储区、堆和栈的区别》。


相关文章
|
2月前
|
存储 安全 C++
如何优雅地在C++库中实现实例化设计(二)
如何优雅地在C++库中实现实例化设计
20 0
|
6天前
|
Java
java反射-获取类的Class对象方式
java反射-获取类的Class对象方式
5 0
|
2月前
|
Java 容器
【Java探索之旅】继承结构 继承和组合 protected final
【Java探索之旅】继承结构 继承和组合 protected final
20 0
|
2月前
|
存储 Java 编译器
实例化&&构造方法&&static统统都学会
实例化&&构造方法&&static统统都学会
27 0
|
2月前
|
存储 设计模式 缓存
如何优雅地在C++库中实现实例化设计(一)
如何优雅地在C++库中实现实例化设计
29 0
|
9月前
|
druid Java 编译器
Java的第七篇文章——面向对象接口(包含了接口、static修饰符、final修饰符、main方法、内部类等知识点)
Java的第七篇文章——面向对象接口(包含了接口、static修饰符、final修饰符、main方法、内部类等知识点)
|
存储 Java 程序员
深入理解Java中的三个修饰符(抽象(abstract)、静态(static)和最终的,不可变(final))【配视频】
🍅程序员小王的博客:程序员小王的博客 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 🍅 如有编辑错误联系作者,如果有比较好的文章欢迎分享给我,我会取其精华去其糟粕 🍅java自学的学习路线:java自学的学习路线
300 0
深入理解Java中的三个修饰符(抽象(abstract)、静态(static)和最终的,不可变(final))【配视频】
|
Java 开发者
Class 类对象的三种实例化模式|学习笔记
快速学习 Class 类对象的三种实例化模式
134 0
Class 类对象的三种实例化模式|学习笔记
|
Java API
Java反射(二)Class类
对class类做出介绍
94 0
|
存储 Java 编译器
【叁】了解对象与类(面向对象思想、final、static静态域和方法)
【叁】了解对象与类(面向对象思想、final、static静态域和方法)
77 0