Java 基础 15 static 关键字介绍


1. 介绍

在Java中,static是一个关键字,用于修饰类、方法和变量。使用static关键字声明的成员属于类级别,不需要实例化对象就可以访问和使用。在类定义中使用static关键字声明的变量可以作为常量使用。

2. 为什么设计 static 关键字

提出问题的主要目的就是让大家思考解决之道,从而引出我们要讲的知识点。

说有一群小孩在玩堆雪人,不定时有新的小孩加入,请问如何之道现在共有多少人在玩,编写程序解决问题。

  • 先使用之前学过的技术解决
    • 思路: 在main方法中定义一个变量count
    • 当有一个小孩加入游戏后, count++, count就记录了有多少小孩, 如果想知道有多少人在玩游戏, 打印count值即可
public class ChildrenGame {
    public static void main(String[] args) {
        int count = 0;
        Chlind c1 = new Chlind("小明");
        count++;
        c1.join();
        Chlind c2 = new Chlind("小红");
        count++;
        c2.join();

        System.out.println("现在共有 "+count+ "个小朋友玩堆雪人") ;

    }
}

class Chlind{
    private String name;

    public Chlind(String name) {
        this.name = name;
    }

    public void join(){
        System.out.println(this.name+" 参加游戏");
    }
}
  • 问题分析:

count 是一个独立的变量, 没有使用到面向对象

如果以后访问count很麻烦,比如问一个小朋友现在有多少人, 他就不知道

  • 解决问题

如果设计一个 count变量,我们在创建一个小孩时,就把count +++ 并且count是对所有对象共享的就OK了,我们可以使用类变量来解决这个问题

 public class ChildrenGame {
     public static void main(String[] args) {
         Child02 c1 = new Child02("小明");
         c1.count++;
         c1.join();
         Child02 c2 = new Child02("小红");
         c2.count++;
         c2.join();

         System.out.println("现在共有 "+Child02.count+ "个小朋友玩堆雪人") ;
     }
 }

 class Child02 {
     // 定义一个 静态变量(类变量) count
     // 类变量的最大的特点就是可以被这个类的所有的实例共享
     public static int count;
     private String name;

     public Child02(String name) {
         this.name = name;
     }

     public void join(){
         System.out.println(this.name+" 参加游戏");
     }
 }

类变量(静态/static变量)是用一个类所有对象共享的,

类变量在类加载的时候就生成了

static 内存模型

注意 在jdk1.7 之前静态变量存储在方法区中的静态域中

3. 类变量和类方法

  • 什么是类变量?

类变量也叫静态变量/静态属性,是该类的所有对象共享的变量,任何一个该类的对象去访问它时,取到的都是相同的值, 同样任何一个该类的对象去修改它时,修改的也是同一个变量。

  • 定义类变量语法
访问修饰符 static 数据类型 变量名称; // 推荐这种方式
static 访问修饰符 数据类型 变量名称;
  • 访问类变量
// 在满足java访问范围限制的情况下:
类名.属性名; // 推荐这种
对象名.属性名;
public class Visit {
    public static void main(String[] args) {
        System.out.println(Person03.public_);
        System.out.println(Person03.protected_);
        System.out.println(Person03.default_);
        //System.out.println(Person03.privare_); // 私有静态属性, 无法访问

        Person03 person = new Person03();
        System.out.println(person.public_);
        System.out.println(person.protected_);
        System.out.println(person.default_);
        //System.out.println(person.privare_); // 私有静态属性, 无法访问
    }
}
class Person03{
    // 定义四种静态属性,分别使用四种不同的访问修饰符修饰
    public static String public_ = "publicVariable";

    protected static String protected_ = "protectedVariable";

    static String default_ = "defaultVariable";

    private static String private_ = "privateVariable";
}

4. 类变量和类方法

  1. 什么时候需要使用类变量

当我们需要让某个类的所有对象都共享一个变量是,就可以考虑使用类变量,比如定义学生类, 统计学生一共交了多少钱

class Student{
    String name;
    static double fee;
}
  1. 类变量与成员变量的区别?

类变量是该类的所有对象共享的, 而成员变量是每个对象特有的

  1. 定义变量时加上 static 修饰的变量即为类变量, 否则即为普通变量/成员变量

  2. 类变量可以通过 类名.类变量对象名.类变量 访问, 通常会使用 类名.类变量 来访问,

  3. 成员变量只能通过 对象名.成员变量名 来访问

  4. 类变量在类加载时就已经初始化了, 也就是说即使没有实例化对象, 只要加载了类, 就可以使用类变量了

  5. 类变量的声明周期是随着类的加载开始, 随着类的销毁结束

public class Static04_visit {
    public static void main(String[] args) {
        System.out.println(A04.a);
    }
}
class A04{
    public static int a = 100;
}

5. 类方法

类方法也叫静态方法

  • 定义静态方法语法
访问修饰符 static 数据类型 方法名称(形参列表){
    方法体;
} // 推荐这种方式

static 访问修饰符 数据类型 方法名称(形参列表){
    方法体;
}

// 如
    public static void aa(){
        int a = 1+1;
    }

    static public void bb(){
        int a = 1+1;
    }
  • 调用静态方法

