Static成员

目录

static使用情景

静态成员变量

静态成员方法

静态成员变量初始化

就地初始化

静态代码块初始化

代码块

普通代码块

构造代码块

静态代码块

static使用情景

现在有一个学生类,我们定义一个学生需要姓名,年龄和班级,假设所有学生来自同一个班级,那么我们在写代码时,就要重复定义多个相同的班级变量,我们应该如何解决这个问题呢?

class Student {
    //成员变量
    private String name;
    private int age;
    public String classRoom;

    //构造函数
    public Student() {

    }
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    //Gettter Setter
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    //成员方法

}
public class Tets1 {
    public static void main(String[] args) {
        Student student1 = new Student("A",15);
        student1.classRoom = "106";
        Student student2 = new Student("B",16);
        student2.classRoom = "106";
        Student student3 = new Student("C",15);
        student3.classRoom = "106";
    }
}

实际上,classroom = "106"这个变量我们只需要一份就好,这就用到了static

静态成员变量

    //成员变量
    private String name;
    private int age;
    //public String classRoom;
    public static String classRoom;

我们修改一下代码,调试一下就会发现:

对象中已经没有classRoom了,classRoom好像不属于对象了。那么classRoom被存到哪里了呢?我们引入一块新的内存,这块内存叫做方法区。

所有对象共用一个classRoom,对classRoom的访问方式也要做出相应的改变。  类名.classRoom

public class Tets1 {
    public static void main(String[] args) {
        Student student1 = new Student("A",15);
        //student1.classRoom = "106";
        Student student2 = new Student("B",16);
        //student2.classRoom = "106";
        Student student3 = new Student("C",15);
        //student3.classRoom = "106";
        Student.classRoom = "106";
    }
}

被static修饰的成员变量叫做静态成员变量,没有被static修饰的成员变量叫做普通成员变量或者非静态成员变量。非静态成员变量都属于对象,访问方式就是 对象名.成员变量名。

静态成员变量的使用不依赖于对象。不实例化对象也能使用。

public static void main(String[] args) {
//        Student student1 = new Student("A",15);
//        //student1.classRoom = "106";
//        Student student2 = new Student("B",16);
//        //student2.classRoom = "106";
//        Student student3 = new Student("C",15);
//        //student3.classRoom = "106";
        Student.classRoom = "106";
        System.out.println(Student.classRoom);//106
    }

静态成员变量最大的特性:不属于某个具体的对象,是所有对象所共享的。

静态成员方法

除了静态成员变量,你也可以写一个静态成员方法。

    //成员方法
    //普通成员方法
    public void eat() {
        System.out.println(this.name+" 正在吃饭!");
    }
    public void show() {
        System.out.println("姓名:"+this.name+" 年龄:"+this.age);
    }
    //静态方法
    public static void func() {
        System.out.println("这是一个静态方法!");
    }

同样静态成员方法的使用也不依赖于对象。调用方法:类名.func();

public class Tets1 {
    public static void main(String[] args) {
        Student.func();//这是一个静态方法!
    }
}

在静态方法内部,不能直接调用非静态方法,因为静态方法依赖对象,而非静态方法不依赖对象,这也就解释了当时我们定义方法时为什么要加static

    public static int add(int a,int b) {
        return a + b;
    }
    public static void main(String[] args) {!
        System.out.println(add(1, 2));
    }

如果把add方法中的static去掉,就相当于在main这个静态方法里调用了add这个非静态方法,java会报错。要调用必须通过对象的引用。

    public int add(int a,int b) {
        return a + b;
    }
    public static void main(String[] args) {
        Tets1 tets1 = new Tets1();
        System.out.println(tets1.add(1,2));
    }

同样,在静态成员方法里直接调用非静态成员变量也不行,也会报错。

    //静态方法
    public static void func() {
        show();//error
        System.out.println("这是一个静态方法!"+this.name);//error
    }

静态方法中不能直接调用非静态的成员方法或者调用成员变量。相反非静态成员方法中是可以调用静态成员方法的。

静态成员变量初始化

在上面的代码中,我们可以在main方法中初始化

    public static void main(String[] args) {
        Student.classRoom = "106";
    }

