Java面向对象软件开发
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.1.6 static静态成员

1.静态类成员

通常,类的成员必须属于一个具体化对象才能访问。但Java也提供了不用创建对象而直接让类中成员工作的机制。只要在该成员的声明前面加上关键字static即可。当声明一个成员为static时,可以在类的任何对象创建之前访问它。static成员的最常见的例子是main()方法,该方法不是作为一个对象的成员被运行的。

被声明为static的成员变量就是静态变量,也称为类变量。当声明该类的对象时,在对象中不生成static变量的副本,类的所有实例将共享同一个static变量。

同理,被声明为static的成员方法是静态方法,也称为类方法。静态方法有几条限制:

(1)它们仅可以调用其他static方法。

(2)它们只能访问static数据成员。

(3)它们不能以任何方式引用this或super(关键字super与继承有关,下一节介绍),因为this和super都是指向一个具体对象。

2.静态代码块

static块(即静态代码块),这个块仅在该类被第一次加载时执行一次。静态代码块的语法格式:

      static {
          // 程序块
      }

静态代码块不是类的方法,没有方法名、返回值和参数表。静态代码块也与类方法一样,不能使用非静态变量及方法,也不能使用this或super关键字。

例2-4】 static方法、static变量、static初始块演示。

            public class UseStatic{
                static int a=3;                        // 静态变量(类变量),并初始化
                static int b;                          // 静态变量
                int c=10;                             // 实例变量
                static void display(int x){             // 静态方法(类方法)
                    System.out.println("x = " + x);
                    System.out.println("a = " + a);
                    System.out.println("b = " + b);
                    //System.out.println("c="+c);    //静态方法不能直接调用非静态成员
                }
                static{                              // 静态代码块
                    System.out.println("静态代码块执行开始");
                    b=a*4;                           // 初始化静态变量b
                }
                public static void main(String  args[]){
                    display(42);                     // 直接调用静态方法
                }
            }

一旦装载了UseStatic类,所有的static语句都被运行。首先,a被设置为3;然后static块执行(打印一条信息),最后,b被初始化为a*4即12;然后执行main()方法,main()中调用display()类方法,把42传递到x。三条println()语句引用两个static变量a、b,一个局部变量x。而c由于是非静态变量,因此不能直接被静态方法调用。

下面是该程序的输出:

            静态代码块执行开始
            x = 42
            a = 3
            b = 12

静态方法和变量可以独立于任何对象使用,仅需指定它们的类名,后跟一个“.”(点)运算符。可以用两种方式调用静态成员,它们的作用相同,因为不管该类有多少个对象都只存在一个静态成员。

静态变量: 类名.静态变量名

类对象.静态变量名

静态方法: 类名.静态方法名( )

类对象.静态方法名( )

例如,如果希望从类UseStatic外调用一个static方法,可以使用下面的形式:

            UseStatic.display(42);

其中UseStatic是类的名字,在该类中直接调用static方法,这种格式与通过对象调用非static方法的格式类似。可以用同样的方式来访问static变量——类名加上“.”(点)运算符。

请看如下代码,注意static方法callme()和static变量b是如何被访问的。

            class StaticDemo{
                static int a=42;       // 静态变量
                static int b=99;       // 静态变量
                static void callme(){  // 静态方法
                    System.out.println("a = " + a);
                }
            }
            public class StaticByName{
                public static void main(String  args[]){
                    StaticDemo.callme();  // 不需创建对象,通过类名直接调用静态方法
                    System.out.println("b="+StaticDemo.b);  // 通过类名直接调用静态变量
                }
            }

下面是该程序的输出:

            a = 42
            b = 99

特别提示:

静态成员表示该类所有对象将共有同一个成员,如果一个对象将静态成员改变,将造成由该类生成的所有对象中的该成员发生相同改变。就好比如果全世界人只有一个钱罐,任何人往钱罐中放入一块钱,对于其他人来说他们的钱罐中也多了一块钱。

工作分解-操作方案

1.分析抽象出类;

2.按照类图编制出类框架;

3.实现类方法;

4.创建对象;

5.调用对象中的方法完成计算功能。

工作实施

1.分析抽象出类

根据类成员的访问权限可知,要使长和宽两个属性不允许另一个类访问,那么其只能是private类型的。存在一个矩形类Rectangle,该类包含两个private类型成员变量:长length和宽width,以及7个成员方法:setter和getter方法分别用于设置和获取各属性,一个带参构造方法Rectangle(double width, double length)用于初始化数据成员,perimeter()和area()方法分别用于计算长方形的周长和面积,如图2-4所示。另外,还有两个包:一个包com.bean,用于存放Rectangle类;另一个包com.test,用于存放主类RectangleTest。

