静态成员
思考:利用类来创建很多个对象,每个对象都需要存储一个相同值的变量时,我们能不能只保存一个呢?静态成员(static)就是来解决这个问题。
举个例子,我们设定一个圆柱(class Cylinder)的类,再用这个类创建200个对象,我们会发现所有圆柱都有pi值,而且pi值都相同的,这样我们就得存200分相同的数据,这样大大浪费了空间,这时候我们就可以引入静态来解决

class Cylinder{
    double radius;
    int height;
    double pi = 3.14;//这样每个对象都得创建一个相同的pi
    }

1.静态成员

实例成员:属于对象,必须创建对象后才可调用的成员
例如:
Cylinder c1 = new Cylinder();c1.radius = 1; c1.Volume();对象名.变量名; 对象名.方法名
这些都是实例成员

对比分析
实例成员
1.不用static修饰的成员
2.属于对象,创建对象后才能访问成员
3.实例变量和实例方法
实例成员必须要实例化才能调用例如:Cylinder c1 = new Cylinder(); 拓展:实例变量:定义在类中但在任何方法之外。
静态成员(类成员)
1.被static修饰的成员
2.属于类,无需创建对象即可访问
3.静态变量和静态方法
而静态成员可以直接调用如:Cylinder.count()

2.静态变量

静态变量:用static修饰的成员变量,类变量

引入了静态变量后的代码:

class Cylinder{
    private static double pi = 3.14;
    private static int num;
    private double r,h;
    ......
    }

java静态成员 list java静态成员实验例子_实例变量


由图可以看出,在由Cyliner类为模板创建出的c1,c2对象的空间中并没有pi和num,因为pi和num被设置为了静态变量

这里的静态变量也可以成为类变量或者说类的域,不属于****任何一个类具体对象,可以看出c1,c2中是没有这两个变量的
静态变量不保存在对象内存空间中,而是保存在类的内存区域,是公共存储单元
可以看出当创建大量对象是,可以节省内存空间

使用格式
类名.静态变量, Cylinder.num(推荐)
对象名.静态变量名 c1.num(虽然正确但不推荐)
因为静态变量是存放在类中而不是对象中,所以第二种用法在表达上不准确

3.静态方法

静态方法:用static修饰的方法,类方法
属于整个类,内存中的代码段将随着类的定义而分配和装载,不被任何一个对象专有

class Cylinder{
    private static double pi = 3.14;
    private static int num=0;
    private double r,h;
    ...... 
	public static void count(){
        System.out.println("创建了"+num+"对象");
    } 
    ......
}

使用格式
类名.静态变量, Cylinder.count()(推荐)
对象名.静态变量名 c1.count()(虽然正确但不推荐)
因为静态方法是存放在类中而不是对象中,所以第二种用法在表达上不准确

4.static的规则

静态的成员(类成员)不能访问实例成员,因为,实例变量只有在创建实例的时候才会被创建而静态成员是加载类的时候被创建。所以有了静态成员未必据有实例变量,即使有了实例变量,那么多实例,它哪知道访问哪个实例变量
类成员不能访问实例成员,类成员属于类,作用域大于实例成员,举个不

class Cylinder{
    private static double pi = 3.14;
    private static int num=0;
    private double r,h;
    ...... 
	public static void count(){
        System.out.println("创建了"+num+"对象");
    } 
    ......
}

在count()方法中不可以访问r,h,可以访问num,pi

编程:
创建一个类,定义静态方法least(),求若干数的最小值

class TestStatic
{
    static void least(int[] array)
   {
       int min=array[0];
       for(int i=1;i<array.length;i++)
           {
                if(array[i]<min)    
                      min=array[i];
            }
        System.out.println("最小数:"+min);
   }
}
 
public class Test    
{
  public static void main(String[] args)
  {
    int[] a={8,3,7,88,9,23};  
    TestStatic.least(a);  
  }
}

扩展

class Value {
    static int c = 0;
    Value() {
        c = 15;
    }
    Value(int i) {
        c = i;
    }
    static void inc() {
        c++;
    }
}

class Count {
    public static void prt(String s) {
        System.out.println(s);
    }

    Value v = new Value(10);
    static Value v1, v2;

    static {
        prt("v1.c=" + v1.c + " v2.c=" + v2.c);
        v1 = new Value(27);
        prt("v1.c=" + v1.c + " v2.c=" + v2.c);
        v2 = new Value(15);
        prt("v1.c=" + v1.c + " v2.c=" + v2.c);
    }

    public static void main(String[] args) {
        Count ct = new Count();
        prt("ct.v.c=" + ct.v.c);
        prt("v1.c=" + v1.c + " v2.c=" + v2.c);
        v1.inc();
        prt("v1.c=" + v1.c + " v2.c=" + v2.c);
        prt("ct.v.c=" + ct.v.c);
    }
}

运行结果如下:

v1.c=0 v2.c=0
v1.c=27 v2.c=27
v1.c=15 v2.c=15
ct.c=10
v1.c=10 v2.c=10
v1.c=11 v2.c=11
ct.c=11

这个程序展示了静态初始化的各种特性。如果你初次接触Java,结果可能令你吃惊。可能会对static后加大括号感到困惑。首先要告诉你的是,static定义的变量会优先于任何其它非static变量,不论其出现的顺序如何。正如在程序中所表现的,虽然v出现在v1和v2的前面,但是结果却是v1和v2的初始化在v的前面。在static{后面跟着一段代码,这是用来进行显式的静态变量初始化,这段代码只会初始化一次,且在类被第一次装载时。如果你能读懂并理解这段代码,会帮助你对static关键字的认识。在涉及到继承的时候,会先初始化父类的static变量,然后是子类的,依次类推。