java基础_面向对象_static关键字

 一直感觉对静态的理解不到位,知道修饰类的属性和方法、修饰代码块(不能修饰普通类但是可以修饰内部类)。在合适的环境下,提高程序的运行性能,优化程序的结构;反之,不合理的运用因为难以被GC掉,构成内存负担造成内存溢出,在android开发中尤为明显,有些闪退就是因为out of memory。

   再去重新理解static的时候我想从最简单的开始,修饰类的属性。

目录


(1) 修饰类的属性

   在类中,static修饰的成员变量称为静态成员变量,它为该类的公有变量,只有在第一次使用时被初始化,对于该类所有对象来说,static成员变量只有一份。

    静态成员变量是属于整个类的,不属于具体的某个对象。那么对这个静态的值怎么访问呢?首先,任何一个对象都可以访问这个静态的值,访问的时候都是访问的同一块内存 。其次,即便是没有对象,你也可以类名.访问这个值。

    举个简单的列子,猜一下输出的结果,然后内存上分析咋回事。

public class Test {
    public static void main(String[] args) {
        Cat.sid = 100;
        Cat cat1 = new Cat();
        Cat cat2 = new Cat();

        cat1.info();
        cat2.info();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
public class Cat {
    static int sid;
    int id;

    public Cat() {
        id = sid++;
    }

    public void info() {
        System.out.println("static cat:" + "sid=" + sid + "  id=" + id);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

显然定义了static int sid,结果:挺有意思。

static cat:sid=102  id=100
static cat:sid=102  id=101
  • 1
  • 2

加载过程,JVM内存分四种:

  1. 栈区(stack segment)- 由编译器自动分配释放,存放函数的参数值,局部变量的值等,具体方法执行结束之后,系统自动释放JVM内存资源。
  2. 堆区(heapsegment)- 存放new出来的对象和数组,jvm不定时查看这个对象,如果没有引用指向这个对象就回收掉。
  3. 方法区(也叫:数据区,共享区,共享数据区) - 存放全局变量,静态变量和字符串常量,和方法。
  4. 代码区(codesegment) - 存放程序中方法的二进制代码,而且是多个对象共享一个代码空间区域。

因此首先Cat.sid = 100;数据区中专门分配一小块位置存放。 
其次Cat cat1 = new Cat();位置栈空间中分配一块名为cat1,值是指向另一大块内存的地址;堆空间中分配一大块内存用于new出来的对象,其中对象的属性id被赋值为100;id = sid++; sid++后为101;同理cat2时,此时sid=101,cat2的id值被赋予101,然后sid为102;

这里写图片描述

以上也就说明了静态成员变量是属于整个类的,不属于具体的某个对象。

那么我们试着把static int sid; 改为非静态int sid; 最后输出:

non static cat:sid=1  id=0
non static cat:sid=1  id=0
  • 1
  • 2

(2) 修饰类的方法

   用static声明的方法为静态方法,在调用该方法时,不会将对象的引用传递给它,所以在static方法中不可以访问非static的成员。 
   动态方法是针对于某一个对象进行调用的。静态的方法呢?它不针对某一个对象,和静态成员变量一样是属于整个类的,没有对象照样可以调用,就像Cat.静态方法。也正因为如此静态方法中不能访问非static的成员和非静态的方法,比如在main方法中id=9会报错的。 
   在工具类中常会有修饰方法,方便调用,免去new对象这个繁琐的过程。比如:TextUtils.isEmpty(string) 源码

     public static boolean isEmpty(@Nullable CharSequence str) {
        if (str == null || str.length() == 0)
            return true;
        else
            return false;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

(3) 修饰代码块

   静态代码块一般和类的加载相关,可以将多个类成员放在一起初始化。


   常见提示错误: 无法从静态上下文中引用非静态 变量 this

   this 是指向当前对象的引用,需要对象实例化以后才能赋值。而静态成员都是类所属的,不需要对实例化就可以使用,所以在静态上下文中引用this时可能其还未赋值,所以应不能这样使用。

   在静态方法内只能引用静态变量

关于static简单的入门级总结就是以上这些,如有疑问或者质疑烦劳留言或私信。

“爱情来得快 去得也快 只有猪肉卷是永恒的” –加菲猫。 
同理“爱情来得快 去得也快 只有java是永恒的”。

猜你喜欢

转载自blog.csdn.net/jxphuijing/article/details/79781371