静态方法可以通过 类名.静态方法名对象名.静态方法名 访问, 通常会使用 类名.静态方法名 来访问,

  • 使用示例
public class Static05_method {
    public static void main(String[] args) {
        Stu05 s1 = new Stu05("小明");
        s1.addFee(100);
        Stu05 s2 = new Stu05("小明");
        s2.addFee(300);

        Stu05.showFee();
    }
}

class Stu05{
    private String name;
    private static double fee;

    // 使用static 修饰的方法就是静态方法,
    // 静态方法可以直接实用类名访问到
    public static void addFee(double fee){
        Stu05.fee +=fee;
    }
    public static void showFee(){
        System.out.println("总费用为:"+ fee);
    }
    public Stu05(String name) {
        this.name = name;
    }
}

6. 类方法使用场景

当类方法中不涉及任何和对象相关的成员, 则可以将方法设计成静态方法, 提高开发效率

比如:Math、Arrays、collections工具类中的方法

在实际开发中, 往往会用到一些通用的方法, 设计成静态方法, 这样我们不需要创建对象就可以使用他们, 比如打印一维数组, 冒泡排序完成某个计算任务等等

public class Static06_utils {
    public static void main(String[] args) {
        System.out.println("12 + 15 = "+ Utils.sum(12,15));
        // 使用Math 工具类开平方方法
        System.out.println("9 开平方结果是:" + Math.sqrt(9));
    }
}

class Utils{
    // 编写一个计算两个数之和的方法
    public static  int sum(int d1,int d2){
        return  d1+d2;
    }
}

7. 类变量与类方法

  1. 类方法和普通方法都是随着类的加载而加载,将结果存储在方法区,

类方法中无this的参数

普通方法中引航者this参数

  1. 类方法可以通过类名调用, 也可以通过对象名调用
  2. 普通方法和对象有关,需要通过对象名调用,比如 对象名.方法名(实参列表) 不能通过类名调用
class Person07{
    private String name;
    private static String age;
    public static void eat(){
        System.out.println("eating . . .");
    }
    public static void run(){
        // 静态方法中不允许使用和对象有关的关键字, 如this、super
        //System.out.println(this.name);
        //  静态方法中不能访问普通成员变量
        //System.out.println(name);

        // 静态方法中可以访问静态变量
        System.out.println(age);
        // 静态方法中可以访问其他的静态方法
        eat();
    }
}
  1. 静态方法中不允许使用和对象有关的关键字,比如 this、super。 普通方法可以使用这些关键字
  2. 在遵守访问权限的前提下,静态方法中只能访问静态变量和静态方法
  3. 在遵守访问权限的前提下,普通成员方法既可以访问静态方法、静态变量, 也可以访问非静态方法、非静态变量

8. main 方法

  • 深入理解main 方法

解释main方法的形式,

// main 方法定义形式
public static void main(String args[]){

}
  1. main方法是在虚拟机调用

  2. java虚拟机需要调用类的main方法, 所以改方法必须是public 级别

  3. java虚拟机在执行main()方法时不必创建对象, 所以该方法必须是static级别的

  4. 该方法接受String类型的数组, 该数组中保存执行java命令时所传递给所运行的类的参数,

  5. 参数传递方式 java 执行程序 参数1 参数2 参数3

  • 特别提示
    1. 在main方法中, 我们可以直接调用main方法所在类的静态方法或静态属性
    2. 但是, 不能直接访问该类中的非静态成员, 必须创建该类的一个实例后, 才能通过这个对象访问非静态成员
class Main11{
    public static void m1(){
        System.out.println("Main11 静态方法");
    }
    public void m2(){
        System.out.println("Main11 非静态方法");
    }
    // 静态变量
    public static int v1 = 100;
    // 非静态变量
    public int v2 = 100;

    public static void main(String[] args) {
        // 可以直接访问静态属性
        System.out.println(v1);
        // 不可以直接访问非静态属性
        //System.out.println(notStaticVariable);
        // 可以直接访问静态方法
        m1();
        // 不可以直接访问非静态方法
        //notStaticMethod();

        // 实例化对象========================
        Main11 m = new Main11();
        // 实例化对象可以直接访问静态属性
        System.out.println(m.v1);
        // 实例化对象可以直接访问非静态属性
        System.out.println(m.v2);
        // 实例化对象可以直接访问静态方法
        m.m1();
        // 实例化对象可以直接访问非静态方法
        m.m2();
    }
}

文章作者: hnbian
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 hnbian !
评论
 上一篇
Java 基础16 static 代码块介绍 Java 基础16 static 代码块介绍
1. 代码块基本介绍代码块又称为初始化块, 属于类中的成员, 即为类的额一部分,类似于方法,将逻辑语句封装在方法体中, 通过 {} 包围起来。 但代码块又和方法不同, 没有方法名,没有返回值, 没有参数,只有方法体,而且不通过对象或类显式调
2018-02-19
下一篇 
Spark 常用参数解析 Spark 常用参数解析
1. shuffle 相关参数1.1 spark.shuffle.manager spark 1.2 官方支持两种shuffle ,即 HashBasedShuffle 和 SortBasedShuffle , spark1.0之前仅支持
2018-02-15
  目录