图2-4 长方形类(Rectangle)图

2.按照类图编制出类框架

先创建包com.bean,然后在该包中定义Rectangle类。

        // 源文件Rectangle.java
        package com.bean;
        public class Rectangle {
                                                // 声明private类型的成员变量,类外不能被访问
            private double length;                // 长
            private double width;                 // 宽
                                                // 带参构造方法(可以在所有包内被访问)
            public Rectangle(double length, double width) {
            }
            /*********以下定义成员方法*********/
            public double getLength(){            // 获取长方形的长
            }
            public void setLength(double length){  // 设置长方形的长
            }
            public double getWidth(){             // 获取长方形的宽
            }
            public void setWidth(double width){    // 设置长方形的宽
            }
            public double perimeter(){            // 求长方形的周长
            }
            public double area(){                 // 求长方形的面积
            }
        }

3.实现类中的方法

        // 带参构造方法,用于初始化长方形的长和宽
       public Rectangle(double length, double width){
            this.width=width;                 //this关键字表示当前对象
            this.length = length;
       }
       public void setLength(double length){      // 设置长方形的长
            this.length = length;
       }
       public double getLength(){                // 获取长方形的长
            return length;
       }
       public void setWidth(double width){        // 设置长方形的宽
            this.width = width;
       }
       public double getWidth(){                 // 获取长方形的宽
            return width;
       }
        public double perimeter(){              // 求长方形的周长
            return 2*(this.getLength() + this.getWidth());
        }
        public double area(){                  // 求长方形的面积
            return this.length*this.width;        // 调用当前对象的成员变量
        }

4.定义主类

先新建一个包com.test,然后在该包中定义一个主类RectangleTest。

        // 源文件RectangleTest.java
        package com.test;
        // 用import引入包
        public class RectangleTest {
            public static void main(String[] args) {
                // 创建类的对象
            }
        }

5.创建类的对象

        // 第1步:将主类中“// 用import引入包”一行语句替换成下面一行语句
        import com.bean.Rectangle;  // 导入com.bean包中的Rectangle类
        // 第2步:在主类的主方法main()中创建对象
        Rectangle rect=new Rectangle(10.0,5.0);// 调用带参构造方法

6.访问对象中成员方法完成具体工作

        // 通过调用成员方法来打印出指定长方形的长、宽、周长和面积
        System.out.println("调用帶参构造方法创建的长方形类对象rect:");
        System.out.print("length = " + rect.getLength() + " width = "+ rect.getWidth());
        System.out.println("perimeter="+rect.perimeter()+"  area="+rect.area());

7.代码调试运行

(1)完整源代码如下:

        // 源文件Rectangle.java
        package com.bean;
        /**
         * 长方形类
         * @author lee
         */
        public class Rectangle {
        // 声明private类型的成员变量,类外不能被访问
        private double length;// 长
        private double width;// 宽
        // 带参构造方法(可以在所有包内被访问),用于初始化长方形的长和宽
        public Rectangle(double length, double width) {
            this.length=length;   //this关键字表示当前对象
            this.width = width;
        }
        public double getLength(){  // 获取长方形的长
            return length;
        }
        public void setLength(double length){  // 设置长方形的长
            this.length = length;
        }
        public double getWidth(){  // 获取长方形的宽
            return width;
        }
        public void setWidth(double width){  // 设置长方形的宽
            this.width = width;
        }
        public double perimeter(){// 求长方形的周长
            return 2 * (this.getLength() + this.getWidth());
        }
        public double area(){// 求长方形的面积
            return this.length*this.width;// 调用当前对象的成员变量
        }
        }
        // 源文件RectangleTest.java
        package com.test;// 所属包
        import com.bean.Rectangle;  // 导入com.bean包中的Rectangle类
        public class RectangleTest {
        public static void main(String[] args) {
            Rectangle rect=new Rectangle(10.0,5.0);// 调用带参构造方法
            // 通过调用成员方法来打印出指定长方形的长、宽、周长和面积
            System.out.println("调用带参构造方法创建的长方形类对象rect:");
            System.out.print("length="+rect.getLength()+"  width="+rect.getWidth());
            System.out.println("  perimeter="+rect.perimeter()+"  area="+rect.area());
        }
        }

(2)调试结果:

        调用带参构造方法创建的长方形类对象rect:
        length=10.0  width=5.0  perimeter=30.0  area=50.0