当静态成员变量被private修饰时,可以通过Getter和Setter进行初始化。

class Student {
    //成员变量
    private static String classRoom;

    //Gettter Setter
    public static String getClassRoom() {
        return classRoom;
    }

    public static void setClassRoom(String classRoom) {
        Student.classRoom = classRoom;
    }
}
public class Tets1 {
  
    public static void main(String[] args) {
        Student.setClassRoom("106");
    }
}

就地初始化

在定义时直接给出初始值

class Student {
    //成员变量
    private static String classRoom = "106";
……

静态代码块初始化

什么是代码块呢?

代码块

使用{}定义的一段代码称为代码块。可以分为四种:普通代码块、构造块、静态块、同步代码块(暂时不讲)。

普通代码块

就是定义在方法中的代码块,用的非常少。

public class Test2 {
    public static void main(String[] args) {
        //普通代码块
        {
            int x = 10;//x是局部变量,所用域是在{}里,出了{}就用不了了
            System.out.println(x);
        }
    }
}
构造代码块

定义在类中的代码块(不加修饰符),也叫做实例代码块。一般用于初始化实例成员变量

class Book {
    //普通成员变量
    private String name;
    private int price;
    //静态成员变量
    public static String author;

    //实例代码块  构造代码块 处于方法的外面,类的里面。
    //用于初始化实例成员变量
    {
        this.name = "海的女儿";
        this.price = 30;
        System.out.println("实例代码块!");
    }
    //Getter和Setter
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }
    
    //构造方法
    public Book() {
        System.out.println("不带参数的构造方法!");
    }
    public Book(String name, int price) {
        this.name = name;
        this.price = price;
    }
    
    //普通成员方法
    public void printBook() {
        System.out.println("书名:"+this.name+" 价格:"+this.price);
    }
    //静态成员方法
    public static void func() {
        System.out.println("这是一个静态成员方法!");
    }
}
public class Test2 {
    public static void main(String[] args) {
        Book book1 = new Book();
        book1.printBook();
    }
}

理论上来说,当我们创建一个实例化对象之后,程序会调用没有参数的构造方法,并且实例代码块会给book1初始化,所以程序会输出-->不带参数的构造方法!实例代码块!书名:海的女儿 价格:30

可当我们运行了这段代码之后,我们会发现输出结果和我们预想的不太一样。

这个输出结果说明,实例代码块会比构造方法先执行。跟实例代码块的位置无关,你可以动手试验一下。

静态代码块
class Book {
    //普通成员变量
    private String name;
    private int price;
    //静态成员变量
    public static String author;
    //实例代码块  构造代码块 处于方法的外面,类的里面。
    //用于初始化实例成员变量
    {
        this.name = "海的女儿";
        this.price = 30;
        System.out.println("实例代码块!");
    }
    //静态代码块 对静态成员变量初始化
    static {
        author = "xxx";
        System.out.println("静态代码块!");
    }
    //Getter和Setter
    public String getName() {
        return name;
    }
……

此时程序的输出结果又是什么呢?

说明静态代码块比实例代码块更早执行。

综上:静态代码块先于实例代码块先于构造方法。

现在我们实例化第二个对象,看看程序的输出结果又是什么。

public class Test2 {
    public static void main(String[] args) {
        Book book1 = new Book();
        book1.printBook();
        System.out.println("===============");
        Book book2 = new Book();
    }
}

为什么是这个输出结果呢?

原因:不管生成几个对象,静态代码块都只执行一次。

一个类里面可以有多个构造代码块或者静态代码块

    ……
    //静态代码块 对静态成员变量初始化
    static {
        author = "xxx";
        System.out.println("静态代码块!2");
    }
    static {
        author = "aaa";
        System.out.println("静态代码块!1");
    }
    ……

如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后顺序依次(合并)。

静态代码块只要类被加载就会被执行;实例代码块只有实例化对象的时候才被执行。

    public static void main(String[] args) {
        System.out.println(Book.author);
    }

在main方法中只输出静态成员变量,输出结果为:

只调用了静态代码块,实例代码块并没有被调用。

  • 20
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值